Rename user into identity

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-12-20 14:14:31 +01:00
parent fa0295f481
commit 0f7c755d53
35 changed files with 606 additions and 664 deletions

View File

@@ -38,12 +38,12 @@ func NewAccessManagementService(svc *Service) *AccessManagementService {
}
// Authorize implements Model 2 authorization:
// - principalID is the actor (User now; later service accounts)
// - credentialID is an optional credential (UserAPIKey now)
// - principalID is the actor (Identity now; later service accounts)
// - credentialID is an optional credential (PersonalAPIKey now)
// - intersection semantics: actor must be allowed AND credential (if present) must be allowed.
//
// Entity scope:
// - Global/self-owned entities (User/Session/UserAPIKey) are authorized via ownership checks only (no global admin).
// - Global/self-owned entities (Identity/Session/PersonalAPIKey) are authorized via ownership checks only (no global admin).
// - Organization-scoped entities are authorized via membership lookups that derive organization_id from entityID.
func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid.GID, credentialID *gid.GID, entityID gid.GID, action Action) error {
requiredRoles := GetPermissionsForAction(entityID.EntityType(), action)
@@ -53,7 +53,7 @@ func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid
}
switch principalID.EntityType() {
case coredata.UserEntityType:
case coredata.IdentityEntityType:
// ok
default:
return NewUnsupportedPrincipalTypeError(principalID.EntityType())
@@ -62,7 +62,7 @@ func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid
return s.pg.WithConn(ctx, func(conn pg.Conn) error {
// Global/self-owned path
switch entityID.EntityType() {
case coredata.UserEntityType:
case coredata.IdentityEntityType:
if entityID != principalID {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
@@ -73,17 +73,17 @@ func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid
if err := sess.LoadByID(ctx, conn, entityID); err != nil {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
if sess.UserID != principalID {
if sess.IdentityID != principalID {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
return nil
case coredata.UserAPIKeyEntityType:
key := &coredata.UserAPIKey{}
case coredata.PersonalAPIKeyEntityType:
key := &coredata.PersonalAPIKey{}
if err := key.LoadByID(ctx, conn, entityID); err != nil {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
if key.UserID != principalID {
if key.IdentityID != principalID {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
return nil
@@ -92,7 +92,7 @@ func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid
// Organization-scoped path (derive org via joins)
scope := coredata.NewScope(entityID.TenantID())
actorRoleName, err := s.loadUserRoleForEntity(ctx, conn, scope, principalID, entityID)
actorRoleName, err := s.loadIdentityRoleForEntity(ctx, conn, scope, principalID, entityID)
if err != nil || !requiredRoleNamesContain(actorRoleName, requiredRoles) {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
@@ -100,13 +100,13 @@ func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid
// Optional credential restriction (intersection)
if credentialID != nil {
switch credentialID.EntityType() {
case coredata.UserAPIKeyEntityType:
case coredata.PersonalAPIKeyEntityType:
// Defensive check: credential must belong to actor
apiKey := &coredata.UserAPIKey{}
apiKey := &coredata.PersonalAPIKey{}
if err := apiKey.LoadByID(ctx, conn, *credentialID); err != nil {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
if apiKey.UserID != principalID {
if apiKey.IdentityID != principalID {
return NewInsufficientPermissionsError(principalID, entityID, action)
}
@@ -123,15 +123,15 @@ func (s *AccessManagementService) Authorize(ctx context.Context, principalID gid
})
}
func (s *AccessManagementService) loadUserRoleForEntity(
func (s *AccessManagementService) loadIdentityRoleForEntity(
ctx context.Context,
conn pg.Conn,
scope coredata.Scoper,
userID gid.GID,
identityID gid.GID,
entityID gid.GID,
) (Role, error) {
var m coredata.Membership
if err := m.LoadRoleByUserAndEntityID(ctx, conn, scope, userID, entityID); err != nil {
if err := m.LoadRoleByIdentityAndEntityID(ctx, conn, scope, identityID, entityID); err != nil {
// Do not leak existence details
if errors.Is(err, coredata.ErrResourceNotFound) {
return "", err
@@ -148,7 +148,7 @@ func (s *AccessManagementService) loadAPIKeyRoleForEntity(
apiKeyID gid.GID,
entityID gid.GID,
) (Role, error) {
var akm coredata.UserAPIKeyMembership
var akm coredata.PersonalAPIKeyMembership
if err := akm.LoadRoleByAPIKeyAndEntityID(ctx, conn, scope, apiKeyID, entityID); err != nil {
return "", err
}
@@ -173,35 +173,3 @@ func requiredRoleNamesContain(roleName Role, required []Role) bool {
}
return false
}
// func (s AccountService) AllAccessibleTenants(ctx context.Context, identityID gid.GID) ([]gid.TenantID, error) {
// var tenants []gid.TenantID
// err := s.pg.WithConn(
// ctx,
// func(conn pg.Conn) error {
// memberships := coredata.Memberships{}
// orderBy := page.OrderBy[coredata.MembershipOrderField]{
// Field: coredata.MembershipOrderFieldCreatedAt,
// Direction: page.OrderDirectionDesc,
// }
// cursor := page.NewCursor(1000, nil, page.Head, orderBy)
// err := memberships.LoadByUserID(ctx, conn, coredata.NewNoScope(), identityID, cursor)
// if err != nil {
// return fmt.Errorf("cannot load memberships: %w", err)
// }
// for _, membership := range memberships {
// tenants = append(tenants, membership.ID.TenantID())
// }
// return nil
// },
// )
// if err != nil {
// return nil, err
// }
// return tenants, nil
// }

View File

@@ -35,7 +35,7 @@ type (
*Service
}
UserAPIKeyTokenData struct {
PersonalAPIKeyTokenData struct {
Version int `json:"v"`
KeyID gid.GID `json:"kid"`
PrincipalID gid.GID `json:"pid"`
@@ -43,8 +43,8 @@ type (
}
EmailConfirmationData struct {
UserID gid.GID `json:"uid"`
Email mail.Addr `json:"email"`
IdentityID gid.GID `json:"uid"`
Email mail.Addr `json:"email"`
}
)
@@ -78,7 +78,7 @@ func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req
s.tokenSecret,
TokenTypeEmailConfirmation,
24*time.Hour,
EmailConfirmationData{UserID: identityID, Email: req.NewEmail},
EmailConfirmationData{IdentityID: identityID, Email: req.NewEmail},
)
if err != nil {
return fmt.Errorf("cannot generate confirmation token: %w", err)
@@ -97,17 +97,17 @@ func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := &coredata.User{}
err := user.LoadByID(ctx, tx, identityID)
identity := &coredata.Identity{}
err := identity.LoadByID(ctx, tx, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(identityID)
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
isPasswordMatch, err := s.hp.ComparePasswordAndHash([]byte(req.Password), user.HashedPassword)
isPasswordMatch, err := s.hp.ComparePasswordAndHash([]byte(req.Password), identity.HashedPassword)
if err != nil {
return fmt.Errorf("cannot compare password: %w", err)
}
@@ -116,18 +116,18 @@ func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req
return NewInvalidPasswordError("invalid password")
}
user.EmailAddress = req.NewEmail
user.EmailAddressVerified = false
user.UpdatedAt = time.Now()
identity.EmailAddress = req.NewEmail
identity.EmailAddressVerified = false
identity.UpdatedAt = time.Now()
err = user.Update(ctx, tx)
err = identity.Update(ctx, tx)
if err != nil {
return fmt.Errorf("cannot update user: %w", err)
return fmt.Errorf("cannot update identity: %w", err)
}
subject, textBody, htmlBody, err := emails.RenderConfirmEmail(
s.baseURL,
user.FullName,
identity.FullName,
confirmationUrl,
)
if err != nil {
@@ -135,8 +135,8 @@ func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req
}
confirmationEmail := coredata.NewEmail(
user.FullName,
user.EmailAddress,
identity.FullName,
identity.EmailAddress,
subject,
textBody,
htmlBody,
@@ -161,30 +161,30 @@ func (s AccountService) VerifyEmail(ctx context.Context, token string) error {
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := &coredata.User{}
err := user.LoadByID(ctx, tx, payload.Data.UserID)
identity := &coredata.Identity{}
err := identity.LoadByID(ctx, tx, payload.Data.IdentityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(payload.Data.UserID)
return NewIdentityNotFoundError(payload.Data.IdentityID)
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
if user.EmailAddress != payload.Data.Email {
if identity.EmailAddress != payload.Data.Email {
return NewEmailVerificationMismatchError()
}
if user.EmailAddressVerified {
if identity.EmailAddressVerified {
return NewEmailAlreadyVerifiedError()
}
user.EmailAddressVerified = true
user.UpdatedAt = time.Now()
identity.EmailAddressVerified = true
identity.UpdatedAt = time.Now()
err = user.Update(ctx, tx)
err = identity.Update(ctx, tx)
if err != nil {
return fmt.Errorf("cannot update user: %w", err)
return fmt.Errorf("cannot update identity: %w", err)
}
return nil
@@ -205,16 +205,16 @@ func (s *AccountService) AcceptInvitation(
err := s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := coredata.User{}
identity := coredata.Identity{}
invitation := coredata.Invitation{}
err := user.LoadByID(ctx, tx, identityID)
err := identity.LoadByID(ctx, tx, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(identityID)
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
err = invitation.LoadByID(ctx, tx, coredata.NewNoScope(), invitationID)
@@ -226,7 +226,7 @@ func (s *AccountService) AcceptInvitation(
return fmt.Errorf("cannot load invitation: %w", err)
}
if invitation.Email != user.EmailAddress {
if invitation.Email != identity.EmailAddress {
return NewInvitationNotFoundError(invitationID)
}
@@ -243,7 +243,7 @@ func (s *AccountService) AcceptInvitation(
membership = &coredata.Membership{
ID: gid.New(tenantID, coredata.MembershipEntityType),
UserID: identityID,
IdentityID: identityID,
OrganizationID: invitation.OrganizationID,
Role: invitation.Role,
CreatedAt: now,
@@ -286,11 +286,11 @@ func (s *AccountService) ListPendingInvitations(
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
identity := coredata.User{}
identity := coredata.Identity{}
err := identity.LoadByID(ctx, conn, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(identityID)
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load identity: %w", err)
@@ -323,7 +323,7 @@ func (s *AccountService) CountPendingInvitations(
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
identity := coredata.User{}
identity := coredata.Identity{}
err := identity.LoadByID(ctx, conn, identityID)
if err != nil {
return fmt.Errorf("cannot load identity: %w", err)
@@ -357,7 +357,7 @@ func (s *AccountService) ListMemberships(
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
err := memberships.LoadByUserID(ctx, conn, coredata.NewNoScope(), identityID, cursor)
err := memberships.LoadByIdentityID(ctx, conn, coredata.NewNoScope(), identityID, cursor)
if err != nil {
return fmt.Errorf("cannot load memberships: %w", err)
}
@@ -383,7 +383,7 @@ func (s *AccountService) CountMemberships(
ctx,
func(conn pg.Conn) (err error) {
memberships := coredata.Memberships{}
count, err = memberships.CountByUserID(ctx, conn, identityID)
count, err = memberships.CountByIdentityID(ctx, conn, identityID)
if err != nil {
return fmt.Errorf("cannot count memberships: %w", err)
}
@@ -407,17 +407,17 @@ func (s AccountService) ChangePassword(ctx context.Context, identityID gid.GID,
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := &coredata.User{}
err := user.LoadByID(ctx, tx, identityID)
identity := &coredata.Identity{}
err := identity.LoadByID(ctx, tx, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(identityID)
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
isLegacyPasswordMatch, err := s.hp.ComparePasswordAndHash([]byte(req.CurrentPassword), user.HashedPassword)
isLegacyPasswordMatch, err := s.hp.ComparePasswordAndHash([]byte(req.CurrentPassword), identity.HashedPassword)
if err != nil {
return fmt.Errorf("cannot compare legacy password: %w", err)
}
@@ -431,15 +431,15 @@ func (s AccountService) ChangePassword(ctx context.Context, identityID gid.GID,
return fmt.Errorf("cannot hash new password: %w", err)
}
user.HashedPassword = newPasswordHash
user.UpdatedAt = time.Now()
identity.HashedPassword = newPasswordHash
identity.UpdatedAt = time.Now()
err = user.Update(ctx, tx)
err = identity.Update(ctx, tx)
if err != nil {
return fmt.Errorf("cannot update user: %w", err)
return fmt.Errorf("cannot update identity: %w", err)
}
// TODO: email to notify user that their password has been changed
// TODO: email to notify identity that their password has been changed
return nil
},
@@ -453,7 +453,7 @@ func (s AccountService) CountSessions(ctx context.Context, identityID gid.GID) (
ctx,
func(conn pg.Conn) (err error) {
sessions := coredata.Sessions{}
count, err = sessions.CountByUserID(ctx, conn, identityID)
count, err = sessions.CountByIdentityID(ctx, conn, identityID)
if err != nil {
return fmt.Errorf("cannot count sessions: %w", err)
}
@@ -475,7 +475,7 @@ func (s AccountService) ListSessions(
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
err := sessions.LoadByUserID(ctx, conn, identityID, cursor)
err := sessions.LoadByIdentityID(ctx, conn, identityID, cursor)
if err != nil {
return fmt.Errorf("cannot load sessions: %w", err)
}
@@ -491,19 +491,19 @@ func (s AccountService) ListSessions(
return page.NewPage(sessions, cursor), nil
}
func (s AccountService) GetIdentity(ctx context.Context, identityID gid.GID) (*coredata.User, error) {
user := &coredata.User{}
func (s AccountService) GetIdentity(ctx context.Context, identityID gid.GID) (*coredata.Identity, error) {
identity := &coredata.Identity{}
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
err := user.LoadByID(ctx, conn, identityID)
err := identity.LoadByID(ctx, conn, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(identityID)
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
return nil
@@ -513,20 +513,20 @@ func (s AccountService) GetIdentity(ctx context.Context, identityID gid.GID) (*c
return nil, err
}
return user, nil
return identity, nil
}
func (s AccountService) ListPersonalAPIKeys(
ctx context.Context,
identityID gid.GID,
cursor *page.Cursor[coredata.UserAPIKeyOrderField],
) (*page.Page[*coredata.UserAPIKey, coredata.UserAPIKeyOrderField], error) {
var personalAccessTokens coredata.UserAPIKeys
cursor *page.Cursor[coredata.PersonalAPIKeyOrderField],
) (*page.Page[*coredata.PersonalAPIKey, coredata.PersonalAPIKeyOrderField], error) {
var personalAccessTokens coredata.PersonalAPIKeys
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
err := personalAccessTokens.LoadByUserID(ctx, conn, identityID)
err := personalAccessTokens.LoadByIdentityID(ctx, conn, identityID)
if err != nil {
return fmt.Errorf("cannot load personal access tokens: %w", err)
}
@@ -548,8 +548,8 @@ func (s AccountService) CountPersonalAPIKeys(ctx context.Context, identityID gid
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) (err error) {
personalAccessTokens := coredata.UserAPIKeys{}
count, err = personalAccessTokens.CountByUserID(ctx, conn, identityID)
personalAccessTokens := coredata.PersonalAPIKeys{}
count, err = personalAccessTokens.CountByIdentityID(ctx, conn, identityID)
if err != nil {
return fmt.Errorf("cannot count personal access tokens: %w", err)
}
@@ -561,10 +561,10 @@ func (s AccountService) CountPersonalAPIKeys(ctx context.Context, identityID gid
return count, err
}
func (s AccountService) GetIdentityForMembership(ctx context.Context, membershipID gid.GID) (*coredata.User, error) {
func (s AccountService) GetIdentityForMembership(ctx context.Context, membershipID gid.GID) (*coredata.Identity, error) {
var (
scope = coredata.NewScopeFromObjectID(membershipID)
identity = &coredata.User{}
identity = &coredata.Identity{}
)
err := s.pg.WithConn(
@@ -580,10 +580,10 @@ func (s AccountService) GetIdentityForMembership(ctx context.Context, membership
return fmt.Errorf("cannot load membership: %w", err)
}
err = identity.LoadByID(ctx, conn, membership.UserID)
err = identity.LoadByID(ctx, conn, membership.IdentityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(membership.UserID)
return NewIdentityNotFoundError(membership.IdentityID)
}
return fmt.Errorf("cannot load identity: %w", err)
@@ -605,10 +605,10 @@ func (s *AccountService) CreatePersonalAPIKey(
identityID gid.GID,
name string,
expiresAt time.Time,
) (*coredata.UserAPIKey, string, error) {
) (*coredata.PersonalAPIKey, string, error) {
var (
userAPIKey *coredata.UserAPIKey
token string
personalAPIKey *coredata.PersonalAPIKey
token string
)
err := s.pg.WithTx(
@@ -616,33 +616,33 @@ func (s *AccountService) CreatePersonalAPIKey(
func(tx pg.Conn) (err error) {
now := time.Now()
userAPIKey = &coredata.UserAPIKey{
ID: gid.New(gid.NilTenant, coredata.UserAPIKeyEntityType),
UserID: identityID,
Name: name,
ExpiresAt: expiresAt,
CreatedAt: now,
UpdatedAt: now,
personalAPIKey = &coredata.PersonalAPIKey{
ID: gid.New(gid.NilTenant, coredata.PersonalAPIKeyEntityType),
IdentityID: identityID,
Name: name,
ExpiresAt: expiresAt,
CreatedAt: now,
UpdatedAt: now,
}
if err := userAPIKey.Insert(ctx, tx); err != nil {
return fmt.Errorf("cannot insert user api key: %w", err)
if err := personalAPIKey.Insert(ctx, tx); err != nil {
return fmt.Errorf("cannot insert personal api key: %w", err)
}
token, err = statelesstoken.NewDeterministicToken(
s.tokenSecret,
TokenTypeAPIKey,
userAPIKey.ExpiresAt,
userAPIKey.CreatedAt,
UserAPIKeyTokenData{
personalAPIKey.ExpiresAt,
personalAPIKey.CreatedAt,
PersonalAPIKeyTokenData{
Version: 2,
KeyID: userAPIKey.ID,
KeyID: personalAPIKey.ID,
PrincipalID: identityID,
IssuedAt: userAPIKey.CreatedAt,
IssuedAt: personalAPIKey.CreatedAt,
},
)
if err != nil {
return fmt.Errorf("cannot generate user api key token: %w", err)
return fmt.Errorf("cannot generate personal api key token: %w", err)
}
return nil
@@ -653,34 +653,34 @@ func (s *AccountService) CreatePersonalAPIKey(
return nil, "", err
}
return userAPIKey, token, nil
return personalAPIKey, token, nil
}
func (s *AccountService) DeletePersonalAPIKey(
ctx context.Context,
identityID gid.GID,
userAPIKeyID gid.GID,
personalAPIKeyID gid.GID,
) error {
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
userAPIKey := &coredata.UserAPIKey{}
err := userAPIKey.LoadByID(ctx, tx, userAPIKeyID)
personalAPIKey := &coredata.PersonalAPIKey{}
err := personalAPIKey.LoadByID(ctx, tx, personalAPIKeyID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserAPIKeyNotFoundError(userAPIKeyID)
return NewPersonalAPIKeyNotFoundError(personalAPIKeyID)
}
return fmt.Errorf("cannot load user api key: %w", err)
return fmt.Errorf("cannot load personal api key: %w", err)
}
if userAPIKey.UserID != identityID {
return NewUserAPIKeyNotFoundError(userAPIKeyID)
if personalAPIKey.IdentityID != identityID {
return NewPersonalAPIKeyNotFoundError(personalAPIKeyID)
}
err = userAPIKey.Delete(ctx, tx)
err = personalAPIKey.Delete(ctx, tx)
if err != nil {
return fmt.Errorf("cannot delete user api key: %w", err)
return fmt.Errorf("cannot delete personal api key: %w", err)
}
return nil
@@ -699,7 +699,7 @@ func (s AccountService) ListOrganizations(ctx context.Context, identityID gid.GI
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
err := organizations.LoadByUserID(ctx, conn, coredata.NewNoScope(), identityID, cursor)
err := organizations.LoadByIdentityID(ctx, conn, coredata.NewNoScope(), identityID, cursor)
if err != nil {
return fmt.Errorf("cannot load organizations: %w", err)
}
@@ -714,35 +714,3 @@ func (s AccountService) ListOrganizations(ctx context.Context, identityID gid.GI
return organizations, nil
}
// func (s AccountService) AllAccessibleTenants(ctx context.Context, identityID gid.GID) ([]gid.TenantID, error) {
// var tenants []gid.TenantID
// err := s.pg.WithConn(
// ctx,
// func(conn pg.Conn) error {
// memberships := coredata.Memberships{}
// orderBy := page.OrderBy[coredata.MembershipOrderField]{
// Field: coredata.MembershipOrderFieldCreatedAt,
// Direction: page.OrderDirectionDesc,
// }
// cursor := page.NewCursor(1000, nil, page.Head, orderBy)
// err := memberships.LoadByUserID(ctx, conn, coredata.NewNoScope(), identityID, cursor)
// if err != nil {
// return fmt.Errorf("cannot load memberships: %w", err)
// }
// for _, membership := range memberships {
// tenants = append(tenants, membership.ID.TenantID())
// }
// return nil
// },
// )
// if err != nil {
// return nil, err
// }
// return tenants, nil
// }

View File

@@ -35,9 +35,9 @@ func NewAPIKeyService(svc *Service) *APIKeyService {
return &APIKeyService{Service: svc}
}
func (s *APIKeyService) GetAPIKey(ctx context.Context, keyID gid.GID) (*coredata.UserAPIKey, error) {
func (s *APIKeyService) GetAPIKey(ctx context.Context, keyID gid.GID) (*coredata.PersonalAPIKey, error) {
var (
apiKey = &coredata.UserAPIKey{}
apiKey = &coredata.PersonalAPIKey{}
now = time.Now()
)
@@ -46,12 +46,12 @@ func (s *APIKeyService) GetAPIKey(ctx context.Context, keyID gid.GID) (*coredata
func(tx pg.Conn) error {
if err := apiKey.LoadByID(ctx, tx, keyID); err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserAPIKeyNotFoundError(keyID)
return NewPersonalAPIKeyNotFoundError(keyID)
}
}
if apiKey.ExpireReason != nil {
return NewUserAPIKeyExpiredError(keyID)
return NewPersonalAPIKeyExpiredError(keyID)
}
if now.After(apiKey.ExpiresAt) {
@@ -60,10 +60,10 @@ func (s *APIKeyService) GetAPIKey(ctx context.Context, keyID gid.GID) (*coredata
apiKey.UpdatedAt = now
if err := apiKey.Update(ctx, tx); err != nil {
return fmt.Errorf("cannot update user api key: %w", err)
return fmt.Errorf("cannot update personal api key: %w", err)
}
return NewUserAPIKeyExpiredError(keyID)
return NewPersonalAPIKeyExpiredError(keyID)
}
return nil

View File

@@ -110,7 +110,7 @@ func (req CreateIdentityWithPasswordRequest) Validate() error {
func (s *AuthService) CreateIdentityFromInvitation(
ctx context.Context,
req *CreateIdentityFromInvitationRequest,
) (*coredata.User, *coredata.Session, error) {
) (*coredata.Identity, *coredata.Session, error) {
if err := req.Validate(); err != nil {
return nil, nil, fmt.Errorf("invalid request: %w", err)
}
@@ -123,7 +123,7 @@ func (s *AuthService) CreateIdentityFromInvitation(
var (
scope = coredata.NewScopeFromObjectID(payload.Data.InvitationID)
invitation = &coredata.Invitation{}
user = &coredata.User{}
identity = &coredata.Identity{}
session = &coredata.Session{}
now = time.Now()
)
@@ -153,8 +153,8 @@ func (s *AuthService) CreateIdentityFromInvitation(
return NewInvitationExpiredError(payload.Data.InvitationID)
}
user = &coredata.User{
ID: gid.New(gid.NilTenant, coredata.UserEntityType),
identity = &coredata.Identity{
ID: gid.New(gid.NilTenant, coredata.IdentityEntityType),
EmailAddress: invitation.Email,
HashedPassword: hashedPassword,
EmailAddressVerified: true,
@@ -163,16 +163,16 @@ func (s *AuthService) CreateIdentityFromInvitation(
UpdatedAt: now,
}
err = user.Insert(ctx, tx)
err = identity.Insert(ctx, tx)
if err != nil {
if err == coredata.ErrResourceAlreadyExists {
return NewUserAlreadyExistsError(invitation.Email)
return NewIdentityAlreadyExistsError(invitation.Email)
}
return fmt.Errorf("cannot insert user: %w", err)
return fmt.Errorf("cannot insert identity: %w", err)
}
session = coredata.NewRootSession(user.ID, coredata.AuthMethodPassword, s.sessionDuration)
session = coredata.NewRootSession(identity.ID, coredata.AuthMethodPassword, s.sessionDuration)
err = session.Insert(ctx, tx)
if err != nil {
return fmt.Errorf("cannot insert session: %w", err)
@@ -186,7 +186,7 @@ func (s *AuthService) CreateIdentityFromInvitation(
return nil, nil, err
}
return user, session, nil
return identity, session, nil
}
func (s AuthService) ResetPassword(
@@ -210,26 +210,26 @@ func (s AuthService) ResetPassword(
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := &coredata.User{}
err := user.LoadByEmail(ctx, tx, payload.Data.Email)
identity := &coredata.Identity{}
err := identity.LoadByEmail(ctx, tx, payload.Data.Email)
if err != nil {
if err == coredata.ErrResourceNotFound {
return nil // Don't leak information about non-existent users
return nil // Don't leak information about non-existent identities
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
user.HashedPassword = hashedPassword
user.UpdatedAt = time.Now()
identity.HashedPassword = hashedPassword
identity.UpdatedAt = time.Now()
err = user.Update(ctx, tx)
err = identity.Update(ctx, tx)
if err != nil {
if err == coredata.ErrResourceNotFound {
return nil // Don't leak information about non-existent users
return nil // Don't leak information about non-existent identities
}
return fmt.Errorf("cannot update user: %w", err)
return fmt.Errorf("cannot update identity: %w", err)
}
return nil
@@ -264,18 +264,18 @@ func (s AuthService) SendPasswordResetInstructionByEmail(
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := &coredata.User{}
if err := user.LoadByEmail(ctx, tx, email); err != nil {
identity := &coredata.Identity{}
if err := identity.LoadByEmail(ctx, tx, email); err != nil {
if err == coredata.ErrResourceNotFound {
return nil // Don't leak information about non-existent users
return nil // Don't leak information about non-existent identities
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
subject, textBody, htmlBody, err := emails.RenderPasswordReset(
s.baseURL,
user.FullName,
identity.FullName,
resetPasswordUrl,
)
if err != nil {
@@ -283,8 +283,8 @@ func (s AuthService) SendPasswordResetInstructionByEmail(
}
passwordResetEmail := coredata.NewEmail(
user.FullName,
user.EmailAddress,
identity.FullName,
identity.EmailAddress,
subject,
textBody,
htmlBody,
@@ -303,7 +303,7 @@ func (s AuthService) SendPasswordResetInstructionByEmail(
func (s AuthService) CreateIdentityWithPassword(
ctx context.Context,
req *CreateIdentityWithPasswordRequest,
) (*coredata.User, *coredata.Session, error) {
) (*coredata.Identity, *coredata.Session, error) {
if s.disableSignup { // TODO Rename this one to disableSignup
return nil, nil, NewErrSignupDisabled()
}
@@ -320,8 +320,8 @@ func (s AuthService) CreateIdentityWithPassword(
var (
now = time.Now()
user = &coredata.User{
ID: gid.New(gid.NilTenant, coredata.UserEntityType),
identity = &coredata.Identity{
ID: gid.New(gid.NilTenant, coredata.IdentityEntityType),
EmailAddress: req.Email,
HashedPassword: hashedPassword,
EmailAddressVerified: false,
@@ -330,14 +330,14 @@ func (s AuthService) CreateIdentityWithPassword(
UpdatedAt: now,
}
session = coredata.NewRootSession(user.ID, coredata.AuthMethodPassword, 24*time.Hour*7)
session = coredata.NewRootSession(identity.ID, coredata.AuthMethodPassword, 24*time.Hour*7)
)
confirmationToken, err := statelesstoken.NewToken(
s.tokenSecret,
TokenTypeEmailConfirmation,
24*time.Hour,
EmailConfirmationData{UserID: user.ID, Email: user.EmailAddress},
EmailConfirmationData{IdentityID: identity.ID, Email: identity.EmailAddress},
)
if err != nil {
return nil, nil, fmt.Errorf("cannot generate confirmation token: %w", err)
@@ -358,7 +358,7 @@ func (s AuthService) CreateIdentityWithPassword(
subject, textBody, htmlBody, err := emails.RenderConfirmEmail(
s.baseURL,
user.FullName,
identity.FullName,
confirmationUrl,
)
if err != nil {
@@ -366,8 +366,8 @@ func (s AuthService) CreateIdentityWithPassword(
}
confirmationEmail := coredata.NewEmail(
user.FullName,
user.EmailAddress,
identity.FullName,
identity.EmailAddress,
subject,
textBody,
htmlBody,
@@ -376,13 +376,13 @@ func (s AuthService) CreateIdentityWithPassword(
err = s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
err := user.Insert(ctx, tx)
err := identity.Insert(ctx, tx)
if err != nil {
if err == coredata.ErrResourceAlreadyExists {
return NewUserAlreadyExistsError(user.EmailAddress)
return NewIdentityAlreadyExistsError(identity.EmailAddress)
}
return fmt.Errorf("cannot insert user: %w", err)
return fmt.Errorf("cannot insert identity: %w", err)
}
if err := confirmationEmail.Insert(ctx, tx); err != nil {
@@ -397,16 +397,16 @@ func (s AuthService) CreateIdentityWithPassword(
},
)
return user, session, err
return identity, session, err
}
func (s AuthService) OpenSessionWithSAML(ctx context.Context, userID gid.GID, organizationID gid.GID) (*coredata.Session, error) {
func (s AuthService) OpenSessionWithSAML(ctx context.Context, identityID gid.GID, organizationID gid.GID) (*coredata.Session, error) {
session := &coredata.Session{}
err := s.pg.WithTx(
ctx,
func(conn pg.Conn) (err error) {
session = coredata.NewRootSession(userID, coredata.AuthMethodSAML, s.sessionDuration)
session = coredata.NewRootSession(identityID, coredata.AuthMethodSAML, s.sessionDuration)
err = session.Insert(ctx, conn)
if err != nil {
return fmt.Errorf("cannot insert session: %w", err)
@@ -423,7 +423,7 @@ func (s AuthService) OpenSessionWithSAML(ctx context.Context, userID gid.GID, or
return session, nil
}
func (s AuthService) OpenSessionWithPassword(ctx context.Context, email mail.Addr, password string) (*coredata.User, *coredata.Session, error) {
func (s AuthService) OpenSessionWithPassword(ctx context.Context, email mail.Addr, password string) (*coredata.Identity, *coredata.Session, error) {
v := validator.New()
v.Check(password, "password", PasswordValidator())
@@ -433,29 +433,29 @@ func (s AuthService) OpenSessionWithPassword(ctx context.Context, email mail.Add
}
var (
user = &coredata.User{}
session = &coredata.Session{}
identity = &coredata.Identity{}
session = &coredata.Session{}
)
err = s.pg.WithTx(
ctx,
func(conn pg.Conn) error {
err := user.LoadByEmail(ctx, conn, email)
err := identity.LoadByEmail(ctx, conn, email)
if err != nil {
// Do not leak information about non-existent users
// Do not leak information about non-existent identities
if err != coredata.ErrResourceNotFound {
return fmt.Errorf("cannot load user by email: %w", err)
return fmt.Errorf("cannot load identity by email: %w", err)
}
}
// Perform a password comparison even when the user does not exist to mitigate timing attacks
// Perform a password comparison even when the identity does not exist to mitigate timing attacks
// and prevent revealing account existence.
if user.ID == gid.Nil {
if identity.ID == gid.Nil {
s.hp.ComparePasswordAndHash([]byte(password+"qwertyuiop1234567890"), []byte("qwertyuiop1234567890"))
return NewInvalidCredentialsError("invalid email or password")
}
isPasswordMatch, err := s.hp.ComparePasswordAndHash([]byte(password), user.HashedPassword)
isPasswordMatch, err := s.hp.ComparePasswordAndHash([]byte(password), identity.HashedPassword)
if err != nil {
return fmt.Errorf("cannot verify password: %w", err)
}
@@ -464,7 +464,7 @@ func (s AuthService) OpenSessionWithPassword(ctx context.Context, email mail.Add
return NewInvalidCredentialsError("invalid email or password")
}
session = coredata.NewRootSession(user.ID, coredata.AuthMethodPassword, s.sessionDuration)
session = coredata.NewRootSession(identity.ID, coredata.AuthMethodPassword, s.sessionDuration)
err = session.Insert(ctx, conn)
if err != nil {
return fmt.Errorf("cannot insert session: %w", err)
@@ -474,5 +474,5 @@ func (s AuthService) OpenSessionWithPassword(ctx context.Context, email mail.Add
},
)
return user, session, err
return identity, session, err
}

View File

@@ -70,7 +70,7 @@ type AuthorizeParams struct {
// It combines self-management policies with role-based policies.
func (a *Authorizer) Authorize(ctx context.Context, params AuthorizeParams) error {
// Validate principal type
if params.Principal.EntityType() != coredata.UserEntityType {
if params.Principal.EntityType() != coredata.IdentityEntityType {
return NewUnsupportedPrincipalTypeError(params.Principal.EntityType())
}
@@ -135,7 +135,7 @@ func (a *Authorizer) loadRolePolicies(ctx context.Context, principalID gid.GID,
scope := coredata.NewScope(resourceID.TenantID())
var m coredata.Membership
if err := m.LoadRoleByUserAndEntityID(ctx, conn, scope, principalID, resourceID); err != nil {
if err := m.LoadRoleByIdentityAndEntityID(ctx, conn, scope, principalID, resourceID); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil // No membership = no role-based policies
}

View File

@@ -61,14 +61,14 @@ func (e ErrInvitationExpired) Error() string {
return fmt.Sprintf("invitation %q expired", e.InvitationID)
}
type ErrUserAlreadyExists struct{ EmailAddress mail.Addr }
type ErrIdentityAlreadyExists struct{ EmailAddress mail.Addr }
func NewUserAlreadyExistsError(emailAddress mail.Addr) error {
return &ErrUserAlreadyExists{EmailAddress: emailAddress}
func NewIdentityAlreadyExistsError(emailAddress mail.Addr) error {
return &ErrIdentityAlreadyExists{EmailAddress: emailAddress}
}
func (e ErrUserAlreadyExists) Error() string {
return fmt.Sprintf("user %q already exists", e.EmailAddress.String())
func (e ErrIdentityAlreadyExists) Error() string {
return fmt.Sprintf("identity %q already exists", e.EmailAddress.String())
}
type ErrEmailAlreadyVerified struct{ message string }
@@ -81,14 +81,14 @@ func (e ErrEmailAlreadyVerified) Error() string {
return e.message
}
type ErrUserNotFound struct{ UserID gid.GID }
type ErrIdentityNotFound struct{ IdentityID gid.GID }
func NewUserNotFoundError(userID gid.GID) error {
return &ErrUserNotFound{userID}
func NewIdentityNotFoundError(identityID gid.GID) error {
return &ErrIdentityNotFound{identityID}
}
func (e ErrUserNotFound) Error() string {
return fmt.Sprintf("user %q not found", e.UserID)
func (e ErrIdentityNotFound) Error() string {
return fmt.Sprintf("identity %q not found", e.IdentityID)
}
type ErrInvalidPassword struct{ message string }
@@ -168,16 +168,16 @@ func (e ErrSessionExpired) Error() string {
}
type ErrMembershipAlreadyExists struct {
UserID gid.GID
IdentityID gid.GID
OrganizationID gid.GID
}
func NewMembershipAlreadyExistsError(userID gid.GID, organizationID gid.GID) error {
return &ErrMembershipAlreadyExists{UserID: userID, OrganizationID: organizationID}
func NewMembershipAlreadyExistsError(identityID gid.GID, organizationID gid.GID) error {
return &ErrMembershipAlreadyExists{IdentityID: identityID, OrganizationID: organizationID}
}
func (e ErrMembershipAlreadyExists) Error() string {
return fmt.Sprintf("membership already exists for user %q in organization %q", e.UserID, e.OrganizationID)
return fmt.Sprintf("membership already exists for identity %q in organization %q", e.IdentityID, e.OrganizationID)
}
type ErrSAMLConfigurationNotFound struct{ ConfigID gid.GID }
@@ -190,24 +190,24 @@ func (e ErrSAMLConfigurationNotFound) Error() string {
return fmt.Sprintf("SAML configuration %q not found", e.ConfigID)
}
type ErrUserAPIKeyNotFound struct{ UserAPIKeyID gid.GID }
type ErrPersonalAPIKeyNotFound struct{ PersonalAPIKeyID gid.GID }
func NewUserAPIKeyNotFoundError(userAPIKeyID gid.GID) error {
return &ErrUserAPIKeyNotFound{UserAPIKeyID: userAPIKeyID}
func NewPersonalAPIKeyNotFoundError(personalAPIKeyID gid.GID) error {
return &ErrPersonalAPIKeyNotFound{PersonalAPIKeyID: personalAPIKeyID}
}
func (e ErrUserAPIKeyNotFound) Error() string {
return fmt.Sprintf("user API key %q not found", e.UserAPIKeyID)
func (e ErrPersonalAPIKeyNotFound) Error() string {
return fmt.Sprintf("personal API key %q not found", e.PersonalAPIKeyID)
}
type ErrUserAPIKeyExpired struct{ UserAPIKeyID gid.GID }
type ErrPersonalAPIKeyExpired struct{ PersonalAPIKeyID gid.GID }
func NewUserAPIKeyExpiredError(userAPIKeyID gid.GID) error {
return &ErrUserAPIKeyExpired{UserAPIKeyID: userAPIKeyID}
func NewPersonalAPIKeyExpiredError(personalAPIKeyID gid.GID) error {
return &ErrPersonalAPIKeyExpired{PersonalAPIKeyID: personalAPIKeyID}
}
func (e ErrUserAPIKeyExpired) Error() string {
return fmt.Sprintf("user API key %q expired", e.UserAPIKeyID)
func (e ErrPersonalAPIKeyExpired) Error() string {
return fmt.Sprintf("personal API key %q expired", e.PersonalAPIKeyID)
}
type ErrSAMLConfigurationDomainNotVerified struct{ ConfigID gid.GID }

View File

@@ -307,22 +307,22 @@ func (s *OrganizationService) InviteMember(
return fmt.Errorf("cannot load organization: %w", err)
}
user := &coredata.User{}
err = user.LoadByEmail(ctx, tx, emailAddress)
identity := &coredata.Identity{}
err = identity.LoadByEmail(ctx, tx, emailAddress)
if err != nil && err != coredata.ErrResourceNotFound {
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
userExists := user.ID != gid.Nil
if userExists {
identityExists := identity.ID != gid.Nil
if identityExists {
membership := &coredata.Membership{}
err = membership.LoadByUserAndOrg(ctx, tx, scope, user.ID, organizationID)
err = membership.LoadByIdentityAndOrg(ctx, tx, scope, identity.ID, organizationID)
if err != nil && err != coredata.ErrResourceNotFound {
return fmt.Errorf("cannot load membership: %w", err)
}
if membership.ID != gid.Nil {
return NewMembershipAlreadyExistsError(user.ID, organizationID)
return NewMembershipAlreadyExistsError(identity.ID, organizationID)
}
}
@@ -506,7 +506,7 @@ func (s *OrganizationService) CreateOrganization(
membership := &coredata.Membership{
ID: gid.New(tenantID, coredata.MembershipEntityType),
UserID: identityID,
IdentityID: identityID,
OrganizationID: organizationID,
Role: coredata.MembershipRoleOwner,
CreatedAt: now,

View File

@@ -413,7 +413,7 @@ var Permissions = map[uint16]map[Action][]Role{
ActionGetTrustCenterFile: EditRoles,
ActionDeleteTrustCenterFile: EditRoles,
},
coredata.UserEntityType: {
coredata.IdentityEntityType: {
ActionGet: NonEmployeeRoles,
},
coredata.MembershipEntityType: {

View File

@@ -171,10 +171,10 @@ func (s *Service) HandleAssertion(
ctx context.Context,
samlResponse string,
configID gid.GID,
) (*coredata.User, *coredata.Membership, error) {
) (*coredata.Identity, *coredata.Membership, error) {
var (
now = time.Now()
user = &coredata.User{}
identity = &coredata.Identity{}
membership = &coredata.Membership{}
)
@@ -251,12 +251,12 @@ func (s *Service) HandleAssertion(
return NewEmailDomainMismatchError(email, config.EmailDomain)
}
err = user.LoadByEmail(ctx, tx, email)
err = identity.LoadByEmail(ctx, tx, email)
if err == coredata.ErrResourceNotFound && !config.AutoSignupEnabled {
return NewSAMLAutoSignupDisabledError(config.ID)
} else if err == coredata.ErrResourceNotFound && config.AutoSignupEnabled {
*user = coredata.User{
ID: gid.New(gid.NilTenant, coredata.UserEntityType),
*identity = coredata.Identity{
ID: gid.New(gid.NilTenant, coredata.IdentityEntityType),
EmailAddress: email,
HashedPassword: nil,
EmailAddressVerified: true,
@@ -265,26 +265,26 @@ func (s *Service) HandleAssertion(
UpdatedAt: now,
}
err := user.Insert(ctx, tx)
err := identity.Insert(ctx, tx)
if err != nil {
return fmt.Errorf("cannot insert user: %w", err)
return fmt.Errorf("cannot insert identity: %w", err)
}
} else if err != nil {
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
} else {
user.SAMLSubject = &assertion.Subject.NameID.Value
user.FullName = fullname
user.EmailAddress = email
user.EmailAddressVerified = true
user.UpdatedAt = now
identity.SAMLSubject = &assertion.Subject.NameID.Value
identity.FullName = fullname
identity.EmailAddress = email
identity.EmailAddressVerified = true
identity.UpdatedAt = now
err = user.Update(ctx, tx)
err = identity.Update(ctx, tx)
if err != nil {
return fmt.Errorf("cannot update user: %w", err)
return fmt.Errorf("cannot update identity: %w", err)
}
}
err = membership.LoadByUserAndOrg(ctx, tx, coredata.NewNoScope(), user.ID, config.OrganizationID)
err = membership.LoadByIdentityAndOrg(ctx, tx, coredata.NewNoScope(), identity.ID, config.OrganizationID)
if err != nil && err != coredata.ErrResourceNotFound {
return fmt.Errorf("cannot load membership: %w", err)
}
@@ -293,7 +293,7 @@ func (s *Service) HandleAssertion(
if !isMember {
membership = &coredata.Membership{
ID: gid.New(config.ID.TenantID(), coredata.MembershipEntityType),
UserID: user.ID,
IdentityID: identity.ID,
OrganizationID: config.OrganizationID,
Role: coredata.MembershipRoleViewer,
CreatedAt: now,
@@ -324,7 +324,7 @@ func (s *Service) HandleAssertion(
return nil, nil, err
}
return user, membership, nil
return identity, membership, nil
}
func (s *Service) validateAssertion(assertion *saml.Assertion, config *coredata.SAMLConfiguration, now time.Time) error {

View File

@@ -129,14 +129,14 @@ func (s SessionService) RevokeSession(ctx context.Context, identityID gid.GID, s
return s.pg.WithTx(
ctx,
func(tx pg.Conn) error {
user := &coredata.User{}
err := user.LoadByID(ctx, tx, identityID)
identity := &coredata.Identity{}
err := identity.LoadByID(ctx, tx, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewUserNotFoundError(identityID)
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
session := &coredata.Session{}
@@ -150,7 +150,7 @@ func (s SessionService) RevokeSession(ctx context.Context, identityID gid.GID, s
}
// TODO: move to dedicated query instead of LoadByID
if session.UserID != identityID {
if session.IdentityID != identityID {
return NewSessionNotFoundError(sessionID)
}
@@ -192,7 +192,7 @@ func (s SessionService) RevokeAllSessions(ctx context.Context, currentSessionID
}
sessions := coredata.Sessions{}
count, err = sessions.ExpireAllForUserExceptOneSession(ctx, tx, session.UserID, session.ID)
count, err = sessions.ExpireAllForIdentityExceptOneSession(ctx, tx, session.IdentityID, session.ID)
if err != nil {
return fmt.Errorf("cannot expire all sessions: %w", err)
}
@@ -323,7 +323,7 @@ func (s SessionService) AssumeOrganizationSession(
var (
now = time.Now()
rootSession = &coredata.Session{}
user = &coredata.User{}
identity = &coredata.Identity{}
membership = &coredata.Membership{}
childSession = &coredata.Session{}
scope = coredata.NewScopeFromObjectID(organizationID)
@@ -348,12 +348,12 @@ func (s SessionService) AssumeOrganizationSession(
return NewSessionExpiredError(sessionID)
}
err = user.LoadByID(ctx, tx, rootSession.UserID)
err = identity.LoadByID(ctx, tx, rootSession.IdentityID)
if err != nil {
return fmt.Errorf("cannot load user: %w", err)
return fmt.Errorf("cannot load identity: %w", err)
}
err = membership.LoadByUserInOrganization(ctx, tx, rootSession.UserID, organizationID)
err = membership.LoadByIdentityInOrganization(ctx, tx, rootSession.IdentityID, organizationID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewMembershipNotFoundError(organizationID)
@@ -367,7 +367,7 @@ func (s SessionService) AssumeOrganizationSession(
tx,
scope,
organizationID,
user.EmailAddress.Domain(),
identity.EmailAddress.Domain(),
)
if err != nil && err != coredata.ErrResourceNotFound {
return fmt.Errorf("cannot load SAML configuration: %w", err)
@@ -389,7 +389,7 @@ func (s SessionService) AssumeOrganizationSession(
tenantID := scope.GetTenantID()
childSession = &coredata.Session{
ID: gid.New(tenantID, coredata.SessionEntityType),
UserID: rootSession.UserID,
IdentityID: rootSession.IdentityID,
TenantID: &tenantID,
MembershipID: &membership.ID,
ParentSessionID: &rootSession.ID,