feat: add session expiration tracking and validation
feat: implement Redis caching for terminated sessions feat: add new session GUID queries for validation refactor: extend Session model with last_refresh_exp_time refactor: update token generation to include role and session refactor: modify auth middleware to validate session status refactor: replace GetUserSessions with GetValidUserSessions chore: add uuid/v5 dependency fix: update router to pass dependencies to auth middleware chore: update SQL schema and queries for new expiration field
This commit is contained in:
@@ -53,7 +53,27 @@ type authServiceImpl struct {
|
||||
}
|
||||
|
||||
func NewAuthService(_log *zap.Logger, _dbctx database.DbContext, _redis *redis.Client, _smtp SmtpService) AuthService {
|
||||
return &authServiceImpl{log: _log, dbctx: _dbctx, redis: _redis, smtp: _smtp}
|
||||
|
||||
authService := &authServiceImpl{log: _log, dbctx: _dbctx, redis: _redis, smtp: _smtp}
|
||||
|
||||
// Cache terminated sessions
|
||||
// FIXME: review possible RAM overflow
|
||||
db := database.NewDbHelper(_dbctx)
|
||||
guids, err := db.Queries.GetUnexpiredTerminatedSessionsGuids(db.CTX)
|
||||
if err != nil {
|
||||
panic("Failed to load terminated sessions' GUIDs")
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
// FIXME: review possible problems due to a large pipeline request
|
||||
pipe := _redis.Pipeline()
|
||||
for _, guid := range guids {
|
||||
if err := pipe.Set(ctx, fmt.Sprint("session:%s:is_terminated", guid), true, 0); err != nil {
|
||||
panic("Failed to cache terminated session: " + err.Err().Error())
|
||||
}
|
||||
}
|
||||
_log.Info("Cached terminated sessions' GUIDs in Redis", zap.Int("amount", len(guids)))
|
||||
return authService
|
||||
}
|
||||
|
||||
func (a *authServiceImpl) RegistrationBegin(request models.RegistrationBeginRequest) (bool, error) {
|
||||
@@ -324,7 +344,8 @@ func (a *authServiceImpl) RegistrationComplete(request models.RegistrationComple
|
||||
return nil, errs.ErrServerError
|
||||
}
|
||||
|
||||
accessToken, refreshToken, err = utils.GenerateTokens(user.Username, session.Guid.String())
|
||||
// TODO: get user role
|
||||
accessToken, refreshToken, err = utils.GenerateTokens(user.Username, session.Guid.String(), enums.UserRole)
|
||||
|
||||
if err != nil {
|
||||
a.log.Error(
|
||||
@@ -415,7 +436,8 @@ func (a *authServiceImpl) Login(request models.LoginRequest) (*models.LoginRespo
|
||||
return nil, errs.ErrServerError
|
||||
}
|
||||
|
||||
accessToken, refreshToken, err := utils.GenerateTokens(userRow.Username, session.Guid.String())
|
||||
// TODO: get user role
|
||||
accessToken, refreshToken, err := utils.GenerateTokens(userRow.Username, session.Guid.String(), enums.UserRole)
|
||||
if err != nil {
|
||||
a.log.Error(
|
||||
"Failed to generate tokens for a new login",
|
||||
@@ -654,7 +676,8 @@ func (a *authServiceImpl) PasswordResetComplete(request models.PasswordResetComp
|
||||
zap.Error(err))
|
||||
}
|
||||
|
||||
if accessToken, refreshToken, err = utils.GenerateTokens(user.Username, session.Guid.String()); err != nil {
|
||||
// TODO: get user role
|
||||
if accessToken, refreshToken, err = utils.GenerateTokens(user.Username, session.Guid.String(), enums.UserRole); err != nil {
|
||||
a.log.Error(
|
||||
"Failed to generate tokens as part of user password reset",
|
||||
zap.String("email", request.Email),
|
||||
|
||||
Reference in New Issue
Block a user