added logout and others
git-svn-id: svn://losandesgames.com/alfheim-website@4 15359d88-9307-4e75-a9c1-e5686e5897df
This commit is contained in:
parent
09e27a029c
commit
3aefbf7bd7
@ -1,8 +1,8 @@
|
|||||||
{{define "body"}}
|
{{define "body"}}
|
||||||
<div class="account-wrapper">
|
<div class="account-wrapper">
|
||||||
<div>Username: {{.Username}}</div>
|
<div>Username: {{.Account.Username}}</div>
|
||||||
<div>First name: {{.Firstname}}</div>
|
<div>First name: {{.Account.Firstname}}</div>
|
||||||
<div>Last name: {{.Lastname}}</div>
|
<div>Last name: {{.Account.Lastname}}</div>
|
||||||
<div>Color: {{.Color}}</div>
|
<div>Color: {{.Account.Color}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@ -19,8 +19,12 @@
|
|||||||
<nav>
|
<nav>
|
||||||
<a href="/"><h1 class="maintitle">Alfheim</h1></a>
|
<a href="/"><h1 class="maintitle">Alfheim</h1></a>
|
||||||
<div class="navbuttons">
|
<div class="navbuttons">
|
||||||
|
{{if .AuthenticatedUser}}
|
||||||
|
<a href="/logout"><div class="loginbutton"><strong>Log out</strong></div></a>
|
||||||
|
{{else}}
|
||||||
<a href="/login"><div class="loginbutton"><strong>Log in</strong><span class="material-symbols-outlined">login</span></div></a>
|
<a href="/login"><div class="loginbutton"><strong>Log in</strong><span class="material-symbols-outlined">login</span></div></a>
|
||||||
<a href="/register"><div class="loginbutton"><strong>Register</strong></div></a>
|
<a href="/register"><div class="loginbutton"><strong>Register</strong></div></a>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
128
handlers.go
128
handlers.go
@ -12,13 +12,33 @@ import "errors"
|
|||||||
import "runtime/debug"
|
import "runtime/debug"
|
||||||
|
|
||||||
type templatedata struct {
|
type templatedata struct {
|
||||||
Formerrors map[string]string
|
AuthenticatedUser int32
|
||||||
|
FormErrors map[string]string
|
||||||
|
Account models.Account
|
||||||
}
|
}
|
||||||
|
|
||||||
func favicon(w http.ResponseWriter, r *http.Request) {
|
func favicon(w http.ResponseWriter, r *http.Request) {
|
||||||
http.ServeFile(w, r, "favicon.ico")
|
http.ServeFile(w, r, "favicon.ico")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func authenticated_user(r *http.Request) int32 {
|
||||||
|
session, err := store.Get(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
id, ok := session.Values["id"].(int32)
|
||||||
|
if !ok {
|
||||||
|
trace := fmt.Sprintf("%s\n%s", errors.New("type assertion to int32 failed").Error(), debug.Stack())
|
||||||
|
_ = trace
|
||||||
|
//log.Println(trace)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
func home(w http.ResponseWriter, r *http.Request) {
|
func home(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path != "/" {
|
if r.URL.Path != "/" {
|
||||||
http.NotFound(w, r);
|
http.NotFound(w, r);
|
||||||
@ -34,16 +54,14 @@ func home(w http.ResponseWriter, r *http.Request) {
|
|||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
|
|
||||||
err = text.Execute(w, true)
|
err = text.Execute(w, templatedata{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
http.Error(w, "Internal Server Error", 500)
|
http.Error(w, "Internal Server Error", 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
data := LoginData{username: r.FormValue("username"), password: r.FormValue("password")}
|
err = text.Execute(w, templatedata{})
|
||||||
fmt.Println(data)
|
|
||||||
err = text.Execute(w, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
http.Error(w, "Internal Server Error", 500)
|
http.Error(w, "Internal Server Error", 500)
|
||||||
@ -69,40 +87,66 @@ func login(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
session, _ := store.Get(r, "id");
|
session, _ := store.Get(r, "id");
|
||||||
logindata := LoginData{username: r.FormValue("username"), password: r.FormValue("password")}
|
password := r.FormValue("password")
|
||||||
|
username := r.FormValue("username")
|
||||||
errors := make(map[string]string)
|
errors := make(map[string]string)
|
||||||
|
|
||||||
if strings.TrimSpace(logindata.username) == "" {
|
if strings.TrimSpace(username) == "" {
|
||||||
errors["username"] = "This field cannot be blank"
|
errors["username"] = "This field cannot be blank"
|
||||||
} else if utf8.RuneCountInString(logindata.username) > 20 {
|
} else if utf8.RuneCountInString(username) > 20 {
|
||||||
errors["username"] = "This field is too long (the maximum is 20 characters)"
|
errors["username"] = "This field is too long (the maximum is 20 characters)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.TrimSpace(logindata.password) == "" {
|
if strings.TrimSpace(password) == "" {
|
||||||
errors["password"] = "This field cannot be blank"
|
errors["password"] = "This field cannot be blank"
|
||||||
} else if utf8.RuneCountInString(logindata.password) < 8 {
|
} else if utf8.RuneCountInString(password) < 8 {
|
||||||
errors["password"] = "This field is too short (the minimum is 8 characters)"
|
errors["password"] = "This field is too short (the minimum is 8 characters)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
|
|
||||||
text.Execute(w, templatedata{errors})
|
text.Execute(w, templatedata{AuthenticatedUser: authenticated_user(r), FormErrors: errors})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
http.Error(w, "Internal Server Error", 500)
|
http.Error(w, "Internal Server Error", 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id, _ := users.Authenticate(logindata.username, logindata.password)
|
id, _ := users.Authenticate(username, password)
|
||||||
if id > 0 {
|
if id > 0 {
|
||||||
session.Values["id"] = id
|
session.Values["id"] = id
|
||||||
|
fmt.Println("Logged in with id:", id)
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
http.Redirect(w, r, "/account", http.StatusSeeOther)
|
http.Redirect(w, r, "/account", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logout(w http.ResponseWriter, r *http.Request) {
|
||||||
|
text, err := template.ParseFiles("base.html", "logout/index.html")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Internal Server Error", 500)
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
|
||||||
|
text.Execute(w, templatedata{})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
http.Error(w, "Internal Server Error", 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
case http.MethodPost:
|
||||||
|
session, _ := store.Get(r, "id");
|
||||||
|
|
||||||
|
session.Values["id"] = 0;
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func register(w http.ResponseWriter, r *http.Request) {
|
func register(w http.ResponseWriter, r *http.Request) {
|
||||||
text, err := template.ParseFiles("base.html", "register/index.html")
|
text, err := template.ParseFiles("base.html", "register/index.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -138,22 +182,19 @@ func register(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
|
|
||||||
text.Execute(w, templatedata{errors})
|
text.Execute(w, templatedata{AuthenticatedUser: authenticated_user(r), FormErrors: errors})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
http.Error(w, "Internal Server Error", 500)
|
http.Error(w, "Internal Server Error", 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(account)
|
|
||||||
|
|
||||||
users.Insert(account.Username, string(account.Password), account.Firstname, account.Lastname, account.Email)
|
users.Insert(account.Username, string(account.Password), account.Firstname, account.Lastname, account.Email)
|
||||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func account(w http.ResponseWriter, r *http.Request) {
|
func account(w http.ResponseWriter, r *http.Request) {
|
||||||
session, _ := store.Get(r, "id")
|
|
||||||
//id, err := strconv.Atoi(r.URL.Query().Get("id"))
|
//id, err := strconv.Atoi(r.URL.Query().Get("id"))
|
||||||
//if err != nil || id < 1 {
|
//if err != nil || id < 1 {
|
||||||
// http.NotFound(w, r)
|
// http.NotFound(w, r)
|
||||||
@ -164,38 +205,29 @@ func account(w http.ResponseWriter, r *http.Request) {
|
|||||||
// log.Fatal(err);
|
// log.Fatal(err);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
id, ok := session.Values["id"].(int32)
|
id := authenticated_user(r)
|
||||||
if !ok {
|
account, err := users.Get_account(id)
|
||||||
trace := fmt.Sprintf("%s\n%s", errors.New("type assertion to int32 failed").Error(), debug.Stack())
|
|
||||||
log.Println(trace)
|
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
} else {
|
|
||||||
account, err := users.Get_account(id)
|
|
||||||
fmt.Println(account)
|
|
||||||
|
|
||||||
text, err := template.ParseFiles("base.html", "account/index.html")
|
text, err := template.ParseFiles("base.html", "account/index.html")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Internal Server Error", 500)
|
http.Error(w, "Internal Server Error", 500)
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
|
||||||
|
|
||||||
switch r.Method {
|
|
||||||
case http.MethodGet:
|
|
||||||
text.Execute(w, account)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
http.Error(w, "Internal Server Error", 500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//case http.MethodPost:
|
|
||||||
// data := LoginData{username: r.FormValue("username"), password: r.FormValue("password")}
|
|
||||||
// fmt.Println(data)
|
|
||||||
// text.Execute(w, false)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatal(err)
|
|
||||||
// http.Error(w, "Internal Server Error", 500)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
text.Execute(w, templatedata{AuthenticatedUser: id, Account: account})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
http.Error(w, "Internal Server Error", 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//case http.MethodPost:
|
||||||
|
// text.Execute(w, false)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// http.Error(w, "Internal Server Error", 500)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,20 @@
|
|||||||
<form method="POST">
|
<form method="POST">
|
||||||
<h1>Log in</h1>
|
<h1>Log in</h1>
|
||||||
|
|
||||||
{{with .Formerrors.username}}
|
{{with .FormErrors.username}}
|
||||||
<label class="error">{{.}}</label>
|
<label class="error">{{.}}</label>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<div {{if .Formerrors.username}}class="input-error"{{else}}class="input-box"{{end}}>
|
<div {{if .FormErrors.username}}class="input-error"{{else}}class="input-box"{{end}}>
|
||||||
<input type="text" id="username" name="username" placeholder="Username" required>
|
<input type="text" id="username" name="username" placeholder="Username" required>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{{with .Formerrors.password}}
|
{{with .FormErrors.password}}
|
||||||
<label class="error">{{.}}</label>
|
<label class="error">{{.}}</label>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<div {{if .Formerrors.password}}class="input-error"{{else}}class="input-box"{{end}}>
|
<div {{if .FormErrors.password}}class="input-error"{{else}}class="input-box"{{end}}>
|
||||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
11
logout/index.html
Normal file
11
logout/index.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{{define "body"}}
|
||||||
|
<div class="wrapper">
|
||||||
|
<form method="POST">
|
||||||
|
<h1>Log out</h1>
|
||||||
|
|
||||||
|
<div class="login-btn-wrapper">
|
||||||
|
<input type="submit" value="Log out" class="btn">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
27
main.go
27
main.go
@ -18,13 +18,7 @@ var store = sessions.NewCookieStore(key)
|
|||||||
|
|
||||||
var emailrx = regexp.MustCompile("/^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/");
|
var emailrx = regexp.MustCompile("/^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/");
|
||||||
|
|
||||||
type LoginData struct {
|
func secure_headers(next http.Handler) http.Handler {
|
||||||
username string
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func secureheaders(next http.Handler) http.Handler {
|
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("X-XSS-Protection", "1; mode=block")
|
w.Header().Set("X-XSS-Protection", "1; mode=block")
|
||||||
w.Header().Set("X-Frame-Options", "deny")
|
w.Header().Set("X-Frame-Options", "deny")
|
||||||
@ -35,6 +29,20 @@ func secureheaders(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(fn)
|
return http.HandlerFunc(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func require_authenticated_user(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// If the user is not authenticated, redirect them to the login page and
|
||||||
|
// return from the middleware chain so that no subsequent handlers in
|
||||||
|
// the chain are executed.
|
||||||
|
if authenticated_user(r) == 0 {
|
||||||
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Otherwise call the next handler in the chain.
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
addr := flag.String("addr", ":8080", "HTTP network address")
|
addr := flag.String("addr", ":8080", "HTTP network address")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -82,12 +90,13 @@ func main() {
|
|||||||
|
|
||||||
mux.HandleFunc("/", home)
|
mux.HandleFunc("/", home)
|
||||||
mux.HandleFunc("/login", login)
|
mux.HandleFunc("/login", login)
|
||||||
|
mux.HandleFunc("/logout", logout)
|
||||||
mux.HandleFunc("/register", register)
|
mux.HandleFunc("/register", register)
|
||||||
mux.HandleFunc("/account", account)
|
mux.HandleFunc("/account", require_authenticated_user(account))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(*addr, secureheaders(mux)))
|
log.Fatal(http.ListenAndServe(*addr, secure_headers(mux)))
|
||||||
}
|
}
|
||||||
|
|
||||||
//cookie := http.Cookie{
|
//cookie := http.Cookie{
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import "time"
|
|||||||
import "golang.org/x/crypto/bcrypt"
|
import "golang.org/x/crypto/bcrypt"
|
||||||
import "database/sql"
|
import "database/sql"
|
||||||
import _ "github.com/lib/pq"
|
import _ "github.com/lib/pq"
|
||||||
import "fmt"
|
import _ "fmt"
|
||||||
|
|
||||||
var Errnorecord = errors.New("no matching record found")
|
var Errnorecord = errors.New("no matching record found")
|
||||||
var Errinvalidcredentials = errors.New("invalid credentials")
|
var Errinvalidcredentials = errors.New("invalid credentials")
|
||||||
@ -44,7 +44,6 @@ func (m *Usermodel) Get_account(id int32) (Account, error) {
|
|||||||
row := m.DB.QueryRow(stmt, id)
|
row := m.DB.QueryRow(stmt, id)
|
||||||
var account Account
|
var account Account
|
||||||
err := row.Scan(&account.Id, &account.Username, &account.Password, &account.Color, &account.Firstname, &account.Lastname, &account.Email, &account.Created)
|
err := row.Scan(&account.Id, &account.Username, &account.Password, &account.Color, &account.Firstname, &account.Lastname, &account.Email, &account.Created)
|
||||||
fmt.Println(err)
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return Account{}, sql.ErrNoRows
|
return Account{}, sql.ErrNoRows
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user