Last active
August 29, 2015 14:00
-
-
Save ewalk153/664589120562be3d094a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "github.com/gorilla/sessions" | |
| "html/template" | |
| "net/http" | |
| "strconv" | |
| ) | |
| const ( | |
| authCookie = "foo_loggedin" | |
| encryptSecret = "supersecret-change-me-please" | |
| ) | |
| const bodyTmpt = `<html> | |
| <body> | |
| <div> | |
| <a href="/">Home</a> | |
| <a href="/trips">Trips</a> | |
| {{if not .Page.LoggedIn}} | |
| <a href="/login">Login</a> | |
| {{else}} | |
| <a href="/logout">Logout</a> | |
| {{end}} | |
| </div> | |
| {{.Body}} | |
| </body> | |
| </html> | |
| ` | |
| var ( | |
| store = sessions.NewCookieStore([]byte(encryptSecret)) | |
| ) | |
| type content struct { | |
| Body template.HTML | |
| Page interface{} | |
| } | |
| // Page holds core page information | |
| type Page struct { | |
| UserID int64 | |
| Data interface{} | |
| } | |
| // NewPage returns a preset page | |
| func NewPage(r *http.Request) *Page { | |
| p := &Page{} | |
| p.Authenticate(r) | |
| return p | |
| } | |
| // StoreID stores the user's id | |
| func StoreID(w http.ResponseWriter, r *http.Request, id string) { | |
| session, _ := store.Get(r, authCookie) | |
| session.Values["UserID"] = id | |
| session.Save(r, w) | |
| } | |
| // Authenticate checks if a cookie is a valid login | |
| func (p *Page) Authenticate(r *http.Request) bool { | |
| session, _ := store.Get(r, authCookie) | |
| id, ok := session.Values["UserID"] | |
| if !ok { | |
| return false | |
| } | |
| var err error | |
| p.UserID, err = strconv.ParseInt(id.(string), 10, 0) | |
| if err != nil { | |
| return false | |
| } | |
| return true | |
| } | |
| // LoggedIn returns if a users is logged in | |
| func (p *Page) LoggedIn() bool { | |
| return p.UserID > 0 | |
| } | |
| func parseTemplate(body string, data interface{}) (out []byte, e error) { | |
| var buf bytes.Buffer | |
| t, err := template.New("page").Parse(body) | |
| if err != nil { | |
| return nil, err | |
| } | |
| err = t.Execute(&buf, data) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return buf.Bytes(), nil | |
| } | |
| func getPage(pageBody string, data interface{}) string { | |
| page, err := parseTemplate(pageBody, data) | |
| if err != nil { | |
| return err.Error() | |
| } | |
| base, err := parseTemplate(bodyTmpt, content{Body: template.HTML(page), Page: data}) | |
| if err != nil { | |
| return err.Error() | |
| } | |
| return string(base) | |
| } | |
| type engine struct{} | |
| // User sample struct | |
| type User struct { | |
| Email string | |
| } | |
| // ProtectPage redirects to login, if user not authed | |
| func (e *engine) ProtectPage(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { | |
| return http.HandlerFunc( | |
| func(w http.ResponseWriter, r *http.Request) { | |
| p := NewPage(r) | |
| if !p.LoggedIn() { | |
| http.Redirect(w, r, "/login?not_auth", http.StatusSeeOther) | |
| return | |
| } | |
| handler(w, r) | |
| }) | |
| } | |
| //Authenticate is a dummy authenication | |
| func (e *engine) Authenticate(email, password string) *User { | |
| if email == "bob" && password == "pass" { | |
| return &User{Email: email} | |
| } | |
| return nil | |
| } | |
| // Index page | |
| func (e *engine) Index(w http.ResponseWriter, r *http.Request) { | |
| p := NewPage(r) | |
| fmt.Fprint(w, getPage("<h1>welcome home</h1>", p)) | |
| } | |
| // Trips page | |
| func (e *engine) Trips(w http.ResponseWriter, r *http.Request) { | |
| p := NewPage(r) | |
| p.Data = struct{ Trips []int }{[]int{1, 2, 3}} | |
| fmt.Fprint(w, getPage("<h1>All Trips</h1> showing all trips {{range .Data.Trips}}Trip id: {{.}}<br>{{end}}", p)) | |
| } | |
| // Login page | |
| func (e *engine) Login(w http.ResponseWriter, r *http.Request) { | |
| p := NewPage(r) | |
| if p.LoggedIn() { | |
| http.Redirect(w, r, "/?dude_already_logged_in", http.StatusSeeOther) | |
| } | |
| fmt.Fprint(w, getPage(` | |
| <h1>Login Now</h1> | |
| <form action="/auth" method="post"> | |
| <input name="email" value="bob" /> | |
| <input name="pass" value="pass" type="password" /> | |
| <input type="submit" value="Login"> | |
| </form> | |
| `, p)) | |
| } | |
| // Auth action | |
| func (e *engine) Auth(w http.ResponseWriter, r *http.Request) { | |
| if e.Authenticate(r.FormValue("email"), r.FormValue("pass")) != nil { | |
| StoreID(w, r, "1") | |
| http.Redirect(w, r, "/?logged_in", http.StatusSeeOther) | |
| return | |
| } | |
| e.Login(w, r) | |
| } | |
| // Logout action | |
| func (e *engine) Logout(w http.ResponseWriter, r *http.Request) { | |
| http.SetCookie(w, &http.Cookie{ | |
| Name: authCookie, | |
| Value: "logginoff", | |
| MaxAge: -1, | |
| }) | |
| http.Redirect(w, r, "/?logged_out", http.StatusSeeOther) | |
| } | |
| func main() { | |
| e := engine{} | |
| http.HandleFunc("/", e.Index) | |
| http.HandleFunc("/trips", e.ProtectPage(e.Trips)) | |
| http.HandleFunc("/login", e.Login) | |
| http.HandleFunc("/auth", e.Auth) | |
| http.HandleFunc("/logout", e.Logout) | |
| http.ListenAndServe(":5050", nil) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment