M accounts/helpers.go => accounts/helpers.go +18 -0
@@ 1,9 1,13 @@
package accounts
import (
+ "context"
+ "database/sql"
"strconv"
"github.com/labstack/echo/v4"
+ "hg.code.netlandish.com/~netlandish/gobwebs"
+ "hg.code.netlandish.com/~netlandish/gobwebs/database"
"hg.code.netlandish.com/~netlandish/gobwebs/server"
)
@@ 24,3 28,17 @@ func UserLogout(c echo.Context) error {
ctx.Server.Session.Remove(c.Request().Context(), userIDKey)
return nil
}
+
+// UpdateLastLogin updates the last login time for a user
+func UpdateLastLogin(db *sql.DB, user gobwebs.User) error {
+ ctx := database.Context(context.Background(), db)
+ err := database.WithTx(ctx, nil, func(tx *sql.Tx) error {
+ // Null any current pending email changes
+ _, err := tx.ExecContext(ctx, `
+ UPDATE "users"
+ SET last_login=NOW() at time zone 'UTC'
+ WHERE id=$1`, user.GetID())
+ return err
+ })
+ return err
+}
M accounts/routes.go => accounts/routes.go +6 -0
@@ 127,7 127,10 @@ func (s *Service) LoginAuthPOST(c echo.Context) error {
}
}
+ gctx := c.(*server.Context)
UserLogin(c, form.user.GetID())
+ UpdateLastLogin(gctx.Server.DB, form.user)
+
if err := s.fetch.ProcessSuccessfulLogin(c, form.user); err != nil {
return err
}
@@ 254,7 257,10 @@ func (s *Service) LoginEmailConf(c echo.Context) error {
if err := conf.Confirm(gctx.Server.DB); err != nil {
return err
}
+
UserLogin(c, user.GetID())
+ UpdateLastLogin(gctx.Server.DB, user)
+
if err := s.fetch.ProcessSuccessfulLogin(c, user); err != nil {
return err
}
M accounts/user.go => accounts/user.go +5 -0
@@ 1,7 1,9 @@
package accounts
import (
+ "database/sql"
"fmt"
+ "time"
"github.com/alexedwards/argon2id"
)
@@ 16,6 18,9 @@ type BaseUser struct {
staff bool `db:"is_staff" validate:"-"`
verified bool `db:"is_verified"`
+ CreatedOn time.Time `db:"created_on"`
+ LastLogin sql.NullTime `db:"last_login"`
+
authenticated bool `db:"-" validate:"-"`
}