From 3a501d85a560b2e2c5c5ded47cc431e4f1315d21 Mon Sep 17 00:00:00 2001 From: Kevin Chabowski Date: Fri, 30 Aug 2013 15:11:50 +0200 Subject: Defined own handler type to reduce repetive jobs. --- activate.go | 26 +++++------- handler.go | 65 ++++++++++++++++++++++++++++++ login.go | 109 ++++++++------------------------------------------ main.go | 10 ++--- register.go | 130 +++++++++++++++++++++++++++++++----------------------------- 5 files changed, 164 insertions(+), 176 deletions(-) create mode 100644 handler.go diff --git a/activate.go b/activate.go index ae392d1..56ef897 100644 --- a/activate.go +++ b/activate.go @@ -1,18 +1,14 @@ package main import ( + "github.com/gorilla/sessions" "kch42.de/gostuff/mailremind/model" "log" "net/http" ) -func activate(rw http.ResponseWriter, req *http.Request) { +func activate(user model.User, sess *sessions.Session, req *http.Request) interface{} { outdata := &msgTpldata{Title: "Activate Account", Class: "error"} - defer func() { - if err := tplMsg.Execute(rw, outdata); err != nil { - log.Printf("Could not execute template in activate: %s", err) - } - }() req.ParseForm() @@ -21,44 +17,44 @@ func activate(rw http.ResponseWriter, req *http.Request) { if (_userid == "") || (code == "") { outdata.Msg = "User or code invalid. Check, if the activation link was correctly copied from the mail." - return + return outdata } userid, err := db.ParseDBID(_userid) if err != nil { outdata.Msg = "User or code invalid. Check, if the activation link was correctly copied from the mail." - return + return outdata } - user, err := dbcon.UserByID(userid) - switch err { + switch user, err = dbcon.UserByID(userid); err { case nil: case model.NotFound: outdata.Msg = "User not found." - return + return outdata default: log.Printf("Error while getting user by ID <%s>: %s", userid, err) outdata.Msg = "An error occurred while loading user data. Send a message to the support, if this happens again." - return + return outdata } if user.ActivationCode() != code { outdata.Msg = "Wrong activation code." - return + return outdata } if err := user.SetActivationCode(""); err != nil { log.Printf("Error while resetting activation code: %s", err) outdata.Msg = "An error occurred while activating the user. Send a message to the support, if this happens again." - return + return outdata } if err := user.SetActive(true); err != nil { log.Printf("Error while resetting activation code: %s", err) outdata.Msg = "An error occurred while activating the user. Send a message to the support, if this happens again." - return + return outdata } outdata.Class = "success" outdata.Msg = "Account activated!" + return outdata } diff --git a/handler.go b/handler.go new file mode 100644 index 0000000..d710b2a --- /dev/null +++ b/handler.go @@ -0,0 +1,65 @@ +package main + +import ( + "github.com/gorilla/sessions" + "html/template" + "kch42.de/gostuff/mailremind/model" + "log" + "net/http" +) + +type Handler func(user model.User, sess *sessions.Session, req *http.Request) interface{} + +func getSess(req *http.Request) (*sessions.Session, error) { + sess, err := SessionStorage.Get(req, "mailremind-sess") + if err != nil { + sess, err = SessionStorage.New(req, "mailremind-sess") + } + + return sess, err +} + +func userFromSess(sess *sessions.Session) model.User { + _id, ok := sess.Values["uid"] + if !ok { + return nil + } + + id, ok := _id.(string) + if !ok { + return nil + } + + uid, err := db.ParseDBID(id) + if err != nil { + return nil + } + + user, err := dbcon.UserByID(uid) + if err != nil { + return nil + } + + return user +} + +func mkHttpHandler(h Handler, tpl *template.Template) http.HandlerFunc { + return func(rw http.ResponseWriter, req *http.Request) { + sess, err := getSess(req) + if err != nil { + log.Printf("Error while getting session: %s", err) + rw.Write([]byte("Unable to create session")) // TODO: Better error message... + } + + user := userFromSess(sess) + outdata := h(user, sess, req) + + if err := sess.Save(req, rw); err != nil { + log.Printf("Error while saving session: %s", err) + } + + if err := tpl.Execute(rw, outdata); err != nil { + log.Printf("Error executing template %s: %s", tpl.Name, err) + } + } +} diff --git a/login.go b/login.go index e5d039d..459d2ff 100644 --- a/login.go +++ b/login.go @@ -16,79 +16,27 @@ type loginFormdata struct { Mail, Password string } -func userFromSess(sess *sessions.Session) model.User { - _id, ok := sess.Values["uid"] - if !ok { - return nil - } - - id, ok := _id.(string) - if !ok { - return nil - } - - uid, err := db.ParseDBID(id) - if err != nil { - return nil - } - - user, err := dbcon.UserByID(uid) - if err != nil { - return nil - } - - return user -} - -func getSess(req *http.Request) (*sessions.Session, error) { - sess, err := SessionStorage.Get(req, "mailremind-sess") - if err != nil { - sess, err = SessionStorage.New(req, "mailremind-sess") - } - - return sess, err -} - -func login(rw http.ResponseWriter, req *http.Request) { +func login(user model.User, sess *sessions.Session, req *http.Request) interface{} { outdata := &loginTpldata{} - defer func() { - if err := tplLogin.Execute(rw, outdata); err != nil { - log.Printf("Error executing template in login: %s", err) - } - }() - sess, err := getSess(req) - if err != nil { - outdata.Error = "Could not create a session. " + err.Error() - return - } - defer func() { - if err := sess.Save(req, rw); err != nil { - log.Printf("Error while saving session: %s", err) - outdata.Success = "" - outdata.Error = "Error while saving session." - return - } - }() - - if user := userFromSess(sess); user != nil { + if user != nil { outdata.Success = "You are already logged in" - return + return outdata } if req.Method != "POST" { - return + return outdata } if err := req.ParseForm(); err != nil { outdata.Error = "Data of form could not be understand. If this happens again, please contact support!" - return + return outdata } indata := new(loginFormdata) if err := formdec.Decode(indata, req.Form); (err != nil) || (indata.Mail == "") || (indata.Password == "") { outdata.Error = "Input data wrong or missing. Please fill in all values." - return + return outdata } user, err := dbcon.UserByMail(indata.Mail) @@ -96,57 +44,32 @@ func login(rw http.ResponseWriter, req *http.Request) { case nil: case model.NotFound: outdata.Error = "E-Mail or password was wrong." - return + return outdata default: log.Printf("Error while loding user data (login): %s", err) outdata.Error = "User data could not be loaded. Please contact support, if this happens again." - return + return outdata } if bcrypt.CompareHashAndPassword(user.PWHash(), []byte(indata.Password)) != nil { outdata.Error = "E-Mail or password was wrong." - return + return outdata } sess.Values["uid"] = user.ID().String() outdata.Success = "Login successful" + return outdata } -func logincheck(rw http.ResponseWriter, req *http.Request) { - sess, _ := getSess(req) - user := userFromSess(sess) - outdata := new(msgTpldata) - if user == nil { - outdata.Msg = "" - } else { +func logincheck(user model.User, sess *sessions.Session, req *http.Request) interface{} { + outdata := &msgTpldata{Msg: ""} + if user != nil { outdata.Msg = user.Email() } - tplMsg.Execute(rw, outdata) + return outdata } -func logout(rw http.ResponseWriter, req *http.Request) { - outdata := &msgTpldata{Class: "error", Title: "Logout"} - defer func() { - if err := tplMsg.Execute(rw, outdata); err != nil { - log.Printf("Error executing template in login: %s", err) - } - }() - - sess, err := getSess(req) - if err != nil { - outdata.Msg = "Could not create a session." - return - } - defer func() { - if err := sess.Save(req, rw); err != nil { - log.Printf("Error while saving session: %s", err) - outdata.Class = "error" - outdata.Msg = "Error while saving session." - return - } - }() - +func logout(user model.User, sess *sessions.Session, req *http.Request) interface{} { delete(sess.Values, "uid") - outdata.Class = "success" - outdata.Msg = "Your are now logged out." + return &msgTpldata{Class: "success", Title: "Logout", Msg: "Your are now logged out."} } diff --git a/main.go b/main.go index 0289256..7698b1e 100644 --- a/main.go +++ b/main.go @@ -76,11 +76,11 @@ func main() { router := mux.NewRouter() router.PathPrefix("/static").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(staticpath)))) - router.HandleFunc("/register", register) - router.HandleFunc("/activate", activate) - router.HandleFunc("/login", login) - router.HandleFunc("/logincheck", logincheck) - router.HandleFunc("/logout", logout) + router.HandleFunc("/register", mkHttpHandler(register, tplRegister)) + router.HandleFunc("/activate", mkHttpHandler(activate, tplMsg)) + router.HandleFunc("/login", mkHttpHandler(login, tplLogin)) + router.HandleFunc("/logincheck", mkHttpHandler(logincheck, tplMsg)) + router.HandleFunc("/logout", mkHttpHandler(logout, tplMsg)) http.Handle("/", router) diff --git a/register.go b/register.go index 936f540..38f7b97 100644 --- a/register.go +++ b/register.go @@ -2,6 +2,7 @@ package main import ( "code.google.com/p/go.crypto/bcrypt" + "github.com/gorilla/sessions" "kch42.de/gostuff/mailremind/model" "log" "math/rand" @@ -33,69 +34,72 @@ func genAcCode() string { return string(code) } -func register(rw http.ResponseWriter, req *http.Request) { +func register(user model.User, sess *sessions.Session, req *http.Request) interface{} { outdata := ®isterData{Timezones: &timeLocs} - defer func() { - if err := tplRegister.Execute(rw, outdata); err != nil { - log.Printf("Exec tplRegister: %s", err) - } - }() - - if req.Method == "POST" { - if err := req.ParseForm(); err != nil { - outdata.Error = "Data of form could not be understand. If this happens again, please contact support!" - return - } - - indata := new(registerFormdata) - if err := formdec.Decode(indata, req.Form); (err != nil) || (indata.Mail == "") || (indata.Timezone.Loc == nil) { - outdata.Error = "Input data wrong or missing. Please fill in all values and make sure to provide a valid E-Mail address." - return - } - - if indata.Password == "" { - outdata.Error = "Empty passwords are not allowed." - return - } - - if indata.Password != indata.RetypePassword { - outdata.Error = "Passwords are not identical." - return - } - - mail := string(indata.Mail) - - switch _, err := dbcon.UserByMail(mail); err { - case nil: - outdata.Error = "This E-Mail address is already used." - return - case model.NotFound: - default: - log.Printf("Error while checking, if mail is used: %s", err) - outdata.Error = "Internal error, sorry. If this happens again, please contact support!" - return - } - - acCode := genAcCode() - pwhash, err := bcrypt.GenerateFromPassword([]byte(indata.Password), bcrypt.DefaultCost) - if err != nil { - log.Printf("Error while hashing password: %s", err) - outdata.Error = "Internal error, sorry. If this happens again, please contact support!" - return - } - - user, err := dbcon.AddUser(mail, pwhash, indata.Timezone.Loc, false, acCode) - if err != nil { - log.Printf("Could not create user (%s): %s", indata.Mail, err) - outdata.Error = "Internal error, sorry. If this happens again, please contact support!" - return - } - - if !SendActivationcode(mail, acCode, user.ID()) { - outdata.Error = "We could not send you a mail with your confirmation code." - return - } - - outdata.Success = "Account created successfully! We sent you an E-Mail that contains a link to activate your account." + + if user != nil { + outdata.Success = "You are already logged in. To register a new account, first log out." + return outdata + } + + if req.Method != "POST" { + return outdata + } + + if err := req.ParseForm(); err != nil { + outdata.Error = "Data of form could not be understand. If this happens again, please contact support!" + return outdata + } + + indata := new(registerFormdata) + if err := formdec.Decode(indata, req.Form); (err != nil) || (indata.Mail == "") || (indata.Timezone.Loc == nil) { + outdata.Error = "Input data wrong or missing. Please fill in all values and make sure to provide a valid E-Mail address." + return outdata + } + + if indata.Password == "" { + outdata.Error = "Empty passwords are not allowed." + return outdata + } + + if indata.Password != indata.RetypePassword { + outdata.Error = "Passwords are not identical." + return outdata + } + + mail := string(indata.Mail) + + switch _, err := dbcon.UserByMail(mail); err { + case nil: + outdata.Error = "This E-Mail address is already used." + return outdata + case model.NotFound: + default: + log.Printf("Error while checking, if mail is used: %s", err) + outdata.Error = "Internal error, sorry. If this happens again, please contact support!" + return outdata + } + + acCode := genAcCode() + pwhash, err := bcrypt.GenerateFromPassword([]byte(indata.Password), bcrypt.DefaultCost) + if err != nil { + log.Printf("Error while hashing password: %s", err) + outdata.Error = "Internal error, sorry. If this happens again, please contact support!" + return outdata } + + user, err = dbcon.AddUser(mail, pwhash, indata.Timezone.Loc, false, acCode) + if err != nil { + log.Printf("Could not create user (%s): %s", indata.Mail, err) + outdata.Error = "Internal error, sorry. If this happens again, please contact support!" + return outdata + } + + if !SendActivationcode(mail, acCode, user.ID()) { + outdata.Error = "We could not send you a mail with your confirmation code." + return outdata + } + + outdata.Success = "Account created successfully! We sent you an E-Mail that contains a link to activate your account." + return outdata } -- cgit v1.2.3-54-g00ecf