40 lines
1012 B
Go
40 lines
1012 B
Go
package auth
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/jackc/pgx/v5"
|
||
|
|
)
|
||
|
|
|
||
|
|
// UserSessionState is the cookie-session gate (active flag + version for revoke-on-reset).
|
||
|
|
type UserSessionState struct {
|
||
|
|
Active bool
|
||
|
|
Version int
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserSessionState loads is_active and session_version for RequireSession.
|
||
|
|
// When session_version is not migrated yet, Version defaults to 0 (pre-hardening sessions keep working).
|
||
|
|
func (s *Service) UserSessionState(ctx context.Context, userID uuid.UUID) (UserSessionState, error) {
|
||
|
|
var st UserSessionState
|
||
|
|
err := s.Pool.QueryRow(ctx, `
|
||
|
|
SELECT is_active, session_version
|
||
|
|
FROM users
|
||
|
|
WHERE id = $1`, userID).Scan(&st.Active, &st.Version)
|
||
|
|
if isUndefinedColumn(err) {
|
||
|
|
err = s.Pool.QueryRow(ctx, `
|
||
|
|
SELECT is_active
|
||
|
|
FROM users
|
||
|
|
WHERE id = $1`, userID).Scan(&st.Active)
|
||
|
|
st.Version = 0
|
||
|
|
}
|
||
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
||
|
|
return UserSessionState{}, ErrUserNotFound
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
return UserSessionState{}, err
|
||
|
|
}
|
||
|
|
return st, nil
|
||
|
|
}
|