mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
feat(domain): introduce error slugs (#12030)
# Which Problems Are Solved As part of https://github.com/zitadel/zitadel/issues/11917 we want to introduce error slugs so (API) clients can rely on stable, machine-readable errors and act accordingly. # How the Problems Are Solved - Added a `NewSlug` helper function in the domain package. - Added `ErrorDetails` to the `ZitadelError` - Added an `zitadel.error.v2.ErrorDetail` proto message - Updated the connectRPC error interceptor to map new slug based errors to the new `ErrorDetail` - Defined some common slugs and error functions like internal errors - Defined (session) specific slugs used in the `DeleteSession` and `CheckUser` functions and replaced old implementations - Updated integration tests to check specific errors if the relation database feature is enabled - Updated doc and guideline to reflect the latest changes and decisions - Updated DeleteSession endpoint API to list possible slugs # Additional Changes None # Additional Context - closes #11957 --------- Co-authored-by: Wim Van Laer <[email protected]>
This commit is contained in:
co-authored by
Wim Van Laer
parent
5c9361f6c7
commit
a2bf528ca0
@@ -8,6 +8,64 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func NewSlug(resource, cause string) zerrors.Slug {
|
||||
return zerrors.Slug(fmt.Sprintf("%s.%s", resource, cause))
|
||||
}
|
||||
|
||||
var (
|
||||
// SlugInternalError is a general slug for any internal error, where the client doesn't have any influence on the error.
|
||||
// It's returned when an unexpected condition in the server occurs, such as a database error, an external service failure, or any other error that is not caused by the client's request.
|
||||
// The error details might contain additional information.
|
||||
SlugInternalError = NewSlug("zitadel", "internal_error")
|
||||
|
||||
// SlugRequestInvalid is a general slug for any request containing missing, malformed or otherwise invalid parameters.
|
||||
// The details typically contain additional information on how to resolve the problem.
|
||||
SlugRequestInvalid = NewSlug("request", "invalid")
|
||||
|
||||
// SlugAuthMissingPermission is a general slug for any authorization error where the user is missing a required permission to perform an action.
|
||||
// The details typically contain the necessary required permission.
|
||||
SlugAuthMissingPermission = NewSlug("auth", "missing_permission")
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrIDMissing is an error that can be returned on any resource if the necessary (resource) ID is missing
|
||||
ErrIDMissing = func() error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindInvalidArgument, nil, string(SlugRequestInvalid), "validation failed: id is required", 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"id": "required"})
|
||||
}
|
||||
|
||||
// ErrInstanceIDMissing is an error that can be returned on any resource if the necessary instance ID is missing
|
||||
ErrInstanceIDMissing = func() error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindInvalidArgument, nil, string(SlugRequestInvalid), "validation failed: instance_id is required", 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"instance_id": "required"})
|
||||
}
|
||||
|
||||
// ErrInvalidRequest is a general error for any invalid request type, like missing or wrong parameters.
|
||||
ErrInvalidRequest = func(message string) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindInvalidArgument, nil, string(SlugRequestInvalid), message, 1)
|
||||
}
|
||||
|
||||
// ErrInternal is a general error for any internal error, where the client doesn't have any influence on the error.
|
||||
// This error should be used for any error that is not caused by the client's request, but rather by an unexpected condition in the server.
|
||||
ErrInternal = func(err error, message string) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindInternal, err, string(SlugInternalError), message, 1)
|
||||
}
|
||||
|
||||
// ErrMoreThanOneRowAffected is an error that can be returned when a database operation affects more rows than expected,
|
||||
// which could indicate a potential issue with the query or the data integrity.
|
||||
ErrMoreThanOneRowAffected = func(message string, rows int64) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindInternal, nil, string(SlugInternalError), message, 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"rows": rows})
|
||||
}
|
||||
|
||||
// ErrAuthMissingPermission is an error that can be returned when a user tries to perform an action that requires a specific permission,
|
||||
// but the user does not have that permission.
|
||||
ErrAuthMissingPermission = func(err error, message, permission string) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindPermissionDenied, err, string(SlugAuthMissingPermission), message, 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"permission": permission})
|
||||
}
|
||||
)
|
||||
|
||||
type wrongIDPTypeError struct {
|
||||
expected IDPType
|
||||
got string
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
@@ -123,3 +124,32 @@ type sessionChanges interface {
|
||||
// SetMetadata adds or updates the metadata of the session.
|
||||
SetMetadata(metadata []*SessionMetadata) database.Change
|
||||
}
|
||||
|
||||
var (
|
||||
// SlugSessionNotFound is a slug used whenever a session is not found by the requested id.
|
||||
SlugSessionNotFound = NewSlug("session", "not_found")
|
||||
|
||||
// SlugSessionUserChange is a slug used when trying to change the user of an already authenticated session, which is not allowed.
|
||||
SlugSessionUserChange = NewSlug("session", "user_change")
|
||||
|
||||
// SlugSessionTokenInvalid is a slug used when the provided session token is invalid, either because it is malformed, expired or does not match the session.
|
||||
SlugSessionTokenInvalid = NewSlug("session", "token_invalid")
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrSessionNotFound is an error that can be returned when a session with the requested id was not found.
|
||||
ErrSessionNotFound = func(err error, id string) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindNotFound, err, string(SlugSessionNotFound), "session was not found", 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"id": id})
|
||||
}
|
||||
|
||||
// ErrSessionUserChange is an error that can be returned when trying to change the user of an already authenticated session, which is not allowed.
|
||||
ErrSessionUserChange = func() error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindInvalidArgument, nil, string(SlugSessionUserChange), "session was already authenticated with another user, you cannot change it to a different one", 1)
|
||||
}
|
||||
|
||||
// ErrSessionTokenInvalid is an error that can be returned whenever the provided (session) token is invalid for the intended session.
|
||||
ErrSessionTokenInvalid = func(err error) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindPermissionDenied, err, string(SlugSessionTokenInvalid), "The provided session token is invalid: either the token is malformed, expired or does not match the session", 1)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -82,13 +82,13 @@ func (u *UserCheckCommand) Execute(ctx context.Context, opts *InvokeOpts) (err e
|
||||
session, err := sessionRepo.Get(ctx, opts.DB(), database.WithCondition(sessionRepo.IDCondition(u.SessionID)))
|
||||
if err != nil {
|
||||
if errors.Is(err, &database.NoRowFoundError{}) {
|
||||
return zerrors.ThrowNotFound(err, "DOM-rbdCv3", "session not found")
|
||||
return ErrSessionNotFound(err, u.SessionID) // TODO: not found vs precondition failed
|
||||
}
|
||||
return zerrors.ThrowInternal(err, "DOM-To1rLz", "failed fetching session")
|
||||
return ErrInternal(err, "failed to fetch the session")
|
||||
}
|
||||
|
||||
if session.UserID != "" && u.FetchedUser.ID != "" && session.UserID != u.FetchedUser.ID {
|
||||
return zerrors.ThrowInvalidArgument(nil, "DOM-78g1TV", "user change not possible")
|
||||
return ErrSessionUserChange()
|
||||
}
|
||||
userFactor := &SessionFactorUser{
|
||||
UserID: u.FetchedUser.ID,
|
||||
@@ -97,16 +97,14 @@ func (u *UserCheckCommand) Execute(ctx context.Context, opts *InvokeOpts) (err e
|
||||
|
||||
updateCount, err := sessionRepo.Update(ctx, opts.DB(), sessionRepo.IDCondition(session.ID), sessionRepo.SetFactor(userFactor))
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "DOM-netNam", "failed updating session")
|
||||
return ErrInternal(err, "failed to update the session")
|
||||
}
|
||||
|
||||
if updateCount == 0 {
|
||||
err = zerrors.ThrowNotFound(nil, "DOM-FszyWS", "session not found")
|
||||
return err
|
||||
return ErrSessionNotFound(err, u.SessionID) // TODO: not found vs precondition failed vs internal
|
||||
}
|
||||
if updateCount > 1 {
|
||||
err = zerrors.ThrowInternal(NewMultipleObjectsUpdatedError(1, updateCount), "DOM-SsIwDt", "unexpected number of rows updated")
|
||||
return err
|
||||
return ErrMoreThanOneRowAffected("unexpected number of rows updated", updateCount)
|
||||
}
|
||||
|
||||
u.UserCheckedAt = userFactor.LastVerifiedAt
|
||||
@@ -126,37 +124,41 @@ func (u *UserCheckCommand) Validate(ctx context.Context, opts *InvokeOpts) (err
|
||||
}
|
||||
|
||||
if u.SessionID == "" {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "DOM-00o0ys", "Errors.Missing.SessionID")
|
||||
return ErrIDMissing() // TODO: precondition failed vs invalid argument
|
||||
}
|
||||
if u.InstanceID == "" {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "DOM-Oe1dtz", "Errors.Missing.InstanceID")
|
||||
return ErrInstanceIDMissing() // TODO: precondition failed vs invalid argument
|
||||
}
|
||||
|
||||
if authZErr := opts.Permissions.CheckSessionPermission(ctx, SessionWritePermission, u.SessionID); authZErr != nil {
|
||||
// TODO: return a more specific error once permissions are implemented?
|
||||
return zerrors.ThrowPermissionDenied(authZErr, "DOM-4qz3mt", "Errors.PermissionDenied")
|
||||
}
|
||||
|
||||
var usrQueryOpt database.QueryOption
|
||||
var query string
|
||||
userRepo := opts.userRepo
|
||||
|
||||
if loginName := u.InputCheckUser.LoginName; loginName != "" {
|
||||
usrQueryOpt = database.WithCondition(userRepo.LoginNameCondition(database.TextOperationEqual, loginName))
|
||||
query = loginName
|
||||
} else if userID := u.InputCheckUser.UserID; userID != "" {
|
||||
usrQueryOpt = database.WithCondition(userRepo.IDCondition(userID))
|
||||
query = userID
|
||||
} else {
|
||||
return zerrors.ThrowInvalidArgument(nil, "DOM-7B2m0b", "no valid query option")
|
||||
return ErrInvalidRequest("either login_name or user_id is required")
|
||||
}
|
||||
|
||||
usr, err := userRepo.Get(ctx, opts.DB(), usrQueryOpt)
|
||||
if err != nil {
|
||||
if errors.Is(err, &database.NoRowFoundError{}) {
|
||||
return zerrors.ThrowNotFound(err, "DOM-lcZeXI", "user not found")
|
||||
return ErrUserNotFound(err, query)
|
||||
}
|
||||
return zerrors.ThrowInternal(err, "DOM-Y846I0", "failed fetching user")
|
||||
return ErrInternal(err, "failed to fetch the user")
|
||||
}
|
||||
|
||||
if usr.State != UserStateActive {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "DOM-vgDIu9", "Errors.User.NotActive")
|
||||
return ErrUserNotActive(usr.ID, "user must be active for sign in")
|
||||
}
|
||||
|
||||
u.FetchedUser = *usr
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestUserCheckCommand_Validate(t *testing.T) {
|
||||
cmd: &domain.UserCheckCommand{
|
||||
InputCheckUser: &domain.CheckUserType{UserID: "user-123"},
|
||||
},
|
||||
expectedError: zerrors.ThrowPreconditionFailed(nil, "DOM-00o0ys", "Errors.Missing.SessionID"),
|
||||
expectedError: domain.ErrIDMissing(),
|
||||
},
|
||||
{
|
||||
testName: "when instance ID is not set should return error",
|
||||
@@ -51,7 +51,7 @@ func TestUserCheckCommand_Validate(t *testing.T) {
|
||||
InputCheckUser: &domain.CheckUserType{UserID: "user-123"},
|
||||
SessionID: "session-1",
|
||||
},
|
||||
expectedError: zerrors.ThrowPreconditionFailed(nil, "DOM-Oe1dtz", "Errors.Missing.InstanceID"),
|
||||
expectedError: domain.ErrInstanceIDMissing(),
|
||||
},
|
||||
{
|
||||
testName: "when permission check fails should return permission denied error",
|
||||
@@ -140,7 +140,7 @@ func TestUserCheckCommand_Validate(t *testing.T) {
|
||||
SessionID: "session-1",
|
||||
InstanceID: "instance-1",
|
||||
},
|
||||
expectedError: zerrors.ThrowPreconditionFailed(nil, "DOM-vgDIu9", "Errors.User.NotActive"),
|
||||
expectedError: domain.ErrUserNotActive("user-123", ""),
|
||||
},
|
||||
{
|
||||
testName: "when user retrieval fails should return error",
|
||||
@@ -171,7 +171,7 @@ func TestUserCheckCommand_Validate(t *testing.T) {
|
||||
SessionID: "session-1",
|
||||
InstanceID: "instance-1",
|
||||
},
|
||||
expectedError: zerrors.ThrowInternal(getErr, "DOM-Y846I0", "failed fetching user"),
|
||||
expectedError: domain.ErrInternal(getErr, ""),
|
||||
},
|
||||
{
|
||||
testName: "when user not found should return not found error",
|
||||
@@ -202,7 +202,7 @@ func TestUserCheckCommand_Validate(t *testing.T) {
|
||||
SessionID: "session-1",
|
||||
InstanceID: "instance-1",
|
||||
},
|
||||
expectedError: zerrors.ThrowNotFound(notFoundErr, "DOM-lcZeXI", "user not found"),
|
||||
expectedError: domain.ErrUserNotFound(notFoundErr, "user-123"),
|
||||
},
|
||||
{
|
||||
testName: "when search type is LoginName should attempt to fetch by login name",
|
||||
@@ -257,7 +257,7 @@ func TestUserCheckCommand_Validate(t *testing.T) {
|
||||
SessionID: "session-1",
|
||||
InstanceID: "instance-1",
|
||||
},
|
||||
expectedError: zerrors.ThrowInvalidArgumentf(nil, "DOM-7B2m0b", "no valid query option"),
|
||||
expectedError: domain.ErrInvalidRequest(""),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ func TestUserCheckCommand_Execute(t *testing.T) {
|
||||
OrganizationID: "org-1",
|
||||
},
|
||||
},
|
||||
expectedError: zerrors.ThrowInternal(getErr, "DOM-To1rLz", "failed fetching session"),
|
||||
expectedError: domain.ErrInternal(getErr, ""),
|
||||
},
|
||||
{
|
||||
testName: "when session not found should return not found error",
|
||||
@@ -357,7 +357,7 @@ func TestUserCheckCommand_Execute(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: zerrors.ThrowNotFound(sessionNotFoundErr, "DOM-rbdCv3", "session not found"),
|
||||
expectedError: domain.ErrSessionNotFound(sessionNotFoundErr, "session-1"),
|
||||
},
|
||||
{
|
||||
testName: "when user change is attempted should return invalid argument error",
|
||||
@@ -385,7 +385,7 @@ func TestUserCheckCommand_Execute(t *testing.T) {
|
||||
OrganizationID: "org-1",
|
||||
},
|
||||
},
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-78g1TV", "user change not possible"),
|
||||
expectedError: domain.ErrSessionUserChange(),
|
||||
},
|
||||
{
|
||||
testName: "when session update fails should return error",
|
||||
@@ -421,7 +421,7 @@ func TestUserCheckCommand_Execute(t *testing.T) {
|
||||
OrganizationID: "org-1",
|
||||
},
|
||||
},
|
||||
expectedError: zerrors.ThrowInternal(updateErr, "DOM-netNam", "failed updating session"),
|
||||
expectedError: domain.ErrInternal(updateErr, "failed to update the session"),
|
||||
},
|
||||
{
|
||||
testName: "when session update returns no rows should return not found error",
|
||||
@@ -457,7 +457,7 @@ func TestUserCheckCommand_Execute(t *testing.T) {
|
||||
OrganizationID: "org-1",
|
||||
},
|
||||
},
|
||||
expectedError: zerrors.ThrowNotFound(nil, "DOM-FszyWS", "session not found"),
|
||||
expectedError: domain.ErrSessionNotFound(nil, "session-1"),
|
||||
},
|
||||
{
|
||||
testName: "when session update returns multiple rows should return internal error",
|
||||
@@ -493,7 +493,7 @@ func TestUserCheckCommand_Execute(t *testing.T) {
|
||||
OrganizationID: "org-1",
|
||||
},
|
||||
},
|
||||
expectedError: zerrors.ThrowInternal(domain.NewMultipleObjectsUpdatedError(1, 2), "DOM-SsIwDt", "unexpected number of rows updated"),
|
||||
expectedError: domain.ErrMoreThanOneRowAffected("unexpected number of rows updated", 2),
|
||||
},
|
||||
{
|
||||
testName: "when session has no user and user is set should execute successfully",
|
||||
|
||||
@@ -3,6 +3,7 @@ package domain
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -10,7 +11,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/session"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type DeleteSessionCommand struct {
|
||||
@@ -49,14 +49,6 @@ func (cmd *DeleteSessionCommand) Events(ctx context.Context, opts *InvokeOpts) (
|
||||
}, nil
|
||||
}
|
||||
|
||||
const (
|
||||
ErrSessionTokenInvalid = "ErrSessionTokenInvalid"
|
||||
ErrMoreThanOneRowAffected = "ErrMoreThanOneRowAffected"
|
||||
ErrIDMissing = "ErrIDMissing"
|
||||
ErrMissingPermission = "ErrMissingPermission"
|
||||
ErrInternal = "ErrInternal"
|
||||
)
|
||||
|
||||
func (cmd *DeleteSessionCommand) sessionDeletePermissionCheckCondition(ctx context.Context, sessionRepo SessionRepository, decryptor SessionTokenDecryptor) (database.Condition, error) {
|
||||
if !cmd.MustCheckPermission {
|
||||
return nil, nil
|
||||
@@ -64,7 +56,7 @@ func (cmd *DeleteSessionCommand) sessionDeletePermissionCheckCondition(ctx conte
|
||||
if cmd.Token != "" {
|
||||
sessionID, tokenID, err := decryptor(ctx, cmd.Token)
|
||||
if err != nil || sessionID != cmd.ID {
|
||||
return nil, zerrors.ThrowPermissionDenied(err, ErrSessionTokenInvalid, "Errors.Session.Token.Invalid")
|
||||
return nil, ErrSessionTokenInvalid(err)
|
||||
}
|
||||
return database.Or(
|
||||
sessionRepo.TokenIDCondition(tokenID),
|
||||
@@ -93,14 +85,13 @@ func (cmd *DeleteSessionCommand) Execute(ctx context.Context, opts *InvokeOpts)
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, new(database.PermissionError)) {
|
||||
return zerrors.ThrowPermissionDenied(err, ErrMissingPermission,
|
||||
"insufficient permissions to delete session, require `session.delete` permission, ownership of the session or current session token")
|
||||
return ErrAuthMissingPermission(err, "insufficient permissions to delete session, require `session.delete` permission, ownership of the session or current session token", SessionDeletePermission)
|
||||
}
|
||||
return zerrors.ThrowInternal(err, ErrInternal, "an unexpected error occurred while deleting the session")
|
||||
return ErrInternal(err, "an unexpected error occurred while deleting the session")
|
||||
}
|
||||
|
||||
if deletedRows > 1 {
|
||||
return zerrors.ThrowInternalf(nil, ErrMoreThanOneRowAffected, "expected 1 session to be deleted, got %d", deletedRows)
|
||||
return ErrMoreThanOneRowAffected(fmt.Sprintf("expected 1 session to be deleted, got %d", deletedRows), deletedRows)
|
||||
}
|
||||
|
||||
cmd.DeletedAt = deletedAt
|
||||
@@ -116,7 +107,7 @@ func (*DeleteSessionCommand) String() string {
|
||||
// Validate implements [Commander].
|
||||
func (cmd *DeleteSessionCommand) Validate(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
if cmd.ID = strings.TrimSpace(cmd.ID); cmd.ID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, ErrIDMissing, "Errors.IDMissing")
|
||||
return ErrIDMissing()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
noopdb "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/noop"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
zdomain "github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestDeleteSessionCommand_Validate(t *testing.T) {
|
||||
@@ -44,7 +43,7 @@ func TestDeleteSessionCommand_Validate(t *testing.T) {
|
||||
sessionID: "",
|
||||
},
|
||||
fields: fields{},
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, domain.ErrIDMissing, "Errors.IDMissing"),
|
||||
expectedError: domain.ErrIDMissing(),
|
||||
},
|
||||
{
|
||||
name: "when sessionID is provided must validate successfully",
|
||||
@@ -208,7 +207,7 @@ func TestDeleteSessionCommand_Execute(t *testing.T) {
|
||||
mustCheckPermission: true,
|
||||
},
|
||||
res: res{
|
||||
error: new(database.PermissionError),
|
||||
error: domain.ErrAuthMissingPermission(nil, "", domain.SessionDeletePermission),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -230,7 +229,7 @@ func TestDeleteSessionCommand_Execute(t *testing.T) {
|
||||
sessionID: "session-1",
|
||||
},
|
||||
res: res{
|
||||
error: zerrors.ThrowInternalf(nil, domain.ErrMoreThanOneRowAffected, "expected 1 session to be deleted, got %d", 2),
|
||||
error: domain.ErrMoreThanOneRowAffected("expected 1 session to be deleted, got 2", 2),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -339,7 +338,7 @@ func mockSessionTokenDecryptor(expectedSessionToken, returnSessionID, returnSess
|
||||
return func(t *testing.T) domain.SessionTokenDecryptor {
|
||||
return func(ctx context.Context, sessionToken string) (sessionID, tokenID string, err error) {
|
||||
if sessionToken != expectedSessionToken {
|
||||
return "", "", zerrors.ThrowInvalidArgumentf(nil, "SESS-S3gq1", "Errors.Session.TokenInvalid")
|
||||
return "", "", domain.ErrSessionTokenInvalid(nil)
|
||||
}
|
||||
return returnSessionID, returnSessionToken, nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
@@ -252,3 +253,26 @@ type HumanRecoveryCodes struct {
|
||||
// It is reset to 0 on successful verification
|
||||
FailedAttempts uint8 `json:"failedAttempts,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
var (
|
||||
// SlugUserNotFound is the slug whenever a user is not found by the provided identifier.
|
||||
SlugUserNotFound = NewSlug("user", "not_found")
|
||||
|
||||
// SlugUserNotActive is the slug whenever the user requires to be in state "active", but isn't.
|
||||
SlugUserNotActive = NewSlug("user", "not_active")
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUserNotFound is an error that can be used when a user is not found by the provided identifier.
|
||||
ErrUserNotFound = func(err error, identifier string) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindNotFound, err, string(SlugUserNotFound), "user was not found", 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"identifier": identifier})
|
||||
}
|
||||
|
||||
// ErrUserNotActive is an error that can be returned when a user needs to be active for the operation,
|
||||
// e.g. sign in, reactivation, etc. but has a different state.
|
||||
ErrUserNotActive = func(id, message string) error {
|
||||
return zerrors.CreateZitadelError(zerrors.KindPreconditionFailed, nil, string(SlugUserNotActive), message, 1).
|
||||
WithDetails(zerrors.ErrorDetailsMap{"id": id})
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user