Documentation
¶
Index ¶
- Constants
- type AuthSvc
- type AuthSvcConfig
- type LoginEndpoint
- type LoginRequest
- type MagicLoginEndpoint
- type MagicLoginRequest
- type RefreshTokenEndpoint
- type RefreshTokenRequest
- type RegisterEndpoint
- type RegisterRequest
- type RequestPasswordResetEndpoint
- type RequestPasswordResetRequest
- type ResetPasswordEndpoint
- type ResetPasswordRequest
- type RevokeRefreshTokenEndpoint
- type RevokeRefreshTokenRequest
- type UpdatePasswordEndpoint
- type UpdatePasswordRequest
- type UpdateScannerPasswordEndpoint
- type UpdateScannerPasswordRequest
Constants ¶
const (
MissingAuthApiKeyError = "This client is not authorized."
)
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AuthSvc ¶
type AuthSvc interface {
Login(ctx context.Context, req *LoginRequest) (*apiresource.User, *apierror.APIError)
Register(ctx context.Context, req *RegisterRequest) (*apiresource.User, *apierror.APIError)
MagicLogin(ctx context.Context, req *MagicLoginRequest) (*apiresource.User, *apierror.APIError)
RefreshToken(ctx context.Context, req *RefreshTokenRequest) (*apiresource.EmptyResource, *apierror.APIError)
RequestPasswordReset(ctx context.Context, req *RequestPasswordResetRequest) (*apiresource.EmptyResource, *apierror.APIError)
ResetPassword(ctx context.Context, req *ResetPasswordRequest) (*apiresource.EmptyResource, *apierror.APIError)
RevokeRefreshToken(ctx context.Context, req *RevokeRefreshTokenRequest) (*apiresource.EmptyResource, *apierror.APIError)
UpdatePassword(ctx context.Context, req *UpdatePasswordRequest) (*apiresource.EmptyResource, *apierror.APIError)
UpdateScannerPassword(ctx context.Context, req *UpdateScannerPasswordRequest) (*apiresource.EmptyResource, *apierror.APIError)
}
func NewAuthSvc ¶
func NewAuthSvc(config *AuthSvcConfig) AuthSvc
type AuthSvcConfig ¶
type AuthSvcConfig struct {
// AuthClient (required) is the auth-service gRPC client.
AuthClient pb.AuthServiceClient
// CoreClient (required) is the core-service gRPC client.
CoreClient corepb.CoreServiceClient
}
type LoginEndpoint ¶
type LoginEndpoint struct{}
Authenticates a user and returns the user object, setting access and refresh tokens in cookies.
Failed attempts are throttled per identifier: after 10 failures within 5 minutes, further attempts for that identifier are rejected with a rate-limit error until the window passes. Invalid credentials always return the same generic error, whether or not the identifier exists.
func (*LoginEndpoint) Materialize ¶
func (e *LoginEndpoint) Materialize() *apiendpoint.APIEndpoint[*LoginRequest, *apiresource.User]
type LoginRequest ¶
type LoginRequest struct {
// Username or email for authentication.
Identifier string `json:"identifier" validate:"required,identifier"`
// User password.
Password string `json:"password" validate:"required,max=72" sensitive:"true"` // #nosec G117 - Struct field, not a hardcoded credential
}
Request to log in a user.
func (*LoginRequest) SchemaExample ¶
func (*LoginRequest) SchemaExample() any
type MagicLoginEndpoint ¶
type MagicLoginEndpoint struct{}
Exchanges a magic login token for a session, setting access and refresh tokens in cookies.
Signs the user in without a password. The token is short-lived, so once it expires the link no longer signs the user in.
func (*MagicLoginEndpoint) Materialize ¶
func (e *MagicLoginEndpoint) Materialize() *apiendpoint.APIEndpoint[*MagicLoginRequest, *apiresource.User]
type MagicLoginRequest ¶
type MagicLoginRequest struct {
// Magic login token taken from the `t` query parameter of the link in the "already registered" email.
//
// The token expires 15 minutes after the email is sent.
Token string `json:"token" validate:"required" sensitive:"true"` // #nosec G117 - Struct field, not a hardcoded credential
}
Request to exchange a magic login token for a session.
func (*MagicLoginRequest) SchemaExample ¶
func (*MagicLoginRequest) SchemaExample() any
type RefreshTokenEndpoint ¶
type RefreshTokenEndpoint struct{}
Issues a new access token from the caller's refresh token, setting it in a cookie.
The refresh token itself is not rotated and keeps its original expiration, so the same cookie can be exchanged repeatedly until it expires or is revoked. A refresh token that has been revoked or has expired fails here and the user must sign in again.
func (*RefreshTokenEndpoint) Materialize ¶
func (e *RefreshTokenEndpoint) Materialize() *apiendpoint.APIEndpoint[*RefreshTokenRequest, *apiresource.EmptyResource]
type RefreshTokenRequest ¶
type RefreshTokenRequest struct {
// Refresh token, read from the `__Secure-openmrp.refresh-token` cookie.
RefreshToken string `cookie:"__Secure-openmrp.refresh-token" validate:"required"` // #nosec G117 - Struct field, not a hardcoded credential
}
Request to refresh an access token.
func (*RefreshTokenRequest) SchemaExample ¶
func (*RefreshTokenRequest) SchemaExample() any
type RegisterEndpoint ¶
type RegisterEndpoint struct{}
Registers a user on the customer portal.
Returns the new user object, sets access and refresh tokens in cookies, and sends the user a welcome email. Registering creates the user record only; membership in an account is granted separately.
If the email is already registered, the request fails with a generic validation error (so existing emails are not revealed) and an "already registered" email containing a magic login link is sent to the existing user instead.
func (*RegisterEndpoint) Materialize ¶
func (e *RegisterEndpoint) Materialize() *apiendpoint.APIEndpoint[*RegisterRequest, *apiresource.User]
type RegisterRequest ¶
type RegisterRequest struct {
// Email address the user will sign in with.
//
// Must not already belong to a user; the request is rejected without revealing that the address is taken.
Email string `json:"email" validate:"required,custom_email"`
// Password the user will sign in with.
Password string `json:"password" validate:"required,password" sensitive:"true"` // #nosec G117 - Struct field, not a hardcoded credential
// Full name of the user, used to address them in emails.
Name string `json:"name" validate:"required"`
// Slug of the customer portal the user is registering from.
//
// Only affects the "already registered" email sent when the address is taken: it points the magic-login link back at that portal instead of the generic dashboard. Accounts with a verified custom portal domain use that domain in the link instead of the slug.
AccountSlug field.Optional[string] `json:"account_slug,omitzero" validate:"omitempty"`
}
Request to register a user.
func (*RegisterRequest) SchemaExample ¶
func (*RegisterRequest) SchemaExample() any
type RequestPasswordResetEndpoint ¶
type RequestPasswordResetEndpoint struct{}
Sends a password reset email to the user.
Always returns an accepted response, whether or not the identifier matches a known user, so it does not reveal which identifiers exist. Reset links expire 15 minutes after they are issued.
func (*RequestPasswordResetEndpoint) Materialize ¶
func (e *RequestPasswordResetEndpoint) Materialize() *apiendpoint.APIEndpoint[*RequestPasswordResetRequest, *apiresource.EmptyResource]
type RequestPasswordResetRequest ¶
type RequestPasswordResetRequest struct {
// Username or email of the user whose password should be reset.
//
// The reset link is always sent to the email address on file for the matched user, and no email is sent if that user has no address on file.
Identifier string `json:"identifier" validate:"required,identifier"`
// Slug of the customer portal the request came from.
//
// Scopes the emailed reset link to that portal so the user sets their new password there instead of on the generic dashboard. Accounts with a verified custom portal domain use that domain in the link instead of the slug.
AccountSlug field.Optional[string] `json:"account_slug,omitzero"`
}
Request for a password reset.
func (*RequestPasswordResetRequest) SchemaExample ¶
func (*RequestPasswordResetRequest) SchemaExample() any
type ResetPasswordEndpoint ¶
type ResetPasswordEndpoint struct{}
Sets a new password using a password reset token and signs the user in.
All of the user's existing refresh tokens are revoked, signing out their other sessions, and fresh access and refresh tokens are set in cookies. A confirmation email is sent to the user.
func (*ResetPasswordEndpoint) Materialize ¶
func (e *ResetPasswordEndpoint) Materialize() *apiendpoint.APIEndpoint[*ResetPasswordRequest, *apiresource.EmptyResource]
type ResetPasswordRequest ¶
type ResetPasswordRequest struct {
// Password reset token taken from the `t` query parameter of the link in the password reset email.
//
// The token expires 15 minutes after the email is sent; after that the user has to request a new reset email.
Token string `json:"token" validate:"required" sensitive:"true"` // #nosec G117 - Struct field, not a hardcoded credential
// New password to set for the user.
Password string `json:"password" validate:"required,password" sensitive:"true"` // #nosec G117 - Struct field, not a hardcoded credential
}
Request to reset a user's password.
func (*ResetPasswordRequest) SchemaExample ¶
func (*ResetPasswordRequest) SchemaExample() any
type RevokeRefreshTokenEndpoint ¶
type RevokeRefreshTokenEndpoint struct{}
Signs the current session out by revoking its refresh token.
The auth cookies are cleared and the refresh token can no longer be exchanged for access tokens. Other sessions belonging to the user are unaffected, and any access token already issued stays valid until it expires.
func (*RevokeRefreshTokenEndpoint) Materialize ¶
func (e *RevokeRefreshTokenEndpoint) Materialize() *apiendpoint.APIEndpoint[*RevokeRefreshTokenRequest, *apiresource.EmptyResource]
type RevokeRefreshTokenRequest ¶
type RevokeRefreshTokenRequest struct {
// Refresh token to revoke, read from the `__Secure-openmrp.refresh-token` cookie.
RefreshToken string `cookie:"__Secure-openmrp.refresh-token" validate:"required"` // #nosec G117 - Struct field, not a hardcoded credential
}
Request to revoke a refresh token.
func (*RevokeRefreshTokenRequest) SchemaExample ¶
func (*RevokeRefreshTokenRequest) SchemaExample() any
type UpdatePasswordEndpoint ¶
type UpdatePasswordEndpoint struct{}
Updates the authenticated user's password after verifying their current password.
Every refresh token for the user is revoked, including the caller's own, so all sessions end once their current access tokens expire. A confirmation email is sent to the user.
func (*UpdatePasswordEndpoint) Materialize ¶
func (e *UpdatePasswordEndpoint) Materialize() *apiendpoint.APIEndpoint[*UpdatePasswordRequest, *apiresource.EmptyResource]
type UpdatePasswordRequest ¶
type UpdatePasswordRequest struct {
// Current password.
OldPassword string `json:"old_password" validate:"required,password,max=255" sensitive:"true"`
// New password.
NewPassword string `json:"new_password" validate:"required,password,max=255" sensitive:"true"`
}
Request to update a user's password.
func (*UpdatePasswordRequest) SchemaExample ¶
func (*UpdatePasswordRequest) SchemaExample() any
type UpdateScannerPasswordEndpoint ¶
type UpdateScannerPasswordEndpoint struct{}
Sets a new password for a scanner-role account user, the login used by a scanning station.
The caller must be signed in as a user with permission to manage team users and must supply their own current password; API keys cannot perform this operation because they have no password to verify. Only scanner-role users in the caller's account can be changed this way — use the password reset flow for everyone else.
func (*UpdateScannerPasswordEndpoint) Materialize ¶
func (e *UpdateScannerPasswordEndpoint) Materialize() *apiendpoint.APIEndpoint[*UpdateScannerPasswordRequest, *apiresource.EmptyResource]
type UpdateScannerPasswordRequest ¶
type UpdateScannerPasswordRequest struct {
// ID of the account user whose password is being changed.
//
// Must belong to the caller's account and hold a scanner role; requests targeting any other user are rejected.
AccountUserID string `json:"account_user_id" validate:"required"`
// The caller's own current password, used to confirm the caller's identity before the scanner password is changed.
RequesterPassword string `json:"requester_password" validate:"required,password,max=255" sensitive:"true"`
// New password to set for the scanner user.
NewPassword string `json:"new_password" validate:"required,password,max=255" sensitive:"true"`
}
Request to update a scanner-role account user's password.
func (*UpdateScannerPasswordRequest) SchemaExample ¶
func (*UpdateScannerPasswordRequest) SchemaExample() any