Starting point for authorization/authentication level stuff, and their storage containers
Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
This commit is contained in:
parent
b266aa1c34
commit
559aa17da4
51
backend/internal/storage/auth/redis-csrf.go
Normal file
51
backend/internal/storage/auth/redis-csrf.go
Normal file
@ -0,0 +1,51 @@
|
||||
package auth_storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.ewellenr.ca/receipt_indexer/backend/internal/lcrypto"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// game plan. store the session token/id and a salt. then, hash them to create the csrf token. give this csrf token out to the user. when the user ends a session, it ends the session but also deletes it from the csrf store
|
||||
|
||||
// const csrfSaltLength = 32
|
||||
// const csrfTokenLength = 128
|
||||
|
||||
// should be set by the hasher
|
||||
|
||||
type redisCSRF struct {
|
||||
rdb *redis.Client
|
||||
hasher lcrypto.Hasher
|
||||
}
|
||||
|
||||
func (r *redisCSRF) AddCSRF(ctx context.Context, sessionToken string) (csrftoken string, err error) {
|
||||
csrf, err := r.hasher.Hash(sessionToken)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
csrftoken = string(csrf)
|
||||
|
||||
if err = r.rdb.Set(ctx, sessionToken, csrftoken, 0).Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return csrftoken, nil
|
||||
}
|
||||
|
||||
func (r *redisCSRF) RemoveCSRF(ctx context.Context, sessionToken string) error {
|
||||
r.rdb.Del(ctx, sessionToken)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *redisCSRF) ValidCSRF(ctx context.Context, sessionToken string, csrfToken string) (bool, error) {
|
||||
storedcsrfToken, err := r.rdb.Get(ctx, sessionToken).Result()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
valid, err := lcrypto.CompareHash([]byte(csrfToken), []byte(storedcsrfToken))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return valid, nil
|
||||
}
|
||||
8
backend/internal/storage/auth/roles.go
Normal file
8
backend/internal/storage/auth/roles.go
Normal file
@ -0,0 +1,8 @@
|
||||
package auth_storage
|
||||
|
||||
type Role struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Level int `json:"level"`
|
||||
}
|
||||
1
backend/internal/storage/auth/sessions.go
Normal file
1
backend/internal/storage/auth/sessions.go
Normal file
@ -0,0 +1 @@
|
||||
package auth_storage
|
||||
42
backend/internal/storage/auth/storage.go
Normal file
42
backend/internal/storage/auth/storage.go
Normal file
@ -0,0 +1,42 @@
|
||||
package auth_storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AuthStorage struct {
|
||||
Users interface { // store user id, username, password(hashed+salted), role?
|
||||
GetByID(ctx context.Context, id int64) (*User, error)
|
||||
GetByEmail(context.Context, string) (*User, error)
|
||||
GetByUsername(context.Context, string) (*User, error)
|
||||
Create(context.Context, *User) error // create a non-exported create function which does take in the tx
|
||||
CreateAndInvite(ctx context.Context, user *User, token string, exp time.Duration) error
|
||||
Activate(context.Context, string) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
|
||||
UpdateUserPass(ctx context.Context, user string, oldPassword string, newPass string) error
|
||||
|
||||
CheckPass(ctx context.Context, name string, pass string) (bool, error)
|
||||
SigninUser(ctx context.Context, name string, pass string) (bool, *User, error)
|
||||
// ValidCredentials(ctx context.Context, user *User, pass string) (bool, error)
|
||||
}
|
||||
|
||||
Sessions interface { // store just session tokens, and their corresponding user id
|
||||
AddSession(ctx context.Context, userid int64) (token string, err error)
|
||||
CheckSession(ctx context.Context, token string) (valid bool, userid int64, err error) // should also extend it by the lifespan if near the end of the time. maybe a 5 min window at the end?
|
||||
RemoveSession(ctx context.Context, token string) error
|
||||
SetLifespan(ctx context.Context, token string, lf time.Time) error
|
||||
}
|
||||
|
||||
CSRF interface {
|
||||
AddCSRF(ctx context.Context, sessionToken string) (csrftoken string, err error)
|
||||
RemoveCSRF(ctx context.Context, sessionToken string) error
|
||||
ValidCSRF(ctx context.Context, sessionToken string, csrfToken string) (bool, error)
|
||||
// CleanupCSRF()
|
||||
}
|
||||
|
||||
Roles interface {
|
||||
GetByName(context.Context, string) (*Role, error)
|
||||
}
|
||||
}
|
||||
27
backend/internal/storage/auth/users.go
Normal file
27
backend/internal/storage/auth/users.go
Normal file
@ -0,0 +1,27 @@
|
||||
package auth_storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrExistingUser = errors.New("user already exists")
|
||||
ErrPasswordIncorrect = errors.New("password incorrect")
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Password Password `json:"-"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
IsActive bool `json:"is_active"`
|
||||
Role Role `json:"role"`
|
||||
}
|
||||
|
||||
type Password struct {
|
||||
text *string
|
||||
hash []byte
|
||||
encoded *string
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user