My Very Own CI-server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

252 lines
9.3 KiB

// the package web contains the web-related stuff, i.e. all handlers
// the routing "table" and loads of functions for rendering the views and
// interacting with the database
package web
import (
"os"
"fmt"
"time"
//"strings"
"strconv"
"net/http"
"html/template"
"mvoCI/core"
"github.com/jinzhu/gorm"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"github.com/foolin/goview/supports/echoview"
"github.com/foolin/goview"
)
// structure for globally known values inside the web-package
type Server struct {
echo *echo.Echo // global reference to the echo object
cfg *core.Config // global reference to the config object
db *gorm.DB // global reference to the database connection
}
var s *Server
// sends an information back, that there was no database object
func dbErrorHandler ( ctx echo.Context ) error {
return ctx.String ( http.StatusOK, "Database connection refused" )
}
// the routing "table"
func (s *Server) Routes () {
if s.db != nil || (s.db == nil && s.cfg.Install != false) {
s.echo.GET ( "/", indexHandler )
s.echo.GET ( "/login", loginHandler )
s.echo.GET ( "/impress", impressHandler )
s.echo.GET ( "/dashboard", indexHandler )
if s.cfg.Install == false {
s.echo.POST ( "/login", doLoginHandler )
s.echo.GET ( "/install/:id", loginHandler )
s.echo.GET ( "/install/", loginHandler )
s.echo.GET ( "/install", loginHandler )
s.echo.GET ( "/logout", doLogoutHandler )
s.echo.GET ( "/integration", integrationHandler )
// USER
s.echo.GET ( "/user", userHandler )
s.echo.GET ( "/user/:id", userEditHandler )
s.echo.GET ( "/user/edit/:id", userEditHandler )
s.echo.GET ( "/user/add", userAddHandler )
s.echo.POST ( "/user/post/add", userAddPostHandler )
s.echo.POST ( "/user/post/edit/:id", userEditPostHandler )
s.echo.GET ( "/user/delete/:id", userDeleteHandler )
s.echo.GET ( "/user/repo/:id", userRepoHandler )
s.echo.POST ( "/user/:id/token/add", userTokenAdd );
s.echo.GET ( "/user/:id/token/invalidate/:tid", userTokenInvalidate );
// REPO
s.echo.GET ( "/repo", repoHandler )
s.echo.GET ( "/repo/add", repoAddHandler );
s.echo.GET ( "/repo/:id", repoViewHandler )
s.echo.GET ( "/repo/view/:id", repoViewHandler )
s.echo.GET ( "/repo/view/:id/:page", repoViewHandler )
s.echo.GET ( "/repo/edit/:id", repoEditHandler )
s.echo.POST ( "/repo/post/add", repoAddPostHandler );
s.echo.POST ( "/repo/post/edit/:id", repoEditPostHandler )
s.echo.GET ( "/repo/delete/:id", repoDeleteHandler );
s.echo.GET ( "/repo/build/:id", repoBuildHandler );
s.echo.GET ( "/repo/state/:id", repoStateHandler );
// BUILDs
s.echo.GET ( "/build/:id", buildViewHandler );
s.echo.GET ( "/build/log/:id", buildLogHandler );
s.echo.GET ( "/build/delete/:id", buildDeleteHandler );
s.echo.GET ( "/build/rebuild/:id", buildRebuildHandler );
s.echo.GET ( "/zip/:file", zipDownloadHandler );
// WEBHOOK!
s.echo.POST ( "/push/hook/:api", webhook )
// oauth redirect URI
s.echo.GET ("/oauth/validate/:api/:oauthid", oauthApiHook );
// OAuth
s.echo.GET ("/oauth", oauthOverviewHandler );
s.echo.GET ("/oauth/add", oauthAddHandler );
s.echo.POST ("/oauth/add", oauthAddPostHandler )
s.echo.GET ("/oauth/:id/invalidate", oauthInvalidateHandler );
// API
if s.cfg.Api.Enable {
s.echo.GET ( "/api/v1/:endpoint", apiHandler );
s.echo.GET ( "/api/v1/:endpoint/:action", apiHandler );
s.echo.GET ( "/api/v1/:endpoint/:action/:id", apiHandler );
if s.cfg.Api.ListingEnable {
s.echo.GET ( "/api/v1", apiListingHandler );
}
}
// admin stuff
s.echo.GET ( "/admin/webhooklog", WebHookLogHandler );
s.echo.GET ( "/admin/webhooklog/:repoid", WebHookLogHandler );
s.echo.GET ( "/admin/webhooklog/detail/:id", WebHookLogDetailHandler );
s.echo.GET ( "/admin/info", AdminInfoHandler );
if s.cfg.PublicEnable == true {
s.echo.GET ( "/public", publicOverviewHandler );
s.echo.GET ( "/public/:id", publicRepoHandler );
s.echo.GET ( "/public/:id/:page", publicRepoHandler );
s.echo.GET ( "/public/zip/:file", publicZipHandler );
}
}
if s.cfg.Install == true {
s.echo.GET ( "/install/:id", installHandler )
s.echo.GET ( "/install/", installHandler )
s.echo.GET ( "/install", installHandler )
s.echo.POST ( "/install/post/:id", installPostHandler )
}
} else {
s.echo.GET ( "/", dbErrorHandler );
}
}
// renders a list of errors
func render_error_list ( errors []string ) template.HTML {
if len(errors) <= 0 {
return template.HTML ( "" );
}
var result string
result = "<div class=\"messages error\"><ul>"
for _, v := range errors {
result += "<li>"+ v +"</li>\n"
}
result += "</ul></div>"
return template.HTML(result)
}
func BuildStatus ( s string ) template.HTML {
var f string
if s == "started" {
f = "<i class=\"fa fa-cog fa-spin\" title=\"Building\"></i>"
} else if s == "enqueued" {
f = "<i class=\"fa fa-clock-o\" title=\"Queued\"></i>"
} else if s == "failed" || s == "Failed" {
f = "<i class=\"fa fa-times-circle\" title=\"Error\"></i>"
} else if s == "finished" || s == "Success" {
f = "<i class=\"fa fa-check-circle\" title=\"Success\"></i>"
} else {
f = "<i class=\"fa fa-question-circle\" title=\"Unknown\"></i>"
}
return template.HTML(f)
}
func RenderTime ( t time.Time ) string {
return t.Format ("Mon Jan _2 15:04:05")
}
// sets up the echo server
func NewServer ( c *core.Config, d *gorm.DB ) Server {
server := Server{}
server.cfg = c
server.db = d
server.echo = echo.New()
var serverlogger *core.ServerLogger;
serverlogger, err := core.ServerLoggerNew ( c.LogServer );
if err == nil {
server.echo.Use(middleware.LoggerWithConfig(
middleware.LoggerConfig{Output: serverlogger}))
} else {
server.echo.Use(middleware.Logger())
}
server.echo.Use(middleware.Recover())
server.echo.Renderer = echoview.New(goview.Config{
Root: "views",
Extension: ".html",
Master: "layouts/master",
Funcs: template.FuncMap{
"app_title": func() string {
return server.cfg.AppTitle
},
"app_version": func() string{
return core.Version
},
"config": func( q string ) string {
return server.cfg.Reflect( q )
},
"config_html": func ( q string ) template.HTML {
return template.HTML ( server.cfg.Reflect ( q ) )
},
"render_error_list": render_error_list,
"build_status": BuildStatus,
"render_time": RenderTime,
},
DisableCache: true,
})
server.echo.Use(middleware.Secure())
server.echo.HTTPErrorHandler = customHTTPErrorHandler
server.Routes()
server.echo.Static ( "/static", "static" )
server.echo.Static ( "/favicon.ico", "static/img/favicon.png" )
//server.echo.Static ( "/zip", "builds" ) //strings.TrimRight(s.cfg.Directory.Build, "/") )
//server.echo.Static ( "/public/zip", "builds" ) // strings.TrimRight(s.cfg.Directory.Build, "/") )
//server.echo.Static ( "/public/zip", s.cfg.Directory.Build )
s = &server
return server;
}
// returns an HTTP error
func HTTPError ( code int, ctx echo.Context ) error {
errorPage := fmt.Sprintf("/error/HTTP%d.html", code)
m := echo.Map{
"author_email": s.cfg.Author.Email,
"author_name": s.cfg.Author.Name,
}
if _, err := os.Stat ( "/view"+errorPage ); err != nil {
return ctx.Render(code, errorPage, m)
} else {
ctx.Logger().Error(err)
return nil
}
}
// serves a custom HTTP error page
func customHTTPErrorHandler(err error, ctx echo.Context) {
code := http.StatusInternalServerError
if he, ok := err.(*echo.HTTPError); ok {
code = he.Code
}
errorPage := fmt.Sprintf("/error/HTTP%d.html", code)
m := echo.Map{
"author_email": s.cfg.Author.Email,
"author_name": s.cfg.Author.Name,
}
if err := ctx.Render(code, errorPage, m); err != nil {
ctx.Logger().Error(err)
}
ctx.Logger().Error(err)
}
// starts the server and prints minor debug information
func (s* Server) Start() {
fmt.Print ("Starting server at "+s.cfg.HttpHost + ":" + strconv.FormatInt( int64(s.cfg.HttpPort), 10 ))
s.echo.Start(s.cfg.HttpHost + ":" + strconv.FormatInt ( int64(s.cfg.HttpPort), 10 ))
}