diff --git a/handlers/signin.go b/handlers/signin.go index 7a07ba6..f668530 100644 --- a/handlers/signin.go +++ b/handlers/signin.go @@ -5,6 +5,7 @@ package handlers import ( "context" + "errors" "net/http" "strconv" @@ -112,7 +113,9 @@ func SigninPost(client *ent.Client) echo.HandlerFunc { loginFailed := "Login Failed!" ctx := context.WithValue(context.Background(), moduser.CtxKey{}, slogger) - if usr, err := moduser.QueryUser(ctx, client, username); err == nil { + usr, err := moduser.QueryUser(ctx, client, username) + + if err == nil { log.Info("attempting login", "user", &usr.ID) if !passwd.Compare(usr.Password, password) { @@ -181,6 +184,19 @@ func SigninPost(client *ent.Client) echo.HandlerFunc { } } + if err = moduser.UpdateUserLastLogin(ctx, client, usr.ID, usr.IsAdmin); err != nil { + if !errors.Is(err, moduser.ErrUnfinishedSetupLastLoginUpdate) { + return renderErrorPage( + c, + http.StatusInternalServerError, + http.StatusText(http.StatusInternalServerError), + err.Error(), + ) + } + + log.Error("could not update LastLogin", "endpoint", "/home", "method", "post") + } + return c.Redirect(http.StatusMovedPermanently, "/home") } } diff --git a/modules/user/error.go b/modules/user/error.go index d811f81..ca44f41 100644 --- a/modules/user/error.go +++ b/modules/user/error.go @@ -6,10 +6,11 @@ package user import "errors" var ( - ErrUsersAlreadyPresent = errors.New("don't call CreateFirst when there already are another users") - ErrUserNotFound = errors.New("user not found") - ErrFailedToQueryUser = errors.New("failed to query user") - ErrBadUUID = errors.New("invalid uuid") - ErrPasswordEmpty = errors.New("password was empty") - ErrNewPasswordCannotEqual = errors.New("the new password cannot be the same as the old one") + ErrUsersAlreadyPresent = errors.New("don't call CreateFirst when there already are another users") + ErrUserNotFound = errors.New("user not found") + ErrFailedToQueryUser = errors.New("failed to query user") + ErrBadUUID = errors.New("invalid uuid") + ErrPasswordEmpty = errors.New("password was empty") + ErrNewPasswordCannotEqual = errors.New("the new password cannot be the same as the old one") + ErrUnfinishedSetupLastLoginUpdate = errors.New("not updating last_login for users with unfinished setup") ) diff --git a/modules/user/user.go b/modules/user/user.go index f314cef..7098cb1 100644 --- a/modules/user/user.go +++ b/modules/user/user.go @@ -309,6 +309,42 @@ func UpdateUserByAdmin(ctx context.Context, client *ent.Client, id uuid.UUID, em return nil } +// UpdateUserLastLogin serves to update the last_login param of the user. This +// parameter will not get updated for users that never finished setting up, +// return nil on success and error on err. +func UpdateUserLastLogin(ctx context.Context, client *ent.Client, id uuid.UUID, isAdmin bool) error { + slogger := ctx.Value(CtxKey{}).(*slogging.Slogger) + log := *slogger + + log.Logger = log.Logger.With( + slog.Group("pcmt extra", slog.String("module", "modules/user")), + ) + + finishedSetup, err := UsrFinishedSetup(ctx, client, id) + if err != nil { + return err + } + + if !isAdmin && !finishedSetup { + return ErrUnfinishedSetupLastLoginUpdate + } + + u, err := client.User. + Update().Where(user.IDEQ(id)). + SetLastLogin(time.Now()). + Save(ctx) + + switch { + case err != nil: + return fmt.Errorf("failed to update last_login for user: %w", err) + + case u > 1: + return fmt.Errorf("somehow updated last_login for more than one user? count: %d", u) + } + + return nil +} + // DeleteUserByID returns nil on successful deletion, err otherwise. func DeleteUserByID(ctx context.Context, client *ent.Client, strID string) error { slogger := ctx.Value(CtxKey{}).(*slogging.Slogger)