mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-10 17:45:36 +00:00
ability to server website from disk
This commit is contained in:
parent
7055966c30
commit
7008e79c9c
5 changed files with 224 additions and 12 deletions
|
@ -2,7 +2,6 @@ package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
@ -13,8 +12,6 @@ import (
|
||||||
"github.com/drone/drone/server/debug"
|
"github.com/drone/drone/server/debug"
|
||||||
"github.com/drone/drone/server/metrics"
|
"github.com/drone/drone/server/metrics"
|
||||||
"github.com/drone/drone/server/template"
|
"github.com/drone/drone/server/template"
|
||||||
|
|
||||||
"github.com/drone/drone-ui/dist"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Load loads the router
|
// Load loads the router
|
||||||
|
@ -24,13 +21,11 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
||||||
e.Use(gin.Recovery())
|
e.Use(gin.Recovery())
|
||||||
e.SetHTMLTemplate(template.T)
|
e.SetHTMLTemplate(template.T)
|
||||||
|
|
||||||
if dir := os.Getenv("DRONE_STATIC_DIR"); dir == "" {
|
ui := server.NewWebsite()
|
||||||
fs := http.FileServer(dist.AssetFS())
|
for _, path := range ui.Routes() {
|
||||||
e.GET("/static/*filepath", func(c *gin.Context) {
|
e.GET(path, func(c *gin.Context) {
|
||||||
fs.ServeHTTP(c.Writer, c.Request)
|
ui.File(c.Writer, c.Request)
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
e.Static("/static", dir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Use(header.NoCache)
|
e.Use(header.NoCache)
|
||||||
|
@ -40,10 +35,11 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
||||||
e.Use(session.SetUser())
|
e.Use(session.SetUser())
|
||||||
e.Use(token.Refresh)
|
e.Use(token.Refresh)
|
||||||
|
|
||||||
e.GET("/login", server.ShowLogin)
|
|
||||||
e.GET("/login/form", server.ShowLoginForm)
|
|
||||||
e.GET("/logout", server.GetLogout)
|
e.GET("/logout", server.GetLogout)
|
||||||
e.NoRoute(server.ShowIndex)
|
e.NoRoute(func(c *gin.Context) {
|
||||||
|
u := session.User(c)
|
||||||
|
ui.Page(c.Writer, c.Request, u)
|
||||||
|
})
|
||||||
|
|
||||||
user := e.Group("/api/user")
|
user := e.Group("/api/user")
|
||||||
{
|
{
|
||||||
|
|
33
server/template/files/index_polymer.html
Normal file
33
server/template/files/index_polymer.html
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="author" content="bradrydzewski">
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
|
||||||
|
|
||||||
|
<title></title>
|
||||||
|
<script>
|
||||||
|
window.ENV = {};
|
||||||
|
window.ENV.server = window.location.protocol+"//"+window.location.host;
|
||||||
|
{{ if .csrf }}window.ENV.csrf = "{{ .csrf }}"{{ end }}
|
||||||
|
{{ if .user }}
|
||||||
|
window.USER = {{ json .user }};
|
||||||
|
{{ end }}
|
||||||
|
</script>
|
||||||
|
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono">
|
||||||
|
<link rel="import" href="/src/drone/drone-app.html">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
padding:0px;
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<drone-app></drone-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -13,6 +13,9 @@ var files = []struct {
|
||||||
}, {
|
}, {
|
||||||
name: "index.html",
|
name: "index.html",
|
||||||
data: index,
|
data: index,
|
||||||
|
}, {
|
||||||
|
name: "index_polymer.html",
|
||||||
|
data: indexpolymer,
|
||||||
}, {
|
}, {
|
||||||
name: "login.html",
|
name: "login.html",
|
||||||
data: login,
|
data: login,
|
||||||
|
@ -83,6 +86,42 @@ var index = `<!DOCTYPE html>
|
||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// files/index_polymer.html
|
||||||
|
var indexpolymer = `<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="author" content="bradrydzewski">
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
|
||||||
|
|
||||||
|
<title></title>
|
||||||
|
<script>
|
||||||
|
window.ENV = {};
|
||||||
|
window.ENV.server = window.location.protocol+"//"+window.location.host;
|
||||||
|
{{ if .csrf }}window.ENV.csrf = "{{ .csrf }}"{{ end }}
|
||||||
|
{{ if .user }}
|
||||||
|
window.USER = {{ json .user }};
|
||||||
|
{{ end }}
|
||||||
|
</script>
|
||||||
|
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono">
|
||||||
|
<link rel="import" href="/src/drone/drone-app.html">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
padding:0px;
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<drone-app></drone-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
|
||||||
// files/login.html
|
// files/login.html
|
||||||
var login = `<!DOCTYPE html>
|
var login = `<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
78
server/ui.go
Normal file
78
server/ui.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/drone/drone-ui/dist"
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/drone/drone/server/template"
|
||||||
|
"github.com/drone/drone/shared/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Website defines an interface to serve the user interface.
|
||||||
|
type Website interface {
|
||||||
|
Page(rw http.ResponseWriter, r *http.Request, u *model.User)
|
||||||
|
File(rw http.ResponseWriter, r *http.Request)
|
||||||
|
Routes() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type website struct {
|
||||||
|
fs http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWebsite returns a new website loader.
|
||||||
|
func NewWebsite() Website {
|
||||||
|
path := os.Getenv("DRONE_WWW")
|
||||||
|
if path != "" {
|
||||||
|
return NewLocalWebsite(path)
|
||||||
|
}
|
||||||
|
return &website{
|
||||||
|
fs: http.FileServer(dist.AssetFS()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page serves a page in the user interface.
|
||||||
|
func (w *website) Page(rw http.ResponseWriter, r *http.Request, u *model.User) {
|
||||||
|
rw.WriteHeader(200)
|
||||||
|
|
||||||
|
path := r.URL.Path
|
||||||
|
switch path {
|
||||||
|
case "/login/form":
|
||||||
|
params := map[string]interface{}{}
|
||||||
|
template.T.ExecuteTemplate(rw, "login.html", params)
|
||||||
|
|
||||||
|
case "/login":
|
||||||
|
if err := r.FormValue("error"); err != "" {
|
||||||
|
params := map[string]interface{}{"error": err}
|
||||||
|
template.T.ExecuteTemplate(rw, "error.html", params)
|
||||||
|
} else {
|
||||||
|
http.Redirect(rw, r, "/authorize", 303)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
var csrf string
|
||||||
|
if u != nil {
|
||||||
|
csrf, _ = token.New(
|
||||||
|
token.CsrfToken,
|
||||||
|
u.Login,
|
||||||
|
).Sign(u.Hash)
|
||||||
|
}
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"user": u,
|
||||||
|
"csrf": csrf,
|
||||||
|
}
|
||||||
|
template.T.ExecuteTemplate(rw, "index.html", params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// File serves a static file for the user interface.
|
||||||
|
func (w *website) File(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
w.fs.ServeHTTP(rw, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *website) Routes() []string {
|
||||||
|
return []string{
|
||||||
|
"/static/*filepath",
|
||||||
|
}
|
||||||
|
}
|
66
server/ui_local.go
Normal file
66
server/ui_local.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/drone/drone/server/template"
|
||||||
|
"github.com/drone/drone/shared/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
type local struct {
|
||||||
|
dir string
|
||||||
|
fs http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocalWebsite returns a new website loader.
|
||||||
|
func NewLocalWebsite(path string) Website {
|
||||||
|
return &local{
|
||||||
|
dir: path,
|
||||||
|
fs: http.FileServer(
|
||||||
|
http.Dir(path),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page serves a page in the user interface.
|
||||||
|
func (w *local) Page(rw http.ResponseWriter, r *http.Request, u *model.User) {
|
||||||
|
rw.WriteHeader(200)
|
||||||
|
|
||||||
|
path := r.URL.Path
|
||||||
|
switch path {
|
||||||
|
case "/login":
|
||||||
|
if err := r.FormValue("error"); err != "" {
|
||||||
|
// TODO login error
|
||||||
|
} else {
|
||||||
|
http.Redirect(rw, r, "/authorize", 303)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
var csrf string
|
||||||
|
if u != nil {
|
||||||
|
csrf, _ = token.New(
|
||||||
|
token.CsrfToken,
|
||||||
|
u.Login,
|
||||||
|
).Sign(u.Hash)
|
||||||
|
}
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"user": u,
|
||||||
|
"csrf": csrf,
|
||||||
|
}
|
||||||
|
|
||||||
|
template.T.ExecuteTemplate(rw, "index_polymer.html", params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// File serves a static file for the user interface.
|
||||||
|
func (w *local) File(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
w.fs.ServeHTTP(rw, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *local) Routes() []string {
|
||||||
|
return []string{
|
||||||
|
"/src/*filepath",
|
||||||
|
"/bower_components/*filepath",
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue