mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 07:47:32 +00:00
chore: move the go code into a subfolder
This commit is contained in:
13
apps/api/internal/user/model/address.go
Normal file
13
apps/api/internal/user/model/address.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package model
|
||||
|
||||
import es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
|
||||
type Address struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Country string
|
||||
Locality string
|
||||
PostalCode string
|
||||
Region string
|
||||
StreetAddress string
|
||||
}
|
41
apps/api/internal/user/model/email.go
Normal file
41
apps/api/internal/user/model/email.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type Email struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
EmailAddress string
|
||||
IsEmailVerified bool
|
||||
}
|
||||
|
||||
type EmailCode struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Code *crypto.CryptoValue
|
||||
Expiry time.Duration
|
||||
}
|
||||
|
||||
func (e *Email) GenerateEmailCodeIfNeeded(emailGenerator crypto.Generator) (*EmailCode, error) {
|
||||
var emailCode *EmailCode
|
||||
if e.IsEmailVerified {
|
||||
return emailCode, nil
|
||||
}
|
||||
emailCode = new(EmailCode)
|
||||
return emailCode, emailCode.GenerateEmailCode(emailGenerator)
|
||||
}
|
||||
|
||||
func (code *EmailCode) GenerateEmailCode(emailGenerator crypto.Generator) error {
|
||||
emailCodeCrypto, _, err := crypto.NewCode(emailGenerator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
code.Code = emailCodeCrypto
|
||||
code.Expiry = emailGenerator.Expiry()
|
||||
return nil
|
||||
}
|
17
apps/api/internal/user/model/external_idp.go
Normal file
17
apps/api/internal/user/model/external_idp.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type ExternalIDP struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
IDPConfigID string
|
||||
UserID string
|
||||
DisplayName string
|
||||
}
|
||||
|
||||
func (idp *ExternalIDP) IsValid() bool {
|
||||
return idp.AggregateID != "" && idp.IDPConfigID != "" && idp.UserID != ""
|
||||
}
|
69
apps/api/internal/user/model/external_idp_view.go
Normal file
69
apps/api/internal/user/model/external_idp_view.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type ExternalIDPView struct {
|
||||
UserID string
|
||||
IDPConfigID string
|
||||
ExternalUserID string
|
||||
IDPName string
|
||||
UserDisplayName string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type ExternalIDPSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn ExternalIDPSearchKey
|
||||
Asc bool
|
||||
Queries []*ExternalIDPSearchQuery
|
||||
}
|
||||
|
||||
type ExternalIDPSearchKey int32
|
||||
|
||||
const (
|
||||
ExternalIDPSearchKeyUnspecified ExternalIDPSearchKey = iota
|
||||
ExternalIDPSearchKeyExternalUserID
|
||||
ExternalIDPSearchKeyUserID
|
||||
ExternalIDPSearchKeyIdpConfigID
|
||||
ExternalIDPSearchKeyResourceOwner
|
||||
ExternalIDPSearchKeyInstanceID
|
||||
ExternalIDPSearchKeyOwnerRemoved
|
||||
)
|
||||
|
||||
type ExternalIDPSearchQuery struct {
|
||||
Key ExternalIDPSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type ExternalIDPSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*ExternalIDPView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *ExternalIDPSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-3n8fM", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ExternalIDPSearchRequest) AppendUserQuery(userID string) {
|
||||
r.Queries = append(r.Queries, &ExternalIDPSearchQuery{Key: ExternalIDPSearchKeyUserID, Method: domain.SearchMethodEquals, Value: userID})
|
||||
}
|
59
apps/api/internal/user/model/notify_user.go
Normal file
59
apps/api/internal/user/model/notify_user.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type NotifyUser struct {
|
||||
ID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
UserName string
|
||||
PreferredLoginName string
|
||||
LoginNames []string
|
||||
FirstName string
|
||||
LastName string
|
||||
NickName string
|
||||
DisplayName string
|
||||
PreferredLanguage string
|
||||
Gender Gender
|
||||
LastEmail string
|
||||
VerifiedEmail string
|
||||
LastPhone string
|
||||
VerifiedPhone string
|
||||
PasswordSet bool
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type NotifyUserSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn NotifyUserSearchKey
|
||||
Asc bool
|
||||
Queries []*NotifyUserSearchQuery
|
||||
}
|
||||
|
||||
type NotifyUserSearchKey int32
|
||||
|
||||
const (
|
||||
NotifyUserSearchKeyUnspecified NotifyUserSearchKey = iota
|
||||
NotifyUserSearchKeyUserID
|
||||
NotifyUserSearchKeyResourceOwner
|
||||
NotifyUserSearchKeyInstanceID
|
||||
)
|
||||
|
||||
type NotifyUserSearchQuery struct {
|
||||
Key NotifyUserSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value string
|
||||
}
|
||||
|
||||
type NotifyUserSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*UserView
|
||||
}
|
24
apps/api/internal/user/model/otp.go
Normal file
24
apps/api/internal/user/model/otp.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package model
|
||||
|
||||
type MFAState int32
|
||||
|
||||
const (
|
||||
MFAStateUnspecified MFAState = iota
|
||||
MFAStateNotReady
|
||||
MFAStateReady
|
||||
)
|
||||
|
||||
type MultiFactor struct {
|
||||
Type MFAType
|
||||
State MFAState
|
||||
Attribute string
|
||||
ID string
|
||||
}
|
||||
|
||||
type MFAType int32
|
||||
|
||||
const (
|
||||
MFATypeUnspecified MFAType = iota
|
||||
MFATypeOTP
|
||||
MFATypeU2F
|
||||
)
|
35
apps/api/internal/user/model/password.go
Normal file
35
apps/api/internal/user/model/password.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type Password struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
SecretString string
|
||||
SecretCrypto *crypto.CryptoValue
|
||||
ChangeRequired bool
|
||||
}
|
||||
|
||||
type PasswordCode struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Code *crypto.CryptoValue
|
||||
Expiry time.Duration
|
||||
NotificationType NotificationType
|
||||
}
|
||||
|
||||
type NotificationType int32
|
||||
|
||||
const (
|
||||
NotificationTypeEmail NotificationType = iota
|
||||
NotificationTypeSms
|
||||
)
|
||||
|
||||
func (p *Password) IsValid() bool {
|
||||
return p.AggregateID != "" && p.SecretString != ""
|
||||
}
|
45
apps/api/internal/user/model/phone.go
Normal file
45
apps/api/internal/user/model/phone.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultRegion = "CH"
|
||||
)
|
||||
|
||||
type Phone struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
PhoneNumber string
|
||||
IsPhoneVerified bool
|
||||
}
|
||||
|
||||
type PhoneCode struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Code *crypto.CryptoValue
|
||||
Expiry time.Duration
|
||||
}
|
||||
|
||||
func (p *Phone) GeneratePhoneCodeIfNeeded(phoneGenerator crypto.Generator) (*PhoneCode, error) {
|
||||
var phoneCode *PhoneCode
|
||||
if p.IsPhoneVerified {
|
||||
return phoneCode, nil
|
||||
}
|
||||
phoneCode = new(PhoneCode)
|
||||
return phoneCode, phoneCode.GeneratePhoneCode(phoneGenerator)
|
||||
}
|
||||
|
||||
func (code *PhoneCode) GeneratePhoneCode(phoneGenerator crypto.Generator) error {
|
||||
phoneCodeCrypto, _, err := crypto.NewCode(phoneGenerator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
code.Code = phoneCodeCrypto
|
||||
code.Expiry = phoneGenerator.Expiry()
|
||||
return nil
|
||||
}
|
29
apps/api/internal/user/model/profile.go
Normal file
29
apps/api/internal/user/model/profile.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"golang.org/x/text/language"
|
||||
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type Profile struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
FirstName string
|
||||
LastName string
|
||||
NickName string
|
||||
DisplayName string
|
||||
PreferredLanguage language.Tag
|
||||
Gender Gender
|
||||
PreferredLoginName string
|
||||
LoginNames []string
|
||||
AvatarKey string
|
||||
}
|
||||
|
||||
func (p *Profile) IsValid() bool {
|
||||
return p.FirstName != "" && p.LastName != ""
|
||||
}
|
||||
|
||||
func (p *Profile) SetNamesAsDisplayname() {
|
||||
p.DisplayName = p.FirstName + " " + p.LastName
|
||||
}
|
19
apps/api/internal/user/model/refresh_token.go
Normal file
19
apps/api/internal/user/model/refresh_token.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type RefreshToken struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
TokenID string
|
||||
ApplicationID string
|
||||
UserAgentID string
|
||||
Audience []string
|
||||
Expiration time.Time
|
||||
Scopes []string
|
||||
PreferredLanguage string
|
||||
}
|
73
apps/api/internal/user/model/refresh_token_view.go
Normal file
73
apps/api/internal/user/model/refresh_token_view.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type RefreshTokenView struct {
|
||||
ID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
ClientID string
|
||||
UserAgentID string
|
||||
AuthMethodsReferences []string
|
||||
Audience []string
|
||||
AuthTime time.Time
|
||||
IdleExpiration time.Time
|
||||
Expiration time.Time
|
||||
Scopes []string
|
||||
Sequence uint64
|
||||
Token string
|
||||
Actor *domain.TokenActor
|
||||
}
|
||||
|
||||
type RefreshTokenSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn RefreshTokenSearchKey
|
||||
Asc bool
|
||||
Queries []*RefreshTokenSearchQuery
|
||||
}
|
||||
|
||||
type RefreshTokenSearchKey int32
|
||||
|
||||
const (
|
||||
RefreshTokenSearchKeyUnspecified RefreshTokenSearchKey = iota
|
||||
RefreshTokenSearchKeyRefreshTokenID
|
||||
RefreshTokenSearchKeyUserID
|
||||
RefreshTokenSearchKeyApplicationID
|
||||
RefreshTokenSearchKeyUserAgentID
|
||||
RefreshTokenSearchKeyExpiration
|
||||
RefreshTokenSearchKeyResourceOwner
|
||||
RefreshTokenSearchKeyInstanceID
|
||||
)
|
||||
|
||||
type RefreshTokenSearchQuery struct {
|
||||
Key RefreshTokenSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type RefreshTokenSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
Result []*RefreshTokenView
|
||||
}
|
||||
|
||||
func (r *RefreshTokenSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-M0fse", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
19
apps/api/internal/user/model/token.go
Normal file
19
apps/api/internal/user/model/token.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
TokenID string
|
||||
ApplicationID string
|
||||
UserAgentID string
|
||||
Audience []string
|
||||
Expiration time.Time
|
||||
Scopes []string
|
||||
PreferredLanguage string
|
||||
}
|
72
apps/api/internal/user/model/token_view.go
Normal file
72
apps/api/internal/user/model/token_view.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type TokenView struct {
|
||||
ID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
ApplicationID string
|
||||
UserAgentID string
|
||||
Audience []string
|
||||
Expiration time.Time
|
||||
Scopes []string
|
||||
Sequence uint64
|
||||
PreferredLanguage string
|
||||
RefreshTokenID string
|
||||
IsPAT bool
|
||||
Reason domain.TokenReason
|
||||
Actor *domain.TokenActor
|
||||
}
|
||||
|
||||
type TokenSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn TokenSearchKey
|
||||
Asc bool
|
||||
Queries []*TokenSearchQuery
|
||||
}
|
||||
|
||||
type TokenSearchKey int32
|
||||
|
||||
const (
|
||||
TokenSearchKeyUnspecified TokenSearchKey = iota
|
||||
TokenSearchKeyTokenID
|
||||
TokenSearchKeyUserID
|
||||
TokenSearchKeyRefreshTokenID
|
||||
TokenSearchKeyApplicationID
|
||||
TokenSearchKeyUserAgentID
|
||||
TokenSearchKeyExpiration
|
||||
TokenSearchKeyResourceOwner
|
||||
TokenSearchKeyInstanceID
|
||||
)
|
||||
|
||||
type TokenSearchQuery struct {
|
||||
Key TokenSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type TokenSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*Token
|
||||
}
|
||||
|
||||
func (r *TokenSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-M0fse", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
21
apps/api/internal/user/model/user_changes.go
Normal file
21
apps/api/internal/user/model/user_changes.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
type UserChanges struct {
|
||||
Changes []*UserChange
|
||||
LastSequence uint64
|
||||
}
|
||||
|
||||
type UserChange struct {
|
||||
ChangeDate *timestamppb.Timestamp `json:"changeDate,omitempty"`
|
||||
EventType string `json:"eventType,omitempty"`
|
||||
Sequence uint64 `json:"sequence,omitempty"`
|
||||
ModifierID string `json:"modifierUser,omitempty"`
|
||||
ModifierName string `json:"-"`
|
||||
ModifierLoginName string `json:"-"`
|
||||
ModifierAvatarURL string `json:"-"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
96
apps/api/internal/user/model/user_membership_view.go
Normal file
96
apps/api/internal/user/model/user_membership_view.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type UserMembershipView struct {
|
||||
UserID string
|
||||
MemberType MemberType
|
||||
AggregateID string
|
||||
//ObjectID differs from aggregate id if obejct is sub of an aggregate
|
||||
ObjectID string
|
||||
|
||||
Roles []string
|
||||
DisplayName string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
ResourceOwnerName string
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type MemberType int32
|
||||
|
||||
const (
|
||||
MemberTypeUnspecified MemberType = iota
|
||||
MemberTypeOrganisation
|
||||
MemberTypeProject
|
||||
MemberTypeProjectGrant
|
||||
MemberTypeIam
|
||||
)
|
||||
|
||||
type UserMembershipSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn UserMembershipSearchKey
|
||||
Asc bool
|
||||
Queries []*UserMembershipSearchQuery
|
||||
}
|
||||
|
||||
type UserMembershipSearchKey int32
|
||||
|
||||
const (
|
||||
UserMembershipSearchKeyUnspecified UserMembershipSearchKey = iota
|
||||
UserMembershipSearchKeyUserID
|
||||
UserMembershipSearchKeyMemberType
|
||||
UserMembershipSearchKeyAggregateID
|
||||
UserMembershipSearchKeyObjectID
|
||||
UserMembershipSearchKeyResourceOwner
|
||||
UserMembershipSearchKeyInstanceID
|
||||
)
|
||||
|
||||
type UserMembershipSearchQuery struct {
|
||||
Key UserMembershipSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type UserMembershipSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*UserMembershipView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *UserMembershipSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-288fJ", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UserMembershipSearchRequest) GetSearchQuery(key UserMembershipSearchKey) (int, *UserMembershipSearchQuery) {
|
||||
for i, q := range r.Queries {
|
||||
if q.Key == key {
|
||||
return i, q
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (r *UserMembershipSearchRequest) AppendResourceOwnerAndIamQuery(orgID, iamID string) {
|
||||
r.Queries = append(r.Queries, &UserMembershipSearchQuery{Key: UserMembershipSearchKeyResourceOwner, Method: domain.SearchMethodIsOneOf, Value: []string{orgID, iamID}})
|
||||
}
|
||||
|
||||
func (r *UserMembershipSearchRequest) AppendUserIDQuery(userID string) {
|
||||
r.Queries = append(r.Queries, &UserMembershipSearchQuery{Key: UserMembershipSearchKeyUserID, Method: domain.SearchMethodEquals, Value: userID})
|
||||
}
|
74
apps/api/internal/user/model/user_session_view.go
Normal file
74
apps/api/internal/user/model/user_session_view.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type UserSessionView struct {
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
State domain.UserSessionState
|
||||
ResourceOwner string
|
||||
UserAgentID string
|
||||
UserID string
|
||||
UserName string
|
||||
LoginName string
|
||||
DisplayName string
|
||||
AvatarKey string
|
||||
SelectedIDPConfigID string
|
||||
PasswordVerification time.Time
|
||||
PasswordlessVerification time.Time
|
||||
ExternalLoginVerification time.Time
|
||||
SecondFactorVerification time.Time
|
||||
SecondFactorVerificationType domain.MFAType
|
||||
MultiFactorVerification time.Time
|
||||
MultiFactorVerificationType domain.MFAType
|
||||
Sequence uint64
|
||||
ID string
|
||||
}
|
||||
|
||||
type UserSessionSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn UserSessionSearchKey
|
||||
Asc bool
|
||||
Queries []*UserSessionSearchQuery
|
||||
}
|
||||
|
||||
type UserSessionSearchKey int32
|
||||
|
||||
const (
|
||||
UserSessionSearchKeyUnspecified UserSessionSearchKey = iota
|
||||
UserSessionSearchKeyUserAgentID
|
||||
UserSessionSearchKeyUserID
|
||||
UserSessionSearchKeyState
|
||||
UserSessionSearchKeyResourceOwner
|
||||
UserSessionSearchKeyInstanceID
|
||||
UserSessionSearchKeyOwnerRemoved
|
||||
)
|
||||
|
||||
type UserSessionSearchQuery struct {
|
||||
Key UserSessionSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type UserSessionSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*UserSessionView
|
||||
}
|
||||
|
||||
func (r *UserSessionSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-27ifs", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
310
apps/api/internal/user/model/user_view.go
Normal file
310
apps/api/internal/user/model/user_view.go
Normal file
@@ -0,0 +1,310 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type UserView struct {
|
||||
ID string
|
||||
UserName string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
State UserState
|
||||
Sequence uint64
|
||||
ResourceOwner string
|
||||
LastLogin time.Time
|
||||
PreferredLoginName string
|
||||
LoginNames []string
|
||||
*MachineView
|
||||
*HumanView
|
||||
}
|
||||
|
||||
type HumanView struct {
|
||||
PasswordSet bool
|
||||
PasswordInitRequired bool
|
||||
PasswordChangeRequired bool
|
||||
UsernameChangeRequired bool
|
||||
PasswordChanged time.Time
|
||||
FirstName string
|
||||
LastName string
|
||||
NickName string
|
||||
DisplayName string
|
||||
AvatarKey string
|
||||
PreferredLanguage string
|
||||
Gender Gender
|
||||
Email string
|
||||
IsEmailVerified bool
|
||||
VerifiedEmail string
|
||||
Phone string
|
||||
IsPhoneVerified bool
|
||||
Country string
|
||||
Locality string
|
||||
PostalCode string
|
||||
Region string
|
||||
StreetAddress string
|
||||
OTPState MFAState
|
||||
OTPSMSAdded bool
|
||||
OTPEmailAdded bool
|
||||
U2FTokens []*WebAuthNView
|
||||
PasswordlessTokens []*WebAuthNView
|
||||
MFAMaxSetUp domain.MFALevel
|
||||
MFAInitSkipped time.Time
|
||||
InitRequired bool
|
||||
PasswordlessInitRequired bool
|
||||
}
|
||||
|
||||
type WebAuthNView struct {
|
||||
TokenID string
|
||||
Name string
|
||||
State MFAState
|
||||
}
|
||||
|
||||
type MachineView struct {
|
||||
LastKeyAdded time.Time
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
type UserSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn UserSearchKey
|
||||
Asc bool
|
||||
Queries []*UserSearchQuery
|
||||
}
|
||||
|
||||
type UserSearchKey int32
|
||||
|
||||
const (
|
||||
UserSearchKeyUnspecified UserSearchKey = iota
|
||||
UserSearchKeyUserID
|
||||
UserSearchKeyUserName
|
||||
UserSearchKeyFirstName
|
||||
UserSearchKeyLastName
|
||||
UserSearchKeyNickName
|
||||
UserSearchKeyDisplayName
|
||||
UserSearchKeyEmail
|
||||
UserSearchKeyState
|
||||
UserSearchKeyResourceOwner
|
||||
UserSearchKeyLoginNames
|
||||
UserSearchKeyType
|
||||
UserSearchKeyPreferredLoginName
|
||||
UserSearchKeyInstanceID
|
||||
UserSearchOwnerRemoved
|
||||
)
|
||||
|
||||
type UserSearchQuery struct {
|
||||
Key UserSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type UserSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*UserView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
type UserState int32
|
||||
|
||||
const (
|
||||
UserStateUnspecified UserState = iota
|
||||
UserStateActive
|
||||
UserStateInactive
|
||||
UserStateDeleted
|
||||
UserStateLocked
|
||||
UserStateSuspend
|
||||
UserStateInitial
|
||||
)
|
||||
|
||||
type Gender int32
|
||||
|
||||
const (
|
||||
GenderUnspecified Gender = iota
|
||||
GenderFemale
|
||||
GenderMale
|
||||
GenderDiverse
|
||||
)
|
||||
|
||||
func (r *UserSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-zz62F", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UserSearchRequest) AppendMyOrgQuery(orgID string) {
|
||||
r.Queries = append(r.Queries, &UserSearchQuery{Key: UserSearchKeyResourceOwner, Method: domain.SearchMethodEquals, Value: orgID})
|
||||
}
|
||||
|
||||
func (u *UserView) MFATypesSetupPossible(level domain.MFALevel, policy *domain.LoginPolicy) []domain.MFAType {
|
||||
types := make([]domain.MFAType, 0)
|
||||
switch level {
|
||||
default:
|
||||
fallthrough
|
||||
case domain.MFALevelSecondFactor:
|
||||
if policy.HasSecondFactors() {
|
||||
for _, mfaType := range policy.SecondFactors {
|
||||
switch mfaType {
|
||||
case domain.SecondFactorTypeTOTP:
|
||||
if u.OTPState != MFAStateReady {
|
||||
types = append(types, domain.MFATypeTOTP)
|
||||
}
|
||||
case domain.SecondFactorTypeU2F:
|
||||
types = append(types, domain.MFATypeU2F)
|
||||
case domain.SecondFactorTypeOTPSMS:
|
||||
if !u.OTPSMSAdded {
|
||||
types = append(types, domain.MFATypeOTPSMS)
|
||||
}
|
||||
case domain.SecondFactorTypeOTPEmail:
|
||||
if !u.OTPEmailAdded {
|
||||
types = append(types, domain.MFATypeOTPEmail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
func (u *UserView) MFATypesAllowed(level domain.MFALevel, policy *domain.LoginPolicy, isInternalAuthentication bool) ([]domain.MFAType, bool) {
|
||||
types := make([]domain.MFAType, 0)
|
||||
required := true
|
||||
switch level {
|
||||
default:
|
||||
required = domain.RequiresMFA(policy.ForceMFA, policy.ForceMFALocalOnly, isInternalAuthentication)
|
||||
fallthrough
|
||||
case domain.MFALevelSecondFactor:
|
||||
if policy.HasSecondFactors() {
|
||||
for _, mfaType := range policy.SecondFactors {
|
||||
switch mfaType {
|
||||
case domain.SecondFactorTypeTOTP:
|
||||
if u.OTPState == MFAStateReady {
|
||||
types = append(types, domain.MFATypeTOTP)
|
||||
}
|
||||
case domain.SecondFactorTypeU2F:
|
||||
if u.IsU2FReady() {
|
||||
types = append(types, domain.MFATypeU2F)
|
||||
}
|
||||
case domain.SecondFactorTypeOTPSMS:
|
||||
if u.OTPSMSAdded {
|
||||
types = append(types, domain.MFATypeOTPSMS)
|
||||
}
|
||||
case domain.SecondFactorTypeOTPEmail:
|
||||
if u.OTPEmailAdded {
|
||||
types = append(types, domain.MFATypeOTPEmail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return types, required
|
||||
}
|
||||
|
||||
func (u *UserView) IsU2FReady() bool {
|
||||
for _, token := range u.U2FTokens {
|
||||
if token.State == MFAStateReady {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *UserView) IsPasswordlessReady() bool {
|
||||
for _, token := range u.PasswordlessTokens {
|
||||
if token.State == MFAStateReady {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *UserView) GetProfile() (*Profile, error) {
|
||||
if u.HumanView == nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "MODEL-WLTce", "Errors.User.NotHuman")
|
||||
}
|
||||
return &Profile{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
FirstName: u.FirstName,
|
||||
LastName: u.LastName,
|
||||
NickName: u.NickName,
|
||||
DisplayName: u.DisplayName,
|
||||
PreferredLanguage: language.Make(u.PreferredLanguage),
|
||||
Gender: u.Gender,
|
||||
PreferredLoginName: u.PreferredLoginName,
|
||||
LoginNames: u.LoginNames,
|
||||
AvatarKey: u.AvatarKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *UserView) GetPhone() (*Phone, error) {
|
||||
if u.HumanView == nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "MODEL-him4a", "Errors.User.NotHuman")
|
||||
}
|
||||
return &Phone{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
PhoneNumber: u.Phone,
|
||||
IsPhoneVerified: u.IsPhoneVerified,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *UserView) GetEmail() (*Email, error) {
|
||||
if u.HumanView == nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "MODEL-PWd6K", "Errors.User.NotHuman")
|
||||
}
|
||||
return &Email{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
EmailAddress: u.Email,
|
||||
IsEmailVerified: u.IsEmailVerified,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *UserView) GetAddress() (*Address, error) {
|
||||
if u.HumanView == nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "MODEL-DN61m", "Errors.User.NotHuman")
|
||||
}
|
||||
return &Address{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
Country: u.Country,
|
||||
Locality: u.Locality,
|
||||
PostalCode: u.PostalCode,
|
||||
Region: u.Region,
|
||||
StreetAddress: u.StreetAddress,
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user