forked from AlexMax/charon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
webbase.go
131 lines (112 loc) · 3.44 KB
/
webbase.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* Charon: A game authentication server
* Copyright (C) 2016 Alex Mayfield <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package charon
import (
"net/http"
"golang.org/x/net/context"
)
// BaseTemplates contains template definitions for the base routes.
var BaseTemplates = TemplateDefs{
"home": TemplateNames{"layout", "header", "home"},
"login": TemplateNames{"layout", "header", "login"},
}
// Home renders the homepage.
func (webApp *WebApp) Home(res http.ResponseWriter, req *http.Request) {
webApp.RenderTemplate(res, req, "home", nil)
}
// LoginData contains the context for the Login page.
type LoginData struct {
Form *LoginForm
Errors FormErrors
}
// LoginForm contains the form data for the Login page.
type LoginForm struct {
Login string
Password string
}
// Login renders the login page.
func (webApp *WebApp) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) {
data := NewLoginData(req)
if req.Method != "GET" {
// Validate the form
data.Form = &LoginForm{
Login: req.PostFormValue("login"),
Password: req.PostFormValue("password"),
}
var user *User
user, data.Errors = data.Form.Validate(webApp.database)
if len(data.Errors) > 0 {
webApp.RenderTemplate(res, req, "login", data)
return
}
// We have a user, but we don't actually want to store the salt or
// verifier in the session, so blank them out.
user.Salt = []byte("")
user.Verifier = []byte("")
// Store user in the session.
session, err := webApp.sessionStore.Get(req, sessionName)
if err != nil {
http.Error(res, err.Error(), 500)
return
}
session.Values["User"] = *user
err = session.Save(req, res)
if err != nil {
http.Error(res, err.Error(), 500)
return
}
// Redirect to the front page.
http.Redirect(res, req, "/", 302)
} else {
webApp.RenderTemplate(res, req, "login", data)
}
}
// Validate validates the LoginForm.
func (form *LoginForm) Validate(db *Database) (user *User, formErrors FormErrors) {
formErrors = make(FormErrors)
if len(form.Login) == 0 {
formErrors["Login"] = "A username or e-mail address is required."
}
if len(form.Password) == 0 {
formErrors["Password"] = "A password is required."
}
// Return early if our username or password doesn't validate.
if len(formErrors) > 0 {
return
}
// Try and log the user in.
user, err := db.LoginUser(form.Login, form.Password)
if err != nil {
formErrors["Flash"] = "Invalid username or password"
}
return
}
// NewLoginData creates a new LoginData that optionally contains prepopulated
// data from the request.
func NewLoginData(req *http.Request) (data *LoginData) {
data = &LoginData{}
if req != nil {
data.Form = &LoginForm{
Login: req.PostFormValue("login"),
Password: req.PostFormValue("password"),
}
} else {
data.Form = &LoginForm{}
}
return
}