mirror of
https://github.com/hay-kot/homebox.git
synced 2024-11-16 21:58:40 +00:00
de419dc37d
* schema changes * db generate * db migration * add role based middleware * implement attachment token access * generate docs * implement role based auth * replace attachment specific tokens with gen token * run linter * cleanup temporary token implementation
129 lines
3 KiB
Go
129 lines
3 KiB
Go
package repo
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/hay-kot/homebox/backend/internal/data/ent"
|
|
"github.com/hay-kot/homebox/backend/internal/data/ent/authroles"
|
|
"github.com/hay-kot/homebox/backend/internal/data/ent/authtokens"
|
|
"github.com/hay-kot/homebox/backend/pkgs/hasher"
|
|
"github.com/hay-kot/homebox/backend/pkgs/set"
|
|
)
|
|
|
|
type TokenRepository struct {
|
|
db *ent.Client
|
|
}
|
|
|
|
type (
|
|
UserAuthTokenCreate struct {
|
|
TokenHash []byte `json:"token"`
|
|
UserID uuid.UUID `json:"userId"`
|
|
ExpiresAt time.Time `json:"expiresAt"`
|
|
}
|
|
|
|
UserAuthToken struct {
|
|
UserAuthTokenCreate
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
}
|
|
)
|
|
|
|
func (u UserAuthToken) IsExpired() bool {
|
|
return u.ExpiresAt.Before(time.Now())
|
|
}
|
|
|
|
// GetUserFromToken get's a user from a token
|
|
func (r *TokenRepository) GetUserFromToken(ctx context.Context, token []byte) (UserOut, error) {
|
|
user, err := r.db.AuthTokens.Query().
|
|
Where(authtokens.Token(token)).
|
|
Where(authtokens.ExpiresAtGTE(time.Now())).
|
|
WithUser().
|
|
QueryUser().
|
|
WithGroup().
|
|
Only(ctx)
|
|
|
|
if err != nil {
|
|
return UserOut{}, err
|
|
}
|
|
|
|
return mapUserOut(user), nil
|
|
}
|
|
|
|
func (r *TokenRepository) GetRoles(ctx context.Context, token string) (*set.Set[string], error) {
|
|
tokenHash := hasher.HashToken(token)
|
|
|
|
roles, err := r.db.AuthRoles.
|
|
Query().
|
|
Where(authroles.HasTokenWith(
|
|
authtokens.Token(tokenHash),
|
|
)).
|
|
All(ctx)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
roleSet := set.Make[string](len(roles))
|
|
|
|
for _, role := range roles {
|
|
roleSet.Insert(role.Role.String())
|
|
}
|
|
|
|
return &roleSet, nil
|
|
}
|
|
|
|
// Creates a token for a user
|
|
func (r *TokenRepository) CreateToken(ctx context.Context, createToken UserAuthTokenCreate, roles ...authroles.Role) (UserAuthToken, error) {
|
|
dbToken, err := r.db.AuthTokens.Create().
|
|
SetToken(createToken.TokenHash).
|
|
SetUserID(createToken.UserID).
|
|
SetExpiresAt(createToken.ExpiresAt).
|
|
Save(ctx)
|
|
|
|
if err != nil {
|
|
return UserAuthToken{}, err
|
|
}
|
|
|
|
for _, role := range roles {
|
|
_, err := r.db.AuthRoles.Create().
|
|
SetRole(role).
|
|
SetToken(dbToken).
|
|
Save(ctx)
|
|
|
|
if err != nil {
|
|
return UserAuthToken{}, err
|
|
}
|
|
}
|
|
|
|
return UserAuthToken{
|
|
UserAuthTokenCreate: UserAuthTokenCreate{
|
|
TokenHash: dbToken.Token,
|
|
UserID: createToken.UserID,
|
|
ExpiresAt: dbToken.ExpiresAt,
|
|
},
|
|
CreatedAt: dbToken.CreatedAt,
|
|
}, nil
|
|
}
|
|
|
|
// DeleteToken remove a single token from the database - equivalent to revoke or logout
|
|
func (r *TokenRepository) DeleteToken(ctx context.Context, token []byte) error {
|
|
_, err := r.db.AuthTokens.Delete().Where(authtokens.Token(token)).Exec(ctx)
|
|
return err
|
|
}
|
|
|
|
// PurgeExpiredTokens removes all expired tokens from the database
|
|
func (r *TokenRepository) PurgeExpiredTokens(ctx context.Context) (int, error) {
|
|
tokensDeleted, err := r.db.AuthTokens.Delete().Where(authtokens.ExpiresAtLTE(time.Now())).Exec(ctx)
|
|
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return tokensDeleted, nil
|
|
}
|
|
|
|
func (r *TokenRepository) DeleteAll(ctx context.Context) (int, error) {
|
|
amount, err := r.db.AuthTokens.Delete().Exec(ctx)
|
|
return amount, err
|
|
}
|