From e48d321f29a5fb2d362ff5342edf32f5c01ddcbf Mon Sep 17 00:00:00 2001 From: Steve Date: Thu, 17 Sep 2020 16:19:05 -0400 Subject: [PATCH] use templates, login/logout session support --- config.go | 16 +++--- go.mod | 1 + go.sum | 2 + index.html | 11 ---- main.go | 65 +++++++++++++++++++++++- session.go | 37 ++++++++++++++ templates/footer.html | 4 ++ templates/header.html | 14 +++++ templates/index.html | 7 +++ templates/login.html | 18 +++++++ register.html => templates/register.html | 11 ++-- 11 files changed, 160 insertions(+), 26 deletions(-) delete mode 100644 index.html create mode 100644 session.go create mode 100644 templates/footer.html create mode 100644 templates/header.html create mode 100644 templates/index.html create mode 100644 templates/login.html rename register.html => templates/register.html (87%) diff --git a/config.go b/config.go index 0f62a74..1fb5591 100644 --- a/config.go +++ b/config.go @@ -12,15 +12,17 @@ type LdapConfig struct { UserAttr string UserOu string LdapDc string + LdapPass string } type Config struct { - Ldap *LdapConfig - Secret string - Tls bool - Key string - Cert string - Port string + Ldap *LdapConfig + Secret string + TplPath string + Tls bool + Key string + Cert string + Port string } func validateConfigEntry(entry string, name string) bool { @@ -51,11 +53,13 @@ func LoadConfig() (*Config, error) { l.UserAttr = viper.GetString("userAttr") l.UserOu = viper.GetString("userOu") l.LdapDc = viper.GetString("ldapDc") + l.LdapPass = viper.GetString("ldapPass") c.Secret = viper.GetString("secret") c.Tls = viper.GetBool("tls") c.Port = viper.GetString("port") c.Key = viper.GetString("tls_key") c.Cert = viper.GetString("tls_cert") + c.TplPath = viper.GetString("templates_path") //Validate configs if validateConfigEntry(l.Url, "ldapUrl") || validateConfigEntry(l.AdminUser, "adminUser") || validateConfigEntry(l.UserOu, "userOu") || validateConfigEntry(l.LdapDc, "ldapDc") || validateConfigEntry(l.UserAttr, "userAttr") { diff --git a/go.mod b/go.mod index ecd0d11..3b1722d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.14 require ( github.com/go-ldap/ldap v3.0.3+incompatible + github.com/gorilla/securecookie v1.1.1 github.com/spf13/viper v1.7.1 gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect ) diff --git a/go.sum b/go.sum index 1a46d62..0a70455 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,8 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= diff --git a/index.html b/index.html deleted file mode 100644 index 258a501..0000000 --- a/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - -

Guildgate

- Register - - diff --git a/main.go b/main.go index d3e11be..bfaf7c1 100644 --- a/main.go +++ b/main.go @@ -3,13 +3,26 @@ package main import ( "log" "net/http" + "text/template" + + "github.com/gorilla/securecookie" ) var Conf *Config +var tpl *template.Template +var cookieHandler = securecookie.New( + securecookie.GenerateRandomKey(64), + securecookie.GenerateRandomKey(32)) func signupPage(res http.ResponseWriter, req *http.Request) { if req.Method != "POST" { - http.ServeFile(res, req, "register.html") + log.Println("GET /register") + u := getUserName(req) + if u != "" { + http.Redirect(res, req, "/", 302) + } else { + tpl.ExecuteTemplate(res, "register", nil) + } return } @@ -35,15 +48,63 @@ func signupPage(res http.ResponseWriter, req *http.Request) { } } +func loginPage(res http.ResponseWriter, req *http.Request) { + if req.Method != "POST" { + log.Println("GET /login") + u := getUserName(req) + if u != "" { + http.Redirect(res, req, "/", 302) + } else { + tpl.ExecuteTemplate(res, "login", nil) + } + return + } + username := req.FormValue("username") + password := req.FormValue("password") + log.Printf("Attempting login for user %v\n", username) + err := loginLDAPAccount(username, password) + if err != nil { + log.Printf("Error logging in user %v: %v\n", username, err) + res.Write([]byte("Error logging in. Incorrect password?")) + return + } else { + setSession(username, res) + http.Redirect(res, req, "/", 302) + return + } +} + +func logoutPage(res http.ResponseWriter, req *http.Request) { + clearSession(res) + http.Redirect(res, req, "/", 302) +} + func homePage(res http.ResponseWriter, req *http.Request) { - http.ServeFile(res, req, "index.html") + u := getUserName(req) + uname := "Unregistered" + if u != "" { + uname = u + } + data := struct { + Title string + Username string + }{ + "Index", + uname, + } + + tpl.ExecuteTemplate(res, "index", data) } func main() { Conf, _ = LoadConfig() log.Println("Loaded config") http.HandleFunc("/register", signupPage) + http.HandleFunc("/login", loginPage) + http.HandleFunc("/logout", logoutPage) http.HandleFunc("/", homePage) + log.Printf("Registering templates from %v/\n", Conf.TplPath) + tpl = template.Must(template.ParseGlob(Conf.TplPath + "/*.html")) log.Printf("Guildgate starting on %v\n", Conf.Port) var err error if Conf.Tls { diff --git a/session.go b/session.go new file mode 100644 index 0000000..62d633a --- /dev/null +++ b/session.go @@ -0,0 +1,37 @@ +package main + +import "net/http" + +func setSession(uname string, res http.ResponseWriter) { + value := map[string]string{ + "name": uname, + } + if encoded, err := cookieHandler.Encode("session", value); err == nil { + cookie := &http.Cookie{ + Name: "session", + Value: encoded, + Path: "/", + } + http.SetCookie(res, cookie) + } +} + +func getUserName(req *http.Request) (uname string) { + if cookie, err := req.Cookie("session"); err == nil { + cookieValue := make(map[string]string) + if err = cookieHandler.Decode("session", cookie.Value, &cookieValue); err == nil { + uname = cookieValue["name"] + } + } + return uname +} + +func clearSession(res http.ResponseWriter) { + cookie := &http.Cookie{ + Name: "session", + Value: "", + Path: "/", + MaxAge: -1, + } + http.SetCookie(res, cookie) +} diff --git a/templates/footer.html b/templates/footer.html new file mode 100644 index 0000000..c8f56d8 --- /dev/null +++ b/templates/footer.html @@ -0,0 +1,4 @@ +{{define "footer"}} + + +{{end}} diff --git a/templates/header.html b/templates/header.html new file mode 100644 index 0000000..d0d814e --- /dev/null +++ b/templates/header.html @@ -0,0 +1,14 @@ +{{ define "header" }} + + + + GuildGate + + + +{{end}} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..ebc139d --- /dev/null +++ b/templates/index.html @@ -0,0 +1,7 @@ +{{ define "index" }} +{{ template "header" .}} + Register + Login + Get Token +{{template "footer" .}} +{{ end }} diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..5daad63 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,18 @@ +{{ define "login" }} +{{ template "header" .}} +

Login

+
+
+ + +
+
+ + +
+
+ +
+
+{{ template "footer" .}} +{{end}} diff --git a/register.html b/templates/register.html similarity index 87% rename from register.html rename to templates/register.html index 3a22e62..d058129 100644 --- a/register.html +++ b/templates/register.html @@ -1,8 +1,5 @@ - - - -

Registration Form

- +{{ define "register" }} +{{ template "header" .}}
@@ -26,5 +23,5 @@
- - +{{ template "footer" .}} +{{ end }}