Skip to content

Instantly share code, notes, and snippets.

@ewalk153
Last active August 29, 2015 14:00
Show Gist options
  • Select an option

  • Save ewalk153/664589120562be3d094a to your computer and use it in GitHub Desktop.

Select an option

Save ewalk153/664589120562be3d094a to your computer and use it in GitHub Desktop.
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