Documentation
¶
Overview ¶
internal/auth/cookie.go
Index ¶
- Constants
- Variables
- func ExpireSessionCookie(cfg CookieConfig) *http.Cookie
- func NewSessionCookie(token string, cfg CookieConfig) *http.Cookie
- func PrincipalUserContextMiddleware(auth UserAuthenticator) func(http.Handler) http.Handler
- func TokenFromRequest(r *http.Request) (string, error)
- func WithPrincipal(ctx context.Context, principal Principal) context.Context
- type CookieConfig
- type HTTPHandler
- func (h *HTTPHandler) ChangePassword(ctx context.Context, request httpapi.ChangePasswordRequestObject) (httpapi.ChangePasswordResponseObject, error)
- func (h *HTTPHandler) CreateUser(ctx context.Context, request httpapi.CreateUserRequestObject) (httpapi.CreateUserResponseObject, error)
- func (h *HTTPHandler) DeleteUser(ctx context.Context, request httpapi.DeleteUserRequestObject) (httpapi.DeleteUserResponseObject, error)
- func (h *HTTPHandler) DemoteUser(ctx context.Context, request httpapi.DemoteUserRequestObject) (httpapi.DemoteUserResponseObject, error)
- func (h *HTTPHandler) GetCurrentUser(ctx context.Context, _ httpapi.GetCurrentUserRequestObject) (httpapi.GetCurrentUserResponseObject, error)
- func (h *HTTPHandler) ListUsers(ctx context.Context, _ httpapi.ListUsersRequestObject) (httpapi.ListUsersResponseObject, error)
- func (h *HTTPHandler) Login(ctx context.Context, request httpapi.LoginRequestObject) (httpapi.LoginResponseObject, error)
- func (h *HTTPHandler) Logout(ctx context.Context, _ httpapi.LogoutRequestObject) (httpapi.LogoutResponseObject, error)
- func (h *HTTPHandler) PromoteUser(ctx context.Context, request httpapi.PromoteUserRequestObject) (httpapi.PromoteUserResponseObject, error)
- func (h *HTTPHandler) UpdateMe(ctx context.Context, request httpapi.UpdateMeRequestObject) (httpapi.UpdateMeResponseObject, error)
- func (h *HTTPHandler) UserAuthenticator() UserAuthenticator
- type Principal
- type ProfileUpdates
- type Repository
- func (r *Repository) CountAdminUsers(ctx context.Context) (int, error)
- func (r *Repository) CountUsers(ctx context.Context) (int, error)
- func (r *Repository) CreateSession(ctx context.Context, session *Session) (*Session, error)
- func (r *Repository) CreateUser(ctx context.Context, user *User) (*User, error)
- func (r *Repository) GetAllUsers(ctx context.Context) ([]User, error)
- func (r *Repository) GetSessionWithRoleByTokenHash(ctx context.Context, tokenHash string) (*SessionWithUser, error)
- func (r *Repository) GetUserByID(ctx context.Context, userID UserID) (*User, error)
- func (r *Repository) GetUserByUsername(ctx context.Context, username string) (*User, error)
- func (r *Repository) RevokeAllUserSessions(ctx context.Context, userID UserID) error
- func (r *Repository) RevokeAllUserSessionsExcept(ctx context.Context, userID UserID, exceptSessionID SessionID) error
- func (r *Repository) RevokeSessionByID(ctx context.Context, id SessionID) error
- func (r *Repository) RunInTx(ctx context.Context, fn func(repository) error) error
- func (r *Repository) SoftDeleteUser(ctx context.Context, userID UserID) error
- func (r *Repository) UpdatePasswordHash(ctx context.Context, userID UserID, newHash []byte) error
- func (r *Repository) UpdateUser(ctx context.Context, user *User) (*User, error)
- type Role
- type Service
- func (s *Service) Authenticate(ctx context.Context, rawToken string) (*Principal, error)
- func (s *Service) BootstrapAdmin(ctx context.Context, conf config.ConfServer) error
- func (s *Service) ChangePassword(ctx context.Context, userID UserID, sessionID SessionID, ...) error
- func (s *Service) CreateUser(ctx context.Context, username string, displayName string, email string, ...) (*User, error)
- func (s *Service) DeleteUser(ctx context.Context, principal *Principal, targetID UserID) error
- func (s *Service) DemoteUser(ctx context.Context, principal *Principal, targetID UserID) (*User, error)
- func (s *Service) GetUserFromPrincipal(ctx context.Context, principal *Principal) (*User, error)
- func (s *Service) ListUsers(ctx context.Context, principal *Principal) ([]User, error)
- func (s *Service) Login(ctx context.Context, username string, password string) (string, *User, error)
- func (s *Service) PromoteUser(ctx context.Context, principal *Principal, targetID UserID) (*User, error)
- func (s *Service) RevokeSession(ctx context.Context, sessionID SessionID) error
- func (s *Service) UpdateOwnProfile(ctx context.Context, userID UserID, updates ProfileUpdates) (*User, error)
- type Session
- type SessionID
- type SessionWithUser
- type User
- type UserAuthenticator
- type UserID
Constants ¶
const ( AttrKeyComponent = logging.AttrKeyComponent AttrKeyOperation = logging.AttrKeyOperation AttrKeyError = logging.AttrKeyError AttrKeyUserID = "user_id" AttrKeyDisplayName = "display_name" AttrKeySessionID = "session_id" AttrKeyUsername = "username" )
Slog attribute key names for the auth domain. Use these constants when logging so keys are consistent and typo-safe across handlers and services.
const ( BootstrapAdminUsername = "admin" BootstrapAdminDisplayName = "Admin" BootstrapAdminEmail = "admin@pulseweaver.invalid" )
const CookieDuration = 7 * 24 * time.Hour
Variables ¶
var ( ErrInvalidCredentials = errors.New("invalid credentials") ErrAdminCredentialsRequired = errors.New("admin credentials are required") ErrUsernameTaken = errors.New("username already taken") ErrEmailTaken = errors.New("email already taken") ErrUserNotFound = errors.New("user not found") ErrInvalidUsername = errors.New("invalid username") ErrInvalidDisplayName = errors.New("invalid display name") ErrInvalidPassword = errors.New("invalid password") ErrSelfDeleteForbidden = errors.New("cannot delete yourself") ErrSelfRoleChangeForbidden = errors.New("cannot change your own role") ErrNoUpdateFields = errors.New("no fields to update") )
var DefaultCookieConfig = CookieConfig{ Name: httpapi.SessionCookieName, Secure: true, HTTPOnly: true, SameSite: http.SameSiteLaxMode, Domain: "", }
Default production config
Functions ¶
func ExpireSessionCookie ¶
func ExpireSessionCookie(cfg CookieConfig) *http.Cookie
ExpireSessionCookie creates a cookie to clear the session
func NewSessionCookie ¶
func NewSessionCookie(token string, cfg CookieConfig) *http.Cookie
NewSessionCookie creates a standardized auth cookie
func PrincipalUserContextMiddleware ¶
func PrincipalUserContextMiddleware(auth UserAuthenticator) func(http.Handler) http.Handler
PrincipalUserContextMiddleware resolves the authenticated principal into a user principal and injects it into the request context.
Types ¶
type CookieConfig ¶
type CookieConfig struct {
Name string
Secure bool
HTTPOnly bool
SameSite http.SameSite
Domain string // Empty for host-only (recommended)
}
CookieConfig holds environment-specific cookie settings
type HTTPHandler ¶
type HTTPHandler struct {
// contains filtered or unexported fields
}
func NewHandler ¶
func NewHandler(service *Service, logger *slog.Logger) *HTTPHandler
func (*HTTPHandler) ChangePassword ¶
func (h *HTTPHandler) ChangePassword(ctx context.Context, request httpapi.ChangePasswordRequestObject) (httpapi.ChangePasswordResponseObject, error)
func (*HTTPHandler) CreateUser ¶
func (h *HTTPHandler) CreateUser(ctx context.Context, request httpapi.CreateUserRequestObject) (httpapi.CreateUserResponseObject, error)
func (*HTTPHandler) DeleteUser ¶
func (h *HTTPHandler) DeleteUser(ctx context.Context, request httpapi.DeleteUserRequestObject) (httpapi.DeleteUserResponseObject, error)
func (*HTTPHandler) DemoteUser ¶
func (h *HTTPHandler) DemoteUser(ctx context.Context, request httpapi.DemoteUserRequestObject) (httpapi.DemoteUserResponseObject, error)
func (*HTTPHandler) GetCurrentUser ¶
func (h *HTTPHandler) GetCurrentUser(ctx context.Context, _ httpapi.GetCurrentUserRequestObject) (httpapi.GetCurrentUserResponseObject, error)
func (*HTTPHandler) ListUsers ¶
func (h *HTTPHandler) ListUsers(ctx context.Context, _ httpapi.ListUsersRequestObject) (httpapi.ListUsersResponseObject, error)
func (*HTTPHandler) Login ¶
func (h *HTTPHandler) Login(ctx context.Context, request httpapi.LoginRequestObject) (httpapi.LoginResponseObject, error)
func (*HTTPHandler) Logout ¶
func (h *HTTPHandler) Logout(ctx context.Context, _ httpapi.LogoutRequestObject) (httpapi.LogoutResponseObject, error)
func (*HTTPHandler) PromoteUser ¶
func (h *HTTPHandler) PromoteUser(ctx context.Context, request httpapi.PromoteUserRequestObject) (httpapi.PromoteUserResponseObject, error)
func (*HTTPHandler) UpdateMe ¶
func (h *HTTPHandler) UpdateMe(ctx context.Context, request httpapi.UpdateMeRequestObject) (httpapi.UpdateMeResponseObject, error)
func (*HTTPHandler) UserAuthenticator ¶
func (h *HTTPHandler) UserAuthenticator() UserAuthenticator
type Principal ¶
func PrincipalFromSession ¶
func PrincipalFromSession(session *SessionWithUser) *Principal
type ProfileUpdates ¶
type Repository ¶
type Repository struct {
// contains filtered or unexported fields
}
func NewRepository ¶
func NewRepository(db *sqlx.DB) *Repository
func (*Repository) CountAdminUsers ¶
func (r *Repository) CountAdminUsers(ctx context.Context) (int, error)
func (*Repository) CountUsers ¶
func (r *Repository) CountUsers(ctx context.Context) (int, error)
func (*Repository) CreateSession ¶
func (*Repository) CreateUser ¶
func (*Repository) GetAllUsers ¶
func (r *Repository) GetAllUsers(ctx context.Context) ([]User, error)
func (*Repository) GetSessionWithRoleByTokenHash ¶
func (r *Repository) GetSessionWithRoleByTokenHash(ctx context.Context, tokenHash string) (*SessionWithUser, error)
GetSessionWithRoleByTokenHash Finds and retrieves valid session(non-expired or revoked) given a tokenHash. Also returns the user_role
func (*Repository) GetUserByID ¶
func (*Repository) GetUserByUsername ¶
func (*Repository) RevokeAllUserSessions ¶
func (r *Repository) RevokeAllUserSessions(ctx context.Context, userID UserID) error
func (*Repository) RevokeAllUserSessionsExcept ¶
func (*Repository) RevokeSessionByID ¶
func (r *Repository) RevokeSessionByID(ctx context.Context, id SessionID) error
func (*Repository) RunInTx ¶
func (r *Repository) RunInTx(ctx context.Context, fn func(repository) error) error
RunInTx runs the callback function inside a transaction. If already running in a transaction context, do not create a new one and reuse it
func (*Repository) SoftDeleteUser ¶
func (r *Repository) SoftDeleteUser(ctx context.Context, userID UserID) error
func (*Repository) UpdatePasswordHash ¶
func (*Repository) UpdateUser ¶
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func (*Service) Authenticate ¶
func (*Service) BootstrapAdmin ¶
func (*Service) ChangePassword ¶
func (*Service) CreateUser ¶
func (*Service) DeleteUser ¶
func (*Service) DemoteUser ¶
func (*Service) GetUserFromPrincipal ¶
func (*Service) PromoteUser ¶
func (*Service) RevokeSession ¶
func (*Service) UpdateOwnProfile ¶
type Session ¶
type Session struct {
ID SessionID `db:"id" `
UserID UserID `db:"user_id" `
TokenHash string `db:"token_hash" `
CreatedAt time.Time `db:"created_at" `
ExpiresAt time.Time `db:"expires_at" `
LastUsedAt *time.Time `db:"last_used_at" `
RevokedAt *time.Time `db:"revoked_at" `
}
func NewSession ¶
type SessionWithUser ¶
type User ¶
type User struct {
ID UserID `db:"id"`
Username string `db:"username"`
DisplayName string `db:"display_name"`
Email string `db:"email"`
PasswordHash []byte `db:"password_hash"`
Role Role `db:"role"`
MustChangePassword bool `db:"must_change_password"`
CreatedBy *UserID `db:"created_by"`
CreatedAt time.Time `db:"created_at"`
DeletedAt *time.Time `db:"deleted_at"`
}
func (*User) Update ¶
func (u *User) Update(up ProfileUpdates) error