118 lines
3.2 KiB
Go
118 lines
3.2 KiB
Go
|
/* Work in progress */
|
||
|
package main
|
||
|
|
||
|
import "log"
|
||
|
import "errors"
|
||
|
import "strconv"
|
||
|
import "net/http"
|
||
|
import "database/sql"
|
||
|
|
||
|
import "./query_gen/lib"
|
||
|
import "golang.org/x/crypto/bcrypt"
|
||
|
|
||
|
var auth Auth
|
||
|
var ErrMismatchedHashAndPassword = bcrypt.ErrMismatchedHashAndPassword
|
||
|
|
||
|
type Auth interface
|
||
|
{
|
||
|
Authenticate(username string, password string) (int,error)
|
||
|
Logout(w http.ResponseWriter, uid int)
|
||
|
ForceLogout(uid int) error
|
||
|
SetCookies(w http.ResponseWriter, uid int, session string)
|
||
|
CreateSession(uid int) (string, error)
|
||
|
}
|
||
|
|
||
|
type DefaultAuth struct
|
||
|
{
|
||
|
login *sql.Stmt
|
||
|
logout *sql.Stmt
|
||
|
}
|
||
|
|
||
|
func NewDefaultAuth() *DefaultAuth {
|
||
|
login_stmt, err := qgen.Builder.SimpleSelect("users","uid, name, password, salt","name = ?","","")
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
logout_stmt, err := qgen.Builder.SimpleUpdate("users","session = ''","uid = ?")
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
return &DefaultAuth{
|
||
|
login: login_stmt,
|
||
|
logout: logout_stmt,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (auth *DefaultAuth) Authenticate(username string, password string) (uid int, err error) {
|
||
|
var real_password, salt string
|
||
|
err = auth.login.QueryRow(username).Scan(&uid, &username, &real_password, &salt)
|
||
|
if err == sql.ErrNoRows {
|
||
|
return 0, errors.New("We couldn't find an account with that username.")
|
||
|
} else if err != nil {
|
||
|
LogError(err)
|
||
|
return 0, errors.New("There was a glitch in the system. Please contact the system administrator.")
|
||
|
}
|
||
|
|
||
|
if salt == "" {
|
||
|
// Send an email to admin for this?
|
||
|
LogError(errors.New("Missing salt for user #" + strconv.Itoa(uid) + ". Potential security breach."))
|
||
|
return 0, errors.New("There was a glitch in the system. Please contact the system administrator.")
|
||
|
}
|
||
|
|
||
|
err = CheckPassword(real_password,password,salt)
|
||
|
if err == ErrMismatchedHashAndPassword {
|
||
|
return 0, errors.New("That's not the correct password.")
|
||
|
} else if err != nil {
|
||
|
LogError(err)
|
||
|
return 0, errors.New("There was a glitch in the system. Please contact the system administrator.")
|
||
|
}
|
||
|
|
||
|
return uid, nil
|
||
|
}
|
||
|
|
||
|
func (auth *DefaultAuth) ForceLogout(uid int) error {
|
||
|
_, err := auth.logout.Exec(uid)
|
||
|
if err != nil {
|
||
|
LogError(err)
|
||
|
return errors.New("There was a glitch in the system. Please contact the system administrator.")
|
||
|
}
|
||
|
|
||
|
// Flush the user out of the cache and reload
|
||
|
err = users.Load(uid)
|
||
|
if err != nil {
|
||
|
return errors.New("Your account no longer exists!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (auth *DefaultAuth) Logout(w http.ResponseWriter, _ int) {
|
||
|
cookie := http.Cookie{Name:"uid",Value:"",Path:"/",MaxAge: year}
|
||
|
http.SetCookie(w,&cookie)
|
||
|
cookie = http.Cookie{Name:"session",Value:"",Path:"/",MaxAge: year}
|
||
|
http.SetCookie(w,&cookie)
|
||
|
}
|
||
|
|
||
|
func (auth *DefaultAuth) SetCookies(w http.ResponseWriter, uid int, session string) {
|
||
|
cookie := http.Cookie{Name: "uid",Value: strconv.Itoa(uid),Path: "/",MaxAge: year}
|
||
|
http.SetCookie(w,&cookie)
|
||
|
cookie = http.Cookie{Name: "session",Value: session,Path: "/",MaxAge: year}
|
||
|
http.SetCookie(w,&cookie)
|
||
|
}
|
||
|
|
||
|
func(auth *DefaultAuth) CreateSession(uid int) (string, error) {
|
||
|
session, err := GenerateSafeString(sessionLength)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
_, err = update_session_stmt.Exec(session, uid)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
// Reload the user data
|
||
|
_ = users.Load(uid)
|
||
|
return session, nil
|
||
|
}
|