93 lines
2 KiB
Go
93 lines
2 KiB
Go
package auth
|
|
|
|
import (
|
|
"bytes"
|
|
"database/sql"
|
|
"math/rand/v2"
|
|
|
|
"golang.org/x/crypto/argon2"
|
|
)
|
|
|
|
type passwordInfo struct {
|
|
hash []byte
|
|
salt []byte
|
|
}
|
|
|
|
func queryGetOwnerSettingsPasswordInfo(db *sql.DB) (passwordInfo, error) {
|
|
out := passwordInfo{}
|
|
err := db.QueryRow(`select password_hash, password_salt from owner_settings`).Scan(&out.hash, &out.salt)
|
|
|
|
return out, err
|
|
}
|
|
|
|
func queryCreateSession(db *sql.DB, sessionId string) error {
|
|
_, err := db.Exec(`insert into session (session_id) values (?)`, sessionId)
|
|
|
|
return err
|
|
}
|
|
|
|
func HashPassword(password []byte, salt []byte) []byte {
|
|
passwordHash := argon2.IDKey(password, salt, 10, 7, 1, 64)
|
|
|
|
return passwordHash
|
|
}
|
|
|
|
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
|
const charsetLen = len(charset)
|
|
|
|
func randomString(n int) string {
|
|
b := make([]byte, n)
|
|
for i := range b {
|
|
ciIdx := rand.IntN(charsetLen)
|
|
|
|
b[i] = charset[ciIdx]
|
|
}
|
|
|
|
return string(b)
|
|
}
|
|
|
|
func Login(db *sql.DB, password string) (bool, string, error) {
|
|
info, err := queryGetOwnerSettingsPasswordInfo(db)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
incomingHash := HashPassword([]byte(password), info.salt)
|
|
if !bytes.Equal(incomingHash, info.hash) {
|
|
return false, "", nil
|
|
}
|
|
|
|
sessionId := randomString(256)
|
|
err = queryCreateSession(db, sessionId)
|
|
|
|
return true, sessionId, err
|
|
}
|
|
|
|
func queryDeleteSession(db *sql.DB, sessionId string) error {
|
|
_, err := db.Exec(`delete from session where session_id = ?`, sessionId)
|
|
return err
|
|
}
|
|
|
|
func SessionDelete(db *sql.DB, sessionId string) error {
|
|
return queryDeleteSession(db, sessionId)
|
|
}
|
|
|
|
type SessionInfo struct {
|
|
IsAdmin bool
|
|
SessionId string
|
|
}
|
|
|
|
func queryCheckAuth(db *sql.DB, sessionId string) (SessionInfo, error) {
|
|
sessionCount := 0
|
|
err := db.QueryRow("select count(*) from session where session_id = ?", sessionId).Scan(&sessionCount)
|
|
if err != nil {
|
|
return SessionInfo{}, err
|
|
}
|
|
|
|
return SessionInfo{IsAdmin: sessionCount == 1, SessionId: sessionId}, nil
|
|
}
|
|
|
|
func SessionCheck(db *sql.DB, sessionId string) (SessionInfo, error) {
|
|
return queryCheckAuth(db, sessionId)
|
|
}
|