Permalink
Browse files

add users to the handlers

  • Loading branch information...
zeebo committed Sep 5, 2012
1 parent 85b30a6 commit 7c2ff89f944d78cb51033c3ac5eeedd4ab552126
Showing with 76 additions and 15 deletions.
  1. +14 −2 context.go
  2. +39 −7 handlers.go
  3. +3 −0 http.go
  4. +8 −0 main.go
  5. +6 −5 templates/index.html
  6. +5 −0 templates/login.html
  7. +1 −1 user.go
@@ -3,12 +3,14 @@ package main
import (
"code.google.com/p/gorilla/sessions"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"net/http"
)
type Context struct {
Database *mgo.Database
Session *sessions.Session
User *User
}
func (c *Context) Close() {
@@ -22,8 +24,18 @@ func (c *Context) C(name string) *mgo.Collection {
func NewContext(req *http.Request) (*Context, error) {
sess, err := store.Get(req, "gostbook")
return &Context{
ctx := &Context{
Database: session.Clone().DB(database),
Session: sess,
}, err
}
if err != nil {
return ctx, err
}
//try to fill in the user from the session
if uid, ok := sess.Values["user"].(bson.ObjectId); ok {
err = ctx.C("users").Find(bson.M{"_id": uid}).One(&ctx.User)
}
return ctx, err
}
@@ -1,6 +1,9 @@
package main
import "net/http"
import (
"errors"
"net/http"
)
func hello(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
//set up the collection and query
@@ -15,17 +18,23 @@ func hello(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
}
//execute the template
return T("index.html").Execute(w, entries)
return T("index.html").Execute(w, map[string]interface{}{
"entries": entries,
"ctx": ctx,
})
}
func sign(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
//we need a user to sign to
if ctx.User == nil {
err = errors.New("Can't sign without being logged in")
return
}
entry := NewEntry()
entry.Name = req.FormValue("name")
entry.Name = ctx.User.Username
entry.Message = req.FormValue("message")
if entry.Name == "" {
entry.Name = "Some dummy who forgot a name"
}
if entry.Message == "" {
entry.Message = "Some dummy who forgot a message."
}
@@ -40,5 +49,28 @@ func sign(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
}
func loginForm(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
return T("login.html").Execute(w, nil)
return T("login.html").Execute(w, map[string]interface{}{
"ctx": ctx,
})
}
func login(w http.ResponseWriter, req *http.Request, ctx *Context) error {
username, password := req.FormValue("username"), req.FormValue("password")
user, e := Login(ctx, username, password)
if e != nil {
ctx.Session.AddFlash("Invalid Username/Password")
return loginForm(w, req, ctx)
}
//store the user id in the values and redirect to index
ctx.Session.Values["user"] = user.ID
http.Redirect(w, req, reverse("index"), http.StatusSeeOther)
return nil
}
func logout(w http.ResponseWriter, req *http.Request, ctx *Context) error {
delete(ctx.Session.Values, "user")
http.Redirect(w, req, reverse("index"), http.StatusSeeOther)
return nil
}
@@ -12,6 +12,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx, err := NewContext(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return

This comment has been minimized.

@zeebo

zeebo Sep 5, 2012

Owner

Whoops! If there's an error, we should just print it and exit instead of continuing with the handler.

}
defer ctx.Close()
@@ -20,11 +21,13 @@ func (h handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
err = h(buf, req, ctx)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return

This comment has been minimized.

@zeebo

zeebo Sep 5, 2012

Owner

Same as above.

}
//save the session
if err = ctx.Session.Save(req, buf); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return

This comment has been minimized.

@zeebo

zeebo Sep 5, 2012

Owner

Same as above.

}
//apply the buffered response to the writer
@@ -3,8 +3,10 @@ package main
import (
"code.google.com/p/gorilla/pat"
"code.google.com/p/gorilla/sessions"
"encoding/gob"
"fmt"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"net/http"
"os"
)
@@ -23,6 +25,10 @@ func reverse(name string, things ...interface{}) string {
return u.Path
}
func init() {
gob.Register(bson.ObjectId(""))
}
var store sessions.Store
var session *mgo.Session
var database string
@@ -40,6 +46,8 @@ func main() {
router = pat.New()
router.Add("GET", "/login", handler(loginForm)).Name("login")
router.Add("GET", "/logout", handler(logout)).Name("logout")
router.Add("POST", "/login", handler(login))
router.Add("GET", "/", handler(hello)).Name("index")
router.Add("POST", "/sign", handler(sign)).Name("sign")
@@ -6,7 +6,7 @@ <h1>Guestbook</h1>
<p>Hello, and welcome to my guestbook, because it's 1997!</p>
<ul class="guests">
{{ range . }}
{{ range .entries }}
<li>
<blockquote>{{ .Message }}</blockquote>
<p>- <cite>{{ .Name }}</cite>, <time>{{ .Timestamp }}</time></p>
@@ -15,12 +15,13 @@ <h1>Guestbook</h1>
</ul>
<hr>
<a href="{{ reverse "login" }}">login</a>
<hr>
{{ if .ctx.User }}
<form action="{{ reverse "sign" }}" method="POST">
<p>Name: <input type="text" name="name"></p>
<p>Name: {{ .ctx.User.Username }} (<a href="{{ reverse "logout" }}">Logout</a>)</p>
<p>Message: <textarea name="message" rows="10" cols="40"></textarea></p>
<p><button>Sign</button></p>
</form>
{{ else }}
<h1>Please <a href="{{ reverse "login" }}">login</a> to sign.</h1>
{{ end }}
{{ end }}
@@ -2,6 +2,11 @@
{{ define "content" }}
<h1>Login</h1>
{{ range .ctx.Session.Flashes }}
<h2>{{ . }}</h2>
{{ end }}
<form action="{{ reverse "login" }}" method="POST">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="password" name="password"></p>
@@ -24,7 +24,7 @@ func (u *User) SetPassword(password string) {
//Login validates and returns a user object if they exist in the database.
func Login(ctx *Context, username, password string) (u *User, err error) {
err = ctx.C("users").Find(bson.M{"username": username}).One(u)
err = ctx.C("users").Find(bson.M{"username": username}).One(&u)

This comment has been minimized.

@zeebo

zeebo Sep 5, 2012

Owner

Oops! I forgot to pass in the address of the user and it would cause an error. This actually is what caused me to find the return cases above. One thing I'm missing in this is tests that would fix issues like this before they got into commits! :)

if err != nil {
return
}

0 comments on commit 7c2ff89

Please sign in to comment.