package api
import (
"errors"
"golang.org/x/crypto/bcrypt"
"log"
"github.com/gofiber/fiber/v2"
_ "github.com/mattn/go-sqlite3"
sq "github.com/Masterminds/squirrel"
"github.com/gofiber/fiber/v2/middleware/session"
"MY/webapp/data"
"MY/webapp/config"
. "MY/webapp/common"
)
func IsAdmin ( user * data . User ) bool {
return user . Username == config . Settings . Admin
}
func CheckAuthed ( c * fiber . Ctx , needs_admin bool ) ( * session . Session , error ) {
sess , err := STORE . Get ( c )
if err != nil { return sess , err }
// BUG: this has to come from the databse, just temporary
admin := sess . Get ( "admin" ) == true
authed := sess . Get ( "authenticated" ) == true
log . Printf ( "session admin=%v, session authed=%v, needs_admin = %v" , admin , authed , needs_admin )
if needs_admin {
authed = admin && authed
log . Printf ( "after needs_admin block: authed=%v" , authed )
}
if authed {
log . Println ( "user is authed, return nil and sess" )
return sess , nil
} else {
log . Println ( "user is NOT authed, return error" )
return sess , errors . New ( "Authentication, permission failure" )
}
}
func LogoutUser ( c * fiber . Ctx ) error {
sess , err := STORE . Get ( c )
if err != nil { return err }
sess . Set ( "authenticated" , false )
err = sess . Save ( )
return err
}
func LoginUser ( result * data . User , login * data . Login ) ( bool , error ) {
sql , args , err := sq . Select ( "username, password" ) .
From ( "user" ) . Where ( "username=?" , login . Username ) . ToSql ( )
if err != nil { return false , err }
err = data . DB . Get ( result , sql , args ... )
if err != nil { return false , err }
pass_good := bcrypt . CompareHashAndPassword ( [ ] byte ( result . Password ) , [ ] byte ( login . Password ) )
if pass_good != nil { return false , pass_good }
return login . Username == result . Username && pass_good == nil , nil
}
func SetUserPassword ( user * data . User ) error {
hashed , err := bcrypt . GenerateFromPassword ( [ ] byte ( user . Password ) , 12 )
if err != nil { return err }
user . Password = string ( hashed )
return nil
}
func GetApiLogout ( c * fiber . Ctx ) error {
err := LogoutUser ( c )
if err != nil { return IfErrNil ( err , c ) }
return c . Redirect ( "/" )
}
func PostApiRegister ( c * fiber . Ctx ) error {
user , err := ReceivePost [ data . User ] ( c )
if err != nil { return IfErrNil ( err , c ) }
err = SetUserPassword ( user )
if err != nil { return IfErrNil ( err , c ) }
sql , args , err := sq . Insert ( "user" ) .
Columns ( "username" , "email" , "password" ) .
Values ( user . Username , user . Email , user . Password ) . ToSql ( )
err = data . Exec ( err , sql , args ... )
if err != nil { return IfErrNil ( err , c ) }
return c . Redirect ( "/login/" )
}
func PostApiLogin ( c * fiber . Ctx ) error {
var user data . User
login , err := ReceivePost [ data . Login ] ( c )
if ( err != nil ) { return IfErrNil ( err , c ) }
pass_good , err := LoginUser ( & user , login )
if err != nil { return IfErrNil ( err , c ) }
if pass_good {
sess , err := STORE . Get ( c )
if err != nil { return IfErrNil ( err , c ) }
sess . Set ( "authenticated" , true )
sess . Set ( "user_id" , user . Id )
sess . Set ( "admin" , IsAdmin ( & user ) )
err = sess . Save ( )
if err != nil { return IfErrNil ( err , c ) }
return c . Redirect ( "/" )
} else {
return c . Redirect ( "/login/" )
}
}