Adjust variable naming

This commit is contained in:
Andrew-71 2024-10-13 17:18:53 +03:00
parent c3334faa9e
commit 78056d8b48
10 changed files with 45 additions and 41 deletions

View file

@ -25,15 +25,15 @@ func Register(w http.ResponseWriter, r *http.Request) {
if ok { if ok {
email = strings.TrimSpace(email) email = strings.TrimSpace(email)
password = strings.TrimSpace(password) password = strings.TrimSpace(password)
if !(validEmail(email) && validPass(password) && !storage.Data.EmailExists(email)) { if !(validEmail(email) && validPass(password) && !storage.Data.Taken(email)) {
slog.Debug("Outcome", slog.Debug("outcome",
"email", validEmail(email), "email", validEmail(email),
"pass", validPass(password), "pass", validPass(password),
"taken", !storage.Data.EmailExists(email)) "taken", !storage.Data.Taken(email))
http.Error(w, "invalid auth credentials", http.StatusBadRequest) http.Error(w, "invalid auth credentials", http.StatusBadRequest)
return return
} }
err := storage.Data.AddUser(email, password) err := storage.Data.Add(email, password)
if err != nil { if err != nil {
slog.Error("error adding a new user", "error", err) slog.Error("error adding a new user", "error", err)
http.Error(w, "error adding a new user", http.StatusInternalServerError) http.Error(w, "error adding a new user", http.StatusInternalServerError)
@ -57,18 +57,18 @@ func Login(w http.ResponseWriter, r *http.Request) {
email = strings.TrimSpace(email) email = strings.TrimSpace(email)
password = strings.TrimSpace(password) password = strings.TrimSpace(password)
user, ok := storage.Data.ByEmail(email) user, ok := storage.Data.ByEmail(email)
if !ok || !user.PasswordFits(password) { if !ok || !user.Fits(password) {
w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`) w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
http.Error(w, "you did something wrong", http.StatusUnauthorized) http.Error(w, "you did something wrong", http.StatusUnauthorized)
return return
} }
s, err := CreateJWT(user) token, err := Create(user)
if err != nil { if err != nil {
http.Error(w, "error creating jwt", http.StatusInternalServerError) http.Error(w, "error creating jwt", http.StatusInternalServerError)
return return
} }
w.Write([]byte(s)) w.Write([]byte(token))
return return
} }

View file

@ -18,7 +18,7 @@ import (
var key *rsa.PrivateKey var key *rsa.PrivateKey
// LoadKey attempts to load a private key from KeyFile. // LoadKey attempts to load a private RS256 key from file.
// If the file does not exist, it generates a new key (and saves it) // If the file does not exist, it generates a new key (and saves it)
func MustLoadKey() { func MustLoadKey() {
// If the key doesn't exist, create it // If the key doesn't exist, create it
@ -58,14 +58,15 @@ func MustLoadKey() {
} }
} }
// PublicKey returns our public key as PEM block over http // ServePublicKey returns our public key as PEM block over HTTP
func PublicKey(w http.ResponseWriter, r *http.Request) { func ServePublicKey(w http.ResponseWriter, r *http.Request) {
key_marshalled := x509.MarshalPKCS1PublicKey(&key.PublicKey) key_marshalled := x509.MarshalPKCS1PublicKey(&key.PublicKey)
block := pem.Block{Bytes: key_marshalled, Type: "RSA PUBLIC KEY"} block := pem.Block{Bytes: key_marshalled, Type: "RSA PUBLIC KEY"}
pem.Encode(w, &block) pem.Encode(w, &block)
} }
func CreateJWT(user storage.User) (string, error) { // Create creates a JSON Web Token that expires after a week
func Create(user storage.User) (token string, err error) {
t := jwt.NewWithClaims(jwt.SigningMethodRS256, t := jwt.NewWithClaims(jwt.SigningMethodRS256,
jwt.MapClaims{ jwt.MapClaims{
"iss": "pye", "iss": "pye",
@ -74,17 +75,17 @@ func CreateJWT(user storage.User) (string, error) {
"iat": time.Now().Unix(), "iat": time.Now().Unix(),
"exp": time.Now().Add(time.Hour * 24 * 7).Unix(), "exp": time.Now().Add(time.Hour * 24 * 7).Unix(),
}) })
s, err := t.SignedString(key) token, err = t.SignedString(key)
if err != nil { if err != nil {
slog.Error("error creating JWT", "error", err) slog.Error("error creating JWT", "error", err)
return "", err return "", err
} }
return s, nil return
} }
// VerifyToken receives a JWT and PEM-encoded public key, // Verify receives a JWT and PEM-encoded public key,
// then returns whether the token is valid // then returns whether the token is valid
func VerifyJWT(token string, publicKey []byte) (*jwt.Token, error) { func Verify(token string, publicKey []byte) (*jwt.Token, error) {
t, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { t, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
key, err := jwt.ParseRSAPublicKeyFromPEM(publicKey) key, err := jwt.ParseRSAPublicKeyFromPEM(publicKey)
if err != nil { if err != nil {
@ -98,8 +99,9 @@ func VerifyJWT(token string, publicKey []byte) (*jwt.Token, error) {
return t, err return t, err
} }
func VerifyLocalJWT(token string) (*jwt.Token, error) { // VerifyLocal calls Verify with public key set to current local one
func VerifyLocal(token string) (*jwt.Token, error) {
key_marshalled := x509.MarshalPKCS1PublicKey(&key.PublicKey) key_marshalled := x509.MarshalPKCS1PublicKey(&key.PublicKey)
block := pem.Block{Bytes: key_marshalled, Type: "RSA PUBLIC KEY"} block := pem.Block{Bytes: key_marshalled, Type: "RSA PUBLIC KEY"}
return VerifyJWT(token, pem.EncodeToMemory(&block)) return Verify(token, pem.EncodeToMemory(&block))
} }

View file

@ -25,14 +25,14 @@ var (
) )
func initConfig() { func initConfig() {
logging.LogInit(*debugMode) logging.Load(*debugMode)
config.MustLoadConfig(cfgFile) config.MustLoad(cfgFile)
if cfgDb != "" { if cfgDb != "" {
config.Cfg.SQLiteFile = cfgDb config.Cfg.SQLiteFile = cfgDb
} }
auth.MustLoadKey() auth.MustLoadKey()
storage.Data = sqlite.MustLoadSQLite(config.Cfg.SQLiteFile) storage.Data = sqlite.MustLoad(config.Cfg.SQLiteFile)
} }
func init() { func init() {

View file

@ -35,7 +35,7 @@ func serveAuth(cmd *cobra.Command, args []string) {
r.Use(middleware.RealIP) r.Use(middleware.RealIP)
r.Use(middleware.Logger, middleware.CleanPath, middleware.StripSlashes) r.Use(middleware.Logger, middleware.CleanPath, middleware.StripSlashes)
r.Get("/pem", auth.PublicKey) r.Get("/pem", auth.ServePublicKey)
r.Post("/register", auth.Register) r.Post("/register", auth.Register)
r.Post("/login", auth.Login) r.Post("/login", auth.Login)

View file

@ -41,14 +41,14 @@ func verifyFunc(cmd *cobra.Command, args []string) {
var err error var err error
if verifyFile == "" { if verifyFile == "" {
fmt.Println("No PEM file supplied, assuming local") fmt.Println("No PEM file supplied, assuming local")
t, err = auth.VerifyLocalJWT(verifyToken) t, err = auth.VerifyLocal(verifyToken)
} else { } else {
key, err_k := os.ReadFile(verifyFile) key, err_k := os.ReadFile(verifyFile)
if err_k != nil { if err_k != nil {
slog.Error("error reading file", "error", err, "file", verifyFile) slog.Error("error reading file", "error", err, "file", verifyFile)
return return
} }
t, err = auth.VerifyJWT(verifyToken, key) t, err = auth.Verify(verifyToken, key)
} }
slog.Debug("result", "token", t, "error", err, "ok", err == nil) slog.Debug("result", "token", t, "error", err, "ok", err == nil)
if err == nil { if err == nil {

View file

@ -27,7 +27,7 @@ var (
Cfg Config Cfg Config
) )
func LoadConfig(filename string) error { func Load(filename string) error {
data, err := os.ReadFile(filename) data, err := os.ReadFile(filename)
if err != nil { if err != nil {
return err return err
@ -42,8 +42,8 @@ func LoadConfig(filename string) error {
return nil return nil
} }
func MustLoadConfig(filename string) { func MustLoad(filename string) {
err := LoadConfig(filename) err := Load(filename)
if err != nil { if err != nil {
slog.Error("error initially loading config", "error", err) slog.Error("error initially loading config", "error", err)
os.Exit(1) os.Exit(1)

View file

@ -10,8 +10,8 @@ import (
"github.com/go-chi/chi/middleware" "github.com/go-chi/chi/middleware"
) )
// LogInit makes slog output to both os.Stdout and a file if needed, and sets slog.LevelDebug if enabled. // Load makes slog output to both os.Stdout and a file if needed, and sets slog.LevelDebug if enabled.
func LogInit(debugMode bool) { func Load(debugMode bool) {
var w io.Writer var w io.Writer
if config.Cfg.LogToFile { if config.Cfg.LogToFile {
f, err := os.OpenFile(config.Cfg.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) f, err := os.OpenFile(config.Cfg.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

View file

@ -23,8 +23,8 @@ type SQLiteStorage struct {
db *sql.DB db *sql.DB
} }
func (s SQLiteStorage) AddUser(email, password string) error { func (s SQLiteStorage) Add(email, password string) error {
user, err := storage.NewUser(email, password) user, err := storage.New(email, password)
if err != nil { if err != nil {
return err return err
} }
@ -53,12 +53,12 @@ func (s SQLiteStorage) ByEmail(email string) (storage.User, bool) {
return user, err == nil return user, err == nil
} }
func (s SQLiteStorage) EmailExists(email string) bool { func (s SQLiteStorage) Taken(email string) bool {
_, ok := s.ByEmail(email) _, ok := s.ByEmail(email)
return ok return ok
} }
func MustLoadSQLite(dataFile string) SQLiteStorage { func MustLoad(dataFile string) SQLiteStorage {
if _, err := os.Stat(dataFile); errors.Is(err, os.ErrNotExist) { if _, err := os.Stat(dataFile); errors.Is(err, os.ErrNotExist) {
os.Create(dataFile) os.Create(dataFile)
slog.Debug("created sqlite3 database file", "file", dataFile) slog.Debug("created sqlite3 database file", "file", dataFile)

View file

@ -1,13 +1,13 @@
package storage package storage
// Storage is an arbitrary storage interface // Storage is an interface for arbitrary storage
type Storage interface { type Storage interface {
AddUser(email, password string) error Add(email, password string) error // Add inserts a user into data
ById(uuid string) (User, bool) ById(uuid string) (User, bool) // ById retrieves a user by their UUID
ByEmail(uuid string) (User, bool) ByEmail(email string) (User, bool) // ByEmail retrieves a user by their email
EmailExists(email string) bool Taken(email string) bool // Taken checks whether an email is taken
} }
// Data stores active information for the app // Data stores active information for the app.
// It should be populated at app startup // It should be populated on startup
var Data Storage var Data Storage

View file

@ -13,12 +13,14 @@ type User struct {
Hash []byte // bcrypt hash of password Hash []byte // bcrypt hash of password
} }
func (u User) PasswordFits(password string) bool { // Fits checks whether the password is correct
func (u User) Fits(password string) bool {
err := bcrypt.CompareHashAndPassword(u.Hash, []byte(password)) err := bcrypt.CompareHashAndPassword(u.Hash, []byte(password))
return err == nil return err == nil
} }
func NewUser(email, password string) (User, error) { // New Creates a new User
func New(email, password string) (User, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 14) hash, err := bcrypt.GenerateFromPassword([]byte(password), 14)
if err != nil { if err != nil {
slog.Error("error creating a new user", "error", err) slog.Error("error creating a new user", "error", err)