mirror of
https://github.com/aclindsa/moneygo.git
synced 2024-10-30 07:40:05 -04:00
Aaron Lindsay
156b9aaf0c
This is part of an ongoing attempt to restructure the code to make it more 'testable'.
140 lines
2.7 KiB
Go
140 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type Session struct {
|
|
SessionId int64
|
|
SessionSecret string `json:"-"`
|
|
UserId int64
|
|
}
|
|
|
|
func (s *Session) Write(w http.ResponseWriter) error {
|
|
enc := json.NewEncoder(w)
|
|
return enc.Encode(s)
|
|
}
|
|
|
|
func GetSession(db *DB, r *http.Request) (*Session, error) {
|
|
var s Session
|
|
|
|
cookie, err := r.Cookie("moneygo-session")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("moneygo-session cookie not set")
|
|
}
|
|
s.SessionSecret = cookie.Value
|
|
|
|
err = db.SelectOne(&s, "SELECT * from sessions where SessionSecret=?", s.SessionSecret)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &s, nil
|
|
}
|
|
|
|
func DeleteSessionIfExists(db *DB, r *http.Request) {
|
|
// TODO do this in one transaction
|
|
session, err := GetSession(db, r)
|
|
if err == nil {
|
|
db.Delete(session)
|
|
}
|
|
}
|
|
|
|
func NewSessionCookie() (string, error) {
|
|
bits := make([]byte, 128)
|
|
if _, err := io.ReadFull(rand.Reader, bits); err != nil {
|
|
return "", err
|
|
}
|
|
return base64.StdEncoding.EncodeToString(bits), nil
|
|
}
|
|
|
|
func NewSession(db *DB, w http.ResponseWriter, r *http.Request, userid int64) (*Session, error) {
|
|
s := Session{}
|
|
|
|
session_secret, err := NewSessionCookie()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cookie := http.Cookie{
|
|
Name: "moneygo-session",
|
|
Value: session_secret,
|
|
Path: "/",
|
|
Domain: r.URL.Host,
|
|
Expires: time.Now().AddDate(0, 1, 0), // a month from now
|
|
Secure: true,
|
|
HttpOnly: true,
|
|
}
|
|
http.SetCookie(w, &cookie)
|
|
|
|
s.SessionSecret = session_secret
|
|
s.UserId = userid
|
|
|
|
err = db.Insert(&s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &s, nil
|
|
}
|
|
|
|
func SessionHandler(w http.ResponseWriter, r *http.Request, db *DB) {
|
|
if r.Method == "POST" || r.Method == "PUT" {
|
|
user_json := r.PostFormValue("user")
|
|
if user_json == "" {
|
|
WriteError(w, 3 /*Invalid Request*/)
|
|
return
|
|
}
|
|
|
|
user := User{}
|
|
err := user.Read(user_json)
|
|
if err != nil {
|
|
WriteError(w, 3 /*Invalid Request*/)
|
|
return
|
|
}
|
|
|
|
dbuser, err := GetUserByUsername(db, user.Username)
|
|
if err != nil {
|
|
WriteError(w, 2 /*Unauthorized Access*/)
|
|
return
|
|
}
|
|
|
|
user.HashPassword()
|
|
if user.PasswordHash != dbuser.PasswordHash {
|
|
WriteError(w, 2 /*Unauthorized Access*/)
|
|
return
|
|
}
|
|
|
|
DeleteSessionIfExists(db, r)
|
|
|
|
session, err := NewSession(db, w, r, dbuser.UserId)
|
|
if err != nil {
|
|
WriteError(w, 999 /*Internal Error*/)
|
|
return
|
|
}
|
|
|
|
err = session.Write(w)
|
|
if err != nil {
|
|
WriteError(w, 999 /*Internal Error*/)
|
|
log.Print(err)
|
|
return
|
|
}
|
|
} else if r.Method == "GET" {
|
|
s, err := GetSession(db, r)
|
|
if err != nil {
|
|
WriteError(w, 1 /*Not Signed In*/)
|
|
return
|
|
}
|
|
|
|
s.Write(w)
|
|
} else if r.Method == "DELETE" {
|
|
DeleteSessionIfExists(db, r)
|
|
WriteSuccess(w)
|
|
}
|
|
}
|