mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
feat(repository): implement user repository (#10967)
## Summary This PR introduces the relational user repository for backend v3, including schema, repository APIs, reducers/projections, and tests for both human and machine users. ## What changed * Added user-focused relational migrations (users, verifications, metadata, PATs, machine keys, passkeys, identity provider links) and related FK wiring. * Implemented/expanded repository domain contracts and storage implementations for human and machine user flows. * Added support for machine secret handling and aligned access token type modeling. * Extended user domain models (verifications, password/email/phone/TOTP state, passkeys, metadata, invite handling, identity provider links). * Updated projection/reduction coverage and integration tests for key user lifecycle events. * Regenerated and updated mocks/enums plus supporting database change/column utilities. ## Notes for reviewers * This PR is large because it establishes the foundational relational user storage layer and related test scaffolding. Sorry for that. ## Closes Closes #10218 Closes #10224 Closes #10225 Closes #10209 Closes #10802 --------- Co-authored-by: Iraq Jaber <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Marco A. <[email protected]> Co-authored-by: Tim Möhlmann <[email protected]>
This commit is contained in:
co-authored by
Iraq Jaber
Copilot
Marco A.
Tim Möhlmann
parent
40c7b38ca1
commit
5df8a97f9d
@@ -0,0 +1,82 @@
|
||||
// Code generated by "enumer -type AccessTokenType -transform lower -trimprefix AccessTokenType"; DO NOT EDIT.
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const _AccessTokenTypeName = "unspecifiedbearerjwt"
|
||||
|
||||
var _AccessTokenTypeIndex = [...]uint8{0, 11, 17, 20}
|
||||
|
||||
const _AccessTokenTypeLowerName = "unspecifiedbearerjwt"
|
||||
|
||||
func (i AccessTokenType) String() string {
|
||||
if i >= AccessTokenType(len(_AccessTokenTypeIndex)-1) {
|
||||
return fmt.Sprintf("AccessTokenType(%d)", i)
|
||||
}
|
||||
return _AccessTokenTypeName[_AccessTokenTypeIndex[i]:_AccessTokenTypeIndex[i+1]]
|
||||
}
|
||||
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
func _AccessTokenTypeNoOp() {
|
||||
var x [1]struct{}
|
||||
_ = x[AccessTokenTypeUnspecified-(0)]
|
||||
_ = x[AccessTokenTypeBearer-(1)]
|
||||
_ = x[AccessTokenTypeJWT-(2)]
|
||||
}
|
||||
|
||||
var _AccessTokenTypeValues = []AccessTokenType{AccessTokenTypeUnspecified, AccessTokenTypeBearer, AccessTokenTypeJWT}
|
||||
|
||||
var _AccessTokenTypeNameToValueMap = map[string]AccessTokenType{
|
||||
_AccessTokenTypeName[0:11]: AccessTokenTypeUnspecified,
|
||||
_AccessTokenTypeLowerName[0:11]: AccessTokenTypeUnspecified,
|
||||
_AccessTokenTypeName[11:17]: AccessTokenTypeBearer,
|
||||
_AccessTokenTypeLowerName[11:17]: AccessTokenTypeBearer,
|
||||
_AccessTokenTypeName[17:20]: AccessTokenTypeJWT,
|
||||
_AccessTokenTypeLowerName[17:20]: AccessTokenTypeJWT,
|
||||
}
|
||||
|
||||
var _AccessTokenTypeNames = []string{
|
||||
_AccessTokenTypeName[0:11],
|
||||
_AccessTokenTypeName[11:17],
|
||||
_AccessTokenTypeName[17:20],
|
||||
}
|
||||
|
||||
// AccessTokenTypeString retrieves an enum value from the enum constants string name.
|
||||
// Throws an error if the param is not part of the enum.
|
||||
func AccessTokenTypeString(s string) (AccessTokenType, error) {
|
||||
if val, ok := _AccessTokenTypeNameToValueMap[s]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
if val, ok := _AccessTokenTypeNameToValueMap[strings.ToLower(s)]; ok {
|
||||
return val, nil
|
||||
}
|
||||
return 0, fmt.Errorf("%s does not belong to AccessTokenType values", s)
|
||||
}
|
||||
|
||||
// AccessTokenTypeValues returns all values of the enum
|
||||
func AccessTokenTypeValues() []AccessTokenType {
|
||||
return _AccessTokenTypeValues
|
||||
}
|
||||
|
||||
// AccessTokenTypeStrings returns a slice of all String values of the enum
|
||||
func AccessTokenTypeStrings() []string {
|
||||
strs := make([]string, len(_AccessTokenTypeNames))
|
||||
copy(strs, _AccessTokenTypeNames)
|
||||
return strs
|
||||
}
|
||||
|
||||
// IsAAccessTokenType returns "true" if the value is listed in the enum definition. "false" otherwise
|
||||
func (i AccessTokenType) IsAAccessTokenType() bool {
|
||||
for _, v := range _AccessTokenTypeValues {
|
||||
if i == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
type Check struct {
|
||||
Code *crypto.CryptoValue `db:"code"`
|
||||
ExpiresAt *time.Time `db:"expires_at"`
|
||||
FailedAttempts uint8 `db:"failed_attempts"`
|
||||
}
|
||||
|
||||
type CheckType interface {
|
||||
isCheckType()
|
||||
}
|
||||
|
||||
type PasswordCheckType interface {
|
||||
isPasswordCheckType()
|
||||
}
|
||||
|
||||
// CheckTypeInit initializes a new check.
|
||||
type CheckTypeInit struct {
|
||||
// CreatedAt is the time when the check was created.
|
||||
// If zero, the current time will be used.
|
||||
CreatedAt time.Time
|
||||
// Expiry is the duration after which the check expires.
|
||||
Expiry *time.Duration
|
||||
// Code to be used for the check.
|
||||
Code *crypto.CryptoValue
|
||||
}
|
||||
|
||||
// isCheckType implements [CheckType].
|
||||
func (v *CheckTypeInit) isCheckType() {}
|
||||
|
||||
var _ CheckType = (*CheckTypeInit)(nil)
|
||||
|
||||
// CheckTypeFailed indicates that the check failed.
|
||||
// It is used to increment the failed attempts counter.
|
||||
type CheckTypeFailed struct {
|
||||
FailedAt time.Time
|
||||
}
|
||||
|
||||
// isCheckType implements [CheckType].
|
||||
func (v *CheckTypeFailed) isCheckType() {}
|
||||
|
||||
// isPasswordCheckType implements [PasswordCheckType].
|
||||
func (v *CheckTypeFailed) isPasswordCheckType() {}
|
||||
|
||||
var (
|
||||
_ CheckType = (*CheckTypeFailed)(nil)
|
||||
_ PasswordCheckType = (*CheckTypeFailed)(nil)
|
||||
)
|
||||
|
||||
// CheckTypeSucceeded indicates that the check succeeded.
|
||||
// It is used to reset the failed attempts counter.
|
||||
type CheckTypeSucceeded struct {
|
||||
SucceededAt time.Time
|
||||
}
|
||||
|
||||
// isCheckType implements [CheckType].
|
||||
func (v *CheckTypeSucceeded) isCheckType() {}
|
||||
|
||||
// isPasswordCheckType implements [PasswordCheckType].
|
||||
func (v *CheckTypeSucceeded) isPasswordCheckType() {}
|
||||
|
||||
var (
|
||||
_ CheckType = (*CheckTypeSucceeded)(nil)
|
||||
_ PasswordCheckType = (*CheckTypeSucceeded)(nil)
|
||||
)
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const _MachineKeyTypeName = "unspecifiedjsonnone"
|
||||
const _MachineKeyTypeName = "nonejson"
|
||||
|
||||
var _MachineKeyTypeIndex = [...]uint8{0, 11, 15, 19}
|
||||
var _MachineKeyTypeIndex = [...]uint8{0, 4, 8}
|
||||
|
||||
const _MachineKeyTypeLowerName = "unspecifiedjsonnone"
|
||||
const _MachineKeyTypeLowerName = "nonejson"
|
||||
|
||||
func (i MachineKeyType) String() string {
|
||||
if i >= MachineKeyType(len(_MachineKeyTypeIndex)-1) {
|
||||
@@ -24,26 +24,22 @@ func (i MachineKeyType) String() string {
|
||||
// Re-run the stringer command to generate them again.
|
||||
func _MachineKeyTypeNoOp() {
|
||||
var x [1]struct{}
|
||||
_ = x[MachineKeyTypeUnspecified-(0)]
|
||||
_ = x[MachineKeyTypeNone-(0)]
|
||||
_ = x[MachineKeyTypeJSON-(1)]
|
||||
_ = x[MachineKeyTypeNone-(2)]
|
||||
}
|
||||
|
||||
var _MachineKeyTypeValues = []MachineKeyType{MachineKeyTypeUnspecified, MachineKeyTypeJSON, MachineKeyTypeNone}
|
||||
var _MachineKeyTypeValues = []MachineKeyType{MachineKeyTypeNone, MachineKeyTypeJSON}
|
||||
|
||||
var _MachineKeyTypeNameToValueMap = map[string]MachineKeyType{
|
||||
_MachineKeyTypeName[0:11]: MachineKeyTypeUnspecified,
|
||||
_MachineKeyTypeLowerName[0:11]: MachineKeyTypeUnspecified,
|
||||
_MachineKeyTypeName[11:15]: MachineKeyTypeJSON,
|
||||
_MachineKeyTypeLowerName[11:15]: MachineKeyTypeJSON,
|
||||
_MachineKeyTypeName[15:19]: MachineKeyTypeNone,
|
||||
_MachineKeyTypeLowerName[15:19]: MachineKeyTypeNone,
|
||||
_MachineKeyTypeName[0:4]: MachineKeyTypeNone,
|
||||
_MachineKeyTypeLowerName[0:4]: MachineKeyTypeNone,
|
||||
_MachineKeyTypeName[4:8]: MachineKeyTypeJSON,
|
||||
_MachineKeyTypeLowerName[4:8]: MachineKeyTypeJSON,
|
||||
}
|
||||
|
||||
var _MachineKeyTypeNames = []string{
|
||||
_MachineKeyTypeName[0:11],
|
||||
_MachineKeyTypeName[11:15],
|
||||
_MachineKeyTypeName[15:19],
|
||||
_MachineKeyTypeName[0:4],
|
||||
_MachineKeyTypeName[4:8],
|
||||
}
|
||||
|
||||
// MachineKeyTypeString retrieves an enum value from the enum constants string name.
|
||||
|
||||
@@ -158,6 +158,44 @@ func (c *MockAuthorizationRepositoryDeleteCall) DoAndReturn(f func(context.Conte
|
||||
return c
|
||||
}
|
||||
|
||||
// ExistsRole mocks base method.
|
||||
func (m *MockAuthorizationRepository) ExistsRole(cond database.Condition) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ExistsRole", cond)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ExistsRole indicates an expected call of ExistsRole.
|
||||
func (mr *MockAuthorizationRepositoryMockRecorder) ExistsRole(cond any) *MockAuthorizationRepositoryExistsRoleCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsRole", reflect.TypeOf((*MockAuthorizationRepository)(nil).ExistsRole), cond)
|
||||
return &MockAuthorizationRepositoryExistsRoleCall{Call: call}
|
||||
}
|
||||
|
||||
// MockAuthorizationRepositoryExistsRoleCall wrap *gomock.Call
|
||||
type MockAuthorizationRepositoryExistsRoleCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockAuthorizationRepositoryExistsRoleCall) Return(arg0 database.Condition) *MockAuthorizationRepositoryExistsRoleCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockAuthorizationRepositoryExistsRoleCall) Do(f func(database.Condition) database.Condition) *MockAuthorizationRepositoryExistsRoleCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockAuthorizationRepositoryExistsRoleCall) DoAndReturn(f func(database.Condition) database.Condition) *MockAuthorizationRepositoryExistsRoleCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockAuthorizationRepository) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.Authorization, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -354,17 +354,17 @@ func (c *MockInstanceDomainRepositoryIsGeneratedColumnCall) DoAndReturn(f func()
|
||||
}
|
||||
|
||||
// IsGeneratedCondition mocks base method.
|
||||
func (m *MockInstanceDomainRepository) IsGeneratedCondition(arg0 bool) database.Condition {
|
||||
func (m *MockInstanceDomainRepository) IsGeneratedCondition(isGenerated bool) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsGeneratedCondition", arg0)
|
||||
ret := m.ctrl.Call(m, "IsGeneratedCondition", isGenerated)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsGeneratedCondition indicates an expected call of IsGeneratedCondition.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) IsGeneratedCondition(arg0 any) *MockInstanceDomainRepositoryIsGeneratedConditionCall {
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) IsGeneratedCondition(isGenerated any) *MockInstanceDomainRepositoryIsGeneratedConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsGeneratedCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).IsGeneratedCondition), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsGeneratedCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).IsGeneratedCondition), isGenerated)
|
||||
return &MockInstanceDomainRepositoryIsGeneratedConditionCall{Call: call}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,6 +237,44 @@ func (c *MockMachineUserRepositoryExistsMetadataCall) DoAndReturn(f func(databas
|
||||
return c
|
||||
}
|
||||
|
||||
// IDColumn mocks base method.
|
||||
func (m *MockMachineUserRepository) IDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IDColumn indicates an expected call of IDColumn.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) IDColumn() *MockMachineUserRepositoryIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDColumn", reflect.TypeOf((*MockMachineUserRepository)(nil).IDColumn))
|
||||
return &MockMachineUserRepositoryIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockMachineUserRepositoryIDColumnCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockMachineUserRepositoryIDColumnCall) Return(arg0 database.Column) *MockMachineUserRepositoryIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositoryIDColumnCall) Do(f func() database.Column) *MockMachineUserRepositoryIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositoryIDColumnCall) DoAndReturn(f func() database.Column) *MockMachineUserRepositoryIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IDCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) IDCondition(userID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -275,6 +313,44 @@ func (c *MockMachineUserRepositoryIDConditionCall) DoAndReturn(f func(string) da
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDColumn mocks base method.
|
||||
func (m *MockMachineUserRepository) InstanceIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDColumn indicates an expected call of InstanceIDColumn.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) InstanceIDColumn() *MockMachineUserRepositoryInstanceIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDColumn", reflect.TypeOf((*MockMachineUserRepository)(nil).InstanceIDColumn))
|
||||
return &MockMachineUserRepositoryInstanceIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockMachineUserRepositoryInstanceIDColumnCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryInstanceIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockMachineUserRepositoryInstanceIDColumnCall) Return(arg0 database.Column) *MockMachineUserRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositoryInstanceIDColumnCall) Do(f func() database.Column) *MockMachineUserRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositoryInstanceIDColumnCall) DoAndReturn(f func() database.Column) *MockMachineUserRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) InstanceIDCondition(instanceID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -351,116 +427,78 @@ func (c *MockMachineUserRepositoryLoginNameConditionCall) DoAndReturn(f func(dat
|
||||
return c
|
||||
}
|
||||
|
||||
// MetadataKeyCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) MetadataKeyCondition(key string) database.Condition {
|
||||
// MetadataConditions mocks base method.
|
||||
func (m *MockMachineUserRepository) MetadataConditions() domain.UserMetadataConditions {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MetadataKeyCondition", key)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
ret := m.ctrl.Call(m, "MetadataConditions")
|
||||
ret0, _ := ret[0].(domain.UserMetadataConditions)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MetadataKeyCondition indicates an expected call of MetadataKeyCondition.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) MetadataKeyCondition(key any) *MockMachineUserRepositoryMetadataKeyConditionCall {
|
||||
// MetadataConditions indicates an expected call of MetadataConditions.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) MetadataConditions() *MockMachineUserRepositoryMetadataConditionsCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MetadataKeyCondition", reflect.TypeOf((*MockMachineUserRepository)(nil).MetadataKeyCondition), key)
|
||||
return &MockMachineUserRepositoryMetadataKeyConditionCall{Call: call}
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MetadataConditions", reflect.TypeOf((*MockMachineUserRepository)(nil).MetadataConditions))
|
||||
return &MockMachineUserRepositoryMetadataConditionsCall{Call: call}
|
||||
}
|
||||
|
||||
// MockMachineUserRepositoryMetadataKeyConditionCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryMetadataKeyConditionCall struct {
|
||||
// MockMachineUserRepositoryMetadataConditionsCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryMetadataConditionsCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockMachineUserRepositoryMetadataKeyConditionCall) Return(arg0 database.Condition) *MockMachineUserRepositoryMetadataKeyConditionCall {
|
||||
func (c *MockMachineUserRepositoryMetadataConditionsCall) Return(arg0 domain.UserMetadataConditions) *MockMachineUserRepositoryMetadataConditionsCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositoryMetadataKeyConditionCall) Do(f func(string) database.Condition) *MockMachineUserRepositoryMetadataKeyConditionCall {
|
||||
func (c *MockMachineUserRepositoryMetadataConditionsCall) Do(f func() domain.UserMetadataConditions) *MockMachineUserRepositoryMetadataConditionsCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositoryMetadataKeyConditionCall) DoAndReturn(f func(string) database.Condition) *MockMachineUserRepositoryMetadataKeyConditionCall {
|
||||
func (c *MockMachineUserRepositoryMetadataConditionsCall) DoAndReturn(f func() domain.UserMetadataConditions) *MockMachineUserRepositoryMetadataConditionsCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// MetadataValueCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) MetadataValueCondition(op database.BytesOperation, value []byte) database.Condition {
|
||||
// OrganizationIDCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) OrganizationIDCondition(orgID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MetadataValueCondition", op, value)
|
||||
ret := m.ctrl.Call(m, "OrganizationIDCondition", orgID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MetadataValueCondition indicates an expected call of MetadataValueCondition.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) MetadataValueCondition(op, value any) *MockMachineUserRepositoryMetadataValueConditionCall {
|
||||
// OrganizationIDCondition indicates an expected call of OrganizationIDCondition.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) OrganizationIDCondition(orgID any) *MockMachineUserRepositoryOrganizationIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MetadataValueCondition", reflect.TypeOf((*MockMachineUserRepository)(nil).MetadataValueCondition), op, value)
|
||||
return &MockMachineUserRepositoryMetadataValueConditionCall{Call: call}
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrganizationIDCondition", reflect.TypeOf((*MockMachineUserRepository)(nil).OrganizationIDCondition), orgID)
|
||||
return &MockMachineUserRepositoryOrganizationIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockMachineUserRepositoryMetadataValueConditionCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryMetadataValueConditionCall struct {
|
||||
// MockMachineUserRepositoryOrganizationIDConditionCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryOrganizationIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockMachineUserRepositoryMetadataValueConditionCall) Return(arg0 database.Condition) *MockMachineUserRepositoryMetadataValueConditionCall {
|
||||
func (c *MockMachineUserRepositoryOrganizationIDConditionCall) Return(arg0 database.Condition) *MockMachineUserRepositoryOrganizationIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositoryMetadataValueConditionCall) Do(f func(database.BytesOperation, []byte) database.Condition) *MockMachineUserRepositoryMetadataValueConditionCall {
|
||||
func (c *MockMachineUserRepositoryOrganizationIDConditionCall) Do(f func(string) database.Condition) *MockMachineUserRepositoryOrganizationIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositoryMetadataValueConditionCall) DoAndReturn(f func(database.BytesOperation, []byte) database.Condition) *MockMachineUserRepositoryMetadataValueConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// OrgIDCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) OrgIDCondition(orgID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OrgIDCondition", orgID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// OrgIDCondition indicates an expected call of OrgIDCondition.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) OrgIDCondition(orgID any) *MockMachineUserRepositoryOrgIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrgIDCondition", reflect.TypeOf((*MockMachineUserRepository)(nil).OrgIDCondition), orgID)
|
||||
return &MockMachineUserRepositoryOrgIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockMachineUserRepositoryOrgIDConditionCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryOrgIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockMachineUserRepositoryOrgIDConditionCall) Return(arg0 database.Condition) *MockMachineUserRepositoryOrgIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositoryOrgIDConditionCall) Do(f func(string) database.Condition) *MockMachineUserRepositoryOrgIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositoryOrgIDConditionCall) DoAndReturn(f func(string) database.Condition) *MockMachineUserRepositoryOrgIDConditionCall {
|
||||
func (c *MockMachineUserRepositoryOrganizationIDConditionCall) DoAndReturn(f func(string) database.Condition) *MockMachineUserRepositoryOrganizationIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
@@ -656,7 +694,7 @@ func (c *MockMachineUserRepositoryRemovePersonalAccessTokenCall) DoAndReturn(f f
|
||||
}
|
||||
|
||||
// SetAccessTokenType mocks base method.
|
||||
func (m *MockMachineUserRepository) SetAccessTokenType(tokenType domain.PersonalAccessTokenType) database.Change {
|
||||
func (m *MockMachineUserRepository) SetAccessTokenType(tokenType domain.AccessTokenType) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetAccessTokenType", tokenType)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
@@ -682,13 +720,13 @@ func (c *MockMachineUserRepositorySetAccessTokenTypeCall) Return(arg0 database.C
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositorySetAccessTokenTypeCall) Do(f func(domain.PersonalAccessTokenType) database.Change) *MockMachineUserRepositorySetAccessTokenTypeCall {
|
||||
func (c *MockMachineUserRepositorySetAccessTokenTypeCall) Do(f func(domain.AccessTokenType) database.Change) *MockMachineUserRepositorySetAccessTokenTypeCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositorySetAccessTokenTypeCall) DoAndReturn(f func(domain.PersonalAccessTokenType) database.Change) *MockMachineUserRepositorySetAccessTokenTypeCall {
|
||||
func (c *MockMachineUserRepositorySetAccessTokenTypeCall) DoAndReturn(f func(domain.AccessTokenType) database.Change) *MockMachineUserRepositorySetAccessTokenTypeCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
@@ -997,6 +1035,44 @@ func (c *MockMachineUserRepositoryStateConditionCall) DoAndReturn(f func(domain.
|
||||
return c
|
||||
}
|
||||
|
||||
// TypeColumn mocks base method.
|
||||
func (m *MockMachineUserRepository) TypeColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TypeColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TypeColumn indicates an expected call of TypeColumn.
|
||||
func (mr *MockMachineUserRepositoryMockRecorder) TypeColumn() *MockMachineUserRepositoryTypeColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TypeColumn", reflect.TypeOf((*MockMachineUserRepository)(nil).TypeColumn))
|
||||
return &MockMachineUserRepositoryTypeColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockMachineUserRepositoryTypeColumnCall wrap *gomock.Call
|
||||
type MockMachineUserRepositoryTypeColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockMachineUserRepositoryTypeColumnCall) Return(arg0 database.Column) *MockMachineUserRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockMachineUserRepositoryTypeColumnCall) Do(f func() database.Column) *MockMachineUserRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockMachineUserRepositoryTypeColumnCall) DoAndReturn(f func() database.Column) *MockMachineUserRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// TypeCondition mocks base method.
|
||||
func (m *MockMachineUserRepository) TypeCondition(userType domain.UserType) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -202,6 +202,82 @@ func (c *MockProjectRepositoryGetCall) DoAndReturn(f func(context.Context, datab
|
||||
return c
|
||||
}
|
||||
|
||||
// GrantedOrganizationIDColumn mocks base method.
|
||||
func (m *MockProjectRepository) GrantedOrganizationIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GrantedOrganizationIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GrantedOrganizationIDColumn indicates an expected call of GrantedOrganizationIDColumn.
|
||||
func (mr *MockProjectRepositoryMockRecorder) GrantedOrganizationIDColumn() *MockProjectRepositoryGrantedOrganizationIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GrantedOrganizationIDColumn", reflect.TypeOf((*MockProjectRepository)(nil).GrantedOrganizationIDColumn))
|
||||
return &MockProjectRepositoryGrantedOrganizationIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockProjectRepositoryGrantedOrganizationIDColumnCall wrap *gomock.Call
|
||||
type MockProjectRepositoryGrantedOrganizationIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockProjectRepositoryGrantedOrganizationIDColumnCall) Return(arg0 database.Column) *MockProjectRepositoryGrantedOrganizationIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockProjectRepositoryGrantedOrganizationIDColumnCall) Do(f func() database.Column) *MockProjectRepositoryGrantedOrganizationIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockProjectRepositoryGrantedOrganizationIDColumnCall) DoAndReturn(f func() database.Column) *MockProjectRepositoryGrantedOrganizationIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// GrantedOrganizationIDCondition mocks base method.
|
||||
func (m *MockProjectRepository) GrantedOrganizationIDCondition(organizationID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GrantedOrganizationIDCondition", organizationID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GrantedOrganizationIDCondition indicates an expected call of GrantedOrganizationIDCondition.
|
||||
func (mr *MockProjectRepositoryMockRecorder) GrantedOrganizationIDCondition(organizationID any) *MockProjectRepositoryGrantedOrganizationIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GrantedOrganizationIDCondition", reflect.TypeOf((*MockProjectRepository)(nil).GrantedOrganizationIDCondition), organizationID)
|
||||
return &MockProjectRepositoryGrantedOrganizationIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockProjectRepositoryGrantedOrganizationIDConditionCall wrap *gomock.Call
|
||||
type MockProjectRepositoryGrantedOrganizationIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockProjectRepositoryGrantedOrganizationIDConditionCall) Return(arg0 database.Condition) *MockProjectRepositoryGrantedOrganizationIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockProjectRepositoryGrantedOrganizationIDConditionCall) Do(f func(string) database.Condition) *MockProjectRepositoryGrantedOrganizationIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockProjectRepositoryGrantedOrganizationIDConditionCall) DoAndReturn(f func(string) database.Condition) *MockProjectRepositoryGrantedOrganizationIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IDColumn mocks base method.
|
||||
func (m *MockProjectRepository) IDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@ import (
|
||||
type MockSessionRepository struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockSessionRepositoryMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockSessionRepositoryMockRecorder is the mock recorder for MockSessionRepository.
|
||||
@@ -43,17 +44,17 @@ func (m *MockSessionRepository) EXPECT() *MockSessionRepositoryMockRecorder {
|
||||
}
|
||||
|
||||
// ClearFactor mocks base method.
|
||||
func (m *MockSessionRepository) ClearFactor(arg0 domain.SessionFactorType) database.Change {
|
||||
func (m *MockSessionRepository) ClearFactor(factor domain.SessionFactorType) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ClearFactor", arg0)
|
||||
ret := m.ctrl.Call(m, "ClearFactor", factor)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ClearFactor indicates an expected call of ClearFactor.
|
||||
func (mr *MockSessionRepositoryMockRecorder) ClearFactor(arg0 any) *MockSessionRepositoryClearFactorCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) ClearFactor(factor any) *MockSessionRepositoryClearFactorCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearFactor", reflect.TypeOf((*MockSessionRepository)(nil).ClearFactor), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearFactor", reflect.TypeOf((*MockSessionRepository)(nil).ClearFactor), factor)
|
||||
return &MockSessionRepositoryClearFactorCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -81,17 +82,17 @@ func (c *MockSessionRepositoryClearFactorCall) DoAndReturn(f func(domain.Session
|
||||
}
|
||||
|
||||
// Create mocks base method.
|
||||
func (m *MockSessionRepository) Create(arg0 context.Context, arg1 database.QueryExecutor, arg2 *domain.Session) error {
|
||||
func (m *MockSessionRepository) Create(ctx context.Context, client database.QueryExecutor, user *domain.Session) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Create", arg0, arg1, arg2)
|
||||
ret := m.ctrl.Call(m, "Create", ctx, client, user)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create.
|
||||
func (mr *MockSessionRepositoryMockRecorder) Create(arg0, arg1, arg2 any) *MockSessionRepositoryCreateCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) Create(ctx, client, user any) *MockSessionRepositoryCreateCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockSessionRepository)(nil).Create), arg0, arg1, arg2)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockSessionRepository)(nil).Create), ctx, client, user)
|
||||
return &MockSessionRepositoryCreateCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -157,17 +158,17 @@ func (c *MockSessionRepositoryCreatedAtColumnCall) DoAndReturn(f func() database
|
||||
}
|
||||
|
||||
// CreatedAtCondition mocks base method.
|
||||
func (m *MockSessionRepository) CreatedAtCondition(arg0 database.NumberOperation, arg1 time.Time) database.Condition {
|
||||
func (m *MockSessionRepository) CreatedAtCondition(op database.NumberOperation, createdAt time.Time) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreatedAtCondition", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "CreatedAtCondition", op, createdAt)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CreatedAtCondition indicates an expected call of CreatedAtCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) CreatedAtCondition(arg0, arg1 any) *MockSessionRepositoryCreatedAtConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) CreatedAtCondition(op, createdAt any) *MockSessionRepositoryCreatedAtConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatedAtCondition", reflect.TypeOf((*MockSessionRepository)(nil).CreatedAtCondition), arg0, arg1)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatedAtCondition", reflect.TypeOf((*MockSessionRepository)(nil).CreatedAtCondition), op, createdAt)
|
||||
return &MockSessionRepositoryCreatedAtConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -195,17 +196,17 @@ func (c *MockSessionRepositoryCreatedAtConditionCall) DoAndReturn(f func(databas
|
||||
}
|
||||
|
||||
// CreatorIDCondition mocks base method.
|
||||
func (m *MockSessionRepository) CreatorIDCondition(arg0 string) database.Condition {
|
||||
func (m *MockSessionRepository) CreatorIDCondition(creatorID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreatorIDCondition", arg0)
|
||||
ret := m.ctrl.Call(m, "CreatorIDCondition", creatorID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CreatorIDCondition indicates an expected call of CreatorIDCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) CreatorIDCondition(arg0 any) *MockSessionRepositoryCreatorIDConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) CreatorIDCondition(creatorID any) *MockSessionRepositoryCreatorIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatorIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).CreatorIDCondition), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatorIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).CreatorIDCondition), creatorID)
|
||||
return &MockSessionRepositoryCreatorIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -233,18 +234,18 @@ func (c *MockSessionRepositoryCreatorIDConditionCall) DoAndReturn(f func(string)
|
||||
}
|
||||
|
||||
// Delete mocks base method.
|
||||
func (m *MockSessionRepository) Delete(arg0 context.Context, arg1 database.QueryExecutor, arg2 database.Condition) (int64, error) {
|
||||
func (m *MockSessionRepository) Delete(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", arg0, arg1, arg2)
|
||||
ret := m.ctrl.Call(m, "Delete", ctx, client, condition)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete.
|
||||
func (mr *MockSessionRepositoryMockRecorder) Delete(arg0, arg1, arg2 any) *MockSessionRepositoryDeleteCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) Delete(ctx, client, condition any) *MockSessionRepositoryDeleteCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockSessionRepository)(nil).Delete), arg0, arg1, arg2)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockSessionRepository)(nil).Delete), ctx, client, condition)
|
||||
return &MockSessionRepositoryDeleteCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -272,17 +273,17 @@ func (c *MockSessionRepositoryDeleteCall) DoAndReturn(f func(context.Context, da
|
||||
}
|
||||
|
||||
// ExistsFactor mocks base method.
|
||||
func (m *MockSessionRepository) ExistsFactor(arg0 database.Condition) database.Condition {
|
||||
func (m *MockSessionRepository) ExistsFactor(condition database.Condition) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ExistsFactor", arg0)
|
||||
ret := m.ctrl.Call(m, "ExistsFactor", condition)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ExistsFactor indicates an expected call of ExistsFactor.
|
||||
func (mr *MockSessionRepositoryMockRecorder) ExistsFactor(arg0 any) *MockSessionRepositoryExistsFactorCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) ExistsFactor(condition any) *MockSessionRepositoryExistsFactorCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsFactor", reflect.TypeOf((*MockSessionRepository)(nil).ExistsFactor), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsFactor", reflect.TypeOf((*MockSessionRepository)(nil).ExistsFactor), condition)
|
||||
return &MockSessionRepositoryExistsFactorCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -310,17 +311,17 @@ func (c *MockSessionRepositoryExistsFactorCall) DoAndReturn(f func(database.Cond
|
||||
}
|
||||
|
||||
// ExistsMetadata mocks base method.
|
||||
func (m *MockSessionRepository) ExistsMetadata(arg0 database.Condition) database.Condition {
|
||||
func (m *MockSessionRepository) ExistsMetadata(condition database.Condition) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ExistsMetadata", arg0)
|
||||
ret := m.ctrl.Call(m, "ExistsMetadata", condition)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ExistsMetadata indicates an expected call of ExistsMetadata.
|
||||
func (mr *MockSessionRepositoryMockRecorder) ExistsMetadata(arg0 any) *MockSessionRepositoryExistsMetadataCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) ExistsMetadata(condition any) *MockSessionRepositoryExistsMetadataCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsMetadata", reflect.TypeOf((*MockSessionRepository)(nil).ExistsMetadata), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsMetadata", reflect.TypeOf((*MockSessionRepository)(nil).ExistsMetadata), condition)
|
||||
return &MockSessionRepositoryExistsMetadataCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -386,17 +387,17 @@ func (c *MockSessionRepositoryExpirationColumnCall) DoAndReturn(f func() databas
|
||||
}
|
||||
|
||||
// ExpirationCondition mocks base method.
|
||||
func (m *MockSessionRepository) ExpirationCondition(arg0 database.NumberOperation, arg1 time.Time) database.Condition {
|
||||
func (m *MockSessionRepository) ExpirationCondition(op database.NumberOperation, expiration time.Time) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ExpirationCondition", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "ExpirationCondition", op, expiration)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ExpirationCondition indicates an expected call of ExpirationCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) ExpirationCondition(arg0, arg1 any) *MockSessionRepositoryExpirationConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) ExpirationCondition(op, expiration any) *MockSessionRepositoryExpirationConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExpirationCondition", reflect.TypeOf((*MockSessionRepository)(nil).ExpirationCondition), arg0, arg1)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExpirationCondition", reflect.TypeOf((*MockSessionRepository)(nil).ExpirationCondition), op, expiration)
|
||||
return &MockSessionRepositoryExpirationConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -462,10 +463,10 @@ func (c *MockSessionRepositoryFactorConditionsCall) DoAndReturn(f func() domain.
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockSessionRepository) Get(arg0 context.Context, arg1 database.QueryExecutor, arg2 ...database.QueryOption) (*domain.Session, error) {
|
||||
func (m *MockSessionRepository) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.Session, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs := []any{ctx, client}
|
||||
for _, a := range opts {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Get", varargs...)
|
||||
@@ -475,9 +476,9 @@ func (m *MockSessionRepository) Get(arg0 context.Context, arg1 database.QueryExe
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockSessionRepositoryMockRecorder) Get(arg0, arg1 any, arg2 ...any) *MockSessionRepositoryGetCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) Get(ctx, client any, opts ...any) *MockSessionRepositoryGetCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{arg0, arg1}, arg2...)
|
||||
varargs := append([]any{ctx, client}, opts...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSessionRepository)(nil).Get), varargs...)
|
||||
return &MockSessionRepositoryGetCall{Call: call}
|
||||
}
|
||||
@@ -544,17 +545,17 @@ func (c *MockSessionRepositoryIDColumnCall) DoAndReturn(f func() database.Column
|
||||
}
|
||||
|
||||
// IDCondition mocks base method.
|
||||
func (m *MockSessionRepository) IDCondition(arg0 string) database.Condition {
|
||||
func (m *MockSessionRepository) IDCondition(sessionID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IDCondition", arg0)
|
||||
ret := m.ctrl.Call(m, "IDCondition", sessionID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IDCondition indicates an expected call of IDCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) IDCondition(arg0 any) *MockSessionRepositoryIDConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) IDCondition(sessionID any) *MockSessionRepositoryIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDCondition", reflect.TypeOf((*MockSessionRepository)(nil).IDCondition), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDCondition", reflect.TypeOf((*MockSessionRepository)(nil).IDCondition), sessionID)
|
||||
return &MockSessionRepositoryIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -620,17 +621,17 @@ func (c *MockSessionRepositoryInstanceIDColumnCall) DoAndReturn(f func() databas
|
||||
}
|
||||
|
||||
// InstanceIDCondition mocks base method.
|
||||
func (m *MockSessionRepository) InstanceIDCondition(arg0 string) database.Condition {
|
||||
func (m *MockSessionRepository) InstanceIDCondition(instanceID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDCondition", arg0)
|
||||
ret := m.ctrl.Call(m, "InstanceIDCondition", instanceID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDCondition indicates an expected call of InstanceIDCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) InstanceIDCondition(arg0 any) *MockSessionRepositoryInstanceIDConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) InstanceIDCondition(instanceID any) *MockSessionRepositoryInstanceIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).InstanceIDCondition), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).InstanceIDCondition), instanceID)
|
||||
return &MockSessionRepositoryInstanceIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -696,10 +697,10 @@ func (c *MockSessionRepositoryLifetimeColumnCall) DoAndReturn(f func() database.
|
||||
}
|
||||
|
||||
// List mocks base method.
|
||||
func (m *MockSessionRepository) List(arg0 context.Context, arg1 database.QueryExecutor, arg2 ...database.QueryOption) ([]*domain.Session, error) {
|
||||
func (m *MockSessionRepository) List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*domain.Session, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs := []any{ctx, client}
|
||||
for _, a := range opts {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "List", varargs...)
|
||||
@@ -709,9 +710,9 @@ func (m *MockSessionRepository) List(arg0 context.Context, arg1 database.QueryEx
|
||||
}
|
||||
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockSessionRepositoryMockRecorder) List(arg0, arg1 any, arg2 ...any) *MockSessionRepositoryListCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) List(ctx, client any, opts ...any) *MockSessionRepositoryListCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{arg0, arg1}, arg2...)
|
||||
varargs := append([]any{ctx, client}, opts...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockSessionRepository)(nil).List), varargs...)
|
||||
return &MockSessionRepositoryListCall{Call: call}
|
||||
}
|
||||
@@ -816,17 +817,17 @@ func (c *MockSessionRepositoryPrimaryKeyColumnsCall) DoAndReturn(f func() []data
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition mocks base method.
|
||||
func (m *MockSessionRepository) PrimaryKeyCondition(arg0, arg1 string) database.Condition {
|
||||
func (m *MockSessionRepository) PrimaryKeyCondition(instanceID, sessionID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PrimaryKeyCondition", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "PrimaryKeyCondition", instanceID, sessionID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition indicates an expected call of PrimaryKeyCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) PrimaryKeyCondition(arg0, arg1 any) *MockSessionRepositoryPrimaryKeyConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) PrimaryKeyCondition(instanceID, sessionID any) *MockSessionRepositoryPrimaryKeyConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrimaryKeyCondition", reflect.TypeOf((*MockSessionRepository)(nil).PrimaryKeyCondition), arg0, arg1)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrimaryKeyCondition", reflect.TypeOf((*MockSessionRepository)(nil).PrimaryKeyCondition), instanceID, sessionID)
|
||||
return &MockSessionRepositoryPrimaryKeyConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -854,17 +855,17 @@ func (c *MockSessionRepositoryPrimaryKeyConditionCall) DoAndReturn(f func(string
|
||||
}
|
||||
|
||||
// SetChallenge mocks base method.
|
||||
func (m *MockSessionRepository) SetChallenge(arg0 domain.SessionChallenge) database.Change {
|
||||
func (m *MockSessionRepository) SetChallenge(challenge domain.SessionChallenge) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetChallenge", arg0)
|
||||
ret := m.ctrl.Call(m, "SetChallenge", challenge)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetChallenge indicates an expected call of SetChallenge.
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetChallenge(arg0 any) *MockSessionRepositorySetChallengeCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetChallenge(challenge any) *MockSessionRepositorySetChallengeCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetChallenge", reflect.TypeOf((*MockSessionRepository)(nil).SetChallenge), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetChallenge", reflect.TypeOf((*MockSessionRepository)(nil).SetChallenge), challenge)
|
||||
return &MockSessionRepositorySetChallengeCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -892,17 +893,17 @@ func (c *MockSessionRepositorySetChallengeCall) DoAndReturn(f func(domain.Sessio
|
||||
}
|
||||
|
||||
// SetFactor mocks base method.
|
||||
func (m *MockSessionRepository) SetFactor(arg0 domain.SessionFactor) database.Change {
|
||||
func (m *MockSessionRepository) SetFactor(factor domain.SessionFactor) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetFactor", arg0)
|
||||
ret := m.ctrl.Call(m, "SetFactor", factor)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetFactor indicates an expected call of SetFactor.
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetFactor(arg0 any) *MockSessionRepositorySetFactorCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetFactor(factor any) *MockSessionRepositorySetFactorCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFactor", reflect.TypeOf((*MockSessionRepository)(nil).SetFactor), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFactor", reflect.TypeOf((*MockSessionRepository)(nil).SetFactor), factor)
|
||||
return &MockSessionRepositorySetFactorCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -930,17 +931,17 @@ func (c *MockSessionRepositorySetFactorCall) DoAndReturn(f func(domain.SessionFa
|
||||
}
|
||||
|
||||
// SetLifetime mocks base method.
|
||||
func (m *MockSessionRepository) SetLifetime(arg0 time.Duration) database.Change {
|
||||
func (m *MockSessionRepository) SetLifetime(lifetime time.Duration) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetLifetime", arg0)
|
||||
ret := m.ctrl.Call(m, "SetLifetime", lifetime)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetLifetime indicates an expected call of SetLifetime.
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetLifetime(arg0 any) *MockSessionRepositorySetLifetimeCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetLifetime(lifetime any) *MockSessionRepositorySetLifetimeCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLifetime", reflect.TypeOf((*MockSessionRepository)(nil).SetLifetime), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLifetime", reflect.TypeOf((*MockSessionRepository)(nil).SetLifetime), lifetime)
|
||||
return &MockSessionRepositorySetLifetimeCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -968,17 +969,17 @@ func (c *MockSessionRepositorySetLifetimeCall) DoAndReturn(f func(time.Duration)
|
||||
}
|
||||
|
||||
// SetMetadata mocks base method.
|
||||
func (m *MockSessionRepository) SetMetadata(arg0 []*domain.SessionMetadata) database.Change {
|
||||
func (m *MockSessionRepository) SetMetadata(metadata []*domain.SessionMetadata) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetMetadata", arg0)
|
||||
ret := m.ctrl.Call(m, "SetMetadata", metadata)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetMetadata indicates an expected call of SetMetadata.
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetMetadata(arg0 any) *MockSessionRepositorySetMetadataCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetMetadata(metadata any) *MockSessionRepositorySetMetadataCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMetadata", reflect.TypeOf((*MockSessionRepository)(nil).SetMetadata), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMetadata", reflect.TypeOf((*MockSessionRepository)(nil).SetMetadata), metadata)
|
||||
return &MockSessionRepositorySetMetadataCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -1006,17 +1007,17 @@ func (c *MockSessionRepositorySetMetadataCall) DoAndReturn(f func([]*domain.Sess
|
||||
}
|
||||
|
||||
// SetToken mocks base method.
|
||||
func (m *MockSessionRepository) SetToken(arg0 string) database.Change {
|
||||
func (m *MockSessionRepository) SetToken(token string) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetToken", arg0)
|
||||
ret := m.ctrl.Call(m, "SetToken", token)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetToken indicates an expected call of SetToken.
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetToken(arg0 any) *MockSessionRepositorySetTokenCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetToken(token any) *MockSessionRepositorySetTokenCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetToken", reflect.TypeOf((*MockSessionRepository)(nil).SetToken), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetToken", reflect.TypeOf((*MockSessionRepository)(nil).SetToken), token)
|
||||
return &MockSessionRepositorySetTokenCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -1044,17 +1045,17 @@ func (c *MockSessionRepositorySetTokenCall) DoAndReturn(f func(string) database.
|
||||
}
|
||||
|
||||
// SetUpdatedAt mocks base method.
|
||||
func (m *MockSessionRepository) SetUpdatedAt(arg0 time.Time) database.Change {
|
||||
func (m *MockSessionRepository) SetUpdatedAt(updatedAt time.Time) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetUpdatedAt", arg0)
|
||||
ret := m.ctrl.Call(m, "SetUpdatedAt", updatedAt)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetUpdatedAt indicates an expected call of SetUpdatedAt.
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetUpdatedAt(arg0 any) *MockSessionRepositorySetUpdatedAtCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) SetUpdatedAt(updatedAt any) *MockSessionRepositorySetUpdatedAtCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUpdatedAt", reflect.TypeOf((*MockSessionRepository)(nil).SetUpdatedAt), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUpdatedAt", reflect.TypeOf((*MockSessionRepository)(nil).SetUpdatedAt), updatedAt)
|
||||
return &MockSessionRepositorySetUpdatedAtCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -1081,49 +1082,49 @@ func (c *MockSessionRepositorySetUpdatedAtCall) DoAndReturn(f func(time.Time) da
|
||||
return c
|
||||
}
|
||||
|
||||
// TokenColumn mocks base method.
|
||||
func (m *MockSessionRepository) TokenColumn() database.Column {
|
||||
// TokenIDColumn mocks base method.
|
||||
func (m *MockSessionRepository) TokenIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TokenColumn")
|
||||
ret := m.ctrl.Call(m, "TokenIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TokenColumn indicates an expected call of TokenColumn.
|
||||
func (mr *MockSessionRepositoryMockRecorder) TokenColumn() *MockSessionRepositoryTokenColumnCall {
|
||||
// TokenIDColumn indicates an expected call of TokenIDColumn.
|
||||
func (mr *MockSessionRepositoryMockRecorder) TokenIDColumn() *MockSessionRepositoryTokenIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TokenColumn", reflect.TypeOf((*MockSessionRepository)(nil).TokenColumn))
|
||||
return &MockSessionRepositoryTokenColumnCall{Call: call}
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TokenIDColumn", reflect.TypeOf((*MockSessionRepository)(nil).TokenIDColumn))
|
||||
return &MockSessionRepositoryTokenIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockSessionRepositoryTokenColumnCall wrap *gomock.Call
|
||||
type MockSessionRepositoryTokenColumnCall struct {
|
||||
// MockSessionRepositoryTokenIDColumnCall wrap *gomock.Call
|
||||
type MockSessionRepositoryTokenIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockSessionRepositoryTokenColumnCall) Return(arg0 database.Column) *MockSessionRepositoryTokenColumnCall {
|
||||
func (c *MockSessionRepositoryTokenIDColumnCall) Return(arg0 database.Column) *MockSessionRepositoryTokenIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockSessionRepositoryTokenColumnCall) Do(f func() database.Column) *MockSessionRepositoryTokenColumnCall {
|
||||
func (c *MockSessionRepositoryTokenIDColumnCall) Do(f func() database.Column) *MockSessionRepositoryTokenIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockSessionRepositoryTokenColumnCall) DoAndReturn(f func() database.Column) *MockSessionRepositoryTokenColumnCall {
|
||||
func (c *MockSessionRepositoryTokenIDColumnCall) DoAndReturn(f func() database.Column) *MockSessionRepositoryTokenIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Update mocks base method.
|
||||
func (m *MockSessionRepository) Update(arg0 context.Context, arg1 database.QueryExecutor, arg2 database.Condition, arg3 ...database.Change) (int64, error) {
|
||||
func (m *MockSessionRepository) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{arg0, arg1, arg2}
|
||||
for _, a := range arg3 {
|
||||
varargs := []any{ctx, client, condition}
|
||||
for _, a := range changes {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Update", varargs...)
|
||||
@@ -1133,9 +1134,9 @@ func (m *MockSessionRepository) Update(arg0 context.Context, arg1 database.Query
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update.
|
||||
func (mr *MockSessionRepositoryMockRecorder) Update(arg0, arg1, arg2 any, arg3 ...any) *MockSessionRepositoryUpdateCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) Update(ctx, client, condition any, changes ...any) *MockSessionRepositoryUpdateCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{arg0, arg1, arg2}, arg3...)
|
||||
varargs := append([]any{ctx, client, condition}, changes...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockSessionRepository)(nil).Update), varargs...)
|
||||
return &MockSessionRepositoryUpdateCall{Call: call}
|
||||
}
|
||||
@@ -1202,17 +1203,17 @@ func (c *MockSessionRepositoryUpdatedAtColumnCall) DoAndReturn(f func() database
|
||||
}
|
||||
|
||||
// UpdatedAtCondition mocks base method.
|
||||
func (m *MockSessionRepository) UpdatedAtCondition(arg0 database.NumberOperation, arg1 time.Time) database.Condition {
|
||||
func (m *MockSessionRepository) UpdatedAtCondition(op database.NumberOperation, updatedAt time.Time) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdatedAtCondition", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "UpdatedAtCondition", op, updatedAt)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdatedAtCondition indicates an expected call of UpdatedAtCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) UpdatedAtCondition(arg0, arg1 any) *MockSessionRepositoryUpdatedAtConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) UpdatedAtCondition(op, updatedAt any) *MockSessionRepositoryUpdatedAtConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatedAtCondition", reflect.TypeOf((*MockSessionRepository)(nil).UpdatedAtCondition), arg0, arg1)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatedAtCondition", reflect.TypeOf((*MockSessionRepository)(nil).UpdatedAtCondition), op, updatedAt)
|
||||
return &MockSessionRepositoryUpdatedAtConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -1240,17 +1241,17 @@ func (c *MockSessionRepositoryUpdatedAtConditionCall) DoAndReturn(f func(databas
|
||||
}
|
||||
|
||||
// UserAgentIDCondition mocks base method.
|
||||
func (m *MockSessionRepository) UserAgentIDCondition(arg0 string) database.Condition {
|
||||
func (m *MockSessionRepository) UserAgentIDCondition(userAgentID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UserAgentIDCondition", arg0)
|
||||
ret := m.ctrl.Call(m, "UserAgentIDCondition", userAgentID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UserAgentIDCondition indicates an expected call of UserAgentIDCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) UserAgentIDCondition(arg0 any) *MockSessionRepositoryUserAgentIDConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) UserAgentIDCondition(userAgentID any) *MockSessionRepositoryUserAgentIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserAgentIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).UserAgentIDCondition), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserAgentIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).UserAgentIDCondition), userAgentID)
|
||||
return &MockSessionRepositoryUserAgentIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
@@ -1316,17 +1317,17 @@ func (c *MockSessionRepositoryUserIDColumnCall) DoAndReturn(f func() database.Co
|
||||
}
|
||||
|
||||
// UserIDCondition mocks base method.
|
||||
func (m *MockSessionRepository) UserIDCondition(arg0 string) database.Condition {
|
||||
func (m *MockSessionRepository) UserIDCondition(userID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UserIDCondition", arg0)
|
||||
ret := m.ctrl.Call(m, "UserIDCondition", userID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UserIDCondition indicates an expected call of UserIDCondition.
|
||||
func (mr *MockSessionRepositoryMockRecorder) UserIDCondition(arg0 any) *MockSessionRepositoryUserIDConditionCall {
|
||||
func (mr *MockSessionRepositoryMockRecorder) UserIDCondition(userID any) *MockSessionRepositoryUserIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).UserIDCondition), arg0)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserIDCondition", reflect.TypeOf((*MockSessionRepository)(nil).UserIDCondition), userID)
|
||||
return &MockSessionRepositoryUserIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
|
||||
+139
-291
@@ -320,6 +320,44 @@ func (c *MockUserRepositoryHumanCall) DoAndReturn(f func() domain.HumanUserRepos
|
||||
return c
|
||||
}
|
||||
|
||||
// IDColumn mocks base method.
|
||||
func (m *MockUserRepository) IDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IDColumn indicates an expected call of IDColumn.
|
||||
func (mr *MockUserRepositoryMockRecorder) IDColumn() *MockUserRepositoryIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDColumn", reflect.TypeOf((*MockUserRepository)(nil).IDColumn))
|
||||
return &MockUserRepositoryIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryIDColumnCall wrap *gomock.Call
|
||||
type MockUserRepositoryIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryIDColumnCall) Return(arg0 database.Column) *MockUserRepositoryIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryIDColumnCall) Do(f func() database.Column) *MockUserRepositoryIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryIDColumnCall) DoAndReturn(f func() database.Column) *MockUserRepositoryIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IDCondition mocks base method.
|
||||
func (m *MockUserRepository) IDCondition(userID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -358,6 +396,44 @@ func (c *MockUserRepositoryIDConditionCall) DoAndReturn(f func(string) database.
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDColumn mocks base method.
|
||||
func (m *MockUserRepository) InstanceIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDColumn indicates an expected call of InstanceIDColumn.
|
||||
func (mr *MockUserRepositoryMockRecorder) InstanceIDColumn() *MockUserRepositoryInstanceIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDColumn", reflect.TypeOf((*MockUserRepository)(nil).InstanceIDColumn))
|
||||
return &MockUserRepositoryInstanceIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryInstanceIDColumnCall wrap *gomock.Call
|
||||
type MockUserRepositoryInstanceIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryInstanceIDColumnCall) Return(arg0 database.Column) *MockUserRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryInstanceIDColumnCall) Do(f func() database.Column) *MockUserRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryInstanceIDColumnCall) DoAndReturn(f func() database.Column) *MockUserRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDCondition mocks base method.
|
||||
func (m *MockUserRepository) InstanceIDCondition(instanceID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -440,234 +516,6 @@ func (c *MockUserRepositoryListCall) DoAndReturn(f func(context.Context, databas
|
||||
return c
|
||||
}
|
||||
|
||||
// LoadIdentityProviderLinks mocks base method.
|
||||
func (m *MockUserRepository) LoadIdentityProviderLinks() domain.UserRepository {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LoadIdentityProviderLinks")
|
||||
ret0, _ := ret[0].(domain.UserRepository)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LoadIdentityProviderLinks indicates an expected call of LoadIdentityProviderLinks.
|
||||
func (mr *MockUserRepositoryMockRecorder) LoadIdentityProviderLinks() *MockUserRepositoryLoadIdentityProviderLinksCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIdentityProviderLinks", reflect.TypeOf((*MockUserRepository)(nil).LoadIdentityProviderLinks))
|
||||
return &MockUserRepositoryLoadIdentityProviderLinksCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryLoadIdentityProviderLinksCall wrap *gomock.Call
|
||||
type MockUserRepositoryLoadIdentityProviderLinksCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryLoadIdentityProviderLinksCall) Return(arg0 domain.UserRepository) *MockUserRepositoryLoadIdentityProviderLinksCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryLoadIdentityProviderLinksCall) Do(f func() domain.UserRepository) *MockUserRepositoryLoadIdentityProviderLinksCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryLoadIdentityProviderLinksCall) DoAndReturn(f func() domain.UserRepository) *MockUserRepositoryLoadIdentityProviderLinksCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// LoadKeys mocks base method.
|
||||
func (m *MockUserRepository) LoadKeys() domain.UserRepository {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LoadKeys")
|
||||
ret0, _ := ret[0].(domain.UserRepository)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LoadKeys indicates an expected call of LoadKeys.
|
||||
func (mr *MockUserRepositoryMockRecorder) LoadKeys() *MockUserRepositoryLoadKeysCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadKeys", reflect.TypeOf((*MockUserRepository)(nil).LoadKeys))
|
||||
return &MockUserRepositoryLoadKeysCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryLoadKeysCall wrap *gomock.Call
|
||||
type MockUserRepositoryLoadKeysCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryLoadKeysCall) Return(arg0 domain.UserRepository) *MockUserRepositoryLoadKeysCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryLoadKeysCall) Do(f func() domain.UserRepository) *MockUserRepositoryLoadKeysCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryLoadKeysCall) DoAndReturn(f func() domain.UserRepository) *MockUserRepositoryLoadKeysCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// LoadMetadata mocks base method.
|
||||
func (m *MockUserRepository) LoadMetadata() domain.UserRepository {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LoadMetadata")
|
||||
ret0, _ := ret[0].(domain.UserRepository)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LoadMetadata indicates an expected call of LoadMetadata.
|
||||
func (mr *MockUserRepositoryMockRecorder) LoadMetadata() *MockUserRepositoryLoadMetadataCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadMetadata", reflect.TypeOf((*MockUserRepository)(nil).LoadMetadata))
|
||||
return &MockUserRepositoryLoadMetadataCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryLoadMetadataCall wrap *gomock.Call
|
||||
type MockUserRepositoryLoadMetadataCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryLoadMetadataCall) Return(arg0 domain.UserRepository) *MockUserRepositoryLoadMetadataCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryLoadMetadataCall) Do(f func() domain.UserRepository) *MockUserRepositoryLoadMetadataCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryLoadMetadataCall) DoAndReturn(f func() domain.UserRepository) *MockUserRepositoryLoadMetadataCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// LoadPATs mocks base method.
|
||||
func (m *MockUserRepository) LoadPATs() domain.UserRepository {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LoadPATs")
|
||||
ret0, _ := ret[0].(domain.UserRepository)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LoadPATs indicates an expected call of LoadPATs.
|
||||
func (mr *MockUserRepositoryMockRecorder) LoadPATs() *MockUserRepositoryLoadPATsCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadPATs", reflect.TypeOf((*MockUserRepository)(nil).LoadPATs))
|
||||
return &MockUserRepositoryLoadPATsCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryLoadPATsCall wrap *gomock.Call
|
||||
type MockUserRepositoryLoadPATsCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryLoadPATsCall) Return(arg0 domain.UserRepository) *MockUserRepositoryLoadPATsCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryLoadPATsCall) Do(f func() domain.UserRepository) *MockUserRepositoryLoadPATsCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryLoadPATsCall) DoAndReturn(f func() domain.UserRepository) *MockUserRepositoryLoadPATsCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// LoadPasskeys mocks base method.
|
||||
func (m *MockUserRepository) LoadPasskeys() domain.UserRepository {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LoadPasskeys")
|
||||
ret0, _ := ret[0].(domain.UserRepository)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LoadPasskeys indicates an expected call of LoadPasskeys.
|
||||
func (mr *MockUserRepositoryMockRecorder) LoadPasskeys() *MockUserRepositoryLoadPasskeysCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadPasskeys", reflect.TypeOf((*MockUserRepository)(nil).LoadPasskeys))
|
||||
return &MockUserRepositoryLoadPasskeysCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryLoadPasskeysCall wrap *gomock.Call
|
||||
type MockUserRepositoryLoadPasskeysCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryLoadPasskeysCall) Return(arg0 domain.UserRepository) *MockUserRepositoryLoadPasskeysCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryLoadPasskeysCall) Do(f func() domain.UserRepository) *MockUserRepositoryLoadPasskeysCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryLoadPasskeysCall) DoAndReturn(f func() domain.UserRepository) *MockUserRepositoryLoadPasskeysCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// LoadVerifications mocks base method.
|
||||
func (m *MockUserRepository) LoadVerifications() domain.UserRepository {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LoadVerifications")
|
||||
ret0, _ := ret[0].(domain.UserRepository)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LoadVerifications indicates an expected call of LoadVerifications.
|
||||
func (mr *MockUserRepositoryMockRecorder) LoadVerifications() *MockUserRepositoryLoadVerificationsCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadVerifications", reflect.TypeOf((*MockUserRepository)(nil).LoadVerifications))
|
||||
return &MockUserRepositoryLoadVerificationsCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryLoadVerificationsCall wrap *gomock.Call
|
||||
type MockUserRepositoryLoadVerificationsCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryLoadVerificationsCall) Return(arg0 domain.UserRepository) *MockUserRepositoryLoadVerificationsCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryLoadVerificationsCall) Do(f func() domain.UserRepository) *MockUserRepositoryLoadVerificationsCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryLoadVerificationsCall) DoAndReturn(f func() domain.UserRepository) *MockUserRepositoryLoadVerificationsCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// LoginNameCondition mocks base method.
|
||||
func (m *MockUserRepository) LoginNameCondition(op database.TextOperation, loginName string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -744,116 +592,78 @@ func (c *MockUserRepositoryMachineCall) DoAndReturn(f func() domain.MachineUserR
|
||||
return c
|
||||
}
|
||||
|
||||
// MetadataKeyCondition mocks base method.
|
||||
func (m *MockUserRepository) MetadataKeyCondition(key string) database.Condition {
|
||||
// MetadataConditions mocks base method.
|
||||
func (m *MockUserRepository) MetadataConditions() domain.UserMetadataConditions {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MetadataKeyCondition", key)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
ret := m.ctrl.Call(m, "MetadataConditions")
|
||||
ret0, _ := ret[0].(domain.UserMetadataConditions)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MetadataKeyCondition indicates an expected call of MetadataKeyCondition.
|
||||
func (mr *MockUserRepositoryMockRecorder) MetadataKeyCondition(key any) *MockUserRepositoryMetadataKeyConditionCall {
|
||||
// MetadataConditions indicates an expected call of MetadataConditions.
|
||||
func (mr *MockUserRepositoryMockRecorder) MetadataConditions() *MockUserRepositoryMetadataConditionsCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MetadataKeyCondition", reflect.TypeOf((*MockUserRepository)(nil).MetadataKeyCondition), key)
|
||||
return &MockUserRepositoryMetadataKeyConditionCall{Call: call}
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MetadataConditions", reflect.TypeOf((*MockUserRepository)(nil).MetadataConditions))
|
||||
return &MockUserRepositoryMetadataConditionsCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryMetadataKeyConditionCall wrap *gomock.Call
|
||||
type MockUserRepositoryMetadataKeyConditionCall struct {
|
||||
// MockUserRepositoryMetadataConditionsCall wrap *gomock.Call
|
||||
type MockUserRepositoryMetadataConditionsCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryMetadataKeyConditionCall) Return(arg0 database.Condition) *MockUserRepositoryMetadataKeyConditionCall {
|
||||
func (c *MockUserRepositoryMetadataConditionsCall) Return(arg0 domain.UserMetadataConditions) *MockUserRepositoryMetadataConditionsCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryMetadataKeyConditionCall) Do(f func(string) database.Condition) *MockUserRepositoryMetadataKeyConditionCall {
|
||||
func (c *MockUserRepositoryMetadataConditionsCall) Do(f func() domain.UserMetadataConditions) *MockUserRepositoryMetadataConditionsCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryMetadataKeyConditionCall) DoAndReturn(f func(string) database.Condition) *MockUserRepositoryMetadataKeyConditionCall {
|
||||
func (c *MockUserRepositoryMetadataConditionsCall) DoAndReturn(f func() domain.UserMetadataConditions) *MockUserRepositoryMetadataConditionsCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// MetadataValueCondition mocks base method.
|
||||
func (m *MockUserRepository) MetadataValueCondition(op database.BytesOperation, value []byte) database.Condition {
|
||||
// OrganizationIDCondition mocks base method.
|
||||
func (m *MockUserRepository) OrganizationIDCondition(orgID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MetadataValueCondition", op, value)
|
||||
ret := m.ctrl.Call(m, "OrganizationIDCondition", orgID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MetadataValueCondition indicates an expected call of MetadataValueCondition.
|
||||
func (mr *MockUserRepositoryMockRecorder) MetadataValueCondition(op, value any) *MockUserRepositoryMetadataValueConditionCall {
|
||||
// OrganizationIDCondition indicates an expected call of OrganizationIDCondition.
|
||||
func (mr *MockUserRepositoryMockRecorder) OrganizationIDCondition(orgID any) *MockUserRepositoryOrganizationIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MetadataValueCondition", reflect.TypeOf((*MockUserRepository)(nil).MetadataValueCondition), op, value)
|
||||
return &MockUserRepositoryMetadataValueConditionCall{Call: call}
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrganizationIDCondition", reflect.TypeOf((*MockUserRepository)(nil).OrganizationIDCondition), orgID)
|
||||
return &MockUserRepositoryOrganizationIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryMetadataValueConditionCall wrap *gomock.Call
|
||||
type MockUserRepositoryMetadataValueConditionCall struct {
|
||||
// MockUserRepositoryOrganizationIDConditionCall wrap *gomock.Call
|
||||
type MockUserRepositoryOrganizationIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryMetadataValueConditionCall) Return(arg0 database.Condition) *MockUserRepositoryMetadataValueConditionCall {
|
||||
func (c *MockUserRepositoryOrganizationIDConditionCall) Return(arg0 database.Condition) *MockUserRepositoryOrganizationIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryMetadataValueConditionCall) Do(f func(database.BytesOperation, []byte) database.Condition) *MockUserRepositoryMetadataValueConditionCall {
|
||||
func (c *MockUserRepositoryOrganizationIDConditionCall) Do(f func(string) database.Condition) *MockUserRepositoryOrganizationIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryMetadataValueConditionCall) DoAndReturn(f func(database.BytesOperation, []byte) database.Condition) *MockUserRepositoryMetadataValueConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// OrgIDCondition mocks base method.
|
||||
func (m *MockUserRepository) OrgIDCondition(orgID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OrgIDCondition", orgID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// OrgIDCondition indicates an expected call of OrgIDCondition.
|
||||
func (mr *MockUserRepositoryMockRecorder) OrgIDCondition(orgID any) *MockUserRepositoryOrgIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrgIDCondition", reflect.TypeOf((*MockUserRepository)(nil).OrgIDCondition), orgID)
|
||||
return &MockUserRepositoryOrgIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryOrgIDConditionCall wrap *gomock.Call
|
||||
type MockUserRepositoryOrgIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryOrgIDConditionCall) Return(arg0 database.Condition) *MockUserRepositoryOrgIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryOrgIDConditionCall) Do(f func(string) database.Condition) *MockUserRepositoryOrgIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryOrgIDConditionCall) DoAndReturn(f func(string) database.Condition) *MockUserRepositoryOrgIDConditionCall {
|
||||
func (c *MockUserRepositoryOrganizationIDConditionCall) DoAndReturn(f func(string) database.Condition) *MockUserRepositoryOrganizationIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
@@ -1162,6 +972,44 @@ func (c *MockUserRepositoryStateConditionCall) DoAndReturn(f func(domain.UserSta
|
||||
return c
|
||||
}
|
||||
|
||||
// TypeColumn mocks base method.
|
||||
func (m *MockUserRepository) TypeColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TypeColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TypeColumn indicates an expected call of TypeColumn.
|
||||
func (mr *MockUserRepositoryMockRecorder) TypeColumn() *MockUserRepositoryTypeColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TypeColumn", reflect.TypeOf((*MockUserRepository)(nil).TypeColumn))
|
||||
return &MockUserRepositoryTypeColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserRepositoryTypeColumnCall wrap *gomock.Call
|
||||
type MockUserRepositoryTypeColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserRepositoryTypeColumnCall) Return(arg0 database.Column) *MockUserRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserRepositoryTypeColumnCall) Do(f func() database.Column) *MockUserRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserRepositoryTypeColumnCall) DoAndReturn(f func() database.Column) *MockUserRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// TypeCondition mocks base method.
|
||||
func (m *MockUserRepository) TypeCondition(userType domain.UserType) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -0,0 +1,899 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/zitadel/zitadel/backend/v3/domain (interfaces: UserIdentityProviderLinkRepository)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -typed -package domainmock -destination ./mock/user_identity_provider_link.mock.go . UserIdentityProviderLinkRepository
|
||||
//
|
||||
|
||||
// Package domainmock is a generated GoMock package.
|
||||
package domainmock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
time "time"
|
||||
|
||||
domain "github.com/zitadel/zitadel/backend/v3/domain"
|
||||
database "github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockUserIdentityProviderLinkRepository is a mock of UserIdentityProviderLinkRepository interface.
|
||||
type MockUserIdentityProviderLinkRepository struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockUserIdentityProviderLinkRepositoryMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryMockRecorder is the mock recorder for MockUserIdentityProviderLinkRepository.
|
||||
type MockUserIdentityProviderLinkRepositoryMockRecorder struct {
|
||||
mock *MockUserIdentityProviderLinkRepository
|
||||
}
|
||||
|
||||
// NewMockUserIdentityProviderLinkRepository creates a new mock instance.
|
||||
func NewMockUserIdentityProviderLinkRepository(ctrl *gomock.Controller) *MockUserIdentityProviderLinkRepository {
|
||||
mock := &MockUserIdentityProviderLinkRepository{ctrl: ctrl}
|
||||
mock.recorder = &MockUserIdentityProviderLinkRepositoryMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockUserIdentityProviderLinkRepository) EXPECT() *MockUserIdentityProviderLinkRepositoryMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Create mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) Create(ctx context.Context, client database.QueryExecutor, link *domain.UserIdentityProviderLink) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Create", ctx, client, link)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) Create(ctx, client, link any) *MockUserIdentityProviderLinkRepositoryCreateCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).Create), ctx, client, link)
|
||||
return &MockUserIdentityProviderLinkRepositoryCreateCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryCreateCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryCreateCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryCreateCall) Return(arg0 error) *MockUserIdentityProviderLinkRepositoryCreateCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryCreateCall) Do(f func(context.Context, database.QueryExecutor, *domain.UserIdentityProviderLink) error) *MockUserIdentityProviderLinkRepositoryCreateCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryCreateCall) DoAndReturn(f func(context.Context, database.QueryExecutor, *domain.UserIdentityProviderLink) error) *MockUserIdentityProviderLinkRepositoryCreateCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// CreatedAtColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) CreatedAtColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreatedAtColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CreatedAtColumn indicates an expected call of CreatedAtColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) CreatedAtColumn() *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatedAtColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).CreatedAtColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryCreatedAtColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Delete mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) Delete(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", ctx, client, condition)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) Delete(ctx, client, condition any) *MockUserIdentityProviderLinkRepositoryDeleteCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).Delete), ctx, client, condition)
|
||||
return &MockUserIdentityProviderLinkRepositoryDeleteCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryDeleteCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryDeleteCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryDeleteCall) Return(arg0 int64, arg1 error) *MockUserIdentityProviderLinkRepositoryDeleteCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryDeleteCall) Do(f func(context.Context, database.QueryExecutor, database.Condition) (int64, error)) *MockUserIdentityProviderLinkRepositoryDeleteCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryDeleteCall) DoAndReturn(f func(context.Context, database.QueryExecutor, database.Condition) (int64, error)) *MockUserIdentityProviderLinkRepositoryDeleteCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) Get(ctx context.Context, client database.QueryExecutor, condition database.Condition, opts ...database.QueryOption) (*domain.UserIdentityProviderLink, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{ctx, client, condition}
|
||||
for _, a := range opts {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Get", varargs...)
|
||||
ret0, _ := ret[0].(*domain.UserIdentityProviderLink)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) Get(ctx, client, condition any, opts ...any) *MockUserIdentityProviderLinkRepositoryGetCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{ctx, client, condition}, opts...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).Get), varargs...)
|
||||
return &MockUserIdentityProviderLinkRepositoryGetCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryGetCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryGetCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryGetCall) Return(arg0 *domain.UserIdentityProviderLink, arg1 error) *MockUserIdentityProviderLinkRepositoryGetCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryGetCall) Do(f func(context.Context, database.QueryExecutor, database.Condition, ...database.QueryOption) (*domain.UserIdentityProviderLink, error)) *MockUserIdentityProviderLinkRepositoryGetCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryGetCall) DoAndReturn(f func(context.Context, database.QueryExecutor, database.Condition, ...database.QueryOption) (*domain.UserIdentityProviderLink, error)) *MockUserIdentityProviderLinkRepositoryGetCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IdentityProviderIDColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) IdentityProviderIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IdentityProviderIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IdentityProviderIDColumn indicates an expected call of IdentityProviderIDColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) IdentityProviderIDColumn() *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityProviderIDColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).IdentityProviderIDColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IdentityProviderIDCondition mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) IdentityProviderIDCondition(op database.TextOperation, id string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IdentityProviderIDCondition", op, id)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IdentityProviderIDCondition indicates an expected call of IdentityProviderIDCondition.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) IdentityProviderIDCondition(op, id any) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityProviderIDCondition", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).IdentityProviderIDCondition), op, id)
|
||||
return &MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall) Return(arg0 database.Condition) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall) Do(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall) DoAndReturn(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryIdentityProviderIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) InstanceIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDColumn indicates an expected call of InstanceIDColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) InstanceIDColumn() *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).InstanceIDColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDCondition mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) InstanceIDCondition(op database.TextOperation, id string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDCondition", op, id)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDCondition indicates an expected call of InstanceIDCondition.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) InstanceIDCondition(op, id any) *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDCondition", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).InstanceIDCondition), op, id)
|
||||
return &MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall) Return(arg0 database.Condition) *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall) Do(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall) DoAndReturn(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryInstanceIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// List mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) List(ctx context.Context, client database.QueryExecutor, condition database.Condition, opts ...database.QueryOption) ([]*domain.UserIdentityProviderLink, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{ctx, client, condition}
|
||||
for _, a := range opts {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "List", varargs...)
|
||||
ret0, _ := ret[0].([]*domain.UserIdentityProviderLink)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) List(ctx, client, condition any, opts ...any) *MockUserIdentityProviderLinkRepositoryListCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{ctx, client, condition}, opts...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).List), varargs...)
|
||||
return &MockUserIdentityProviderLinkRepositoryListCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryListCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryListCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryListCall) Return(arg0 []*domain.UserIdentityProviderLink, arg1 error) *MockUserIdentityProviderLinkRepositoryListCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryListCall) Do(f func(context.Context, database.QueryExecutor, database.Condition, ...database.QueryOption) ([]*domain.UserIdentityProviderLink, error)) *MockUserIdentityProviderLinkRepositoryListCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryListCall) DoAndReturn(f func(context.Context, database.QueryExecutor, database.Condition, ...database.QueryOption) ([]*domain.UserIdentityProviderLink, error)) *MockUserIdentityProviderLinkRepositoryListCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// PrimaryKeyColumns mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) PrimaryKeyColumns() []database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PrimaryKeyColumns")
|
||||
ret0, _ := ret[0].([]database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PrimaryKeyColumns indicates an expected call of PrimaryKeyColumns.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) PrimaryKeyColumns() *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrimaryKeyColumns", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).PrimaryKeyColumns))
|
||||
return &MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall) Return(arg0 []database.Column) *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall) Do(f func() []database.Column) *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall) DoAndReturn(f func() []database.Column) *MockUserIdentityProviderLinkRepositoryPrimaryKeyColumnsCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) PrimaryKeyCondition(instanceID, idpID, providedID string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PrimaryKeyCondition", instanceID, idpID, providedID)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition indicates an expected call of PrimaryKeyCondition.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) PrimaryKeyCondition(instanceID, idpID, providedID any) *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrimaryKeyCondition", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).PrimaryKeyCondition), instanceID, idpID, providedID)
|
||||
return &MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall) Return(arg0 database.Condition) *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall) Do(f func(string, string, string) database.Condition) *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall) DoAndReturn(f func(string, string, string) database.Condition) *MockUserIdentityProviderLinkRepositoryPrimaryKeyConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// ProvidedIDColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) ProvidedIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProvidedIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ProvidedIDColumn indicates an expected call of ProvidedIDColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) ProvidedIDColumn() *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidedIDColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).ProvidedIDColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryProvidedIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// ProvidedIDCondition mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) ProvidedIDCondition(op database.TextOperation, id string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProvidedIDCondition", op, id)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ProvidedIDCondition indicates an expected call of ProvidedIDCondition.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) ProvidedIDCondition(op, id any) *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidedIDCondition", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).ProvidedIDCondition), op, id)
|
||||
return &MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall) Return(arg0 database.Condition) *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall) Do(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall) DoAndReturn(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryProvidedIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// ProvidedUsernameColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) ProvidedUsernameColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProvidedUsernameColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ProvidedUsernameColumn indicates an expected call of ProvidedUsernameColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) ProvidedUsernameColumn() *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidedUsernameColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).ProvidedUsernameColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryProvidedUsernameColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// ProvidedUsernameCondition mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) ProvidedUsernameCondition(op database.TextOperation, username string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProvidedUsernameCondition", op, username)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ProvidedUsernameCondition indicates an expected call of ProvidedUsernameCondition.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) ProvidedUsernameCondition(op, username any) *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidedUsernameCondition", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).ProvidedUsernameCondition), op, username)
|
||||
return &MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall) Return(arg0 database.Condition) *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall) Do(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall) DoAndReturn(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryProvidedUsernameConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// SetProvidedUserID mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) SetProvidedUserID(providedID string) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetProvidedUserID", providedID)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetProvidedUserID indicates an expected call of SetProvidedUserID.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) SetProvidedUserID(providedID any) *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetProvidedUserID", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).SetProvidedUserID), providedID)
|
||||
return &MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall) Return(arg0 database.Change) *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall) Do(f func(string) database.Change) *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall) DoAndReturn(f func(string) database.Change) *MockUserIdentityProviderLinkRepositorySetProvidedUserIDCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// SetProvidedUsername mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) SetProvidedUsername(username string) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetProvidedUsername", username)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetProvidedUsername indicates an expected call of SetProvidedUsername.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) SetProvidedUsername(username any) *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetProvidedUsername", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).SetProvidedUsername), username)
|
||||
return &MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall) Return(arg0 database.Change) *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall) Do(f func(string) database.Change) *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall) DoAndReturn(f func(string) database.Change) *MockUserIdentityProviderLinkRepositorySetProvidedUsernameCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// SetUpdatedAt mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) SetUpdatedAt(updatedAt time.Time) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetUpdatedAt", updatedAt)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetUpdatedAt indicates an expected call of SetUpdatedAt.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) SetUpdatedAt(updatedAt any) *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUpdatedAt", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).SetUpdatedAt), updatedAt)
|
||||
return &MockUserIdentityProviderLinkRepositorySetUpdatedAtCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositorySetUpdatedAtCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositorySetUpdatedAtCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall) Return(arg0 database.Change) *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall) Do(f func(time.Time) database.Change) *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall) DoAndReturn(f func(time.Time) database.Change) *MockUserIdentityProviderLinkRepositorySetUpdatedAtCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Update mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{ctx, client, condition}
|
||||
for _, a := range changes {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Update", varargs...)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) Update(ctx, client, condition any, changes ...any) *MockUserIdentityProviderLinkRepositoryUpdateCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{ctx, client, condition}, changes...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).Update), varargs...)
|
||||
return &MockUserIdentityProviderLinkRepositoryUpdateCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryUpdateCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryUpdateCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUpdateCall) Return(arg0 int64, arg1 error) *MockUserIdentityProviderLinkRepositoryUpdateCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUpdateCall) Do(f func(context.Context, database.QueryExecutor, database.Condition, ...database.Change) (int64, error)) *MockUserIdentityProviderLinkRepositoryUpdateCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUpdateCall) DoAndReturn(f func(context.Context, database.QueryExecutor, database.Condition, ...database.Change) (int64, error)) *MockUserIdentityProviderLinkRepositoryUpdateCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdatedAtColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) UpdatedAtColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdatedAtColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdatedAtColumn indicates an expected call of UpdatedAtColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) UpdatedAtColumn() *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatedAtColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).UpdatedAtColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryUpdatedAtColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// UserIDColumn mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) UserIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UserIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UserIDColumn indicates an expected call of UserIDColumn.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) UserIDColumn() *MockUserIdentityProviderLinkRepositoryUserIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserIDColumn", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).UserIDColumn))
|
||||
return &MockUserIdentityProviderLinkRepositoryUserIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryUserIDColumnCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryUserIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUserIDColumnCall) Return(arg0 database.Column) *MockUserIdentityProviderLinkRepositoryUserIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUserIDColumnCall) Do(f func() database.Column) *MockUserIdentityProviderLinkRepositoryUserIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUserIDColumnCall) DoAndReturn(f func() database.Column) *MockUserIdentityProviderLinkRepositoryUserIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// UserIDCondition mocks base method.
|
||||
func (m *MockUserIdentityProviderLinkRepository) UserIDCondition(op database.TextOperation, id string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UserIDCondition", op, id)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UserIDCondition indicates an expected call of UserIDCondition.
|
||||
func (mr *MockUserIdentityProviderLinkRepositoryMockRecorder) UserIDCondition(op, id any) *MockUserIdentityProviderLinkRepositoryUserIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserIDCondition", reflect.TypeOf((*MockUserIdentityProviderLinkRepository)(nil).UserIDCondition), op, id)
|
||||
return &MockUserIdentityProviderLinkRepositoryUserIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockUserIdentityProviderLinkRepositoryUserIDConditionCall wrap *gomock.Call
|
||||
type MockUserIdentityProviderLinkRepositoryUserIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUserIDConditionCall) Return(arg0 database.Condition) *MockUserIdentityProviderLinkRepositoryUserIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUserIDConditionCall) Do(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryUserIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockUserIdentityProviderLinkRepositoryUserIDConditionCall) DoAndReturn(f func(database.TextOperation, string) database.Condition) *MockUserIdentityProviderLinkRepositoryUserIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
// Code generated by "enumer -type PasskeyType -transform lower -trimprefix PasskeyType"; DO NOT EDIT.
|
||||
// Code generated by "enumer -type PasskeyType -transform lower -trimprefix PasskeyType -json -sql"; DO NOT EDIT.
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
@@ -80,3 +82,50 @@ func (i PasskeyType) IsAPasskeyType() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface for PasskeyType
|
||||
func (i PasskeyType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface for PasskeyType
|
||||
func (i *PasskeyType) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return fmt.Errorf("PasskeyType should be a string, got %s", data)
|
||||
}
|
||||
|
||||
var err error
|
||||
*i, err = PasskeyTypeString(s)
|
||||
return err
|
||||
}
|
||||
|
||||
func (i PasskeyType) Value() (driver.Value, error) {
|
||||
return i.String(), nil
|
||||
}
|
||||
|
||||
func (i *PasskeyType) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var str string
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
str = string(v)
|
||||
case string:
|
||||
str = v
|
||||
case fmt.Stringer:
|
||||
str = v.String()
|
||||
default:
|
||||
return fmt.Errorf("invalid value of PasskeyType: %[1]T(%[1]v)", value)
|
||||
}
|
||||
|
||||
val, err := PasskeyTypeString(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*i = val
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
// Code generated by "enumer -type PersonalAccessTokenType -transform lower -trimprefix PersonalAccessTokenType"; DO NOT EDIT.
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const _PersonalAccessTokenTypeName = "unspecifiedbearerjwt"
|
||||
|
||||
var _PersonalAccessTokenTypeIndex = [...]uint8{0, 11, 17, 20}
|
||||
|
||||
const _PersonalAccessTokenTypeLowerName = "unspecifiedbearerjwt"
|
||||
|
||||
func (i PersonalAccessTokenType) String() string {
|
||||
if i >= PersonalAccessTokenType(len(_PersonalAccessTokenTypeIndex)-1) {
|
||||
return fmt.Sprintf("PersonalAccessTokenType(%d)", i)
|
||||
}
|
||||
return _PersonalAccessTokenTypeName[_PersonalAccessTokenTypeIndex[i]:_PersonalAccessTokenTypeIndex[i+1]]
|
||||
}
|
||||
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
func _PersonalAccessTokenTypeNoOp() {
|
||||
var x [1]struct{}
|
||||
_ = x[PersonalAccessTokenTypeUnspecified-(0)]
|
||||
_ = x[PersonalAccessTokenTypeBearer-(1)]
|
||||
_ = x[PersonalAccessTokenTypeJWT-(2)]
|
||||
}
|
||||
|
||||
var _PersonalAccessTokenTypeValues = []PersonalAccessTokenType{PersonalAccessTokenTypeUnspecified, PersonalAccessTokenTypeBearer, PersonalAccessTokenTypeJWT}
|
||||
|
||||
var _PersonalAccessTokenTypeNameToValueMap = map[string]PersonalAccessTokenType{
|
||||
_PersonalAccessTokenTypeName[0:11]: PersonalAccessTokenTypeUnspecified,
|
||||
_PersonalAccessTokenTypeLowerName[0:11]: PersonalAccessTokenTypeUnspecified,
|
||||
_PersonalAccessTokenTypeName[11:17]: PersonalAccessTokenTypeBearer,
|
||||
_PersonalAccessTokenTypeLowerName[11:17]: PersonalAccessTokenTypeBearer,
|
||||
_PersonalAccessTokenTypeName[17:20]: PersonalAccessTokenTypeJWT,
|
||||
_PersonalAccessTokenTypeLowerName[17:20]: PersonalAccessTokenTypeJWT,
|
||||
}
|
||||
|
||||
var _PersonalAccessTokenTypeNames = []string{
|
||||
_PersonalAccessTokenTypeName[0:11],
|
||||
_PersonalAccessTokenTypeName[11:17],
|
||||
_PersonalAccessTokenTypeName[17:20],
|
||||
}
|
||||
|
||||
// PersonalAccessTokenTypeString retrieves an enum value from the enum constants string name.
|
||||
// Throws an error if the param is not part of the enum.
|
||||
func PersonalAccessTokenTypeString(s string) (PersonalAccessTokenType, error) {
|
||||
if val, ok := _PersonalAccessTokenTypeNameToValueMap[s]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
if val, ok := _PersonalAccessTokenTypeNameToValueMap[strings.ToLower(s)]; ok {
|
||||
return val, nil
|
||||
}
|
||||
return 0, fmt.Errorf("%s does not belong to PersonalAccessTokenType values", s)
|
||||
}
|
||||
|
||||
// PersonalAccessTokenTypeValues returns all values of the enum
|
||||
func PersonalAccessTokenTypeValues() []PersonalAccessTokenType {
|
||||
return _PersonalAccessTokenTypeValues
|
||||
}
|
||||
|
||||
// PersonalAccessTokenTypeStrings returns a slice of all String values of the enum
|
||||
func PersonalAccessTokenTypeStrings() []string {
|
||||
strs := make([]string, len(_PersonalAccessTokenTypeNames))
|
||||
copy(strs, _PersonalAccessTokenTypeNames)
|
||||
return strs
|
||||
}
|
||||
|
||||
// IsAPersonalAccessTokenType returns "true" if the value is listed in the enum definition. "false" otherwise
|
||||
func (i PersonalAccessTokenType) IsAPersonalAccessTokenType() bool {
|
||||
for _, v := range _PersonalAccessTokenTypeValues {
|
||||
if i == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
+108
-93
@@ -4,6 +4,8 @@ import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
@@ -15,48 +17,50 @@ type User struct {
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
||||
|
||||
Machine *MachineUser `json:"machine,omitempty" db:"machine"`
|
||||
Human *HumanUser `json:"human,omitempty" db:"human"`
|
||||
Metadata []*UserMetadata `json:"metadata,omitempty" db:"metadata"`
|
||||
Machine *MachineUser `json:"machine,omitempty" db:"-"`
|
||||
Human *HumanUser `json:"human,omitempty" db:"-"`
|
||||
Metadata []*Metadata `json:"metadata,omitempty" db:"metadata"`
|
||||
}
|
||||
|
||||
type MachineUser struct {
|
||||
Name string `json:"name,omitempty" db:"name"`
|
||||
Description string `json:"description,omitempty" db:"description"`
|
||||
Secret string `json:"secret,omitempty" db:"secret"`
|
||||
AccessTokenType PersonalAccessTokenType `json:"access_token_type,omitempty" db:"access_token_type"`
|
||||
Name string `json:"name,omitempty" db:"-"`
|
||||
Description string `json:"description,omitempty" db:"-"`
|
||||
Secret string `json:"secret,omitempty" db:"-"`
|
||||
AccessTokenType AccessTokenType `json:"accessTokenType,omitempty" db:"-"`
|
||||
|
||||
PATs []*PersonalAccessToken `json:"pats,omitempty" db:"pats"`
|
||||
Keys []*MachineKey `json:"keys,omitempty" db:"keys"`
|
||||
PATs []*PersonalAccessToken `json:"pats,omitempty" db:"-"`
|
||||
Keys []*MachineKey `json:"keys,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type HumanUser struct {
|
||||
FirstName string `json:"firstName,omitempty" db:"first_name"`
|
||||
LastName string `json:"lastName,omitempty" db:"last_name"`
|
||||
Nickname string `json:"nickname,omitempty" db:"nickname"`
|
||||
DisplayName string `json:"displayName,omitempty" db:"display_name"`
|
||||
PreferredLanguage language.Tag `json:"preferredLanguage,omitzero" db:"preferred_language"`
|
||||
Gender HumanGender `json:"gender,omitempty" db:"gender"`
|
||||
AvatarKey string `json:"avatarKey,omitempty" db:"avatar_key"`
|
||||
FirstName string `json:"firstName,omitempty" db:"-"`
|
||||
LastName string `json:"lastName,omitempty" db:"-"`
|
||||
Nickname string `json:"nickname,omitempty" db:"-"`
|
||||
DisplayName string `json:"displayName,omitempty" db:"-"`
|
||||
PreferredLanguage language.Tag `json:"preferredLanguage,omitzero" db:"-"`
|
||||
Gender HumanGender `json:"gender,omitempty" db:"-"`
|
||||
AvatarKey string `json:"avatarKey,omitempty" db:"-"`
|
||||
|
||||
MultifactorInitializationSkippedAt time.Time `json:"multifactorInitializationSkippedAt,omitzero" db:"multifactor_initialization_skipped_at"`
|
||||
MultifactorInitializationSkippedAt time.Time `json:"multifactorInitializationSkippedAt,omitzero" db:"-"`
|
||||
|
||||
Email HumanEmail `json:"email,omitzero" db:"email"`
|
||||
Phone *HumanPhone `json:"phone,omitempty" db:"phone"`
|
||||
Passkeys []*Passkey `json:"passkeys,omitempty" db:"passkeys"`
|
||||
Password HumanPassword `json:"password,omitzero" db:"password"`
|
||||
TOTP HumanTOTP `json:"totp,omitzero" db:"totp"`
|
||||
Email HumanEmail `json:"email,omitzero" db:"-"`
|
||||
Phone *HumanPhone `json:"phone,omitempty" db:"-"`
|
||||
Passkeys []*Passkey `json:"passkeys,omitempty" db:"-"`
|
||||
Password HumanPassword `json:"password,omitzero" db:"-"`
|
||||
TOTP *HumanTOTP `json:"totp,omitempty" db:"-"`
|
||||
|
||||
IdentityProviderLinks []*IdentityProviderLink `json:"identityProviderLinks,omitempty" db:"identity_provider_links"`
|
||||
IdentityProviderLinks []*IdentityProviderLink `json:"identityProviderLinks,omitempty" db:"-"`
|
||||
|
||||
Invite *HumanInvite `json:"invite,omitempty" db:"-"`
|
||||
|
||||
// Verifications are used if the Login does something on behalf of the user that requires verification
|
||||
// e.g. starting passkey registration
|
||||
Verifications []*Verification `db:"verifications" json:"verifications,omitempty"`
|
||||
Verifications []*Verification `json:"verifications,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type UserMetadata struct {
|
||||
Metadata
|
||||
UserID string `json:"userId,omitempty" db:"user_id"`
|
||||
UserID string `json:"userId,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
//go:generate enumer -type UserState -transform lower -trimprefix UserState -sql
|
||||
@@ -83,81 +87,84 @@ const (
|
||||
)
|
||||
|
||||
type HumanPassword struct {
|
||||
// Password is the hashed password
|
||||
Password string `json:"-" db:"password"`
|
||||
// Hash is the hashed password
|
||||
Hash string `json:"hash" db:"-"`
|
||||
// IsChangeRequired indicates if the user must change their password
|
||||
IsChangeRequired bool `json:"isChangeRequired,omitempty" db:"is_change_required"`
|
||||
// VerifiedAt is the time when the current password was verified
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"verified_at"`
|
||||
// Unverified is the verification data for setting a new password
|
||||
IsChangeRequired bool `json:"isChangeRequired,omitempty" db:"-"`
|
||||
// ChangedAt is the time when the current password was last updated
|
||||
ChangedAt time.Time `json:"changedAt,omitzero" db:"-"`
|
||||
// PendingVerification is the verification data for setting a new password
|
||||
// If nil, no password change is in progress
|
||||
Unverified *Verification `json:"-"`
|
||||
PendingVerification *Verification `json:"pendingVerification,omitempty" db:"-"`
|
||||
// LastSuccessfullyCheckedAt is the time when the password was last successfully checked
|
||||
LastSuccessfullyCheckedAt *time.Time `json:"lastSuccessfullyCheckedAt,omitzero" db:"-"`
|
||||
// FailedAttempts is the number of consecutive failed password attempts
|
||||
// It is reset to 0 on successful verification
|
||||
FailedAttempts uint8 `json:"failedAttempts,omitempty" db:"failed_attempts"`
|
||||
FailedAttempts uint8 `json:"failedAttempts,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type HumanEmail struct {
|
||||
Address string `json:"address" db:"email"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"verified_at"`
|
||||
OTP OTP `json:"-"`
|
||||
// Unverified is the verification data for setting a new email
|
||||
Address string `json:"address" db:"-"`
|
||||
UnverifiedAddress string `json:"unverifiedAddress,omitempty" db:"-"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"-"`
|
||||
OTP OTP `json:"otp" db:"-"`
|
||||
// PendingVerification is the verification data for UnverifiedAddress
|
||||
// If nil, no email change is in progress
|
||||
Unverified *Verification `json:"-"`
|
||||
PendingVerification *Verification `json:"pendingVerification,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type HumanPhone struct {
|
||||
Number string `json:"number" db:"phone"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"verified_at"`
|
||||
OTP OTP `json:"-"`
|
||||
// Unverified is the verification data for setting a new phone number
|
||||
Number string `json:"number" db:"-"`
|
||||
UnverifiedNumber string `json:"unverifiedNumber,omitempty" db:"-"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"-"`
|
||||
OTP OTP `json:"otp,omitzero" db:"-"`
|
||||
// PendingVerification is the verification data for setting a new phone number
|
||||
// If nil, no phone change is in progress
|
||||
Unverified *Verification `json:"-"`
|
||||
PendingVerification *Verification `json:"pendingVerification,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type HumanTOTP struct {
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"verified_at"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"-"`
|
||||
Secret *crypto.CryptoValue `json:"secret,omitempty" db:"-"`
|
||||
// LastSuccessfullyCheckedAt is the time when the TOTP was last successfully checked
|
||||
LastSuccessfullyCheckedAt *time.Time `json:"lastSuccessfullyCheckedAt,omitzero" db:"-"`
|
||||
|
||||
LastSuccessfullyCheckedAt time.Time `json:"lastSuccessfullyCheckedAt,omitzero" db:"last_successfully_checked_at"`
|
||||
// Check is the verified secret
|
||||
Check *Check `json:"-"`
|
||||
// Unverified is the unverified secret
|
||||
Unverified *Verification `json:"-"`
|
||||
// FailedAttempts is the number of consecutive failed password attempts
|
||||
// It is reset to 0 on successful verification
|
||||
FailedAttempts uint8 `json:"failedAttempts,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type OTP struct {
|
||||
EnabledAt time.Time `json:"enabledAt,omitzero" db:"enabled_at"`
|
||||
LastSuccessfullyCheckedAt time.Time `json:"lastSuccessfullyCheckedAt,omitzero" db:"last_successfully_checked_at"`
|
||||
// Check is the currently active OTP check
|
||||
// If nil, no OTP check is active
|
||||
Check *Check `json:"-"`
|
||||
EnabledAt time.Time `json:"enabledAt,omitzero" db:"-"`
|
||||
// LastSuccessfullyCheckedAt is the time when the OTP was last successfully checked
|
||||
LastSuccessfullyCheckedAt *time.Time `json:"lastSuccessfullyCheckedAt,omitzero" db:"-"`
|
||||
// FailedAttempts is the number of consecutive failed password attempts
|
||||
// It is reset to 0 on successful verification
|
||||
FailedAttempts uint8 `json:"failedAttempts,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
type PersonalAccessToken struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||
ExpiresAt time.Time `json:"expiresAt,omitzero" db:"expires_at"`
|
||||
Type PersonalAccessTokenType `json:"type" db:"type"`
|
||||
PublicKey string `json:"-" db:"public_key"`
|
||||
Scopes []string `json:"scopes" db:"scopes"`
|
||||
ID string `json:"id" db:"-"`
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"-"`
|
||||
ExpiresAt time.Time `json:"expiresAt,omitzero" db:"-"`
|
||||
Scopes []string `json:"scopes" db:"-"`
|
||||
}
|
||||
|
||||
//go:generate enumer -type PersonalAccessTokenType -transform lower -trimprefix PersonalAccessTokenType
|
||||
|
||||
type PersonalAccessTokenType uint8
|
||||
//go:generate enumer -type AccessTokenType -transform lower -trimprefix AccessTokenType
|
||||
type AccessTokenType uint8
|
||||
|
||||
const (
|
||||
PersonalAccessTokenTypeUnspecified PersonalAccessTokenType = iota
|
||||
PersonalAccessTokenTypeBearer
|
||||
PersonalAccessTokenTypeJWT
|
||||
AccessTokenTypeUnspecified AccessTokenType = iota
|
||||
AccessTokenTypeBearer
|
||||
AccessTokenTypeJWT
|
||||
)
|
||||
|
||||
type MachineKey struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
PublicKey []byte `json:"-" db:"public_key"`
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||
ExpiresAt time.Time `json:"expiresAt,omitzero" db:"expires_at"`
|
||||
Type MachineKeyType `json:"type" db:"type"`
|
||||
ID string `json:"id" db:"-"`
|
||||
PublicKey []byte `json:"publicKey" db:"-"`
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"-"`
|
||||
ExpiresAt time.Time `json:"expiresAt,omitzero" db:"-"`
|
||||
Type MachineKeyType `json:"type" db:"-"`
|
||||
}
|
||||
|
||||
//go:generate enumer -type MachineKeyType -transform lower -trimprefix MachineKeyType
|
||||
@@ -165,35 +172,34 @@ type MachineKey struct {
|
||||
type MachineKeyType uint8
|
||||
|
||||
const (
|
||||
MachineKeyTypeUnspecified MachineKeyType = iota
|
||||
MachineKeyTypeNone MachineKeyType = iota
|
||||
MachineKeyTypeJSON
|
||||
MachineKeyTypeNone
|
||||
)
|
||||
|
||||
type Passkey struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
KeyID []byte `json:"-" db:"key_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
SignCount uint32 `json:"-" db:"sign_count"`
|
||||
PublicKey []byte `json:"-" db:"public_key"`
|
||||
AttestationType string `json:"attestationType" db:"attestation_type"`
|
||||
AuthenticatorAttestationGUID []byte `json:"aaGuid" db:"authenticator_attestation_guid"`
|
||||
Type PasskeyType `json:"type" db:"type"`
|
||||
ID string `json:"id" db:"-"`
|
||||
KeyID []byte `json:"keyId" db:"-"`
|
||||
Name string `json:"name" db:"-"`
|
||||
SignCount uint32 `json:"signCount" db:"-"`
|
||||
PublicKey []byte `json:"publicKey" db:"-"`
|
||||
AttestationType string `json:"attestationType" db:"-"`
|
||||
AuthenticatorAttestationGUID []byte `json:"aaGuid" db:"-"`
|
||||
Type PasskeyType `json:"type" db:"-"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"verified_at"`
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"-"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"-"`
|
||||
VerifiedAt time.Time `json:"verifiedAt,omitzero" db:"-"`
|
||||
|
||||
// Challenge is used during device registration
|
||||
Challenge []byte `json:"-" db:"challenge"`
|
||||
Challenge []byte `json:"challenge" db:"-"`
|
||||
// RelyingPartyID is used during device registration
|
||||
RelyingPartyID string `json:"-" db:"relying_party_id"`
|
||||
RelyingPartyID string `json:"rpId" db:"-"`
|
||||
|
||||
// Initialization is used during user registration
|
||||
Initialization *Verification `json:"-" db:"initialization"`
|
||||
Initialization *Verification `json:"-" db:"-"`
|
||||
}
|
||||
|
||||
//go:generate enumer -type PasskeyType -transform lower -trimprefix PasskeyType
|
||||
//go:generate enumer -type PasskeyType -transform lower -trimprefix PasskeyType -json -sql
|
||||
|
||||
type PasskeyType uint8
|
||||
|
||||
@@ -204,12 +210,12 @@ const (
|
||||
)
|
||||
|
||||
type IdentityProviderLink struct {
|
||||
ProviderID string `json:"providerId" db:"provider_id"`
|
||||
ProvidedUserID string `json:"providedUserId" db:"provided_user_id"`
|
||||
ProvidedUsername string `json:"providedUsername" db:"provided_username"`
|
||||
ProviderID string `json:"providerId" db:"-"`
|
||||
ProvidedUserID string `json:"providedUserId" db:"-"`
|
||||
ProvidedUsername string `json:"providedUsername" db:"-"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"-"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"-"`
|
||||
}
|
||||
|
||||
//go:generate enumer -type UserType -transform lower -trimprefix UserType
|
||||
@@ -221,3 +227,12 @@ const (
|
||||
UserTypeHuman
|
||||
UserTypeMachine
|
||||
)
|
||||
|
||||
type HumanInvite struct {
|
||||
AcceptedAt time.Time `json:"acceptedAt,omitzero" db:"-"`
|
||||
// PendingVerification is the verification data for UnverifiedAddress
|
||||
// If nil, no email change is in progress
|
||||
PendingVerification *Verification `json:"pendingVerification,omitempty" db:"-"`
|
||||
// FailedAttempts is the number of consecutive failed invite attempts
|
||||
FailedAttempts uint8 `json:"failedAttempts,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type UserIdentityProviderLink struct {
|
||||
InstanceID string `json:"instanceID" db:"instance_id"`
|
||||
UserID string `json:"userID" db:"user_id"`
|
||||
IdentityProviderID string `json:"identityProviderID" db:"identity_provider_id"`
|
||||
ProvidedID string `json:"providedID" db:"provided_id"`
|
||||
ProvidedUsername string `json:"providedUsername" db:"provided_username"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitempty" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty" db:"updated_at"`
|
||||
}
|
||||
|
||||
//go:generate mockgen -typed -package domainmock -destination ./mock/user_identity_provider_link.mock.go . UserIdentityProviderLinkRepository
|
||||
type UserIdentityProviderLinkRepository interface {
|
||||
Repository
|
||||
userIdentityProviderLinkColumns
|
||||
userIdentityProviderLinkConditions
|
||||
userIdentityProviderLinkChanges
|
||||
|
||||
Get(ctx context.Context, client database.QueryExecutor, condition database.Condition, opts ...database.QueryOption) (*UserIdentityProviderLink, error)
|
||||
List(ctx context.Context, client database.QueryExecutor, condition database.Condition, opts ...database.QueryOption) ([]*UserIdentityProviderLink, error)
|
||||
|
||||
Create(ctx context.Context, client database.QueryExecutor, link *UserIdentityProviderLink) error
|
||||
Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error)
|
||||
Delete(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error)
|
||||
}
|
||||
|
||||
type userIdentityProviderLinkColumns interface {
|
||||
InstanceIDColumn() database.Column
|
||||
UserIDColumn() database.Column
|
||||
IdentityProviderIDColumn() database.Column
|
||||
ProvidedIDColumn() database.Column
|
||||
ProvidedUsernameColumn() database.Column
|
||||
|
||||
CreatedAtColumn() database.Column
|
||||
UpdatedAtColumn() database.Column
|
||||
}
|
||||
|
||||
type userIdentityProviderLinkConditions interface {
|
||||
PrimaryKeyCondition(instanceID, idpID, providedID string) database.Condition
|
||||
InstanceIDCondition(op database.TextOperation, id string) database.Condition
|
||||
UserIDCondition(op database.TextOperation, id string) database.Condition
|
||||
IdentityProviderIDCondition(op database.TextOperation, id string) database.Condition
|
||||
ProvidedIDCondition(op database.TextOperation, id string) database.Condition
|
||||
ProvidedUsernameCondition(op database.TextOperation, username string) database.Condition
|
||||
}
|
||||
|
||||
type userIdentityProviderLinkChanges interface {
|
||||
SetProvidedUsername(username string) database.Change
|
||||
SetUpdatedAt(updatedAt time.Time) database.Change
|
||||
SetProvidedUserID(providedID string) database.Change
|
||||
}
|
||||
+135
-76
@@ -7,6 +7,7 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
//go:generate mockgen -typed -package domainmock -destination ./mock/user.mock.go . UserRepository
|
||||
@@ -22,13 +23,6 @@ type UserRepository interface {
|
||||
Human() HumanUserRepository
|
||||
Machine() MachineUserRepository
|
||||
|
||||
LoadMetadata() UserRepository
|
||||
LoadPasskeys() UserRepository
|
||||
LoadIdentityProviderLinks() UserRepository
|
||||
LoadVerifications() UserRepository
|
||||
LoadPATs() UserRepository
|
||||
LoadKeys() UserRepository
|
||||
|
||||
userConditions
|
||||
userChanges
|
||||
userColumns
|
||||
@@ -37,18 +31,18 @@ type UserRepository interface {
|
||||
type userConditions interface {
|
||||
PrimaryKeyCondition(instanceID, userID string) database.Condition
|
||||
InstanceIDCondition(instanceID string) database.Condition
|
||||
OrgIDCondition(orgID string) database.Condition
|
||||
OrganizationIDCondition(orgID string) database.Condition
|
||||
IDCondition(userID string) database.Condition
|
||||
UsernameCondition(op database.TextOperation, username string) database.Condition
|
||||
StateCondition(state UserState) database.Condition
|
||||
TypeCondition(userType UserType) database.Condition
|
||||
LoginNameCondition(op database.TextOperation, loginName string) database.Condition
|
||||
|
||||
userMetadataConditions
|
||||
ExistsMetadata(condition database.Condition) database.Condition
|
||||
MetadataConditions() UserMetadataConditions
|
||||
}
|
||||
|
||||
type userMetadataConditions interface {
|
||||
ExistsMetadata(condition database.Condition) database.Condition
|
||||
type UserMetadataConditions interface {
|
||||
MetadataKeyCondition(op database.TextOperation, key string) database.Condition
|
||||
MetadataValueCondition(op database.BytesOperation, value []byte) database.Condition
|
||||
}
|
||||
@@ -62,8 +56,8 @@ type userChanges interface {
|
||||
// SetUpdatedAt sets the updated at field
|
||||
// This is used to replay events
|
||||
SetUpdatedAt(updatedAt time.Time) database.Change
|
||||
// AddMetadata adds metadata for the user
|
||||
AddMetadata(metadata ...*Metadata) database.Change
|
||||
// SetMetadata adds metadata for the user
|
||||
SetMetadata(metadata ...*Metadata) database.Change
|
||||
// RemoveMetadata removes the metadata for the user
|
||||
// Use one of the following conditions to specify which metadata to remove:
|
||||
// - [userMetadataConditions.MetadataKeyCondition]
|
||||
@@ -74,6 +68,8 @@ type userChanges interface {
|
||||
|
||||
type userColumns interface {
|
||||
PrimaryKeyColumns() []database.Column
|
||||
InstanceIDColumn() database.Column
|
||||
IDColumn() database.Column
|
||||
UsernameColumn() database.Column
|
||||
StateColumn() database.Column
|
||||
TypeColumn() database.Column
|
||||
@@ -98,18 +94,32 @@ type humanConditions interface {
|
||||
NicknameCondition(op database.TextOperation, nickname string) database.Condition
|
||||
DisplayNameCondition(op database.TextOperation, displayName string) database.Condition
|
||||
PreferredLanguageCondition(lang language.Tag) database.Condition
|
||||
EmailCondition(op database.TextOperation, email string) database.Condition
|
||||
PhoneCondition(op database.TextOperation, phone string) database.Condition
|
||||
PasskeyIDCondition(passkeyID string) database.Condition
|
||||
IdentityProviderIDCondition(idpID string) database.Condition
|
||||
ProvidedUserIDCondition(providedUserID string) database.Condition
|
||||
ProvidedUsernameCondition(username string) database.Condition
|
||||
|
||||
humanPasskeyConditions
|
||||
// EmailCondition searches for the given email in both verified and unverified email columns
|
||||
EmailCondition(op database.TextOperation, email string) database.Condition
|
||||
// UnverifiedEmailCondition searches for the given email in the unverified email column
|
||||
UnverifiedEmailCondition(op database.TextOperation, email string) database.Condition
|
||||
// VerifiedEmailCondition searches for the given email in the verified email column
|
||||
VerifiedEmailCondition(op database.TextOperation, email string) database.Condition
|
||||
|
||||
// PhoneCondition searches for the given phone number in both verified and unverified phone number columns
|
||||
PhoneCondition(op database.TextOperation, phone string) database.Condition
|
||||
// UnverifiedPhoneCondition searches for the given phone number in the unverified phone number column
|
||||
UnverifiedPhoneCondition(op database.TextOperation, phone string) database.Condition
|
||||
// VerifiedPhoneCondition searches for the given phone number in the verified phone number column
|
||||
VerifiedPhoneCondition(op database.TextOperation, phone string) database.Condition
|
||||
|
||||
ExistsPasskey(condition database.Condition) database.Condition
|
||||
PasskeyConditions() HumanPasskeyConditions
|
||||
// ExistsVerification(condition database.Condition) database.Condition
|
||||
// VerificationConditions() HumanVerificationConditions
|
||||
ExistsIdentityProviderLink(condition database.Condition) database.Condition
|
||||
IdentityProviderLinkConditions() HumanIdentityProviderLinkConditions
|
||||
}
|
||||
|
||||
type humanChanges interface {
|
||||
userChanges
|
||||
|
||||
// SetFirstName sets the first name field
|
||||
SetFirstName(firstName string) database.Change
|
||||
// SetLastName sets the last name field
|
||||
@@ -127,99 +137,148 @@ type humanChanges interface {
|
||||
// SetAvatarKey sets the avatar key field
|
||||
// If avatarKey is nil, it will be set to NULL in the database
|
||||
SetAvatarKey(avatarKey *string) database.Change
|
||||
// SetMultifactorInitializationSkippedAt sets the multifactor initialization skipped at field
|
||||
SetMultifactorInitializationSkippedAt(skippedAt time.Time) database.Change
|
||||
|
||||
// SetPassword sets the password based on the verification
|
||||
SetPassword(verification VerificationType) database.Change
|
||||
// SetPasswordChangeRequired sets whether a password change is required
|
||||
SetPasswordChangeRequired(required bool) database.Change
|
||||
// CheckPassword sets the password check based on the check type
|
||||
// * [CheckTypeFailed] increments failed attempts
|
||||
// * [CheckTypeSucceeded] to mark the check as succeeded, removes the check and updates verified at time
|
||||
CheckPassword(check PasswordCheckType) database.Change
|
||||
// SkipMultifactorInitializationAt sets the multifactor initialization skipped at field
|
||||
SkipMultifactorInitializationAt(skippedAt time.Time) database.Change
|
||||
// SkipMultifactorInitializationAt sets the multifactor initialization skipped at field
|
||||
SkipMultifactorInitialization() database.Change
|
||||
|
||||
// SetVerification sets the verification based on the verification type
|
||||
SetVerification(id string, verification VerificationType) database.Change
|
||||
SetVerification(verification VerificationType) database.Change
|
||||
|
||||
humanPasswordChanges
|
||||
humanEmailChanges
|
||||
humanPhoneChanges
|
||||
humanTOTPChanges
|
||||
identityProviderLinkChanges
|
||||
humanPasskeyChanges
|
||||
inviteChanges
|
||||
}
|
||||
|
||||
type humanPasswordChanges interface {
|
||||
// SetPassword overwrites the password field.
|
||||
// It resets the password verification and the last successful password check time.
|
||||
SetPassword(hash string) database.Change
|
||||
// SetResetPassword handles the password reset process based on the verification type:
|
||||
// * [VerificationTypeInit]: to initialize password reset, a verification will be created. The current password remains unchanged
|
||||
// * [VerificationTypeSucceeded]: to mark the password as reset and remove the verification. The current password remains unchanged use [humanPasswordChanges.SetPassword] to set the new password.
|
||||
// * [VerificationTypeUpdate]: to update the existing password reset verification. If a new code is requested, use [VerificationTypeInit].
|
||||
// * [VerificationTypeFailed]: to increment the failed attempts of the verification.
|
||||
SetResetPasswordVerification(verification VerificationType) database.Change
|
||||
// SetPasswordChangeRequired sets whether a password change is required
|
||||
SetPasswordChangeRequired(required bool) database.Change
|
||||
// SetLastSuccessfulPasswordCheck sets the last successful password check time
|
||||
// If checkedAt is zero, it will be set to NOW()
|
||||
SetLastSuccessfulPasswordCheck(checkedAt time.Time) database.Change
|
||||
// IncrementPasswordFailedAttempts increments the password failed attempts
|
||||
IncrementPasswordFailedAttempts() database.Change
|
||||
// ResetPasswordFailedAttempts resets the password failed attempts
|
||||
ResetPasswordFailedAttempts() database.Change
|
||||
}
|
||||
|
||||
type humanEmailChanges interface {
|
||||
// SetEmail sets the email based on the verification
|
||||
// * [VerificationTypeInit] to initialize email verification, previously verified email remains verified
|
||||
// * [VerificationTypeVerified] to mark email as verified, a verification must exist
|
||||
// * [VerificationTypeUpdate] to update email verification, a verification must exist (e.g. resend code)
|
||||
// * [VerificationTypeSkipped] to skip email verification, existing verification is removed (e.g. admin set email)
|
||||
SetEmail(verification VerificationType) database.Change
|
||||
// CheckEmailOTP sets the OTP Email based on the check
|
||||
// * [CheckTypeInit] to initialize a new check, previous check is overwritten
|
||||
// * [CheckTypeFailed] increments failed attempts
|
||||
// * [CheckTypeSucceeded] to mark the check as succeeded, removes the check and updates verified at time
|
||||
CheckEmailOTP(check CheckType) database.Change
|
||||
// EnableEmailOTPAt enables the OTP Email
|
||||
// SetEmail sets the verified email address
|
||||
SetEmail(address string) database.Change
|
||||
// SetUnverifiedEmail sets the unverified email address
|
||||
// Make sure to add [humanEmailChanges.SetEmailVerification] to the changes list.
|
||||
SetUnverifiedEmail(address string) database.Change
|
||||
// SetEmailVerification sets the email verification based on the verification
|
||||
// * [VerificationTypeInit]: to overwrite a email verification, the previously verified email address remains verified.
|
||||
// * [VerificationTypeSucceeded]: to mark the unverified email address as verified and remove the verification.
|
||||
// * [VerificationTypeUpdate]: to update the existing email verification. If a new code is requested, use [VerificationTypeInit].
|
||||
// * [VerificationTypeFailed]: to increment the failed attempts of the verification.
|
||||
SetEmailVerification(verification VerificationType) database.Change
|
||||
// EnableEmailOTPAt enables the email OTP
|
||||
// If enabledAt is zero, it will be set to NOW()
|
||||
EnableEmailOTPAt(enabledAt time.Time) database.Change
|
||||
// EnableEmailOTP sets the enabled at time to NOW()
|
||||
EnableEmailOTP() database.Change
|
||||
// DisableEmailOTP clears the enabled at time
|
||||
DisableEmailOTP() database.Change
|
||||
// SetLastSuccessfulEmailOTPCheck sets the last successful email OTP check time
|
||||
// If checkedAt is zero, it will be set to NOW()
|
||||
// It resets the failed attempts
|
||||
SetLastSuccessfulEmailOTPCheck(checkedAt time.Time) database.Change
|
||||
// IncrementEmailOTPFailedAttempts increments the email OTP failed attempts
|
||||
IncrementEmailOTPFailedAttempts() database.Change
|
||||
// ResetEmailOTPFailedAttempts resets the email OTP failed attempts
|
||||
ResetEmailOTPFailedAttempts() database.Change
|
||||
}
|
||||
|
||||
type humanPhoneChanges interface {
|
||||
// SetPhone sets the phone based on the verification
|
||||
// * [VerificationTypeInit] to initialize phone verification, previously verified phone remains verified
|
||||
// * [VerificationTypeVerified] to mark phone as verified, a verification must exist
|
||||
// * [VerificationTypeUpdate] to update phone verification, a verification must exist (e.g. resend code)
|
||||
// * [VerificationTypeSkipped] to skip phone verification, existing verification is removed (e.g. admin set phone)
|
||||
SetPhone(verification VerificationType) database.Change
|
||||
// SetPhone sets the verified phone number
|
||||
SetPhone(number string) database.Change
|
||||
// SetUnverifiedPhone sets the unverified phone number
|
||||
// Make sure to add [humanPhoneChanges.SetPhoneVerification] to the changes list.
|
||||
SetUnverifiedPhone(number string) database.Change
|
||||
// SetPhoneVerification sets the phone verification based on the verification
|
||||
// * [VerificationTypeInit]: to overwrite a phone verification, the previously verified phone number remains verified.
|
||||
// * [VerificationTypeSucceeded]: to mark the unverified phone number as verified and remove the verification.
|
||||
// * [VerificationTypeUpdate]: to update the existing phone verification. If a new code is requested, use [VerificationTypeInit].
|
||||
// * [VerificationTypeFailed]: to increment the failed attempts of the verification.
|
||||
SetPhoneVerification(verification VerificationType) database.Change
|
||||
// RemovePhone removes the phone number
|
||||
RemovePhone() database.Change
|
||||
// CheckSMSOTP sets the OTP SMS based on the check
|
||||
// * [CheckTypeInit] to initialize a new check, previous check is overwritten
|
||||
// * [CheckTypeFailed] increments failed attempts
|
||||
// * [CheckTypeSucceeded] to mark the check as succeeded, removes the check and updates verified at time
|
||||
CheckSMSOTP(check CheckType) database.Change
|
||||
// EnableSMSOTPAt enables the OTP SMS
|
||||
// EnableSMSOTPAt enables the SMS OTP
|
||||
// If enabledAt is zero, it will be set to NOW()
|
||||
EnableSMSOTPAt(enabledAt time.Time) database.Change
|
||||
// EnableSMSOTP sets the enabled at time to NOW()
|
||||
EnableSMSOTP() database.Change
|
||||
// DisableSMSOTP clears the enabled at time
|
||||
DisableSMSOTP() database.Change
|
||||
// SetLastSuccessfulSMSOTPCheck sets the last successful SMS OTP check time
|
||||
// If checkedAt is zero, it will be set to NOW()
|
||||
// It resets the failed attempts
|
||||
SetLastSuccessfulSMSOTPCheck(checkedAt time.Time) database.Change
|
||||
// IncrementSMSOTPFailedAttempts increments the SMS OTP failed attempts
|
||||
IncrementSMSOTPFailedAttempts() database.Change
|
||||
// ResetSMSOTPFailedAttempts resets the SMS OTP failed attempts
|
||||
ResetSMSOTPFailedAttempts() database.Change
|
||||
}
|
||||
|
||||
type humanTOTPChanges interface {
|
||||
// SetTOTP changes the TOTP secret based on the verification
|
||||
// * [VerificationTypeInit] to initialize totp verification, previously verified totp remains verified
|
||||
// * [VerificationTypeVerified] to mark totp as verified, a verification must exist
|
||||
// * [VerificationTypeUpdate] to update totp verification, a verification must exist (e.g. resend code)
|
||||
// * [VerificationTypeSkipped] to skip totp verification, existing verification is removed (e.g. admin set totp)
|
||||
SetTOTP(verification VerificationType) database.Change
|
||||
// SetTOTPCheck sets the TOTP check based on the check type
|
||||
// * [CheckTypeFailed] increments failed attempts
|
||||
// * [CheckTypeSucceeded] to mark the check as succeeded, removes the check and updates verified at time
|
||||
// * [CheckTypeInit] is not allowed for TOTP
|
||||
CheckTOTP(check CheckType) database.Change
|
||||
// SetTOTP changes the TOTP secret and verification timestamp
|
||||
SetTOTPSecret(secret *crypto.CryptoValue) database.Change
|
||||
// SetTOTPVerifiedAt sets the TOTP verified at time
|
||||
// If verifiedAt is zero, it will be set to NOW()
|
||||
SetTOTPVerifiedAt(verifiedAt time.Time) database.Change
|
||||
// RemoveTOTP removes the TOTP
|
||||
RemoveTOTP() database.Change
|
||||
// SetLastSuccessfulTOTPCheck sets the last successful TOTP check time
|
||||
// If checkedAt is zero, it will be set to NOW()
|
||||
// It resets the failed attempts
|
||||
SetLastSuccessfulTOTPCheck(checkedAt time.Time) database.Change
|
||||
// IncrementTOTPFailedAttempts increments the TOTP failed attempts
|
||||
IncrementTOTPFailedAttempts() database.Change
|
||||
// ResetTOTPFailedAttempts resets the TOTP failed attempts
|
||||
ResetTOTPFailedAttempts() database.Change
|
||||
}
|
||||
|
||||
type identityProviderLinkChanges interface {
|
||||
// AddIdentityProviderLink adds or updates an identity provider link
|
||||
AddIdentityProviderLink(link *IdentityProviderLink) database.Change
|
||||
UpdateIdentityProviderLink(changes ...database.Change) database.Change
|
||||
UpdateIdentityProviderLink(condition database.Condition, changes ...database.Change) database.Change
|
||||
// RemoveIdentityProviderLink removes an identity provider link based on the condition
|
||||
RemoveIdentityProviderLink(providerID, providedUserID string) database.Change
|
||||
|
||||
// SetIdentityProviderLinkUsername sets the username for an identity provider link
|
||||
SetIdentityProviderLinkUsername(providerID, providedUserID, username string) database.Change
|
||||
SetIdentityProviderLinkUsername(username string) database.Change
|
||||
// SetIdentityProviderLinkProvidedID sets the provided user ID for an identity provider link
|
||||
SetIdentityProviderLinkProvidedID(providerID, currentProvidedUserID, newProvidedUserID string) database.Change
|
||||
SetIdentityProviderLinkProvidedID(providedUserID string) database.Change
|
||||
}
|
||||
|
||||
type inviteChanges interface {
|
||||
// SetInviteVerification sets the invite verification based on the verification type:
|
||||
// * [VerificationTypeInit]: to initialize invite verification, a verification will be created. The current accepted at time remains unchanged
|
||||
// * [VerificationTypeSucceeded]: to mark the invite as accepted and remove the verification. The current accepted at time remains unchanged use [inviteChanges.AcceptInvite] to set the accepted at time.
|
||||
// * [VerificationTypeUpdate]: to update the existing invite verification. If a new code is requested, use [VerificationTypeInit].
|
||||
// * [VerificationTypeFailed]: to increment the failed attempts of the verification.
|
||||
SetInviteVerification(verification VerificationType) database.Change
|
||||
}
|
||||
|
||||
type HumanIdentityProviderLinkConditions interface {
|
||||
ProviderIDCondition(providerID string) database.Condition
|
||||
ProvidedUserIDCondition(providedUserID string) database.Condition
|
||||
ProvidedUsernameCondition(op database.TextOperation, username string) database.Condition
|
||||
}
|
||||
|
||||
type humanColumns interface {
|
||||
@@ -256,7 +315,7 @@ type machineChanges interface {
|
||||
// nil will set the secret to NULL in the database
|
||||
SetSecret(secret *string) database.Change
|
||||
// SetAccessTokenType sets the personal access token type field
|
||||
SetAccessTokenType(tokenType PersonalAccessTokenType) database.Change
|
||||
SetAccessTokenType(tokenType AccessTokenType) database.Change
|
||||
|
||||
// AddKey adds a key for the service account
|
||||
AddKey(key *MachineKey) database.Change
|
||||
@@ -273,11 +332,11 @@ type machineColumns interface {
|
||||
userColumns
|
||||
}
|
||||
|
||||
type humanPasskeyConditions interface {
|
||||
PasskeyIDCondition(passkeyID string) database.Condition
|
||||
PasskeyKeyIDCondition(keyID string) database.Condition
|
||||
PasskeyChallengeCondition(challenge string) database.Condition
|
||||
PasskeyTypeCondition(passkeyType PasskeyType) database.Condition
|
||||
type HumanPasskeyConditions interface {
|
||||
IDCondition(passkeyID string) database.Condition
|
||||
KeyIDCondition(keyID string) database.Condition
|
||||
ChallengeCondition(challenge []byte) database.Condition
|
||||
TypeCondition(passkeyType PasskeyType) database.Condition
|
||||
}
|
||||
|
||||
type humanPasskeyChanges interface {
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
type Verification struct {
|
||||
Value *string `db:"value"`
|
||||
Code []byte `db:"code"`
|
||||
ExpiresAt *time.Time `db:"expires_at"`
|
||||
FailedAttempts uint8 `db:"failed_attempts"`
|
||||
VerifiedAt time.Time `db:"verified_at"`
|
||||
ID string `json:"id" db:"id"`
|
||||
Code *crypto.CryptoValue `json:"code" db:"code"`
|
||||
CreatedAt time.Time `json:"createdAt" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
|
||||
ExpiresAt *time.Time `json:"expiresAt" db:"expires_at"`
|
||||
FailedAttempts uint8 `json:"failedAttempts" db:"failed_attempts"`
|
||||
}
|
||||
|
||||
type VerificationType interface {
|
||||
@@ -16,15 +21,16 @@ type VerificationType interface {
|
||||
|
||||
// VerificationTypeInit indicates that an object which needs verification is created.
|
||||
type VerificationTypeInit struct {
|
||||
// ID is the ID of the verification.
|
||||
// The id must be set if the the object can have multiple verifications.
|
||||
ID *string
|
||||
// CreatedAt is the time when the verification was created.
|
||||
// If zero, the current time will be used.
|
||||
CreatedAt time.Time
|
||||
// Expiry is the duration after which the verification expires.
|
||||
Expiry *time.Duration
|
||||
// Code is the code to be used for verification.
|
||||
Code []byte
|
||||
// Value is the value to be set after successful verification.
|
||||
Value *string
|
||||
Code *crypto.CryptoValue
|
||||
}
|
||||
|
||||
// isVerificationType implements [VerificationType].
|
||||
@@ -32,24 +38,31 @@ func (v *VerificationTypeInit) isVerificationType() {}
|
||||
|
||||
var _ VerificationType = (*VerificationTypeInit)(nil)
|
||||
|
||||
// VerificationTypeVerified indicates that the verification was successful.
|
||||
// VerificationTypeSucceeded indicates that the verification was successful.
|
||||
// If VerifiedAt is zero, the current time will be used.
|
||||
// If the Value of the verification is present, it is used as the new value to be set.
|
||||
type VerificationTypeVerified struct {
|
||||
type VerificationTypeSucceeded struct {
|
||||
// ID is the ID of the verification.
|
||||
// The id must be set if the the object can have multiple verifications.
|
||||
ID *string
|
||||
// If zero, the current time will be used.
|
||||
VerifiedAt time.Time
|
||||
}
|
||||
|
||||
// isVerificationType implements [VerificationType].
|
||||
func (v *VerificationTypeVerified) isVerificationType() {}
|
||||
func (v *VerificationTypeSucceeded) isVerificationType() {}
|
||||
|
||||
var _ VerificationType = (*VerificationTypeVerified)(nil)
|
||||
var _ VerificationType = (*VerificationTypeSucceeded)(nil)
|
||||
|
||||
// VerificationTypeUpdate updates an existing verification.
|
||||
// Non-nil fields get updated.
|
||||
type VerificationTypeUpdate struct {
|
||||
Code []byte
|
||||
Value *string
|
||||
// ID is the ID of the verification.
|
||||
// The id must be set if the the object can have multiple verifications.
|
||||
ID *string
|
||||
Code *crypto.CryptoValue
|
||||
Expiry *time.Duration
|
||||
// If zero, the current time will be used.
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// isVerificationType implements [VerificationType].
|
||||
@@ -58,10 +71,12 @@ func (v *VerificationTypeUpdate) isVerificationType() {}
|
||||
var _ VerificationType = (*VerificationTypeUpdate)(nil)
|
||||
|
||||
// VerificationTypeSkipped indicates that the verification was skipped.
|
||||
// If Value is present, it is used as the new value to be set.
|
||||
type VerificationTypeSkipped struct {
|
||||
VerifiedAt time.Time
|
||||
Value *string
|
||||
// ID is the ID of the verification.
|
||||
// The id must be set if the the object can have multiple verifications.
|
||||
ID *string
|
||||
// If zero, the current time will be used.
|
||||
SkippedAt time.Time
|
||||
}
|
||||
|
||||
// isVerificationType implements [VerificationType].
|
||||
@@ -70,6 +85,10 @@ func (v *VerificationTypeSkipped) isVerificationType() {}
|
||||
var _ VerificationType = (*VerificationTypeSkipped)(nil)
|
||||
|
||||
type VerificationTypeFailed struct {
|
||||
// ID is the ID of the verification.
|
||||
// The id must be set if the the object can have multiple verifications.
|
||||
ID *string
|
||||
// If zero, the current time will be used.
|
||||
FailedAt time.Time
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,15 @@ import (
|
||||
"slices"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/instrumentation/logging"
|
||||
)
|
||||
|
||||
// Change represents a change to a column in a database table.
|
||||
// Its written in the SET clause of an UPDATE statement.
|
||||
type Change interface {
|
||||
gomock.Matcher
|
||||
argWriter
|
||||
// Write writes the change to the given statement builder.
|
||||
Write(builder *StatementBuilder) error
|
||||
// IsOnColumn checks if the change is on the given column.
|
||||
@@ -44,6 +47,25 @@ func (c *change[V]) String() string {
|
||||
return "database.change"
|
||||
}
|
||||
|
||||
// WriteArg implements [Change].
|
||||
func (c change[V]) WriteArg(builder *StatementBuilder) {
|
||||
err := c.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write arg failed", "error", err)
|
||||
}
|
||||
|
||||
// Write implements [Change].
|
||||
func (c change[V]) Write(builder *StatementBuilder) error {
|
||||
c.column.WriteUnqualified(builder)
|
||||
builder.WriteString(" = ")
|
||||
builder.WriteArg(c.value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsOnColumn implements [Change].
|
||||
func (c change[V]) IsOnColumn(col Column) bool {
|
||||
return c.column.Equals(col)
|
||||
}
|
||||
|
||||
var (
|
||||
_ Change = (*change[string])(nil)
|
||||
_ gomock.Matcher = (*change[string])(nil)
|
||||
@@ -67,22 +89,9 @@ func NewChangePtr[V Value](col Column, value *V) Change {
|
||||
return NewChange(col, *value)
|
||||
}
|
||||
|
||||
// Write implements [Change].
|
||||
func (c change[V]) Write(builder *StatementBuilder) error {
|
||||
c.column.WriteUnqualified(builder)
|
||||
builder.WriteString(" = ")
|
||||
builder.WriteArg(c.value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsOnColumn implements [Change].
|
||||
func (c change[V]) IsOnColumn(col Column) bool {
|
||||
return c.column.Equals(col)
|
||||
}
|
||||
|
||||
type Changes []Change
|
||||
|
||||
func NewChanges(cols ...Change) Change {
|
||||
func NewChanges(cols ...Change) Changes {
|
||||
return Changes(cols)
|
||||
}
|
||||
|
||||
@@ -152,6 +161,12 @@ func (c Changes) NoChange() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// WriteArg implements [Change].
|
||||
func (c Changes) WriteArg(builder *StatementBuilder) {
|
||||
err := c.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write arg failed", "error", err)
|
||||
}
|
||||
|
||||
var _ Change = Changes(nil)
|
||||
|
||||
func NewChangeToNull(col Column) Change {
|
||||
@@ -194,26 +209,34 @@ func (c *changeToColumn) Write(builder *StatementBuilder) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Change = (*changeToColumn)(nil)
|
||||
|
||||
type incrementColumnChange struct {
|
||||
column Column
|
||||
// WriteArg implements [Change].
|
||||
func (c *changeToColumn) WriteArg(builder *StatementBuilder) {
|
||||
err := c.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write arg failed", "error", err)
|
||||
}
|
||||
|
||||
func NewIncrementColumnChange(col Column) Change {
|
||||
return &incrementColumnChange{
|
||||
var _ Change = (*changeToColumn)(nil)
|
||||
|
||||
type incrementColumnChange[V Value] struct {
|
||||
column Column
|
||||
value V
|
||||
}
|
||||
|
||||
func NewIncrementColumnChange[V Value](col Column, value V) *incrementColumnChange[V] {
|
||||
return &incrementColumnChange[V]{
|
||||
column: col,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// IsOnColumn implements [Change].
|
||||
func (i *incrementColumnChange) IsOnColumn(col Column) bool {
|
||||
func (i incrementColumnChange[V]) IsOnColumn(col Column) bool {
|
||||
return i.column.Equals(col)
|
||||
}
|
||||
|
||||
// Matches implements [Change].
|
||||
func (i *incrementColumnChange) Matches(x any) bool {
|
||||
toMatch, ok := x.(*incrementColumnChange)
|
||||
func (i *incrementColumnChange[V]) Matches(x any) bool {
|
||||
toMatch, ok := x.(*incrementColumnChange[V])
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
@@ -221,20 +244,26 @@ func (i *incrementColumnChange) Matches(x any) bool {
|
||||
}
|
||||
|
||||
// String implements [Change].
|
||||
func (i *incrementColumnChange) String() string {
|
||||
func (i incrementColumnChange[V]) String() string {
|
||||
return "database.incrementColumnChange"
|
||||
}
|
||||
|
||||
// Write implements [Change].
|
||||
func (i *incrementColumnChange) Write(builder *StatementBuilder) error {
|
||||
func (i incrementColumnChange[V]) Write(builder *StatementBuilder) error {
|
||||
i.column.WriteUnqualified(builder)
|
||||
builder.WriteString(" = ")
|
||||
i.column.WriteUnqualified(builder)
|
||||
builder.WriteArg(i.value)
|
||||
builder.WriteString(" + 1")
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Change = (*incrementColumnChange)(nil)
|
||||
// WriteArg implements [Change].
|
||||
func (i incrementColumnChange[V]) WriteArg(builder *StatementBuilder) {
|
||||
err := i.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write arg failed", "error", err)
|
||||
}
|
||||
|
||||
var _ Change = (*incrementColumnChange[any])(nil)
|
||||
|
||||
func NewChangeToStatement(col Column, stmt func(builder *StatementBuilder)) Change {
|
||||
return &changeToStatement{
|
||||
@@ -293,6 +322,12 @@ func (c *changeToStatement) Write(builder *StatementBuilder) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteArg implements [Change].
|
||||
func (c *changeToStatement) WriteArg(builder *StatementBuilder) {
|
||||
err := c.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write arg failed", "error", err)
|
||||
}
|
||||
|
||||
var _ Change = (*changeToStatement)(nil)
|
||||
|
||||
// CTEChange represents a change that uses a Common Table Expression (CTE).
|
||||
@@ -322,7 +357,7 @@ type cteChange struct {
|
||||
}
|
||||
|
||||
// IsOnColumn implements [CTEChange].
|
||||
func (c *cteChange) IsOnColumn(col Column) bool {
|
||||
func (c cteChange) IsOnColumn(col Column) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -335,11 +370,15 @@ func (c *cteChange) Matches(x any) bool {
|
||||
var expectedCTEBuilder, actualCTEBuilder StatementBuilder
|
||||
c.cte(&expectedCTEBuilder)
|
||||
if c.change != nil {
|
||||
c.change(c.name).Write(&expectedCTEBuilder)
|
||||
if err := c.change(c.name).Write(&expectedCTEBuilder); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
toMatch.cte(&actualCTEBuilder)
|
||||
if toMatch.change != nil {
|
||||
toMatch.change(toMatch.name).Write(&actualCTEBuilder)
|
||||
if err := toMatch.change(toMatch.name).Write(&actualCTEBuilder); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if expectedCTEBuilder.String() != actualCTEBuilder.String() {
|
||||
@@ -359,21 +398,26 @@ func (c *cteChange) String() string {
|
||||
}
|
||||
|
||||
// Write implements [CTEChange].
|
||||
func (c *cteChange) Write(builder *StatementBuilder) error {
|
||||
func (c cteChange) Write(builder *StatementBuilder) error {
|
||||
if c.change == nil {
|
||||
return nil
|
||||
}
|
||||
c.change(c.name).Write(builder)
|
||||
return nil
|
||||
return c.change(c.name).Write(builder)
|
||||
}
|
||||
|
||||
// WriteCTE implements [CTEChange].
|
||||
func (c *cteChange) WriteCTE(builder *StatementBuilder) {
|
||||
func (c cteChange) WriteCTE(builder *StatementBuilder) {
|
||||
c.cte(builder)
|
||||
}
|
||||
|
||||
// NoChange implements [NoChange].
|
||||
// It returns true if there is no change function defined.
|
||||
func (c *cteChange) NoChange() bool {
|
||||
func (c cteChange) NoChange() bool {
|
||||
return c.change == nil
|
||||
}
|
||||
|
||||
// WriteArg implements [Change].
|
||||
func (c cteChange) WriteArg(builder *StatementBuilder) {
|
||||
err := c.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write arg failed", "error", err)
|
||||
}
|
||||
|
||||
@@ -42,23 +42,32 @@ func TestChangeWrite(t *testing.T) {
|
||||
args: []any{42},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change to NULL",
|
||||
change: NewChangeToNull(NewColumn("table", "column")),
|
||||
want: want{
|
||||
stmt: "column = NULL",
|
||||
args: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple changes",
|
||||
change: NewChanges(
|
||||
NewChange(NewColumn("table", "column1"), "value1"),
|
||||
NewChangePtr[int](NewColumn("table", "column2"), nil),
|
||||
NewChange(NewColumn("table", "column3"), 123),
|
||||
NewChangeToNull(NewColumn("table", "column4")),
|
||||
),
|
||||
want: want{
|
||||
stmt: "column1 = $1, column2 = NULL, column3 = $2",
|
||||
stmt: "column1 = $1, column2 = NULL, column3 = $2, column4 = NULL",
|
||||
args: []any{"value1", 123},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "increment change",
|
||||
change: NewIncrementColumnChange(NewColumn("table", "counter")),
|
||||
change: NewIncrementColumnChange(NewColumn("table", "counter"), NewColumn("table", "counter")),
|
||||
want: want{
|
||||
stmt: "counter = counter + 1",
|
||||
stmt: "counter = table.counter + 1",
|
||||
},
|
||||
},
|
||||
} {
|
||||
@@ -111,11 +120,11 @@ func TestChangeToStatement(t *testing.T) {
|
||||
name: "change to statement with existing builder args",
|
||||
prefillBuilder: func(builder *StatementBuilder) {
|
||||
builder.WriteString("UPDATE table SET ")
|
||||
NewChanges(
|
||||
assert.NoError(t, NewChanges(
|
||||
NewChange(NewColumn("table", "field1"), "asdf"),
|
||||
NewChangeToNull(NewColumn("table", "field2")),
|
||||
NewChangeToColumn(NewColumn("table", "field3"), NewColumn("table", "field4")),
|
||||
).Write(builder)
|
||||
).Write(builder))
|
||||
builder.WriteString(", ")
|
||||
},
|
||||
change: NewChangeToStatement(NewColumn("table", "column"), func(builder *StatementBuilder) {
|
||||
@@ -135,7 +144,7 @@ func TestChangeToStatement(t *testing.T) {
|
||||
if test.prefillBuilder != nil {
|
||||
test.prefillBuilder(&builder)
|
||||
}
|
||||
test.change.Write(&builder)
|
||||
assert.NoError(t, test.change.Write(&builder))
|
||||
assert.Equal(t, test.want.stmt, builder.String())
|
||||
assert.Equal(t, builder.Args(), test.want.args)
|
||||
})
|
||||
@@ -250,7 +259,7 @@ func TestCTEChange(t *testing.T) {
|
||||
if test.afterCTE != nil {
|
||||
test.afterCTE(&builder)
|
||||
}
|
||||
test.change.Write(&builder)
|
||||
assert.NoError(t, test.change.Write(&builder))
|
||||
|
||||
assert.Equal(t, test.want.stmt, builder.String())
|
||||
assert.Equal(t, builder.Args(), test.want.args)
|
||||
|
||||
@@ -2,6 +2,18 @@ package database
|
||||
|
||||
import "go.uber.org/mock/gomock"
|
||||
|
||||
// Column represents a column in a database table.
|
||||
type Column interface {
|
||||
gomock.Matcher
|
||||
argWriter
|
||||
// WriteQualified writes the column with the table name as prefix.
|
||||
WriteQualified(builder *StatementBuilder)
|
||||
// WriteUnqualified writes the column without the table name as prefix.
|
||||
WriteUnqualified(builder *StatementBuilder)
|
||||
// Equals checks if two columns are equal.
|
||||
Equals(col Column) bool
|
||||
}
|
||||
|
||||
type Columns []Column
|
||||
|
||||
// Matches implements [Column].
|
||||
@@ -59,24 +71,22 @@ func (c Columns) Equals(col Column) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var _ Column = (Columns)(nil)
|
||||
|
||||
// Column represents a column in a database table.
|
||||
type Column interface {
|
||||
gomock.Matcher
|
||||
// WriteQualified writes the column with the table name as prefix.
|
||||
WriteQualified(builder *StatementBuilder)
|
||||
// WriteUnqualified writes the column without the table name as prefix.
|
||||
WriteUnqualified(builder *StatementBuilder)
|
||||
// Equals checks if two columns are equal.
|
||||
Equals(col Column) bool
|
||||
// WriteArg implements [Column].
|
||||
func (c Columns) WriteArg(builder *StatementBuilder) {
|
||||
c.WriteQualified(builder)
|
||||
}
|
||||
|
||||
var _ Column = (Columns)(nil)
|
||||
|
||||
type column struct {
|
||||
table string
|
||||
name string
|
||||
}
|
||||
|
||||
func NewColumn(table, name string) Column {
|
||||
return &column{table: table, name: name}
|
||||
}
|
||||
|
||||
// Matches implements [Column].
|
||||
func (c column) Matches(x any) bool {
|
||||
toMatch, ok := x.(*column)
|
||||
@@ -91,10 +101,6 @@ func (c column) String() string {
|
||||
return "database.column"
|
||||
}
|
||||
|
||||
func NewColumn(table, name string) Column {
|
||||
return &column{table: table, name: name}
|
||||
}
|
||||
|
||||
// WriteQualified implements [Column].
|
||||
func (c column) WriteQualified(builder *StatementBuilder) {
|
||||
builder.Grow(len(c.table) + len(c.name) + 1)
|
||||
@@ -120,6 +126,26 @@ func (c *column) Equals(col Column) bool {
|
||||
return c.table == toMatch.table && c.name == toMatch.name
|
||||
}
|
||||
|
||||
// WriteArg implements [Column].
|
||||
func (c column) WriteArg(builder *StatementBuilder) {
|
||||
c.WriteQualified(builder)
|
||||
}
|
||||
|
||||
var _ Column = (*column)(nil)
|
||||
|
||||
type functionColumn struct {
|
||||
fn function
|
||||
col Column
|
||||
}
|
||||
|
||||
type function string
|
||||
|
||||
const (
|
||||
_ function = ""
|
||||
functionLower function = "LOWER"
|
||||
functionSHA256 function = "SHA256"
|
||||
)
|
||||
|
||||
// LowerColumn returns a column that represents LOWER(col).
|
||||
func LowerColumn(col Column) Column {
|
||||
return &functionColumn{fn: functionLower, col: col}
|
||||
@@ -130,11 +156,6 @@ func SHA256Column(col Column) Column {
|
||||
return &functionColumn{fn: functionSHA256, col: col}
|
||||
}
|
||||
|
||||
type functionColumn struct {
|
||||
fn function
|
||||
col Column
|
||||
}
|
||||
|
||||
// Matches implements [Column].
|
||||
func (c *functionColumn) Matches(x any) bool {
|
||||
toMatch, ok := x.(*functionColumn)
|
||||
@@ -155,14 +176,6 @@ func (c *functionColumn) String() string {
|
||||
return "database.functionColumn"
|
||||
}
|
||||
|
||||
type function string
|
||||
|
||||
const (
|
||||
_ function = ""
|
||||
functionLower function = "LOWER"
|
||||
functionSHA256 function = "SHA256"
|
||||
)
|
||||
|
||||
// WriteQualified implements [Column].
|
||||
func (c functionColumn) WriteQualified(builder *StatementBuilder) {
|
||||
builder.Grow(len(c.fn) + 2)
|
||||
@@ -193,4 +206,9 @@ func (c *functionColumn) Equals(col Column) bool {
|
||||
return c.col.Equals(toMatch.col)
|
||||
}
|
||||
|
||||
// WriteArg implements [Column].
|
||||
func (c functionColumn) WriteArg(builder *StatementBuilder) {
|
||||
c.WriteQualified(builder)
|
||||
}
|
||||
|
||||
var _ Column = (*functionColumn)(nil)
|
||||
|
||||
@@ -14,7 +14,6 @@ CREATE TABLE zitadel.authorizations
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (instance_id, id),
|
||||
-- FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users (instance_id, id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (instance_id, project_id) REFERENCES zitadel.projects (instance_id, id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (instance_id, grant_id) REFERENCES zitadel.project_grants (instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -22,7 +22,6 @@ CREATE TABLE zitadel.sessions (
|
||||
|
||||
, PRIMARY KEY (instance_id, id)
|
||||
, FOREIGN KEY (instance_id) REFERENCES zitadel.instances(id)
|
||||
-- , FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE
|
||||
, FOREIGN KEY (instance_id, user_agent_id) REFERENCES zitadel.session_user_agents(instance_id, fingerprint_id) ON DELETE SET NULL (user_agent_id)
|
||||
);
|
||||
|
||||
|
||||
-2
@@ -31,8 +31,6 @@ CREATE TABLE zitadel.identity_provider_intents
|
||||
expires_at TIMESTAMPTZ,
|
||||
|
||||
PRIMARY KEY (instance_id, id),
|
||||
-- TODO(@adlerhurst): easiest would be to create the index in the user migrations so that we can merge this one but the problem is that the migration might fail if there are already intents created.
|
||||
-- FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users (instance_id, id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (instance_id, idp_id) REFERENCES zitadel.identity_providers (instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package migration
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed 013_user_table/up.sql
|
||||
up013UserTable string
|
||||
//go:embed 013_user_table/down.sql
|
||||
down013UserTable string
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerSQLMigration(13, up013UserTable, down013UserTable)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
DROP TABLE IF EXISTS zitadel.user_identity_provider_links;
|
||||
DROP TABLE IF EXISTS zitadel.user_passkeys;
|
||||
DROP TYPE IF EXISTS zitadel.passkey_type;
|
||||
DROP TABLE IF EXISTS zitadel.machine_keys;
|
||||
DROP TABLE IF EXISTS zitadel.user_personal_access_tokens;
|
||||
DROP TABLE IF EXISTS zitadel.user_metadata CASCADE;
|
||||
|
||||
ALTER TABLE zitadel.identity_provider_intents DROP CONSTRAINT IF EXISTS fk_idp_intent_user;
|
||||
ALTER TABLE zitadel.sessions DROP CONSTRAINT IF EXISTS fk_session_user;
|
||||
ALTER TABLE zitadel.authorizations DROP CONSTRAINT IF EXISTS fk_authorization_user;
|
||||
|
||||
DROP TABLE IF EXISTS zitadel.users;
|
||||
DROP TYPE IF EXISTS zitadel.user_type;
|
||||
DROP TYPE IF EXISTS zitadel.user_state;
|
||||
@@ -0,0 +1,228 @@
|
||||
CREATE TYPE zitadel.user_state AS ENUM (
|
||||
'initial'
|
||||
, 'active'
|
||||
, 'inactive'
|
||||
, 'locked'
|
||||
, 'suspended'
|
||||
);
|
||||
|
||||
CREATE TYPE zitadel.user_type AS ENUM (
|
||||
'human'
|
||||
, 'machine'
|
||||
);
|
||||
|
||||
CREATE TABLE zitadel.users(
|
||||
instance_id TEXT NOT NULL
|
||||
, organization_id TEXT NOT NULL
|
||||
, id TEXT NOT NULL CHECK (id <> '')
|
||||
|
||||
, username TEXT NOT NULL CHECK (username <> '')
|
||||
, username_org_unique BOOLEAN DEFAULT FALSE NOT NULL -- this field MUST be filled if the username must be unique on organization level
|
||||
, state zitadel.user_state NOT NULL DEFAULT 'active'
|
||||
, type zitadel.user_type NOT NULL
|
||||
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
|
||||
, PRIMARY KEY (instance_id, id)
|
||||
, FOREIGN KEY (instance_id, organization_id) REFERENCES zitadel.organizations(instance_id, id) ON DELETE CASCADE
|
||||
|
||||
-- human
|
||||
|
||||
, first_name TEXT CHECK ((type = 'machine' AND first_name IS NULL) OR (type = 'human' AND first_name <> ''))
|
||||
, last_name TEXT CHECK ((type = 'machine' AND last_name IS NULL) OR (type = 'human' AND last_name <> ''))
|
||||
, nickname TEXT CHECK ((type = 'machine' AND nickname IS NULL) OR (type = 'human'))
|
||||
, display_name TEXT CHECK ((type = 'machine' AND display_name IS NULL) OR (type = 'human'))
|
||||
, preferred_language TEXT CHECK ((type = 'machine' AND preferred_language IS NULL) OR (type = 'human'))
|
||||
, gender SMALLINT CHECK ((type = 'machine' AND gender IS NULL) OR (type = 'human'))
|
||||
, avatar_key TEXT CHECK ((type = 'machine' AND avatar_key IS NULL) OR (type = 'human'))
|
||||
, multifactor_initialization_skipped_at TIMESTAMPTZ CHECK ((type = 'machine' AND multifactor_initialization_skipped_at IS NULL) OR (type = 'human'))
|
||||
|
||||
, password_hash TEXT CHECK ((type = 'machine' AND password_hash IS NULL) OR (type = 'human'))
|
||||
, password_change_required BOOLEAN CHECK ((type = 'machine' AND password_change_required IS NULL) OR (type = 'human'))
|
||||
, password_changed_at TIMESTAMPTZ CHECK ((type = 'machine' AND password_changed_at IS NULL) OR (type = 'human'))
|
||||
, password_verification_id TEXT CHECK ((type = 'machine' AND password_verification_id IS NULL) OR (type = 'human')) -- used for reset password flow
|
||||
, password_last_successful_check TIMESTAMPTZ CHECK ((type = 'machine' AND password_last_successful_check IS NULL) OR (type = 'human'))
|
||||
, password_failed_attempts SMALLINT CHECK ((type = 'machine' AND password_failed_attempts IS NULL) OR (type = 'human') AND (password_failed_attempts >= 0))
|
||||
|
||||
, email TEXT CHECK ((type = 'machine' AND email IS NULL) OR (type = 'human'))
|
||||
, unverified_email TEXT CHECK ((type = 'machine' AND unverified_email IS NULL) OR (type = 'human' AND unverified_email <> '')) -- after successful verification this column is not cleared.
|
||||
, email_verified_at TIMESTAMPTZ CHECK ((type = 'machine' AND email_verified_at IS NULL) OR (type = 'human'))
|
||||
, email_verification_id TEXT CHECK ((type = 'machine' AND email_verification_id IS NULL) OR (type = 'human' AND (email IS DISTINCT FROM unverified_email OR email_verification_id IS NULL)))
|
||||
, email_otp_enabled_at TIMESTAMPTZ CHECK ((type = 'machine' AND email_otp_enabled_at IS NULL) OR (type = 'human'))
|
||||
, email_otp_last_successful_check TIMESTAMPTZ CHECK ((type = 'machine' AND email_otp_last_successful_check IS NULL) OR (type = 'human'))
|
||||
, email_otp_failed_attempts SMALLINT CHECK ((type = 'machine' AND email_otp_failed_attempts IS NULL) OR (type = 'human'))
|
||||
|
||||
, phone TEXT CHECK ((type = 'machine' AND phone IS NULL) OR (type = 'human'))
|
||||
, unverified_phone TEXT CHECK ((type = 'machine' AND unverified_phone IS NULL) OR (type = 'human')) -- after successful verification this column is not cleared.
|
||||
, phone_verified_at TIMESTAMPTZ CHECK ((type = 'machine' AND phone_verified_at IS NULL) OR (type = 'human'))
|
||||
, phone_verification_id TEXT CHECK ((type = 'machine' AND phone_verification_id IS NULL) OR (type = 'human' AND (phone IS DISTINCT FROM unverified_phone OR phone_verification_id IS NULL)))
|
||||
, sms_otp_enabled_at TIMESTAMPTZ CHECK ((type = 'machine' AND sms_otp_enabled_at IS NULL) OR (type = 'human'))
|
||||
, sms_otp_last_successful_check TIMESTAMPTZ CHECK ((type = 'machine' AND sms_otp_last_successful_check IS NULL) OR (type = 'human'))
|
||||
, sms_otp_failed_attempts SMALLINT CHECK ((type = 'machine' AND sms_otp_failed_attempts IS NULL) OR (type = 'human'))
|
||||
|
||||
, totp_secret BYTEA CHECK ((type = 'machine' AND totp_secret IS NULL) OR (type = 'human'))
|
||||
, totp_verified_at TIMESTAMPTZ CHECK ((type = 'machine' AND totp_verified_at IS NULL) OR (type = 'human'))
|
||||
, totp_last_successful_check TIMESTAMPTZ CHECK ((type = 'machine' AND totp_last_successful_check IS NULL) OR (type = 'human'))
|
||||
, totp_failed_attempts SMALLINT CHECK ((type = 'machine' AND totp_failed_attempts IS NULL) OR (type = 'human'))
|
||||
|
||||
, invite_verification_id TEXT CHECK ((type = 'machine' AND invite_verification_id IS NULL) OR (type = 'human'))
|
||||
, invite_accepted_at TIMESTAMPTZ CHECK ((type = 'machine' AND invite_accepted_at IS NULL) OR (type = 'human'))
|
||||
, invite_failed_attempts SMALLINT CHECK ((type = 'machine' AND invite_failed_attempts IS NULL) OR (type = 'human'))
|
||||
|
||||
-- foreign keys for verifications are created in the verification migration
|
||||
|
||||
-- machine
|
||||
|
||||
, name TEXT CHECK ((type = 'human' AND name IS NULL) OR (type = 'machine'))
|
||||
, description TEXT CHECK ((type = 'human' AND description IS NULL) OR (type = 'machine'))
|
||||
, secret TEXT CHECK ((type = 'human' AND secret IS NULL) OR (type = 'machine'))
|
||||
, access_token_type SMALLINT CHECK ((type = 'human' AND access_token_type IS NULL) OR (type = 'machine'))
|
||||
);
|
||||
|
||||
-- previously created tables
|
||||
ALTER TABLE zitadel.identity_provider_intents ADD CONSTRAINT fk_idp_intent_user FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users (instance_id, id) ON DELETE CASCADE;
|
||||
ALTER TABLE zitadel.sessions ADD CONSTRAINT fk_session_user FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE;
|
||||
ALTER TABLE zitadel.authorizations ADD CONSTRAINT fk_authorization_user FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users (instance_id, id) ON DELETE CASCADE;
|
||||
|
||||
-- user
|
||||
CREATE UNIQUE INDEX ON zitadel.users(instance_id, organization_id, username) WHERE username_org_unique IS TRUE; --TODO(adlerhurst): does that work if a username is already present on a user without org unique?
|
||||
CREATE UNIQUE INDEX ON zitadel.users(instance_id, username) WHERE username_org_unique IS FALSE;
|
||||
CREATE INDEX idx_user_username ON zitadel.users (username);
|
||||
CREATE INDEX idx_user_username_lower ON zitadel.users (lower(username));
|
||||
CREATE INDEX idx_machine_name ON zitadel.users (name);
|
||||
CREATE INDEX idx_human_email ON zitadel.users (email);
|
||||
CREATE INDEX idx_human_email_lower ON zitadel.users (lower(email));
|
||||
CREATE INDEX idx_human_phone ON zitadel.users (phone);
|
||||
CREATE INDEX idx_human_phone_lower ON zitadel.users (lower(phone));
|
||||
|
||||
-- human
|
||||
CREATE UNIQUE INDEX ON zitadel.users(password_verification_id) WHERE password_verification_id IS NOT NULL;
|
||||
CREATE UNIQUE INDEX ON zitadel.users(email_verification_id) WHERE email_verification_id IS NOT NULL;
|
||||
CREATE UNIQUE INDEX ON zitadel.users(phone_verification_id) WHERE phone_verification_id IS NOT NULL;
|
||||
|
||||
CREATE TRIGGER trigger_set_updated_at
|
||||
BEFORE UPDATE ON zitadel.users
|
||||
FOR EACH ROW
|
||||
WHEN (NEW.updated_at IS NULL)
|
||||
EXECUTE FUNCTION zitadel.set_updated_at();
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- user metadata
|
||||
-- ----------------------------------------------------------------
|
||||
|
||||
CREATE TABLE zitadel.user_metadata (
|
||||
instance_id TEXT NOT NULL
|
||||
, user_id TEXT NOT NULL
|
||||
, key TEXT NOT NULL CHECK (key <> '')
|
||||
, value BYTEA NOT NULL
|
||||
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
|
||||
, PRIMARY KEY (instance_id, user_id, key)
|
||||
, FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users (instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_user_metadata_key ON zitadel.user_metadata (key);
|
||||
CREATE INDEX idx_user_metadata_value ON zitadel.user_metadata (sha256(value));
|
||||
|
||||
CREATE TRIGGER trg_set_updated_at_user_metadata
|
||||
BEFORE INSERT OR UPDATE ON zitadel.user_metadata
|
||||
FOR EACH ROW
|
||||
WHEN (NEW.updated_at IS NULL)
|
||||
EXECUTE FUNCTION zitadel.set_updated_at();
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- personal access tokens
|
||||
-- ----------------------------------------------------------------
|
||||
|
||||
CREATE TABLE zitadel.user_personal_access_tokens(
|
||||
instance_id TEXT NOT NULL
|
||||
, user_id TEXT NOT NULL
|
||||
|
||||
, id TEXT NOT NULL
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, expires_at TIMESTAMPTZ
|
||||
, scopes TEXT[]
|
||||
|
||||
, PRIMARY KEY (instance_id, id)
|
||||
, FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- machine keys
|
||||
-- ----------------------------------------------------------------
|
||||
|
||||
CREATE TABLE zitadel.machine_keys(
|
||||
instance_id TEXT NOT NULL
|
||||
, user_id TEXT NOT NULL
|
||||
|
||||
, id TEXT NOT NULL
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, expires_at TIMESTAMPTZ
|
||||
|
||||
, type SMALLINT NOT NULL CHECK (type >= 0)
|
||||
, public_key BYTEA NOT NULL
|
||||
|
||||
, PRIMARY KEY (instance_id, id)
|
||||
, FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- passkeys
|
||||
-- ----------------------------------------------------------------
|
||||
|
||||
CREATE TYPE zitadel.passkey_type AS ENUM (
|
||||
'passwordless'
|
||||
, 'u2f'
|
||||
);
|
||||
|
||||
CREATE TABLE zitadel.user_passkeys(
|
||||
instance_id TEXT NOT NULL
|
||||
, token_id TEXT NOT NULL
|
||||
, key_id BYTEA NOT NULL
|
||||
|
||||
, user_id TEXT NOT NULL
|
||||
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, verified_at TIMESTAMPTZ
|
||||
|
||||
, type zitadel.passkey_type NOT NULL
|
||||
, name TEXT NOT NULL CHECK (name <> '')
|
||||
, sign_count INT NOT NULL DEFAULT 0 CHECK (sign_count >= 0)
|
||||
, challenge BYTEA NOT NULL
|
||||
, public_key BYTEA NOT NULL
|
||||
, attestation_type TEXT NOT NULL CHECK (attestation_type <> '')
|
||||
, authenticator_attestation_guid BYTEA NOT NULL
|
||||
, relying_party_id TEXT NOT NULL CHECK (relying_party_id <> '')
|
||||
|
||||
, PRIMARY KEY (instance_id, token_id)
|
||||
, FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_user_passkeys_challenge ON zitadel.user_passkeys (sha256(challenge));
|
||||
CREATE INDEX idx_user_passkeys_key_id ON zitadel.user_passkeys (key_id);
|
||||
CREATE INDEX idx_user_passkeys_type ON zitadel.user_passkeys (type);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- identity provider links
|
||||
-- ----------------------------------------------------------------
|
||||
|
||||
CREATE TABLE zitadel.user_identity_provider_links(
|
||||
instance_id TEXT NOT NULL
|
||||
, identity_provider_id TEXT NOT NULL
|
||||
, user_id TEXT NOT NULL
|
||||
|
||||
, provided_user_id TEXT NOT NULL CHECK(provided_user_id <> '')
|
||||
, provided_username TEXT NOT NULL
|
||||
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
|
||||
, PRIMARY KEY (instance_id, identity_provider_id, provided_user_id)
|
||||
|
||||
, FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE
|
||||
, FOREIGN KEY (instance_id, identity_provider_id) REFERENCES zitadel.identity_providers(instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -0,0 +1,16 @@
|
||||
package migration
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed 014_verification_table/up.sql
|
||||
up014VerificationTable string
|
||||
//go:embed 014_verification_table/down.sql
|
||||
down014VerificationTable string
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerSQLMigration(14, up014VerificationTable, down014VerificationTable)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE zitadel.users DROP CONSTRAINT IF EXISTS fk_unverified_password;
|
||||
ALTER TABLE zitadel.users DROP CONSTRAINT IF EXISTS fk_unverified_email;
|
||||
ALTER TABLE zitadel.users DROP CONSTRAINT IF EXISTS fk_unverified_phone;
|
||||
|
||||
DROP TRIGGER IF EXISTS user_verification_integrity_trigger ON zitadel.users;
|
||||
DROP FUNCTION IF EXISTS zitadel.ensure_user_verification_integrity() CASCADE;
|
||||
DROP TABLE IF EXISTS zitadel.verifications CASCADE;
|
||||
@@ -0,0 +1,61 @@
|
||||
CREATE TABLE zitadel.verifications(
|
||||
instance_id TEXT NOT NULL
|
||||
, user_id TEXT
|
||||
, id TEXT NOT NULL DEFAULT gen_random_uuid()::TEXT
|
||||
|
||||
, code BYTEA
|
||||
|
||||
, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
, expiry INTERVAL
|
||||
|
||||
, failed_attempts SMALLINT NOT NULL DEFAULT 0 CHECK (failed_attempts >= 0)
|
||||
|
||||
, PRIMARY KEY (instance_id, id)
|
||||
, FOREIGN KEY (instance_id, user_id) REFERENCES zitadel.users(instance_id, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
ALTER TABLE zitadel.users ADD CONSTRAINT fk_unverified_password FOREIGN KEY (instance_id, password_verification_id) REFERENCES zitadel.verifications(instance_id, id) ON DELETE SET NULL (password_verification_id);
|
||||
ALTER TABLE zitadel.users ADD CONSTRAINT fk_unverified_email FOREIGN KEY (instance_id, email_verification_id) REFERENCES zitadel.verifications(instance_id, id) ON DELETE SET NULL (email_verification_id);
|
||||
ALTER TABLE zitadel.users ADD CONSTRAINT fk_unverified_phone FOREIGN KEY (instance_id, phone_verification_id) REFERENCES zitadel.verifications(instance_id, id) ON DELETE SET NULL (phone_verification_id);
|
||||
|
||||
CREATE OR REPLACE FUNCTION zitadel.ensure_user_verification_integrity() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
IF (NEW.password_verification_id IS DISTINCT FROM OLD.password_verification_id) THEN
|
||||
DELETE FROM zitadel.verifications
|
||||
WHERE instance_id = NEW.instance_id
|
||||
AND id = OLD.password_verification_id;
|
||||
END IF;
|
||||
|
||||
IF (NEW.email_verification_id IS DISTINCT FROM OLD.email_verification_id) THEN
|
||||
DELETE FROM zitadel.verifications
|
||||
WHERE instance_id = NEW.instance_id
|
||||
AND id = OLD.email_verification_id;
|
||||
END IF;
|
||||
|
||||
IF (NEW.phone_verification_id IS DISTINCT FROM OLD.phone_verification_id) THEN
|
||||
DELETE FROM zitadel.verifications
|
||||
WHERE instance_id = NEW.instance_id
|
||||
AND id = OLD.phone_verification_id;
|
||||
END IF;
|
||||
|
||||
IF (NEW.invite_verification_id IS DISTINCT FROM OLD.invite_verification_id) THEN
|
||||
DELETE FROM zitadel.verifications
|
||||
WHERE instance_id = NEW.instance_id
|
||||
AND id = OLD.invite_verification_id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER user_verification_integrity_trigger
|
||||
AFTER UPDATE ON zitadel.users
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION zitadel.ensure_user_verification_integrity();
|
||||
|
||||
CREATE TRIGGER trigger_set_updated_at
|
||||
BEFORE UPDATE ON zitadel.verifications
|
||||
FOR EACH ROW
|
||||
WHEN (NEW.updated_at IS NULL)
|
||||
EXECUTE FUNCTION zitadel.set_updated_at();
|
||||
@@ -435,6 +435,8 @@ func TestServer_AuthorizationReduces(t *testing.T) {
|
||||
}
|
||||
|
||||
func createAndEnsureAuthorization(t *testing.T, instanceID, orgID, userID, projectID string, roles []string, retryDuration time.Duration, tick time.Duration) *authorization_v2.CreateAuthorizationResponse {
|
||||
t.Helper()
|
||||
|
||||
// create authorization
|
||||
createdAuthorization, err := AuthorizationClient.CreateAuthorization(CTX, &authorization_v2.CreateAuthorizationRequest{
|
||||
UserId: userID,
|
||||
@@ -454,11 +456,13 @@ func createAndEnsureAuthorization(t *testing.T, instanceID, orgID, userID, proje
|
||||
assert.Equal(collect, domain.AuthorizationStateActive, az.State)
|
||||
assert.Equal(collect, createdAuthorization.GetCreationDate().AsTime().UTC(), az.CreatedAt.UTC())
|
||||
assert.Equal(collect, createdAuthorization.GetCreationDate().AsTime().UTC(), az.UpdatedAt.UTC())
|
||||
}, retryDuration, tick, "authorization not found within %v: %v", retryDuration, err)
|
||||
}, retryDuration, tick, "authorization %q not found within %v: %v", createdAuthorization.Id, retryDuration, err)
|
||||
return createdAuthorization
|
||||
}
|
||||
|
||||
func prepareProjectAndProjectRoles(t *testing.T, orgID string, roles []string) string {
|
||||
t.Helper()
|
||||
|
||||
project, err := ProjectClient.CreateProject(CTX, &project_v2beta.CreateProjectRequest{
|
||||
OrganizationId: orgID,
|
||||
Name: integration.ProjectName(),
|
||||
@@ -477,7 +481,7 @@ func prepareProjectAndProjectRoles(t *testing.T, orgID string, roles []string) s
|
||||
projectRepo.PrimaryKeyCondition(Instance.ID(), project.Id),
|
||||
))
|
||||
require.NoError(collect, err)
|
||||
}, retryDuration, tick, "project not found")
|
||||
}, retryDuration, tick, "project %q not found within %v: %v", project.Id, retryDuration, err)
|
||||
|
||||
for _, role := range roles {
|
||||
_, err = ProjectClient.AddProjectRole(CTX, &project_v2beta.AddProjectRoleRequest{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
package events_test
|
||||
|
||||
// TODO(adlerhurst): Uncomment once users table is created and FK can be enforced
|
||||
// The tests of this file fail because we would need to mock an ldap, OIDC and Oauth server.
|
||||
|
||||
// import (
|
||||
// "net"
|
||||
|
||||
@@ -325,7 +325,7 @@ func TestServer_SessionReduces(t *testing.T) {
|
||||
Metadata: metadata,
|
||||
UserAgent: userAgent,
|
||||
}, dbSession)
|
||||
}, retryDuration, tick, "session not found within %v: %v", retryDuration, err)
|
||||
}, retryDuration, tick, "session %q not found within %v: %v", createdSession.GetSessionId(), retryDuration, err)
|
||||
})
|
||||
|
||||
t.Run("checks with challenges set reduces", func(t *testing.T) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,112 @@
|
||||
package database
|
||||
|
||||
type coalesce struct {
|
||||
values []any
|
||||
}
|
||||
|
||||
func Coalesce(values ...any) *coalesce {
|
||||
return &coalesce{values: values}
|
||||
}
|
||||
|
||||
// WriteArg implements [Change].
|
||||
func (c *coalesce) WriteArg(builder *StatementBuilder) {
|
||||
c.WriteQualified(builder)
|
||||
}
|
||||
|
||||
// IsOnColumn implements [Change].
|
||||
func (c coalesce) IsOnColumn(col Column) bool {
|
||||
for _, value := range c.values {
|
||||
if change, ok := value.(Change); ok {
|
||||
if change.IsOnColumn(col) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Write implements [Change].
|
||||
func (c coalesce) Write(builder *StatementBuilder) error {
|
||||
builder.WriteString("COALESCE(")
|
||||
for i, value := range c.values {
|
||||
if i > 0 {
|
||||
builder.WriteString(", ")
|
||||
}
|
||||
builder.WriteArg(value)
|
||||
}
|
||||
builder.WriteString(")")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Equals implements [Column].
|
||||
func (c *coalesce) Equals(col Column) bool {
|
||||
if col == nil {
|
||||
return c == nil
|
||||
}
|
||||
other, ok := col.(*coalesce)
|
||||
if !ok || len(other.values) != len(c.values) {
|
||||
return false
|
||||
}
|
||||
for i, value := range c.values {
|
||||
if value != other.values[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Matches implements [Column].
|
||||
func (c *coalesce) Matches(x any) bool {
|
||||
toMatch, ok := x.(*coalesce)
|
||||
if !ok || len(toMatch.values) != len(c.values) {
|
||||
return false
|
||||
}
|
||||
for i, value := range c.values {
|
||||
if value != toMatch.values[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// String implements [Column].
|
||||
func (c *coalesce) String() string {
|
||||
return "database.coalesce"
|
||||
}
|
||||
|
||||
// WriteQualified implements [Column].
|
||||
func (c *coalesce) WriteQualified(builder *StatementBuilder) {
|
||||
builder.WriteString("COALESCE(")
|
||||
for i, value := range c.values {
|
||||
if i > 0 {
|
||||
builder.WriteString(", ")
|
||||
}
|
||||
if col, ok := value.(Column); ok {
|
||||
col.WriteQualified(builder)
|
||||
continue
|
||||
}
|
||||
builder.WriteArg(value)
|
||||
}
|
||||
builder.WriteString(")")
|
||||
}
|
||||
|
||||
// WriteUnqualified implements [Column].
|
||||
func (c *coalesce) WriteUnqualified(builder *StatementBuilder) {
|
||||
builder.WriteString("COALESCE(")
|
||||
for i, value := range c.values {
|
||||
if i > 0 {
|
||||
builder.WriteString(", ")
|
||||
}
|
||||
if col, ok := value.(Column); ok {
|
||||
col.WriteUnqualified(builder)
|
||||
continue
|
||||
}
|
||||
builder.WriteArg(value)
|
||||
}
|
||||
builder.WriteString(")")
|
||||
}
|
||||
|
||||
var (
|
||||
_ Column = (*coalesce)(nil)
|
||||
_ Change = (*coalesce)(nil)
|
||||
)
|
||||
@@ -176,6 +176,7 @@ func NewJsonChanges(col database.Column, changes ...JsonUpdate) database.Change
|
||||
}
|
||||
}
|
||||
|
||||
// WriteArg implements [gomock.Matcher].
|
||||
func (c *jsonChanges) Matches(x any) bool {
|
||||
toMatch, ok := x.(*jsonChanges)
|
||||
if !ok {
|
||||
@@ -205,10 +206,12 @@ func (c *jsonChanges) Matches(x any) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// WriteArg implements [database.Change].
|
||||
func (c *jsonChanges) String() string {
|
||||
return "database.json.jsonChange"
|
||||
}
|
||||
|
||||
// WriteArg implements [database.Change].
|
||||
func (c jsonChanges) Write(builder *database.StatementBuilder) error {
|
||||
c.column.WriteUnqualified(builder)
|
||||
builder.WriteString(" = ")
|
||||
@@ -220,6 +223,12 @@ func (c jsonChanges) Write(builder *database.StatementBuilder) error {
|
||||
return c.changes[len(c.changes)-1].writeUpdate(builder, c, len(c.changes)-2)
|
||||
}
|
||||
|
||||
// WriteArg implements [database.Change].
|
||||
func (c jsonChanges) IsOnColumn(col database.Column) bool {
|
||||
return c.column.Equals(col)
|
||||
}
|
||||
|
||||
// WriteArg implements [database.Change].
|
||||
func (c jsonChanges) WriteArg(builder *database.StatementBuilder) {
|
||||
c.column.WriteArg(builder)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (b wrappedValue[V]) WriteArg(builder *StatementBuilder) {
|
||||
var _ argWriter = (*wrappedValue[string])(nil)
|
||||
|
||||
type Value interface {
|
||||
Boolean | Number | Text | Instruction | Bytes
|
||||
Boolean | Number | Text | Instruction | Bytes | any
|
||||
}
|
||||
|
||||
//go:generate enumer -type NumberOperation,TextOperation,BytesOperation -linecomment -output ./operators_enumer.go
|
||||
|
||||
@@ -36,17 +36,6 @@ func (a authorization) qualifiedAuthorizationRolesTableName() string {
|
||||
// repository
|
||||
// -------------------------------------------------------------
|
||||
|
||||
const insertAuthorizationStmt = `INSERT INTO zitadel.authorizations (
|
||||
instance_id, id, user_id, grant_id, project_id, state, created_at, updated_at
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING created_at, updated_at`
|
||||
|
||||
const insertAuthorizationWithRolesStmt = `WITH roles AS (
|
||||
INSERT INTO zitadel.authorization_roles
|
||||
(instance_id, authorization_id, grant_id, project_id, role_key)
|
||||
VALUES ($1, $2, $4, $5, unnest($9::text[])))` + insertAuthorizationStmt
|
||||
|
||||
// Create implements [domain.AuthorizationRepository].
|
||||
func (a authorization) Create(ctx context.Context, client database.QueryExecutor, authorization *domain.Authorization) error {
|
||||
var (
|
||||
@@ -59,17 +48,12 @@ func (a authorization) Create(ctx context.Context, client database.QueryExecutor
|
||||
updatedAt = authorization.UpdatedAt
|
||||
}
|
||||
|
||||
builder := database.NewStatementBuilder(insertAuthorizationWithRolesStmt,
|
||||
authorization.InstanceID,
|
||||
authorization.ID,
|
||||
authorization.UserID,
|
||||
authorization.GrantID,
|
||||
authorization.ProjectID,
|
||||
authorization.State,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
authorization.Roles,
|
||||
builder := database.NewStatementBuilder("WITH roles AS (INSERT INTO zitadel.authorization_roles (instance_id, authorization_id, grant_id, project_id, role_key)"+
|
||||
" VALUES ($1, $2, $3, $4, unnest($5::text[]))) INSERT INTO zitadel.authorizations (instance_id, id, grant_id, project_id, user_id, state, created_at, updated_at) VALUES ($1, $2, $3, $4, $6, $7, ",
|
||||
authorization.InstanceID, authorization.ID, authorization.GrantID, authorization.ProjectID, authorization.Roles, authorization.UserID, authorization.State,
|
||||
)
|
||||
builder.WriteArgs(createdAt, updatedAt)
|
||||
builder.WriteString(") RETURNING created_at, updated_at")
|
||||
|
||||
if err := client.QueryRow(
|
||||
ctx,
|
||||
@@ -191,10 +175,10 @@ func (a authorization) setRoles(ctx context.Context, client database.QueryExecut
|
||||
|
||||
// set the roles
|
||||
builder.WriteString(updateAuthorizationRoleStmt)
|
||||
err := database.Changes(changes).Write(builder)
|
||||
if err != nil {
|
||||
if err := database.Changes(changes).Write(builder); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
builder.WriteString(updateAuthorizationRoleStmtWhere)
|
||||
|
||||
return client.Exec(ctx, builder.String(), builder.Args()...)
|
||||
|
||||
@@ -29,10 +29,8 @@ func TestCreateAuthorization(t *testing.T) {
|
||||
// create project roles
|
||||
role1 := createProjectRole(t, tx, instanceID, organizationID, projectID, "role1")
|
||||
role2 := createProjectRole(t, tx, instanceID, organizationID, projectID, "role2")
|
||||
// TODO: uncomment when user table is available
|
||||
// userID := createUser(t, tx, instanceID, organizationID)
|
||||
// require.NotNil(t, userID)
|
||||
userID := integration.ID()
|
||||
userID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
require.NotNil(t, userID)
|
||||
|
||||
authorizationRepo := repository.AuthorizationRepository()
|
||||
|
||||
@@ -116,19 +114,18 @@ func TestCreateAuthorization(t *testing.T) {
|
||||
},
|
||||
wantErr: new(database.ForeignKeyError),
|
||||
},
|
||||
// TODO: uncomment when user table is available
|
||||
// {
|
||||
// name: "non-existent user",
|
||||
// authorization: &domain.Authorization{
|
||||
// ID: integration.ID(),
|
||||
// UserID: "random-id",
|
||||
// ProjectID: projectID,
|
||||
// InstanceID: instanceID,
|
||||
// State: domain.AuthorizationStateActive,
|
||||
// Roles: nil,
|
||||
// },
|
||||
// wantErr: new(database.ForeignKeyError),
|
||||
// },
|
||||
{
|
||||
name: "non-existent user",
|
||||
authorization: &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: "random-id",
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
Roles: nil,
|
||||
},
|
||||
wantErr: new(database.ForeignKeyError),
|
||||
},
|
||||
{
|
||||
name: "duplicate authorization",
|
||||
authorization: &domain.Authorization{
|
||||
@@ -265,10 +262,8 @@ func TestGetAuthorization(t *testing.T) {
|
||||
role1 := createProjectRole(t, tx, instanceID, organizationID, projectID, "role1")
|
||||
role2 := createProjectRole(t, tx, instanceID, organizationID, projectID, "role2")
|
||||
|
||||
// TODO: uncomment when user table is available
|
||||
// userID := createUser(t, tx, instanceID, organizationID)
|
||||
// require.NotNil(t, userID)
|
||||
userID := integration.ID()
|
||||
userID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
require.NotNil(t, userID)
|
||||
|
||||
// create authorization with roles
|
||||
authorizationRepo := repository.AuthorizationRepository()
|
||||
@@ -458,13 +453,10 @@ func TestListAuthorization(t *testing.T) {
|
||||
project2Role1 := createProjectRole(t, tx, instanceID, organizationID, project2ID, "project2Role1")
|
||||
project2Role2 := createProjectRole(t, tx, instanceID, organizationID, project2ID, "project2Role2")
|
||||
|
||||
// TODO: uncomment when user table is available
|
||||
// user1ID := createUser(t, tx, instanceID, organizationID)
|
||||
// require.NotNil(t, user1ID)
|
||||
user1ID := integration.ID()
|
||||
// user2ID := createUser(t, tx, instanceID, organizationID)
|
||||
// require.NotNil(t, user2ID)
|
||||
user2ID := integration.ID()
|
||||
user1ID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
require.NotNil(t, user1ID)
|
||||
user2ID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
require.NotNil(t, user2ID)
|
||||
|
||||
// create authorization with roles for user1 for project1
|
||||
authorizationRepo := repository.AuthorizationRepository()
|
||||
@@ -890,11 +882,12 @@ func TestUpdateAuthorization(t *testing.T) {
|
||||
instanceID := createInstance(t, tx)
|
||||
organizationID := createOrganization(t, tx, instanceID)
|
||||
projectID := createProject(t, tx, instanceID, organizationID)
|
||||
userID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
|
||||
authorizationRepo := repository.AuthorizationRepository()
|
||||
activeAuthorization := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
@@ -907,7 +900,7 @@ func TestUpdateAuthorization(t *testing.T) {
|
||||
|
||||
inactiveAuthorization := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateInactive,
|
||||
@@ -1012,10 +1005,12 @@ func TestAuthorizationUpdate_setRoles(t *testing.T) {
|
||||
role5 := createProjectRole(t, tx, instanceID, organizationID, project2ID, "role5")
|
||||
role6 := createProjectRole(t, tx, instanceID, organizationID, project2ID, "role6")
|
||||
|
||||
userID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
|
||||
authorizationRepo := repository.AuthorizationRepository()
|
||||
authorization1 := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
@@ -1028,7 +1023,7 @@ func TestAuthorizationUpdate_setRoles(t *testing.T) {
|
||||
|
||||
authorization2 := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: project2ID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
@@ -1132,11 +1127,12 @@ func TestDeleteAuthorization(t *testing.T) {
|
||||
projectID := createProject(t, tx, instanceID, organizationID)
|
||||
role1 := createProjectRole(t, tx, instanceID, organizationID, projectID, "role1")
|
||||
role2 := createProjectRole(t, tx, instanceID, organizationID, projectID, "role2")
|
||||
userID := createHumanUser(t, tx, instanceID, organizationID)
|
||||
|
||||
authorizationRepo := repository.AuthorizationRepository()
|
||||
authorizationWithRoles := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
@@ -1149,7 +1145,7 @@ func TestDeleteAuthorization(t *testing.T) {
|
||||
|
||||
authorizationWithoutRoles := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
@@ -1162,7 +1158,7 @@ func TestDeleteAuthorization(t *testing.T) {
|
||||
|
||||
deletedAuthorization := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
InstanceID: instanceID,
|
||||
State: domain.AuthorizationStateActive,
|
||||
@@ -1182,7 +1178,7 @@ func TestDeleteAuthorization(t *testing.T) {
|
||||
grantID := createProjectGrant(t, tx, instanceID, organizationID, grantedOrganizationID, projectID, []string{role1})
|
||||
authorizationProjectGrant := &domain.Authorization{
|
||||
ID: integration.ID(),
|
||||
UserID: integration.ID(),
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
GrantID: gu.Ptr(grantID),
|
||||
InstanceID: instanceID,
|
||||
|
||||
@@ -2,7 +2,6 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -95,7 +94,6 @@ func (i idpIntentRepository) Get(ctx context.Context, client database.QueryExecu
|
||||
var builder database.StatementBuilder
|
||||
builder.WriteString(queryIDPIntentStmt)
|
||||
options.Write(&builder)
|
||||
fmt.Println(builder.String())
|
||||
|
||||
return scanIDPIntent(ctx, client, &builder)
|
||||
}
|
||||
|
||||
@@ -315,6 +315,8 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
err = idpIntentRepo.Create(t.Context(), tx, &intent2)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := createHumanUser(t, tx, instanceID, orgID)
|
||||
|
||||
now := time.Now()
|
||||
tomorrow := now.AddDate(0, 0, 1)
|
||||
tt := []struct {
|
||||
@@ -344,7 +346,7 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
idpIntentRepo.SetIDPUser([]byte("update user")),
|
||||
idpIntentRepo.SetIDPUserID("idp user id updated"),
|
||||
idpIntentRepo.SetIDPUsername("idp username updated"),
|
||||
idpIntentRepo.SetUserID("some-user-id"),
|
||||
idpIntentRepo.SetUserID(userID),
|
||||
idpIntentRepo.SetIDPAccessToken([]byte(`{"secret": "g1g4 s3cr3t 4cc3ss t0k3n"}`)),
|
||||
idpIntentRepo.SetIDPIDToken("idp id token"),
|
||||
idpIntentRepo.SetSucceededAt(now),
|
||||
@@ -355,7 +357,7 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
toReturn.IDPUser = []byte("update user")
|
||||
toReturn.IDPUserID = "idp user id updated"
|
||||
toReturn.IDPUsername = "idp username updated"
|
||||
toReturn.UserID = "some-user-id"
|
||||
toReturn.UserID = userID
|
||||
toReturn.IDPAccessToken = []byte(`{"secret": "g1g4 s3cr3t 4cc3ss t0k3n"}`)
|
||||
toReturn.IDPIDToken = "idp id token"
|
||||
toReturn.SucceededAt = &now
|
||||
@@ -373,7 +375,7 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
idpIntentRepo.SetIDPUser([]byte("update user")),
|
||||
idpIntentRepo.SetIDPUserID("idp user id updated"),
|
||||
idpIntentRepo.SetIDPUsername("idp username updated"),
|
||||
idpIntentRepo.SetUserID("some-user-id"),
|
||||
idpIntentRepo.SetUserID(userID),
|
||||
idpIntentRepo.SetAssertion([]byte(`{"assertion": "val1"}`)),
|
||||
idpIntentRepo.SetSucceededAt(now),
|
||||
idpIntentRepo.SetExpiresAt(tomorrow),
|
||||
@@ -383,7 +385,7 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
toReturn.IDPUser = []byte("update user")
|
||||
toReturn.IDPUserID = "idp user id updated"
|
||||
toReturn.IDPUsername = "idp username updated"
|
||||
toReturn.UserID = "some-user-id"
|
||||
toReturn.UserID = userID
|
||||
toReturn.Assertion = []byte(`{"assertion": "val1"}`)
|
||||
toReturn.SucceededAt = &now
|
||||
toReturn.ExpiresAt = &tomorrow
|
||||
@@ -400,7 +402,7 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
idpIntentRepo.SetIDPUser([]byte("update user")),
|
||||
idpIntentRepo.SetIDPUserID("idp user id updated"),
|
||||
idpIntentRepo.SetIDPUsername("idp username updated"),
|
||||
idpIntentRepo.SetUserID("some-user-id"),
|
||||
idpIntentRepo.SetUserID(userID),
|
||||
idpIntentRepo.SetIDPEntryAttributes(marshalledAttrs),
|
||||
idpIntentRepo.SetSucceededAt(now),
|
||||
idpIntentRepo.SetExpiresAt(tomorrow),
|
||||
@@ -410,7 +412,7 @@ func TestUpdateIDPIntent(t *testing.T) {
|
||||
toReturn.IDPUser = []byte("update user")
|
||||
toReturn.IDPUserID = "idp user id updated"
|
||||
toReturn.IDPUsername = "idp username updated"
|
||||
toReturn.UserID = "some-user-id"
|
||||
toReturn.UserID = userID
|
||||
toReturn.EntryAttributes = entryAttrs
|
||||
toReturn.SucceededAt = &now
|
||||
toReturn.ExpiresAt = &tomorrow
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package repository_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
)
|
||||
|
||||
func assertMetadata(t *testing.T, expected, gotten []*domain.Metadata) {
|
||||
t.Helper()
|
||||
|
||||
assert.Len(t, gotten, len(expected), "metadata length mismatch")
|
||||
for _, exp := range expected {
|
||||
var actual *domain.Metadata
|
||||
gotten = slices.DeleteFunc(gotten, func(m *domain.Metadata) bool {
|
||||
if exp.Key != m.Key || exp.InstanceID != m.InstanceID {
|
||||
return false
|
||||
}
|
||||
actual = m
|
||||
return true
|
||||
})
|
||||
require.NotNil(t, actual, "metadata with key %s and instance %s not found", exp.Key, exp.InstanceID)
|
||||
assert.Equal(t, exp.Value, actual.Value, "metadata value mismatch for key %s and instance %s", exp.Key, exp.InstanceID)
|
||||
assert.NotZero(t, actual.CreatedAt, "metadata created at is zero for key %s and instance %s", exp.Key, exp.InstanceID)
|
||||
assert.NotZero(t, actual.UpdatedAt, "metadata updated at is zero for key %s and instance %s", exp.Key, exp.InstanceID)
|
||||
|
||||
}
|
||||
assert.Empty(t, gotten, "unmatched metadata found")
|
||||
}
|
||||
@@ -123,7 +123,9 @@ func (p projectGrant) Update(ctx context.Context, client database.QueryExecutor,
|
||||
|
||||
// now we add the logic to do the required changes based on the given project grant
|
||||
builder.WriteString(updateProjectGrantRoleStmt)
|
||||
database.Changes(changes).Write(builder)
|
||||
if err := database.Changes(changes).Write(builder); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
builder.WriteString(updateProjectGrantRoleStmtWhere)
|
||||
|
||||
return client.Exec(ctx, builder.String(), builder.Args()...)
|
||||
|
||||
@@ -85,7 +85,9 @@ func updateOne[Target updatable](ctx context.Context, client database.QueryExecu
|
||||
builder := database.NewStatementBuilder("UPDATE ")
|
||||
builder.WriteString(target.qualifiedTableName())
|
||||
builder.WriteString(" SET ")
|
||||
database.Changes(changes).Write(builder)
|
||||
if err := database.Changes(changes).Write(builder); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
writeCondition(builder, condition)
|
||||
|
||||
return client.Exec(ctx, builder.String(), builder.Args()...)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dialect/postgres"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dialect/postgres/embedded"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
@@ -31,30 +32,48 @@ func runTests(m *testing.M) int {
|
||||
var err error
|
||||
ctx := context.Background()
|
||||
pool, stop, err = newEmbeddedDB(ctx)
|
||||
defer stop()
|
||||
if err != nil {
|
||||
log.Printf("error with embedded postgres database: %v", err)
|
||||
return 1
|
||||
}
|
||||
defer stop()
|
||||
defer func() {
|
||||
r := recover()
|
||||
pool.Close(ctx)
|
||||
stop()
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
return m.Run()
|
||||
}
|
||||
|
||||
func newEmbeddedDB(ctx context.Context) (pool database.PoolTest, stop func(), err error) {
|
||||
connector, stop, err := embedded.StartEmbedded()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to start embedded postgres: %w", err)
|
||||
var connector database.Connector
|
||||
if url := os.Getenv("ZITADEL_TEST_POSTGRES_URL"); url != "" {
|
||||
log.Println("using database provided by env")
|
||||
connector, err = postgres.DecodeConfig(url)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to connect to provided postgres: %w", err)
|
||||
}
|
||||
stop = func() {}
|
||||
} else {
|
||||
connector, stop, err = embedded.StartEmbedded()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to start embedded postgres: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
pool_, err := connector.Connect(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to connect to embedded postgres: %w", err)
|
||||
return nil, stop, fmt.Errorf("unable to connect to embedded postgres: %w", err)
|
||||
}
|
||||
pool = pool_.(database.PoolTest)
|
||||
|
||||
err = pool.MigrateTest(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to migrate database: %w", err)
|
||||
return nil, stop, fmt.Errorf("unable to migrate database: %w", err)
|
||||
}
|
||||
return pool, stop, err
|
||||
}
|
||||
@@ -64,7 +83,8 @@ func transactionForRollback(t *testing.T) (tx database.Transaction, rollback fun
|
||||
tx, err := pool.Begin(t.Context(), nil)
|
||||
require.NoError(t, err)
|
||||
return tx, func() {
|
||||
err := tx.Rollback(t.Context())
|
||||
// context.Background to ensure rollback does not return an error if test is already done
|
||||
err := tx.Rollback(context.Background())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
@@ -74,12 +94,13 @@ func savepointForRollback(t *testing.T, tx database.Transaction) (savepoint data
|
||||
savepoint, err := tx.Begin(t.Context())
|
||||
require.NoError(t, err)
|
||||
return savepoint, func() {
|
||||
err := savepoint.Rollback(t.Context())
|
||||
// context.Background to ensure rollback does not return an error if test is already done
|
||||
err := savepoint.Rollback(context.Background())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func createInstance(t *testing.T, tx database.Transaction) (instanceID string) {
|
||||
func createInstance(t *testing.T, tx database.QueryExecutor) (instanceID string) {
|
||||
t.Helper()
|
||||
instance := domain.Instance{
|
||||
ID: gofakeit.UUID(),
|
||||
@@ -97,7 +118,7 @@ func createInstance(t *testing.T, tx database.Transaction) (instanceID string) {
|
||||
return instance.ID
|
||||
}
|
||||
|
||||
func createOrganization(t *testing.T, tx database.Transaction, instanceID string) (orgID string) {
|
||||
func createOrganization(t *testing.T, tx database.QueryExecutor, instanceID string) (orgID string) {
|
||||
t.Helper()
|
||||
org := domain.Organization{
|
||||
InstanceID: instanceID,
|
||||
@@ -112,7 +133,7 @@ func createOrganization(t *testing.T, tx database.Transaction, instanceID string
|
||||
return org.ID
|
||||
}
|
||||
|
||||
func createProject(t *testing.T, tx database.Transaction, instanceID, orgID string) (projectID string) {
|
||||
func createProject(t *testing.T, tx database.QueryExecutor, instanceID, orgID string) (projectID string) {
|
||||
t.Helper()
|
||||
project := domain.Project{
|
||||
InstanceID: instanceID,
|
||||
@@ -128,7 +149,7 @@ func createProject(t *testing.T, tx database.Transaction, instanceID, orgID stri
|
||||
return project.ID
|
||||
}
|
||||
|
||||
func createProjectRole(t *testing.T, tx database.Transaction, instanceID, orgID, projectID, key string) string {
|
||||
func createProjectRole(t *testing.T, tx database.QueryExecutor, instanceID, orgID, projectID, key string) string {
|
||||
t.Helper()
|
||||
if key == "" {
|
||||
key = integration.RoleKey()
|
||||
@@ -210,3 +231,46 @@ func createIDPIntent(t *testing.T, tx database.Transaction, instanceID, idpID st
|
||||
|
||||
return intent.ID
|
||||
}
|
||||
|
||||
func createMachineUser(t *testing.T, tx database.QueryExecutor, instanceID, orgID string) (userID string) {
|
||||
t.Helper()
|
||||
user := domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: gofakeit.UUID(),
|
||||
Username: gofakeit.Username(),
|
||||
State: domain.UserStateActive,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: gofakeit.Name(),
|
||||
},
|
||||
}
|
||||
userRepo := repository.UserRepository()
|
||||
err := userRepo.Create(t.Context(), tx, &user)
|
||||
require.NoError(t, err)
|
||||
return user.ID
|
||||
}
|
||||
|
||||
func createHumanUser(t *testing.T, tx database.QueryExecutor, instanceID, orgID string) string {
|
||||
t.Helper()
|
||||
user := &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: gofakeit.UUID(),
|
||||
Username: gofakeit.Username(),
|
||||
State: domain.UserStateActive,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: gofakeit.FirstName(),
|
||||
LastName: gofakeit.LastName(),
|
||||
Email: domain.HumanEmail{
|
||||
Address: gofakeit.Email(),
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: "hashed-password",
|
||||
},
|
||||
},
|
||||
}
|
||||
userRepo := repository.UserRepository()
|
||||
err := userRepo.Create(t.Context(), tx, user)
|
||||
require.NoError(t, err)
|
||||
return user.ID
|
||||
}
|
||||
|
||||
@@ -176,7 +176,9 @@ func (s session) Create(ctx context.Context, client database.QueryExecutor, sess
|
||||
)
|
||||
fingerprintID = session.UserAgent.FingerprintID
|
||||
}
|
||||
builder.WriteString(`INSERT INTO ` + s.qualifiedTableName() + ` (instance_id, id, lifetime, creator_id, user_agent_id, created_at, updated_at) VALUES ( `)
|
||||
builder.WriteString(`INSERT INTO `)
|
||||
builder.WriteString(s.qualifiedTableName())
|
||||
builder.WriteString(` (instance_id, id, lifetime, creator_id, user_agent_id, created_at, updated_at) VALUES ( `)
|
||||
builder.WriteArgs(session.InstanceID, session.ID, session.Lifetime, session.CreatorID, fingerprintID, createdAt, updatedAt)
|
||||
builder.WriteString(` ) RETURNING created_at, updated_at`)
|
||||
return client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&session.CreatedAt, &session.UpdatedAt)
|
||||
|
||||
@@ -232,6 +232,9 @@ func TestSession_Update(t *testing.T) {
|
||||
err = instanceRepo.Create(t.Context(), tx, &instance)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := createOrganization(t, tx, instanceId)
|
||||
userID := createHumanUser(t, tx, instanceId, orgID)
|
||||
|
||||
testNow := time.Now()
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -474,7 +477,7 @@ func TestSession_Update(t *testing.T) {
|
||||
// update with updated values
|
||||
session.Factors = []domain.SessionFactor{
|
||||
&domain.SessionFactorUser{
|
||||
UserID: "user-id",
|
||||
UserID: userID,
|
||||
LastVerifiedAt: testNow,
|
||||
},
|
||||
}
|
||||
@@ -482,7 +485,7 @@ func TestSession_Update(t *testing.T) {
|
||||
},
|
||||
update: []database.Change{
|
||||
sessionRepo.SetFactor(&domain.SessionFactorUser{
|
||||
UserID: "user-id",
|
||||
UserID: userID,
|
||||
LastVerifiedAt: testNow,
|
||||
}),
|
||||
},
|
||||
@@ -748,7 +751,7 @@ func TestSession_Update(t *testing.T) {
|
||||
session.TokenID = "new-token"
|
||||
session.Factors = []domain.SessionFactor{
|
||||
&domain.SessionFactorUser{
|
||||
UserID: "user-id",
|
||||
UserID: userID,
|
||||
LastVerifiedAt: testNow,
|
||||
},
|
||||
&domain.SessionFactorPassword{
|
||||
@@ -794,7 +797,7 @@ func TestSession_Update(t *testing.T) {
|
||||
sessionRepo.SetUpdatedAt(testNow),
|
||||
sessionRepo.SetLifetime(time.Hour * 48),
|
||||
sessionRepo.SetFactor(&domain.SessionFactorUser{
|
||||
UserID: "user-id",
|
||||
UserID: userID,
|
||||
LastVerifiedAt: testNow,
|
||||
}),
|
||||
sessionRepo.SetFactor(&domain.SessionFactorPassword{
|
||||
@@ -846,7 +849,7 @@ func TestSession_Update(t *testing.T) {
|
||||
updatedRows, err := sessionRepo.Update(t.Context(), tx,
|
||||
sessionRepo.PrimaryKeyCondition(session.InstanceID, session.ID),
|
||||
sessionRepo.SetFactor(&domain.SessionFactorUser{
|
||||
UserID: "user-id",
|
||||
UserID: userID,
|
||||
LastVerifiedAt: testNow,
|
||||
}),
|
||||
sessionRepo.SetFactor(&domain.SessionFactorPassword{
|
||||
@@ -859,7 +862,7 @@ func TestSession_Update(t *testing.T) {
|
||||
// update with updated values
|
||||
session.Factors = []domain.SessionFactor{
|
||||
&domain.SessionFactorUser{
|
||||
UserID: "user-id",
|
||||
UserID: userID,
|
||||
LastVerifiedAt: testNow,
|
||||
},
|
||||
}
|
||||
@@ -1101,9 +1104,12 @@ func TestSession_List(t *testing.T) {
|
||||
err = instanceRepo.Create(t.Context(), tx, &instance)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := createOrganization(t, tx, instanceId)
|
||||
userIDs := []string{createHumanUser(t, tx, instanceId, orgID), createHumanUser(t, tx, instanceId, orgID)}
|
||||
|
||||
// create sessions
|
||||
sessions := make([]*domain.Session, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
for i := range 5 {
|
||||
session := &domain.Session{
|
||||
InstanceID: instanceId,
|
||||
ID: strconv.Itoa(i),
|
||||
@@ -1138,7 +1144,7 @@ func TestSession_List(t *testing.T) {
|
||||
session.Metadata = metadata
|
||||
changes = append(changes, sessionRepo.SetMetadata(metadata))
|
||||
userFactor := &domain.SessionFactorUser{
|
||||
UserID: "user-" + strconv.Itoa(i%2), // two users: user-0 and user-1
|
||||
UserID: userIDs[i%2],
|
||||
LastVerifiedAt: time.Now(),
|
||||
}
|
||||
session.Factors.AppendTo(userFactor)
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// repository
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func UserRepository() domain.UserRepository {
|
||||
return new(user)
|
||||
}
|
||||
|
||||
func MachineUserRepository() domain.MachineUserRepository {
|
||||
return &userMachine{user: user{}}
|
||||
}
|
||||
|
||||
type user struct {
|
||||
verification verification
|
||||
tableName string
|
||||
machineKey
|
||||
userPersonalAccessToken
|
||||
userMetadata
|
||||
userPasskey
|
||||
userIdentityProviderLink
|
||||
}
|
||||
|
||||
func (u user) HumanRepository() domain.HumanUserRepository {
|
||||
return userHuman{user: u}
|
||||
}
|
||||
|
||||
// existingUser is used to get the columns and conditions for the CTE that selects the existing user in update and delete operations.
|
||||
var existingUser = user{tableName: "existing_user"}
|
||||
|
||||
// Create implements [domain.UserRepository].
|
||||
func (u user) Create(ctx context.Context, client database.QueryExecutor, user *domain.User) error {
|
||||
var create func(context.Context, *database.StatementBuilder, database.QueryExecutor, *domain.User) error
|
||||
switch {
|
||||
case user.Human != nil:
|
||||
create = userHuman{user: u}.create
|
||||
case user.Machine != nil:
|
||||
create = userMachine{user: u}.create
|
||||
default:
|
||||
return zerrors.ThrowInvalidArgument(nil, "REPOS-KxMnG", "no user type defined")
|
||||
}
|
||||
// we need to cheat a bit here to be able to use CTEChanges
|
||||
// we pretend we have an existing user to be able to use the existing change mechanisms
|
||||
builder := database.NewStatementBuilder("WITH existing_user AS (SELECT $1 AS instance_id, $2 AS organization_id, $3 AS id)", user.InstanceID, user.OrganizationID, user.ID)
|
||||
return create(ctx, builder, client, user)
|
||||
}
|
||||
|
||||
// Delete implements [domain.UserRepository].
|
||||
func (u user) Delete(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error) {
|
||||
if err := checkPKCondition(u, condition); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
builder := database.NewStatementBuilder("DELETE FROM zitadel.users")
|
||||
writeCondition(builder, condition)
|
||||
return client.Exec(ctx, builder.String(), builder.Args()...)
|
||||
}
|
||||
|
||||
var queryUserStmt = "SELECT users.instance_id, users.organization_id, users.id, users.username" +
|
||||
", users.state, users.created_at, users.updated_at" +
|
||||
// metadata
|
||||
`, jsonb_agg(DISTINCT jsonb_build_object('instanceId', user_metadata.instance_id, 'key', user_metadata.key, 'value', encode(user_metadata.value, 'base64'), 'createdAt', user_metadata.created_at, 'updatedAt', user_metadata.updated_at)) FILTER (WHERE user_metadata.user_id IS NOT NULL) AS metadata` +
|
||||
// machine
|
||||
`, CASE WHEN users.type = 'machine' THEN jsonb_build_object('name', users.name` +
|
||||
`, 'description', users.description, 'secret', users.secret` +
|
||||
`, 'accessTokenType', users.access_token_type` +
|
||||
`, 'keys', jsonb_agg(DISTINCT jsonb_build_object('id', machine_keys.id, 'publicKey', encode(machine_keys.public_key, 'base64'), 'createdAt', machine_keys.created_at, 'expiresAt', machine_keys.expires_at, 'type', machine_keys.type)) FILTER (WHERE machine_keys.user_id IS NOT NULL)` +
|
||||
`, 'pats', jsonb_agg(DISTINCT jsonb_build_object('id', user_personal_access_tokens.id, 'createdAt', user_personal_access_tokens.created_at, 'expiresAt', user_personal_access_tokens.expires_at, 'scopes', user_personal_access_tokens.scopes)) FILTER (WHERE user_personal_access_tokens.user_id IS NOT NULL)` +
|
||||
`) END AS machine` +
|
||||
// human
|
||||
`, CASE WHEN users.type = 'human' THEN jsonb_build_object('firstName', users.first_name, 'lastName', users.last_name` +
|
||||
`, 'nickname', users.nickname, 'displayName', users.display_name` +
|
||||
`, 'preferredLanguage', users.preferred_language, 'gender', users.gender` +
|
||||
`, 'avatarKey', users.avatar_key` +
|
||||
`, 'multifactorInitializationSkippedAt', users.multifactor_initialization_skipped_at` +
|
||||
`, 'password', jsonb_build_object('hash', users.password_hash, 'isChangeRequired', users.password_change_required, 'changedAt', users.password_changed_at, 'failedAttempts', users.password_failed_attempts, 'lastSuccessfullyCheckedAt', users.password_last_successful_check, 'pendingVerification', ` + verificationQuery(userHuman{}.passwordVerificationIDColumn()) + `)` +
|
||||
`, 'email', jsonb_build_object('address', users.email, 'unverifiedAddress', users.unverified_email, 'verifiedAt', users.email_verified_at, 'otp', jsonb_build_object('enabledAt', users.email_otp_enabled_at, 'lastSuccessfullyCheckedAt', users.email_otp_last_successful_check, 'failedAttempts', users.email_otp_failed_attempts), 'pendingVerification', ` + verificationQuery(userHuman{}.emailVerificationIDColumn()) + `)` +
|
||||
`, 'phone', CASE WHEN users.phone IS NOT NULL OR users.phone_verification_id IS NOT NULL THEN jsonb_build_object('number', users.phone, 'unverifiedNumber', users.unverified_phone, 'verifiedAt', users.phone_verified_at, 'otp', jsonb_build_object('enabledAt', users.sms_otp_enabled_at, 'lastSuccessfullyCheckedAt', users.sms_otp_last_successful_check, 'failedAttempts', users.sms_otp_failed_attempts), 'pendingVerification', ` + verificationQuery(userHuman{}.phoneVerificationIDColumn()) + `) ELSE NULL END` +
|
||||
`, 'totp', CASE WHEN users.totp_secret IS NOT NULL THEN jsonb_build_object('secret', encode(users.totp_secret, 'escape')::JSONB, 'verifiedAt', users.totp_verified_at, 'lastSuccessfullyCheckedAt', users.totp_last_successful_check, 'failedAttempts', users.totp_failed_attempts) ELSE NULL END` +
|
||||
`, 'passkeys', jsonb_agg(DISTINCT jsonb_build_object('id', user_passkeys.token_id, 'keyId', encode(user_passkeys.key_id, 'base64'), 'type', user_passkeys.type, 'name', user_passkeys.name, 'signCount', user_passkeys.sign_count, 'challenge', encode(user_passkeys.challenge, 'base64'), 'publicKey', encode(user_passkeys.public_key, 'base64'), 'attestationType', user_passkeys.attestation_type, 'aaGuid', encode(user_passkeys.authenticator_attestation_guid, 'base64'), 'rpId', user_passkeys.relying_party_id, 'createdAt', user_passkeys.created_at, 'updatedAt', user_passkeys.updated_at, 'verifiedAt', user_passkeys.verified_at)) FILTER (WHERE user_passkeys.user_id IS NOT NULL)` +
|
||||
`, 'verifications', (SELECT jsonb_agg(jsonb_build_object('id', verifications.id, 'code', encode(verifications.code, 'escape')::JSONB, 'createdAt', verifications.created_at, 'updatedAt', verifications.updated_at, 'expiresAt', verifications.created_at+verifications.expiry, 'failedAttempts', verifications.failed_attempts)) FROM zitadel.verifications WHERE verifications.instance_id = users.instance_id AND verifications.user_id = users.id AND verifications.id NOT IN (COALESCE(users.password_verification_id, ''), COALESCE(users.email_verification_id, ''), COALESCE(users.phone_verification_id, ''), COALESCE(users.invite_verification_id, '')))` +
|
||||
`, 'identityProviderLinks', jsonb_agg(DISTINCT jsonb_build_object('providerId', user_identity_provider_links.identity_provider_id, 'providedUserId', user_identity_provider_links.provided_user_id, 'providedUsername', user_identity_provider_links.provided_username, 'createdAt', user_identity_provider_links.created_at, 'updatedAt', user_identity_provider_links.updated_at)) FILTER (WHERE user_identity_provider_links.user_id IS NOT NULL)` +
|
||||
`, 'invite', CASE WHEN users.invite_verification_id IS NOT NULL OR users.invite_accepted_at IS NOT NULL THEN jsonb_build_object('acceptedAt', users.invite_accepted_at, 'failedAttempts', users.invite_failed_attempts, 'pendingVerification', ` + verificationQuery(userHuman{}.inviteVerificationIDColumn()) + `) ELSE NULL END` +
|
||||
`) END AS human FROM zitadel.users`
|
||||
|
||||
func verificationQuery(column database.Column) string {
|
||||
var builder database.StatementBuilder
|
||||
builder.WriteString("CASE WHEN ")
|
||||
column.WriteQualified(&builder)
|
||||
builder.WriteString(` IS NOT NULL THEN (SELECT row_to_json(res.*) FROM (SELECT verifications.id, encode(verifications.code, 'escape')::JSONB AS code, verifications.created_at as "createdAt", verifications.updated_at as "updatedAt", verifications.created_at+verifications.expiry AS "expiresAt", verifications.failed_attempts as "failedAttempts" FROM zitadel.verifications WHERE verifications.instance_id = users.instance_id AND verifications.id = `)
|
||||
column.WriteQualified(&builder)
|
||||
builder.WriteString(`) AS res) ELSE NULL END`)
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// Get implements [domain.UserRepository].
|
||||
func (u user) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.User, error) {
|
||||
options := new(database.QueryOpts)
|
||||
for _, opt := range u.appendQueryOpts(opts) {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
if !options.Condition.IsRestrictingColumn(u.InstanceIDColumn()) {
|
||||
return nil, database.NewMissingConditionError(u.InstanceIDColumn())
|
||||
}
|
||||
|
||||
builder := database.NewStatementBuilder(queryUserStmt)
|
||||
options.Write(builder)
|
||||
|
||||
return scanUser(ctx, client, builder)
|
||||
}
|
||||
|
||||
// List implements [domain.UserRepository].
|
||||
func (u user) List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*domain.User, error) {
|
||||
options := new(database.QueryOpts)
|
||||
for _, opt := range u.appendQueryOpts(opts) {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
if !options.Condition.IsRestrictingColumn(u.InstanceIDColumn()) {
|
||||
return nil, database.NewMissingConditionError(u.InstanceIDColumn())
|
||||
}
|
||||
|
||||
builder := database.NewStatementBuilder(queryUserStmt)
|
||||
options.Write(builder)
|
||||
|
||||
return scanUsers(ctx, client, builder)
|
||||
}
|
||||
|
||||
func (u user) appendQueryOpts(opts []database.QueryOption) []database.QueryOption {
|
||||
return append(opts,
|
||||
u.joinMachineKeys(),
|
||||
u.joinPATs(),
|
||||
u.joinMetadata(),
|
||||
u.joinVerifications(),
|
||||
u.joinPasskeys(),
|
||||
u.joinIdentityProviderLinks(),
|
||||
database.WithGroupBy(u.PrimaryKeyColumns()...),
|
||||
)
|
||||
}
|
||||
|
||||
// Update implements [domain.UserRepository].
|
||||
func (u user) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
||||
if err := checkPKCondition(u, condition); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return 0, database.ErrNoChanges
|
||||
}
|
||||
if !database.Changes(changes).IsOnColumn(u.updatedAtColumn()) {
|
||||
changes = append(changes, u.clearUpdatedAt())
|
||||
}
|
||||
|
||||
builder := database.NewStatementBuilder("WITH existing_user AS (SELECT * FROM zitadel.users")
|
||||
writeCondition(builder, condition)
|
||||
builder.WriteString(") ")
|
||||
for i, change := range changes {
|
||||
sessionCTE(change, i, 0, builder)
|
||||
}
|
||||
|
||||
builder.WriteString("UPDATE zitadel.users SET ")
|
||||
if err := database.Changes(changes).Write(builder); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
builder.WriteString(" FROM existing_user")
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(u.IDColumn(), existingUser.IDColumn()),
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), existingUser.InstanceIDColumn()),
|
||||
))
|
||||
|
||||
return client.Exec(ctx, builder.String(), builder.Args()...)
|
||||
}
|
||||
|
||||
func (u user) unqualifiedTableName() string {
|
||||
if u.tableName != "" {
|
||||
return u.tableName
|
||||
}
|
||||
return "users"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetState implements [domain.UserRepository].
|
||||
func (u user) SetState(state domain.UserState) database.Change {
|
||||
return database.NewChange(u.StateColumn(), state)
|
||||
}
|
||||
|
||||
// SetUpdatedAt implements [domain.UserRepository].
|
||||
func (u user) SetUpdatedAt(updatedAt time.Time) database.Change {
|
||||
return database.NewChange(u.updatedAtColumn(), updatedAt)
|
||||
}
|
||||
|
||||
// SetUsername implements [domain.UserRepository].
|
||||
func (u user) SetUsername(username string) database.Change {
|
||||
return database.NewChange(u.UsernameColumn(), username)
|
||||
}
|
||||
|
||||
func (u user) clearUpdatedAt() database.Change {
|
||||
return database.NewChange(u.updatedAtColumn(), database.NullInstruction)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// IDCondition implements [domain.UserRepository].
|
||||
func (u user) IDCondition(userID string) database.Condition {
|
||||
return database.NewTextCondition(u.IDColumn(), database.TextOperationEqual, userID)
|
||||
}
|
||||
|
||||
// InstanceIDCondition implements [domain.UserRepository].
|
||||
func (u user) InstanceIDCondition(instanceID string) database.Condition {
|
||||
return database.NewTextCondition(u.InstanceIDColumn(), database.TextOperationEqual, instanceID)
|
||||
}
|
||||
|
||||
// LoginNameCondition implements [domain.UserRepository].
|
||||
func (u user) LoginNameCondition(op database.TextOperation, loginName string) database.Condition {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// OrganizationIDCondition implements [domain.UserRepository].
|
||||
func (u user) OrganizationIDCondition(orgID string) database.Condition {
|
||||
return database.NewTextCondition(u.organizationIDColumn(), database.TextOperationEqual, orgID)
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition implements [domain.UserRepository].
|
||||
func (u user) PrimaryKeyCondition(instanceID string, userID string) database.Condition {
|
||||
return database.And(
|
||||
u.InstanceIDCondition(instanceID),
|
||||
u.IDCondition(userID),
|
||||
)
|
||||
}
|
||||
|
||||
// StateCondition implements [domain.UserRepository].
|
||||
func (u user) StateCondition(state domain.UserState) database.Condition {
|
||||
return database.NewNumberCondition(u.StateColumn(), database.NumberOperationEqual, state)
|
||||
}
|
||||
|
||||
// TypeCondition implements [domain.UserRepository].
|
||||
func (u user) TypeCondition(userType domain.UserType) database.Condition {
|
||||
return database.NewNumberCondition(u.TypeColumn(), database.NumberOperationEqual, userType)
|
||||
}
|
||||
|
||||
// UsernameCondition implements [domain.UserRepository].
|
||||
func (u user) UsernameCondition(op database.TextOperation, username string) database.Condition {
|
||||
return database.NewTextCondition(u.UsernameColumn(), op, username)
|
||||
}
|
||||
|
||||
// ExistsMetadata implements [domain.UserRepository].
|
||||
func (u user) ExistsMetadata(condition database.Condition) database.Condition {
|
||||
return database.Exists(
|
||||
u.userMetadata.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userMetadata.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userMetadata.userIDColumn()),
|
||||
condition,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// ExistsPasskey implements [domain.HumanUserRepository].
|
||||
func (u user) ExistsPasskey(condition database.Condition) database.Condition {
|
||||
return database.Exists(
|
||||
u.userPasskey.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userPasskey.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userPasskey.userIDColumn()),
|
||||
condition,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// ExistsIdentityProviderLink implements [domain.HumanUserRepository].
|
||||
func (u user) ExistsIdentityProviderLink(condition database.Condition) database.Condition {
|
||||
return database.Exists(
|
||||
u.userIdentityProviderLink.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userIdentityProviderLink.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userIdentityProviderLink.userIDColumn()),
|
||||
condition,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// PrimaryKeyColumns implements [domain.UserRepository].
|
||||
func (u user) PrimaryKeyColumns() []database.Column {
|
||||
return database.Columns{
|
||||
u.InstanceIDColumn(),
|
||||
u.IDColumn(),
|
||||
}
|
||||
}
|
||||
|
||||
// CreatedAtColumn implements [domain.UserRepository].
|
||||
func (u user) CreatedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "created_at")
|
||||
}
|
||||
|
||||
// StateColumn implements [domain.UserRepository].
|
||||
func (u user) StateColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "state")
|
||||
}
|
||||
|
||||
// TypeColumn implements [domain.UserRepository].
|
||||
func (u user) TypeColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "type")
|
||||
}
|
||||
|
||||
// UsernameColumn implements [domain.UserRepository].
|
||||
func (u user) UsernameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "username")
|
||||
}
|
||||
|
||||
// IDColumn implements [domain.UserRepository].
|
||||
func (u user) IDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "id")
|
||||
}
|
||||
|
||||
func (u user) InstanceIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
|
||||
func (u user) updatedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "updated_at")
|
||||
}
|
||||
|
||||
func (u user) organizationIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "organization_id")
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// scanners
|
||||
// -------------------------------------------------------------
|
||||
|
||||
type rawUser struct {
|
||||
domain.User
|
||||
Machine *json.RawMessage `json:"machine,omitempty" db:"machine"`
|
||||
Human *json.RawMessage `json:"human,omitempty" db:"human"`
|
||||
}
|
||||
|
||||
func (u *rawUser) toDomain() (*domain.User, error) {
|
||||
if u.Machine != nil {
|
||||
err := json.Unmarshal(*u.Machine, &u.User.Machine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if u.Human != nil {
|
||||
err := json.Unmarshal(*u.Human, &u.User.Human)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &u.User, nil
|
||||
}
|
||||
|
||||
func scanUser(ctx context.Context, client database.QueryExecutor, builder *database.StatementBuilder) (*domain.User, error) {
|
||||
rows, err := client.Query(ctx, builder.String(), builder.Args()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var user rawUser
|
||||
if err = rows.(database.CollectableRows).CollectExactlyOneRow(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.toDomain()
|
||||
}
|
||||
|
||||
func scanUsers(ctx context.Context, client database.QueryExecutor, builder *database.StatementBuilder) ([]*domain.User, error) {
|
||||
rows, err := client.Query(ctx, builder.String(), builder.Args()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var users []rawUser
|
||||
if err = rows.(database.CollectableRows).Collect(&users); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]*domain.User, len(users))
|
||||
for i, user := range users {
|
||||
domainUser, err := user.toDomain()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[i] = domainUser
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// sub repositories
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// Human implements [domain.UserRepository].
|
||||
func (u user) Human() domain.HumanUserRepository {
|
||||
return userHuman{user: u}
|
||||
}
|
||||
|
||||
// Machine implements [domain.UserRepository].
|
||||
func (u user) Machine() domain.MachineUserRepository {
|
||||
return userMachine{user: u}
|
||||
}
|
||||
|
||||
func (u user) joinMachineKeys() database.QueryOption {
|
||||
return database.WithLeftJoin(
|
||||
u.machineKey.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.machineKey.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.machineKey.userIDColumn()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (u user) joinPATs() database.QueryOption {
|
||||
return database.WithLeftJoin(
|
||||
u.userPersonalAccessToken.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userPersonalAccessToken.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userPersonalAccessToken.userIDColumn()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (u user) joinMetadata() database.QueryOption {
|
||||
return database.WithLeftJoin(
|
||||
u.userMetadata.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userMetadata.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userMetadata.userIDColumn()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (u user) joinPasskeys() database.QueryOption {
|
||||
return database.WithLeftJoin(
|
||||
u.userPasskey.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userPasskey.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userPasskey.userIDColumn()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (u user) joinVerifications() database.QueryOption {
|
||||
return database.WithLeftJoin(
|
||||
u.verification.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.verification.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.verification.userIDColumn()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (u user) joinIdentityProviderLinks() database.QueryOption {
|
||||
return database.WithLeftJoin(
|
||||
u.userIdentityProviderLink.qualifiedTableName(),
|
||||
database.And(
|
||||
database.NewColumnCondition(u.InstanceIDColumn(), u.userIdentityProviderLink.instanceIDColumn()),
|
||||
database.NewColumnCondition(u.IDColumn(), u.userIdentityProviderLink.userIDColumn()),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/instrumentation/logging"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// repository
|
||||
// -------------------------------------------------------------
|
||||
|
||||
type userHuman struct {
|
||||
user
|
||||
}
|
||||
|
||||
var existingHumanUser = userHuman{
|
||||
user: user{
|
||||
tableName: "existing_user",
|
||||
},
|
||||
}
|
||||
|
||||
func HumanUserRepository() domain.HumanUserRepository {
|
||||
return &userHuman{
|
||||
user: user{},
|
||||
}
|
||||
}
|
||||
|
||||
func (u userHuman) create(ctx context.Context, builder *database.StatementBuilder, client database.QueryExecutor, user *domain.User) error {
|
||||
var createdAt any = database.NowInstruction
|
||||
if !user.CreatedAt.IsZero() {
|
||||
createdAt = user.CreatedAt
|
||||
}
|
||||
columnValues := map[string]any{
|
||||
"instance_id": user.InstanceID,
|
||||
"organization_id": user.OrganizationID,
|
||||
"id": user.ID,
|
||||
"username": user.Username,
|
||||
"state": user.State,
|
||||
"type": "human",
|
||||
"first_name": user.Human.FirstName,
|
||||
"last_name": user.Human.LastName,
|
||||
"created_at": createdAt,
|
||||
"updated_at": createdAt,
|
||||
}
|
||||
if !user.Human.MultifactorInitializationSkippedAt.IsZero() {
|
||||
columnValues["multifactor_initialization_skipped_at"] = user.Human.MultifactorInitializationSkippedAt
|
||||
}
|
||||
columnValues = u.setOptionalProfileColumns(columnValues, user.Human)
|
||||
|
||||
ctes := make(map[string]database.CTEChange)
|
||||
|
||||
columnValues, ctes = u.setPasswordColumns(columnValues, ctes, user, createdAt)
|
||||
columnValues, ctes = u.setEmailColumns(columnValues, ctes, user, createdAt)
|
||||
columnValues, ctes = u.setPhoneColumns(columnValues, ctes, user, createdAt)
|
||||
columnValues, ctes = u.setInviteColumns(columnValues, ctes, user, createdAt)
|
||||
|
||||
for i, passkey := range user.Human.Passkeys {
|
||||
ctes[fmt.Sprintf("passkey_%d", i)] = u.AddPasskey(passkey).(database.CTEChange)
|
||||
}
|
||||
|
||||
if user.Human.TOTP != nil {
|
||||
columnValues["totp_secret"] = user.Human.TOTP.Secret
|
||||
if !user.Human.TOTP.VerifiedAt.IsZero() {
|
||||
columnValues["totp_verified_at"] = user.Human.TOTP.VerifiedAt
|
||||
}
|
||||
}
|
||||
|
||||
for i, link := range user.Human.IdentityProviderLinks {
|
||||
name := fmt.Sprintf("idp_link_%d", i)
|
||||
ctes[name] = u.AddIdentityProviderLink(link).(database.CTEChange)
|
||||
}
|
||||
|
||||
for i, verification := range user.Human.Verifications {
|
||||
ctes[fmt.Sprintf("verification_%d", i)] = u.SetVerification(&domain.VerificationTypeInit{
|
||||
ID: gu.Ptr(verification.ID),
|
||||
CreatedAt: user.CreatedAt,
|
||||
Code: verification.Code,
|
||||
}).(database.CTEChange)
|
||||
}
|
||||
|
||||
for i, metadata := range user.Metadata {
|
||||
ctes[fmt.Sprintf("metadata_%d", i)] = u.SetMetadata(metadata).(database.CTEChange)
|
||||
}
|
||||
|
||||
// write CTE changes
|
||||
for name, cte := range ctes {
|
||||
cte.SetName(name)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString(name)
|
||||
builder.WriteString(" AS (")
|
||||
cte.WriteCTE(builder)
|
||||
builder.WriteString(")")
|
||||
}
|
||||
columns := slices.Sorted(maps.Keys(columnValues))
|
||||
|
||||
// write final insert
|
||||
builder.WriteString(" INSERT INTO zitadel.users (")
|
||||
builder.WriteString(strings.Join(columns, ", "))
|
||||
builder.WriteString(") VALUES (")
|
||||
for i, column := range columns {
|
||||
if i > 0 {
|
||||
builder.WriteString(", ")
|
||||
}
|
||||
value := columnValues[column]
|
||||
if fn, ok := value.(func(builder *database.StatementBuilder)); ok {
|
||||
fn(builder)
|
||||
continue
|
||||
}
|
||||
builder.WriteArg(value)
|
||||
}
|
||||
builder.WriteString(") RETURNING created_at, updated_at")
|
||||
|
||||
return client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&user.CreatedAt, &user.UpdatedAt)
|
||||
}
|
||||
|
||||
func (u userHuman) setPasswordColumns(columnValues map[string]any, ctes map[string]database.CTEChange, user *domain.User, createdAt any) (map[string]any, map[string]database.CTEChange) {
|
||||
if user.Human.Password.PendingVerification != nil {
|
||||
verification := &domain.VerificationTypeInit{
|
||||
CreatedAt: user.CreatedAt,
|
||||
Code: user.Human.Password.PendingVerification.Code,
|
||||
}
|
||||
if user.Human.Password.PendingVerification.ID != "" {
|
||||
verification.ID = &user.Human.Password.PendingVerification.ID
|
||||
}
|
||||
if user.Human.Password.PendingVerification.ExpiresAt != nil && !user.Human.Password.PendingVerification.ExpiresAt.IsZero() {
|
||||
verification.Expiry = gu.Ptr(time.Since(*user.Human.Password.PendingVerification.ExpiresAt))
|
||||
}
|
||||
|
||||
ctes["password_verification"] = u.SetResetPasswordVerification(verification).(database.CTEChange)
|
||||
columnValues["password_verification_id"] = func(builder *database.StatementBuilder) {
|
||||
builder.WriteString(`(SELECT id FROM password_verification)`)
|
||||
}
|
||||
} else if user.Human.Password.Hash != "" {
|
||||
columnValues["password_hash"] = user.Human.Password.Hash
|
||||
columnValues["password_changed_at"] = createdAt
|
||||
if !user.Human.Password.ChangedAt.IsZero() {
|
||||
columnValues["password_changed_at"] = user.Human.Password.ChangedAt
|
||||
}
|
||||
}
|
||||
return columnValues, ctes
|
||||
}
|
||||
|
||||
func (u userHuman) setEmailColumns(columnValues map[string]any, ctes map[string]database.CTEChange, user *domain.User, createdAt any) (map[string]any, map[string]database.CTEChange) {
|
||||
if user.Human.Email.PendingVerification != nil {
|
||||
verification := &domain.VerificationTypeInit{
|
||||
CreatedAt: user.CreatedAt,
|
||||
Code: user.Human.Email.PendingVerification.Code,
|
||||
}
|
||||
if user.Human.Email.PendingVerification.ID != "" {
|
||||
verification.ID = &user.Human.Email.PendingVerification.ID
|
||||
}
|
||||
if user.Human.Email.PendingVerification.ExpiresAt != nil && !user.Human.Email.PendingVerification.ExpiresAt.IsZero() {
|
||||
verification.Expiry = gu.Ptr(time.Since(*user.Human.Email.PendingVerification.ExpiresAt))
|
||||
}
|
||||
|
||||
ctes["email_verification"] = u.SetEmailVerification(verification).(database.CTEChange)
|
||||
columnValues["email_verification_id"] = func(builder *database.StatementBuilder) {
|
||||
builder.WriteString(`(SELECT id FROM email_verification)`)
|
||||
}
|
||||
}
|
||||
if user.Human.Email.Address != "" {
|
||||
columnValues["email"] = user.Human.Email.Address
|
||||
columnValues["unverified_email"] = user.Human.Email.Address
|
||||
columnValues["email_verified_at"] = createdAt
|
||||
if !user.Human.Email.VerifiedAt.IsZero() {
|
||||
columnValues["email_verified_at"] = user.Human.Email.VerifiedAt
|
||||
}
|
||||
}
|
||||
if user.Human.Email.UnverifiedAddress != "" {
|
||||
columnValues["unverified_email"] = user.Human.Email.UnverifiedAddress
|
||||
}
|
||||
return columnValues, ctes
|
||||
}
|
||||
|
||||
func (u userHuman) setPhoneColumns(columnValues map[string]any, ctes map[string]database.CTEChange, user *domain.User, createdAt any) (map[string]any, map[string]database.CTEChange) {
|
||||
if user.Human.Phone == nil {
|
||||
return columnValues, ctes
|
||||
}
|
||||
if user.Human.Phone.PendingVerification != nil {
|
||||
verification := &domain.VerificationTypeInit{
|
||||
CreatedAt: user.CreatedAt,
|
||||
Code: user.Human.Phone.PendingVerification.Code,
|
||||
}
|
||||
if user.Human.Phone.PendingVerification.ID != "" {
|
||||
verification.ID = &user.Human.Phone.PendingVerification.ID
|
||||
}
|
||||
if user.Human.Phone.PendingVerification.ExpiresAt != nil && !user.Human.Phone.PendingVerification.ExpiresAt.IsZero() {
|
||||
verification.Expiry = gu.Ptr(time.Since(*user.Human.Phone.PendingVerification.ExpiresAt))
|
||||
}
|
||||
|
||||
ctes["phone_verification"] = u.SetPhoneVerification(verification).(database.CTEChange)
|
||||
columnValues["phone_verification_id"] = func(builder *database.StatementBuilder) {
|
||||
builder.WriteString(`(SELECT id FROM phone_verification)`)
|
||||
}
|
||||
}
|
||||
if user.Human.Phone.Number != "" {
|
||||
columnValues["phone"] = user.Human.Phone.Number
|
||||
columnValues["unverified_phone"] = user.Human.Phone.Number
|
||||
columnValues["phone_verified_at"] = createdAt
|
||||
if !user.Human.Phone.VerifiedAt.IsZero() {
|
||||
columnValues["phone_verified_at"] = user.Human.Phone.VerifiedAt
|
||||
}
|
||||
}
|
||||
if user.Human.Phone.UnverifiedNumber != "" {
|
||||
columnValues["unverified_phone"] = user.Human.Phone.UnverifiedNumber
|
||||
}
|
||||
return columnValues, ctes
|
||||
}
|
||||
|
||||
func (u userHuman) setInviteColumns(columnValues map[string]any, ctes map[string]database.CTEChange, user *domain.User, createdAt any) (map[string]any, map[string]database.CTEChange) {
|
||||
if user.Human.Invite == nil {
|
||||
return columnValues, ctes
|
||||
}
|
||||
if user.Human.Invite.PendingVerification != nil {
|
||||
verification := &domain.VerificationTypeInit{
|
||||
CreatedAt: user.CreatedAt,
|
||||
Code: user.Human.Invite.PendingVerification.Code,
|
||||
}
|
||||
if user.Human.Invite.PendingVerification.ID != "" {
|
||||
verification.ID = &user.Human.Invite.PendingVerification.ID
|
||||
}
|
||||
if user.Human.Invite.PendingVerification.ExpiresAt != nil && !user.Human.Invite.PendingVerification.ExpiresAt.IsZero() {
|
||||
verification.Expiry = gu.Ptr(time.Since(*user.Human.Invite.PendingVerification.ExpiresAt))
|
||||
}
|
||||
ctes["invite_verification"] = u.SetInviteVerification(verification).(database.CTEChange)
|
||||
}
|
||||
if !user.Human.Invite.AcceptedAt.IsZero() {
|
||||
columnValues["invite_accepted_at"] = createdAt
|
||||
}
|
||||
return columnValues, ctes
|
||||
}
|
||||
|
||||
func (u userHuman) setOptionalProfileColumns(columnValues map[string]any, human *domain.HumanUser) map[string]any {
|
||||
if !human.PreferredLanguage.IsRoot() {
|
||||
columnValues["preferred_language"] = human.PreferredLanguage
|
||||
}
|
||||
if human.DisplayName != "" {
|
||||
columnValues["display_name"] = human.DisplayName
|
||||
}
|
||||
if human.Nickname != "" {
|
||||
columnValues["nickname"] = human.Nickname
|
||||
}
|
||||
if human.Gender != domain.HumanGenderUnspecified {
|
||||
columnValues["gender"] = human.Gender
|
||||
}
|
||||
if human.AvatarKey != "" {
|
||||
columnValues["avatar_key"] = human.AvatarKey
|
||||
}
|
||||
if human.Password.IsChangeRequired {
|
||||
columnValues["password_change_required"] = true
|
||||
}
|
||||
return columnValues
|
||||
}
|
||||
|
||||
func (u userHuman) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
||||
if !condition.IsRestrictingColumn(u.TypeColumn()) {
|
||||
condition = database.And(condition, u.TypeCondition(domain.UserTypeHuman))
|
||||
}
|
||||
return u.user.Update(ctx, client, condition, changes...)
|
||||
}
|
||||
|
||||
var _ domain.HumanUserRepository = (*userHuman)(nil)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetAvatarKey implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetAvatarKey(avatarKey *string) database.Change {
|
||||
return database.NewChangePtr(u.avatarKeyColumn(), avatarKey)
|
||||
}
|
||||
|
||||
// SetDisplayName implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetDisplayName(displayName string) database.Change {
|
||||
return database.NewChange(u.DisplayNameColumn(), displayName)
|
||||
}
|
||||
|
||||
// SetFirstName implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetFirstName(firstName string) database.Change {
|
||||
return database.NewChange(u.FirstNameColumn(), firstName)
|
||||
}
|
||||
|
||||
// SetGender implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetGender(gender domain.HumanGender) database.Change {
|
||||
return database.NewChange(u.genderColumn(), gender)
|
||||
}
|
||||
|
||||
// SetLastName implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetLastName(lastName string) database.Change {
|
||||
return database.NewChange(u.LastNameColumn(), lastName)
|
||||
}
|
||||
|
||||
// SkipMultifactorInitializationAt implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SkipMultifactorInitializationAt(skippedAt time.Time) database.Change {
|
||||
if skippedAt.IsZero() {
|
||||
return u.SkipMultifactorInitialization()
|
||||
}
|
||||
return database.NewChange(u.multifactorInitializationSkippedAtColumn(), skippedAt)
|
||||
}
|
||||
|
||||
// SkipMultifactorInitialization implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SkipMultifactorInitialization() database.Change {
|
||||
return database.NewChange(u.multifactorInitializationSkippedAtColumn(), database.NowInstruction)
|
||||
}
|
||||
|
||||
// SetNickname implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetNickname(nickname string) database.Change {
|
||||
return database.NewChange(u.NicknameColumn(), nickname)
|
||||
}
|
||||
|
||||
// SetPreferredLanguage implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetPreferredLanguage(preferredLanguage language.Tag) database.Change {
|
||||
if preferredLanguage == language.Und {
|
||||
return database.NewChangeToNull(u.preferredLanguageColumn())
|
||||
}
|
||||
return database.NewChange(u.preferredLanguageColumn(), preferredLanguage.String())
|
||||
}
|
||||
|
||||
// SetVerification implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetVerification(verification domain.VerificationType) database.Change {
|
||||
switch typ := verification.(type) {
|
||||
case *domain.VerificationTypeInit:
|
||||
return database.NewCTEChange(func(builder *database.StatementBuilder) {
|
||||
var (
|
||||
createdAt any = database.NowInstruction
|
||||
expiry any = database.NullInstruction
|
||||
id any = database.DefaultInstruction
|
||||
)
|
||||
if !typ.CreatedAt.IsZero() {
|
||||
createdAt = typ.CreatedAt
|
||||
}
|
||||
if typ.Expiry != nil {
|
||||
expiry = *typ.Expiry
|
||||
}
|
||||
if typ.ID != nil {
|
||||
id = *typ.ID
|
||||
}
|
||||
builder.WriteString("INSERT INTO zitadel.verifications(instance_id, user_id, id, code, created_at, expiry) SELECT instance_id, id, ")
|
||||
builder.WriteArgs(id, typ.Code, createdAt, expiry)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
builder.WriteString(" RETURNING id")
|
||||
}, nil)
|
||||
case *domain.VerificationTypeSucceeded:
|
||||
return database.NewCTEChange(func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM zitadel.verifications USING existing_user")
|
||||
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(u.verification.instanceIDColumn(), existingHumanUser.InstanceIDColumn()),
|
||||
database.NewColumnCondition(u.verification.userIDColumn(), existingHumanUser.IDColumn()),
|
||||
database.NewTextCondition(u.verification.idColumn(), database.TextOperationEqual, *typ.ID),
|
||||
))
|
||||
}, nil)
|
||||
|
||||
case *domain.VerificationTypeUpdate:
|
||||
changes := make(database.Changes, 0, 3)
|
||||
if typ.Code != nil {
|
||||
changes = append(changes, database.NewChange(u.verification.codeColumn(), typ.Code))
|
||||
}
|
||||
if typ.Expiry != nil {
|
||||
changes = append(changes, database.NewChange(u.verification.expiryColumn(), *typ.Expiry))
|
||||
}
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("UPDATE zitadel.verifications SET ")
|
||||
err := changes.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write changes in cte failed", "error", err)
|
||||
builder.WriteString(" FROM existing_user")
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(u.verification.instanceIDColumn(), existingHumanUser.InstanceIDColumn()),
|
||||
database.NewColumnCondition(u.verification.userIDColumn(), existingHumanUser.IDColumn()),
|
||||
database.NewTextCondition(u.verification.idColumn(), database.TextOperationEqual, *typ.ID),
|
||||
))
|
||||
},
|
||||
nil,
|
||||
)
|
||||
case *domain.VerificationTypeSkipped:
|
||||
panic("skip verification is not supported for verifications")
|
||||
case *domain.VerificationTypeFailed:
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("UPDATE ")
|
||||
builder.WriteString(u.verification.qualifiedTableName())
|
||||
builder.WriteString(" SET ")
|
||||
err := database.NewIncrementColumnChange(u.verification.failedAttemptsColumn(), database.Coalesce(u.verification.failedAttemptsColumn(), 0)).Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write cte failed", "error", err)
|
||||
builder.WriteString(" FROM existing_user")
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(u.verification.instanceIDColumn(), existingHumanUser.InstanceIDColumn()),
|
||||
database.NewColumnCondition(u.verification.userIDColumn(), existingHumanUser.IDColumn()),
|
||||
database.NewTextCondition(u.verification.idColumn(), database.TextOperationEqual, *typ.ID),
|
||||
))
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
panic(fmt.Sprintf("undefined verification type %T", verification))
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// DisplayNameCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) DisplayNameCondition(op database.TextOperation, displayName string) database.Condition {
|
||||
return database.NewTextCondition(u.DisplayNameColumn(), op, displayName)
|
||||
}
|
||||
|
||||
// FirstNameCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) FirstNameCondition(op database.TextOperation, firstName string) database.Condition {
|
||||
return database.NewTextCondition(u.FirstNameColumn(), op, firstName)
|
||||
}
|
||||
|
||||
// LastNameCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) LastNameCondition(op database.TextOperation, lastName string) database.Condition {
|
||||
return database.NewTextCondition(u.LastNameColumn(), op, lastName)
|
||||
}
|
||||
|
||||
// NicknameCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) NicknameCondition(op database.TextOperation, nickname string) database.Condition {
|
||||
return database.NewTextCondition(u.NicknameColumn(), op, nickname)
|
||||
}
|
||||
|
||||
// PreferredLanguageCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) PreferredLanguageCondition(lang language.Tag) database.Condition {
|
||||
return database.NewTextCondition(u.preferredLanguageColumn(), database.TextOperationEqual, lang.String())
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// DisplayNameColumn implements [domain.HumanUserRepository].
|
||||
func (u userHuman) DisplayNameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "display_name")
|
||||
}
|
||||
|
||||
func (u userHuman) genderColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "gender")
|
||||
}
|
||||
|
||||
func (u userHuman) avatarKeyColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "avatar_key")
|
||||
}
|
||||
|
||||
// FirstNameColumn implements [domain.HumanUserRepository].
|
||||
func (u userHuman) FirstNameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "first_name")
|
||||
}
|
||||
|
||||
// LastNameColumn implements [domain.HumanUserRepository].
|
||||
func (u userHuman) LastNameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "last_name")
|
||||
}
|
||||
|
||||
// NicknameColumn implements [domain.HumanUserRepository].
|
||||
func (u userHuman) NicknameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "nickname")
|
||||
}
|
||||
|
||||
func (u userHuman) multifactorInitializationSkippedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "multifactor_initialization_skipped_at")
|
||||
}
|
||||
|
||||
func (u userHuman) preferredLanguageColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "preferred_language")
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// scanners
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// sub repositories
|
||||
// -------------------------------------------------------------
|
||||
@@ -0,0 +1,132 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userHuman) SetEmail(email string) database.Change {
|
||||
return database.NewChange(u.EmailColumn(), email)
|
||||
}
|
||||
|
||||
func (u userHuman) SetUnverifiedEmail(email string) database.Change {
|
||||
return database.NewChange(u.unverifiedEmailColumn(), email)
|
||||
}
|
||||
|
||||
// SetEmailVerification implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetEmailVerification(verification domain.VerificationType) database.Change {
|
||||
switch typ := verification.(type) {
|
||||
case *domain.VerificationTypeInit:
|
||||
return u.verification.init(typ, existingHumanUser.unqualifiedTableName(), existingHumanUser.emailVerificationIDColumn())
|
||||
case *domain.VerificationTypeUpdate:
|
||||
return u.verification.update(typ, existingHumanUser.unqualifiedTableName(),
|
||||
existingHumanUser.InstanceIDColumn(), existingHumanUser.emailVerificationIDColumn())
|
||||
case *domain.VerificationTypeSucceeded:
|
||||
return database.NewChanges(
|
||||
u.verification.verified(typ, existingUser.unqualifiedTableName(), existingUser.InstanceIDColumn(),
|
||||
existingHumanUser.emailVerificationIDColumn(), u.emailVerifiedAtColumn(), u.failedEmailOTPAttemptsColumn(),
|
||||
),
|
||||
database.NewChangeToColumn(u.EmailColumn(), u.unverifiedEmailColumn()),
|
||||
)
|
||||
case *domain.VerificationTypeFailed:
|
||||
return u.verification.failed(existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(), existingHumanUser.emailVerificationIDColumn())
|
||||
case *domain.VerificationTypeSkipped:
|
||||
return u.verification.skipped(typ, u.emailVerifiedAtColumn(), u.emailVerificationIDColumn(), u.failedEmailOTPAttemptsColumn())
|
||||
}
|
||||
panic(fmt.Sprintf("type not allowed for email verification change %T", verification))
|
||||
}
|
||||
|
||||
// EnableEmailOTPAt implements [domain.HumanUserRepository].
|
||||
func (u userHuman) EnableEmailOTPAt(enabledAt time.Time) database.Change {
|
||||
return database.NewChange(u.emailOTPEnabledAtColumn(), enabledAt)
|
||||
}
|
||||
|
||||
// EnableEmailOTP implements [domain.HumanUserRepository].
|
||||
func (u userHuman) EnableEmailOTP() database.Change {
|
||||
return database.NewChange(u.emailOTPEnabledAtColumn(), database.NowInstruction)
|
||||
}
|
||||
|
||||
// DisableEmailOTP implements [domain.HumanUserRepository].
|
||||
func (u userHuman) DisableEmailOTP() database.Change {
|
||||
return database.NewChangeToNull(u.emailOTPEnabledAtColumn())
|
||||
}
|
||||
|
||||
func (u userHuman) SetLastSuccessfulEmailOTPCheck(checkedAt time.Time) database.Change {
|
||||
if checkedAt.IsZero() {
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulEmailOTPCheckColumn(), database.NowInstruction),
|
||||
u.ResetEmailOTPFailedAttempts(),
|
||||
)
|
||||
}
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulEmailOTPCheckColumn(), checkedAt),
|
||||
u.ResetEmailOTPFailedAttempts(),
|
||||
)
|
||||
}
|
||||
|
||||
func (u userHuman) IncrementEmailOTPFailedAttempts() database.Change {
|
||||
return database.NewIncrementColumnChange(u.failedEmailOTPAttemptsColumn(), database.Coalesce(u.failedEmailOTPAttemptsColumn(), 0))
|
||||
}
|
||||
|
||||
func (u userHuman) ResetEmailOTPFailedAttempts() database.Change {
|
||||
return database.NewChange(u.failedEmailOTPAttemptsColumn(), 0)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// EmailCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) EmailCondition(op database.TextOperation, email string) database.Condition {
|
||||
return database.Or(u.VerifiedEmailCondition(op, email), u.UnverifiedEmailCondition(op, email))
|
||||
}
|
||||
|
||||
// UnverifiedEmailCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) UnverifiedEmailCondition(op database.TextOperation, email string) database.Condition {
|
||||
return database.NewTextCondition(u.unverifiedEmailColumn(), op, email)
|
||||
}
|
||||
|
||||
// VerifiedEmailCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) VerifiedEmailCondition(op database.TextOperation, email string) database.Condition {
|
||||
return database.NewTextCondition(u.EmailColumn(), op, email)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// EmailColumn implements [domain.HumanUserRepository].
|
||||
func (u userHuman) EmailColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "email")
|
||||
}
|
||||
|
||||
func (u userHuman) unverifiedEmailColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "unverified_email")
|
||||
}
|
||||
|
||||
func (u userHuman) emailOTPEnabledAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "email_otp_enabled_at")
|
||||
}
|
||||
|
||||
func (u userHuman) emailVerifiedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "email_verified_at")
|
||||
}
|
||||
|
||||
func (u userHuman) emailVerificationIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "email_verification_id")
|
||||
}
|
||||
|
||||
func (u userHuman) failedEmailOTPAttemptsColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "email_otp_failed_attempts")
|
||||
}
|
||||
|
||||
func (u userHuman) lastSuccessfulEmailOTPCheckColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "email_otp_last_successful_check")
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userHuman) SetPassword(password string) database.Change {
|
||||
return database.NewChange(u.passwordHashColumn(), password)
|
||||
}
|
||||
|
||||
// SetResetPasswordVerification implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetResetPasswordVerification(verification domain.VerificationType) database.Change {
|
||||
switch typ := verification.(type) {
|
||||
case *domain.VerificationTypeInit:
|
||||
return u.verification.init(typ, existingUser.unqualifiedTableName(), existingHumanUser.passwordVerificationIDColumn())
|
||||
case *domain.VerificationTypeUpdate:
|
||||
return u.verification.update(typ, existingHumanUser.unqualifiedTableName(),
|
||||
existingHumanUser.InstanceIDColumn(), existingHumanUser.passwordVerificationIDColumn(),
|
||||
)
|
||||
case *domain.VerificationTypeSucceeded:
|
||||
return u.verification.verified(typ, existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(),
|
||||
existingHumanUser.passwordVerificationIDColumn(), u.passwordVerifiedAtColumn(), u.failedPasswordAttemptsColumn(),
|
||||
)
|
||||
case *domain.VerificationTypeSkipped:
|
||||
return u.verification.skipped(typ, u.passwordVerifiedAtColumn(), u.passwordVerificationIDColumn(), u.failedPasswordAttemptsColumn())
|
||||
case *domain.VerificationTypeFailed:
|
||||
return u.verification.failed(existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(), existingHumanUser.passwordVerificationIDColumn())
|
||||
}
|
||||
panic(fmt.Sprintf("undefined verification type %T", verification))
|
||||
}
|
||||
|
||||
// SetPasswordChangeRequired implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetPasswordChangeRequired(required bool) database.Change {
|
||||
return database.NewChange(u.passwordChangeRequiredColumn(), required)
|
||||
}
|
||||
|
||||
func (u userHuman) SetLastSuccessfulPasswordCheck(checkedAt time.Time) database.Change {
|
||||
if checkedAt.IsZero() {
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulPasswordCheckColumn(), database.NowInstruction),
|
||||
u.ResetPasswordFailedAttempts(),
|
||||
)
|
||||
}
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulPasswordCheckColumn(), checkedAt),
|
||||
u.ResetPasswordFailedAttempts(),
|
||||
)
|
||||
}
|
||||
|
||||
func (u userHuman) IncrementPasswordFailedAttempts() database.Change {
|
||||
return database.NewIncrementColumnChange(u.failedPasswordAttemptsColumn(), database.Coalesce(u.failedPasswordAttemptsColumn(), 0))
|
||||
}
|
||||
|
||||
func (u userHuman) ResetPasswordFailedAttempts() database.Change {
|
||||
return database.NewChange(u.failedPasswordAttemptsColumn(), 0)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userHuman) passwordHashColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "password_hash")
|
||||
}
|
||||
|
||||
func (u userHuman) passwordChangeRequiredColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "password_change_required")
|
||||
}
|
||||
|
||||
func (u userHuman) passwordVerifiedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "password_changed_at")
|
||||
}
|
||||
|
||||
func (u userHuman) passwordVerificationIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "password_verification_id")
|
||||
}
|
||||
|
||||
func (u userHuman) lastSuccessfulPasswordCheckColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "password_last_successful_check")
|
||||
}
|
||||
|
||||
func (u userHuman) failedPasswordAttemptsColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "password_failed_attempts")
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetPhone implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetPhone(phone string) database.Change {
|
||||
return database.NewChange(u.phoneColumn(), phone)
|
||||
}
|
||||
|
||||
// SetUnverifiedPhone implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetUnverifiedPhone(phone string) database.Change {
|
||||
return database.NewChange(u.unverifiedPhoneColumn(), phone)
|
||||
}
|
||||
|
||||
// SetPhoneVerification implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetPhoneVerification(verification domain.VerificationType) database.Change {
|
||||
switch typ := verification.(type) {
|
||||
case *domain.VerificationTypeInit:
|
||||
return u.verification.init(typ, existingHumanUser.unqualifiedTableName(), existingHumanUser.phoneVerificationIDColumn())
|
||||
case *domain.VerificationTypeUpdate:
|
||||
return u.verification.update(typ, existingHumanUser.unqualifiedTableName(),
|
||||
existingHumanUser.InstanceIDColumn(), existingHumanUser.phoneVerificationIDColumn(),
|
||||
)
|
||||
case *domain.VerificationTypeSucceeded:
|
||||
return database.NewChanges(
|
||||
u.verification.verified(typ, existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(),
|
||||
existingHumanUser.phoneVerificationIDColumn(), u.phoneVerifiedAtColumn(), u.failedSMSOTPAttemptsColumn(),
|
||||
),
|
||||
database.NewChangeToColumn(u.phoneColumn(), u.unverifiedPhoneColumn()),
|
||||
)
|
||||
case *domain.VerificationTypeFailed:
|
||||
return u.verification.failed(existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(), existingHumanUser.phoneVerificationIDColumn())
|
||||
case *domain.VerificationTypeSkipped:
|
||||
return u.verification.skipped(typ, u.phoneVerifiedAtColumn(), u.phoneVerificationIDColumn(), u.failedSMSOTPAttemptsColumn())
|
||||
}
|
||||
panic(fmt.Sprintf("type not allowed for phone verification change %T", verification))
|
||||
}
|
||||
|
||||
// RemovePhone implements [domain.HumanUserRepository].
|
||||
func (u userHuman) RemovePhone() database.Change {
|
||||
return database.NewChanges(
|
||||
database.NewChangeToNull(u.phoneColumn()),
|
||||
database.NewChangeToNull(u.phoneVerifiedAtColumn()),
|
||||
database.NewChangeToNull(u.phoneVerificationIDColumn()),
|
||||
database.NewChangeToNull(u.smsOTPEnabledAtColumn()),
|
||||
database.NewChangeToNull(u.lastSuccessfulSMSOTPCheckColumn()),
|
||||
database.NewChangeToNull(u.failedSMSOTPAttemptsColumn()),
|
||||
)
|
||||
}
|
||||
|
||||
// EnableSMSOTPAt implements [domain.HumanUserRepository].
|
||||
func (u userHuman) EnableSMSOTPAt(enabledAt time.Time) database.Change {
|
||||
return database.NewChange(u.smsOTPEnabledAtColumn(), enabledAt)
|
||||
}
|
||||
|
||||
// EnableSMSOTP implements [domain.HumanUserRepository].
|
||||
func (u userHuman) EnableSMSOTP() database.Change {
|
||||
return database.NewChange(u.smsOTPEnabledAtColumn(), database.NowInstruction)
|
||||
}
|
||||
|
||||
// DisableSMSOTP implements [domain.HumanUserRepository].
|
||||
func (u userHuman) DisableSMSOTP() database.Change {
|
||||
return database.NewChangeToNull(u.smsOTPEnabledAtColumn())
|
||||
}
|
||||
|
||||
func (u userHuman) SetLastSuccessfulSMSOTPCheck(checkedAt time.Time) database.Change {
|
||||
if checkedAt.IsZero() {
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulSMSOTPCheckColumn(), database.NowInstruction),
|
||||
u.ResetSMSOTPFailedAttempts(),
|
||||
)
|
||||
}
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulSMSOTPCheckColumn(), checkedAt),
|
||||
u.ResetSMSOTPFailedAttempts(),
|
||||
)
|
||||
}
|
||||
|
||||
// IncrementSMSOTPFailedAttempts implements [domain.HumanUserRepository].
|
||||
func (u userHuman) IncrementSMSOTPFailedAttempts() database.Change {
|
||||
return database.NewIncrementColumnChange(u.failedSMSOTPAttemptsColumn(), database.Coalesce(u.failedSMSOTPAttemptsColumn(), 0))
|
||||
}
|
||||
|
||||
// ResetSMSOTPFailedAttempts implements [domain.HumanUserRepository].
|
||||
func (u userHuman) ResetSMSOTPFailedAttempts() database.Change {
|
||||
return database.NewChange(u.failedSMSOTPAttemptsColumn(), 0)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// PhoneCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) PhoneCondition(op database.TextOperation, phone string) database.Condition {
|
||||
return database.Or(u.UnverifiedPhoneCondition(op, phone), u.VerifiedPhoneCondition(op, phone))
|
||||
}
|
||||
|
||||
// UnverifiedPhoneCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) UnverifiedPhoneCondition(op database.TextOperation, phone string) database.Condition {
|
||||
return database.NewTextCondition(u.unverifiedPhoneColumn(), op, phone)
|
||||
}
|
||||
|
||||
// VerifiedPhoneCondition implements [domain.HumanUserRepository].
|
||||
func (u userHuman) VerifiedPhoneCondition(op database.TextOperation, phone string) database.Condition {
|
||||
return database.NewTextCondition(u.phoneColumn(), op, phone)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userHuman) phoneColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "phone")
|
||||
}
|
||||
|
||||
func (u userHuman) unverifiedPhoneColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "unverified_phone")
|
||||
}
|
||||
|
||||
func (u userHuman) phoneVerifiedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "phone_verified_at")
|
||||
}
|
||||
|
||||
func (u userHuman) phoneVerificationIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "phone_verification_id")
|
||||
}
|
||||
|
||||
func (u userHuman) smsOTPEnabledAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "sms_otp_enabled_at")
|
||||
}
|
||||
|
||||
func (u userHuman) lastSuccessfulSMSOTPCheckColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "sms_otp_last_successful_check")
|
||||
}
|
||||
|
||||
func (u userHuman) failedSMSOTPAttemptsColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "sms_otp_failed_attempts")
|
||||
}
|
||||
@@ -0,0 +1,598 @@
|
||||
package repository_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
func Test_humanUser_create(t *testing.T) {
|
||||
tx, rollback := transactionForRollback(t)
|
||||
t.Cleanup(rollback)
|
||||
// tx := pool
|
||||
|
||||
userRepo := repository.UserRepository()
|
||||
|
||||
instanceID := createInstance(t, tx)
|
||||
orgID := createOrganization(t, tx, instanceID)
|
||||
createdAt := time.Now().Round(time.Millisecond).UTC()
|
||||
|
||||
existingUserID := createMachineUser(t, tx, instanceID, orgID)
|
||||
password := gofakeit.Password(true, true, true, true, false, 16)
|
||||
|
||||
type args struct {
|
||||
user *domain.User
|
||||
}
|
||||
type want struct {
|
||||
err error
|
||||
user *domain.User
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
args args
|
||||
want want
|
||||
}
|
||||
tests := []test{
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
|
||||
return test{
|
||||
name: "minimal representation",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
UnverifiedAddress: email,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
UnverifiedAddress: email,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
|
||||
return test{
|
||||
name: "including optional profile fields",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Nickname: "Nick",
|
||||
DisplayName: firstName + " " + lastName,
|
||||
PreferredLanguage: language.Georgian,
|
||||
Gender: domain.HumanGenderFemale,
|
||||
AvatarKey: "http://localhost:8080/my/profile/picture",
|
||||
MultifactorInitializationSkippedAt: createdAt,
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
},
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Nickname: "Nick",
|
||||
DisplayName: firstName + " " + lastName,
|
||||
PreferredLanguage: language.Georgian,
|
||||
Gender: domain.HumanGenderFemale,
|
||||
AvatarKey: "http://localhost:8080/my/profile/picture",
|
||||
MultifactorInitializationSkippedAt: createdAt,
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
UnverifiedAddress: email,
|
||||
VerifiedAt: createdAt,
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
ChangedAt: createdAt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
code := &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "aes256",
|
||||
KeyID: "key-id",
|
||||
Crypted: []byte("crypted"),
|
||||
}
|
||||
|
||||
return test{
|
||||
name: "with unverified email without expiry",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
},
|
||||
Email: domain.HumanEmail{
|
||||
UnverifiedAddress: email,
|
||||
PendingVerification: &domain.Verification{
|
||||
ID: "test",
|
||||
Code: code,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
UnverifiedAddress: email,
|
||||
PendingVerification: &domain.Verification{
|
||||
ID: "test",
|
||||
Code: code,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
},
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
ChangedAt: createdAt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
phone := gofakeit.Phone()
|
||||
code := &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "aes256",
|
||||
KeyID: "key-id",
|
||||
Crypted: []byte("crypted"),
|
||||
}
|
||||
|
||||
return test{
|
||||
name: "with unverified phone without expiry",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
},
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
UnverifiedAddress: email,
|
||||
VerifiedAt: createdAt,
|
||||
},
|
||||
Phone: &domain.HumanPhone{
|
||||
UnverifiedNumber: phone,
|
||||
PendingVerification: &domain.Verification{
|
||||
ID: "id",
|
||||
Code: code,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
UnverifiedAddress: email,
|
||||
VerifiedAt: createdAt,
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
ChangedAt: createdAt,
|
||||
},
|
||||
Phone: &domain.HumanPhone{
|
||||
UnverifiedNumber: phone,
|
||||
PendingVerification: &domain.Verification{
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
ID: "id",
|
||||
Code: code,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
passkeys := []*domain.Passkey{
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
KeyID: []byte(gofakeit.UUID()),
|
||||
Type: domain.PasskeyTypePasswordless,
|
||||
Name: "passwordless",
|
||||
PublicKey: []byte("public key"),
|
||||
AttestationType: "don't know",
|
||||
AuthenticatorAttestationGUID: []byte("aaguid"),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Challenge: []byte("challenge"),
|
||||
VerifiedAt: createdAt,
|
||||
RelyingPartyID: "rpid",
|
||||
},
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
KeyID: []byte(gofakeit.UUID()),
|
||||
Type: domain.PasskeyTypeU2F,
|
||||
Name: "u2f",
|
||||
PublicKey: []byte("public key"),
|
||||
AttestationType: "don't know",
|
||||
AuthenticatorAttestationGUID: []byte("aaguid"),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Challenge: []byte("challenge"),
|
||||
VerifiedAt: createdAt,
|
||||
RelyingPartyID: "rpid",
|
||||
},
|
||||
}
|
||||
|
||||
return test{
|
||||
name: "with verified passkeys",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
},
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
},
|
||||
Passkeys: passkeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
UnverifiedAddress: email,
|
||||
VerifiedAt: createdAt,
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
ChangedAt: createdAt,
|
||||
},
|
||||
Passkeys: passkeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
code := &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "aes256",
|
||||
KeyID: "key-id",
|
||||
Crypted: []byte("crypted"),
|
||||
}
|
||||
verifications := []*domain.Verification{
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
Code: code,
|
||||
},
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
Code: code,
|
||||
},
|
||||
}
|
||||
|
||||
return test{
|
||||
name: "with verifications",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
},
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
},
|
||||
Verifications: verifications,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
UnverifiedAddress: email,
|
||||
VerifiedAt: createdAt,
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
ChangedAt: createdAt,
|
||||
},
|
||||
Verifications: verifications,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
firstName := gofakeit.FirstName()
|
||||
lastName := gofakeit.LastName()
|
||||
email := gofakeit.Email()
|
||||
|
||||
return test{
|
||||
name: "with totp",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
},
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
},
|
||||
TOTP: &domain.HumanTOTP{
|
||||
VerifiedAt: createdAt,
|
||||
Secret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "aes-256",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("secret"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Human: &domain.HumanUser{
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: domain.HumanEmail{
|
||||
Address: email,
|
||||
UnverifiedAddress: email,
|
||||
VerifiedAt: createdAt,
|
||||
},
|
||||
Password: domain.HumanPassword{
|
||||
Hash: password,
|
||||
IsChangeRequired: true,
|
||||
ChangedAt: createdAt,
|
||||
},
|
||||
TOTP: &domain.HumanTOTP{
|
||||
VerifiedAt: createdAt,
|
||||
Secret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "aes-256",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("secret"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
return test{
|
||||
name: "already exists",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: existingUserID,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
err: new(database.UniqueError),
|
||||
},
|
||||
}
|
||||
}(),
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
savepoint, err := tx.Begin(t.Context())
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err := savepoint.Rollback(context.Background())
|
||||
if err != nil {
|
||||
t.Log("rollback savepoint failed", err)
|
||||
}
|
||||
})
|
||||
|
||||
err = userRepo.Create(t.Context(), savepoint, tt.args.user)
|
||||
require.ErrorIs(t, err, tt.want.err)
|
||||
if tt.want.err != nil {
|
||||
return
|
||||
}
|
||||
got, err := userRepo.Get(t.Context(), savepoint, database.WithCondition(
|
||||
userRepo.PrimaryKeyCondition(tt.want.user.InstanceID, tt.want.user.ID),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
assertUser(t, tt.want.user, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetTOTPSecret implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetTOTPSecret(secret *crypto.CryptoValue) database.Change {
|
||||
return database.NewChange(u.totpSecretColumn(), secret)
|
||||
}
|
||||
|
||||
// SetTOTPVerifiedAt implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetTOTPVerifiedAt(verifiedAt time.Time) database.Change {
|
||||
if verifiedAt.IsZero() {
|
||||
return database.NewChange(u.totpVerifiedAtColumn(), database.NowInstruction)
|
||||
}
|
||||
return database.NewChange(u.totpVerifiedAtColumn(), verifiedAt)
|
||||
}
|
||||
|
||||
// RemoveTOTP implements [domain.HumanUserRepository].
|
||||
func (u userHuman) RemoveTOTP() database.Change {
|
||||
return database.NewChanges(
|
||||
database.NewChangeToNull(u.totpSecretColumn()),
|
||||
database.NewChangeToNull(u.totpVerifiedAtColumn()),
|
||||
database.NewChangeToNull(u.lastSuccessfulTOTPCheckColumn()),
|
||||
)
|
||||
}
|
||||
|
||||
// SetLastSuccessfulTOTPCheck implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetLastSuccessfulTOTPCheck(checkedAt time.Time) database.Change {
|
||||
if checkedAt.IsZero() {
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulTOTPCheckColumn(), database.NowInstruction),
|
||||
u.ResetTOTPFailedAttempts(),
|
||||
)
|
||||
}
|
||||
return database.NewChanges(
|
||||
database.NewChange(u.lastSuccessfulTOTPCheckColumn(), checkedAt),
|
||||
u.ResetTOTPFailedAttempts(),
|
||||
)
|
||||
}
|
||||
|
||||
// IncrementTOTPFailedAttempts implements [domain.HumanUserRepository].
|
||||
func (u userHuman) IncrementTOTPFailedAttempts() database.Change {
|
||||
return database.NewIncrementColumnChange(u.totpFailedAttemptsColumn(), database.Coalesce(u.totpFailedAttemptsColumn(), 0))
|
||||
}
|
||||
|
||||
// ResetTOTPFailedAttempts implements [domain.HumanUserRepository].
|
||||
func (u userHuman) ResetTOTPFailedAttempts() database.Change {
|
||||
return database.NewChange(u.totpFailedAttemptsColumn(), 0)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userHuman) totpSecretColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "totp_secret")
|
||||
}
|
||||
|
||||
func (u userHuman) totpVerifiedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "totp_verified_at")
|
||||
}
|
||||
|
||||
func (u userHuman) lastSuccessfulTOTPCheckColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "totp_last_successful_check")
|
||||
}
|
||||
|
||||
func (u userHuman) totpFailedAttemptsColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "totp_failed_attempts")
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/instrumentation/logging"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type userIdentityProviderLink struct{}
|
||||
|
||||
func (u userIdentityProviderLink) unqualifiedTableName() string {
|
||||
return "user_identity_provider_links"
|
||||
}
|
||||
|
||||
func (u userIdentityProviderLink) qualifiedTableName() string {
|
||||
return "zitadel.user_identity_provider_links"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// AddIdentityProviderLink implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) AddIdentityProviderLink(link *domain.IdentityProviderLink) database.Change {
|
||||
var createdAt, updatedAt any = database.NowInstruction, database.NowInstruction
|
||||
if !link.CreatedAt.IsZero() {
|
||||
createdAt = link.CreatedAt
|
||||
}
|
||||
if !link.UpdatedAt.IsZero() {
|
||||
updatedAt = link.UpdatedAt
|
||||
}
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("INSERT INTO ")
|
||||
builder.WriteString(u.qualifiedTableName())
|
||||
builder.WriteString("(instance_id, user_id, provided_user_id, provided_username, identity_provider_id, created_at, updated_at) SELECT ")
|
||||
database.Columns{
|
||||
existingHumanUser.InstanceIDColumn(),
|
||||
existingHumanUser.IDColumn(),
|
||||
}.WriteQualified(builder)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteArgs(
|
||||
link.ProvidedUserID,
|
||||
link.ProvidedUsername,
|
||||
link.ProviderID,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
builder.WriteString(" RETURNING *")
|
||||
}, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// UpdateIdentityProviderLink implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) UpdateIdentityProviderLink(condition database.Condition, changes ...database.Change) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("UPDATE zitadel.user_identity_provider_links SET ")
|
||||
err := database.Changes(changes).Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write changes in cte failed", "error", err)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(existingHumanUser.InstanceIDColumn(), u.instanceIDColumn()),
|
||||
database.NewColumnCondition(existingHumanUser.IDColumn(), u.userIDColumn()),
|
||||
condition,
|
||||
))
|
||||
}, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// RemoveIdentityProviderLink implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) RemoveIdentityProviderLink(providerID string, providedUserID string) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM ")
|
||||
builder.WriteString(u.qualifiedTableName())
|
||||
builder.WriteString(" USING ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(
|
||||
existingHumanUser.InstanceIDColumn(),
|
||||
u.instanceIDColumn(),
|
||||
),
|
||||
database.NewColumnCondition(
|
||||
existingHumanUser.IDColumn(),
|
||||
u.userIDColumn(),
|
||||
),
|
||||
database.NewTextCondition(
|
||||
u.providerIDColumn(),
|
||||
database.TextOperationEqual,
|
||||
providerID,
|
||||
),
|
||||
database.NewTextCondition(
|
||||
u.providedUserIDColumn(),
|
||||
database.TextOperationEqual,
|
||||
providedUserID,
|
||||
),
|
||||
))
|
||||
}, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// SetIdentityProviderLinkUsername implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) SetIdentityProviderLinkUsername(username string) database.Change {
|
||||
return database.NewChange(u.providedUsernameColumn(), username)
|
||||
}
|
||||
|
||||
// SetIdentityProviderLinkProvidedID implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) SetIdentityProviderLinkProvidedID(providedUserID string) database.Change {
|
||||
return database.NewChange(u.providedUserIDColumn(), providedUserID)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// IdentityProviderLinkConditions implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) IdentityProviderLinkConditions() domain.HumanIdentityProviderLinkConditions {
|
||||
return u
|
||||
}
|
||||
|
||||
// ProviderIDCondition implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) ProviderIDCondition(idpID string) database.Condition {
|
||||
return database.NewTextCondition(u.providerIDColumn(), database.TextOperationEqual, idpID)
|
||||
}
|
||||
|
||||
// ProvidedUserIDCondition implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) ProvidedUserIDCondition(providedUserID string) database.Condition {
|
||||
return database.NewTextCondition(u.providedUserIDColumn(), database.TextOperationEqual, providedUserID)
|
||||
}
|
||||
|
||||
// ProvidedUsernameCondition implements [domain.HumanUserRepository].
|
||||
func (u userIdentityProviderLink) ProvidedUsernameCondition(op database.TextOperation, username string) database.Condition {
|
||||
return database.NewTextCondition(u.providedUsernameColumn(), op, username)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userIdentityProviderLink) instanceIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
func (u userIdentityProviderLink) userIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "user_id")
|
||||
}
|
||||
|
||||
func (u userIdentityProviderLink) providerIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "identity_provider_id")
|
||||
}
|
||||
|
||||
func (u userIdentityProviderLink) providedUserIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "provided_user_id")
|
||||
}
|
||||
|
||||
func (u userIdentityProviderLink) providedUsernameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "provided_username")
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetInviteVerification implements [domain.HumanUserRepository].
|
||||
func (u userHuman) SetInviteVerification(verification domain.VerificationType) database.Change {
|
||||
switch typ := verification.(type) {
|
||||
case *domain.VerificationTypeInit:
|
||||
return u.verification.init(typ, existingUser.unqualifiedTableName(), existingHumanUser.inviteVerificationIDColumn())
|
||||
case *domain.VerificationTypeUpdate:
|
||||
return u.verification.update(typ, existingHumanUser.unqualifiedTableName(),
|
||||
existingHumanUser.InstanceIDColumn(), existingHumanUser.inviteVerificationIDColumn(),
|
||||
)
|
||||
case *domain.VerificationTypeSucceeded:
|
||||
return u.verification.verified(typ, existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(),
|
||||
existingHumanUser.inviteVerificationIDColumn(), u.inviteAcceptedAtColumn(), u.failedInviteAttemptsColumn(),
|
||||
)
|
||||
case *domain.VerificationTypeSkipped:
|
||||
return u.verification.skipped(typ, u.inviteAcceptedAtColumn(), u.inviteVerificationIDColumn(), u.failedInviteAttemptsColumn())
|
||||
case *domain.VerificationTypeFailed:
|
||||
return u.verification.failed(existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(), existingHumanUser.inviteVerificationIDColumn())
|
||||
}
|
||||
panic(fmt.Sprintf("undefined verification type %T", verification))
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userHuman) inviteVerificationIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "invite_verification_id")
|
||||
}
|
||||
|
||||
func (u userHuman) inviteAcceptedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "invite_accepted_at")
|
||||
}
|
||||
|
||||
func (u userHuman) failedInviteAttemptsColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "invite_failed_attempts")
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type userMachine struct {
|
||||
user
|
||||
machineKey
|
||||
userPersonalAccessToken
|
||||
}
|
||||
|
||||
func (u userMachine) create(ctx context.Context, builder *database.StatementBuilder, client database.QueryExecutor, user *domain.User) error {
|
||||
changes := make(database.Changes, 0, len(user.Machine.Keys)+len(user.Machine.PATs))
|
||||
for _, key := range user.Machine.Keys {
|
||||
changes = append(changes, u.AddKey(key))
|
||||
}
|
||||
for _, pat := range user.Machine.PATs {
|
||||
changes = append(changes, u.AddPersonalAccessToken(pat))
|
||||
}
|
||||
for _, metadata := range user.Metadata {
|
||||
changes = append(changes, u.SetMetadata(metadata))
|
||||
}
|
||||
for i, change := range changes {
|
||||
sessionCTE(change, i, 0, builder)
|
||||
}
|
||||
|
||||
builder.WriteString("INSERT INTO zitadel.users (" +
|
||||
"instance_id, organization_id, id, username, state, type" +
|
||||
", name, description, secret, access_token_type, created_at, updated_at) VALUES (",
|
||||
)
|
||||
|
||||
var createdAt any = database.NowInstruction
|
||||
if !user.CreatedAt.IsZero() {
|
||||
createdAt = user.CreatedAt
|
||||
}
|
||||
builder.WriteArgs(
|
||||
user.InstanceID, user.OrganizationID, user.ID, user.Username, user.State, "machine",
|
||||
user.Machine.Name, user.Machine.Description, user.Machine.Secret, uint8(user.Machine.AccessTokenType),
|
||||
createdAt, createdAt,
|
||||
)
|
||||
|
||||
builder.WriteString(") RETURNING created_at, updated_at")
|
||||
|
||||
return client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&user.CreatedAt, &user.UpdatedAt)
|
||||
}
|
||||
|
||||
// Update implements [domain.MachineUserRepository].
|
||||
func (u userMachine) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
||||
if !condition.IsRestrictingColumn(u.TypeColumn()) {
|
||||
condition = database.And(condition, u.TypeCondition(domain.UserTypeMachine))
|
||||
}
|
||||
return u.user.Update(ctx, client, condition, changes...)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetAccessTokenType implements [domain.MachineUserRepository].
|
||||
func (u userMachine) SetAccessTokenType(tokenType domain.AccessTokenType) database.Change {
|
||||
return database.NewChange(u.accessTokenTypeColumn(), tokenType)
|
||||
}
|
||||
|
||||
// SetDescription implements [domain.MachineUserRepository].
|
||||
func (u userMachine) SetDescription(description string) database.Change {
|
||||
return database.NewChange(u.descriptionColumn(), description)
|
||||
}
|
||||
|
||||
// SetName implements [domain.MachineUserRepository].
|
||||
func (u userMachine) SetName(name string) database.Change {
|
||||
return database.NewChange(u.nameColumn(), name)
|
||||
}
|
||||
|
||||
// SetSecret implements [domain.MachineUserRepository].
|
||||
func (u userMachine) SetSecret(secret *string) database.Change {
|
||||
return database.NewChangePtr(u.secretColumn(), secret)
|
||||
}
|
||||
|
||||
var _ domain.MachineUserRepository = (*userMachine)(nil)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userMachine) nameColumn() database.Column {
|
||||
return database.NewColumn(u.user.unqualifiedTableName(), "name")
|
||||
}
|
||||
|
||||
func (u userMachine) descriptionColumn() database.Column {
|
||||
return database.NewColumn(u.user.unqualifiedTableName(), "description")
|
||||
}
|
||||
|
||||
func (u userMachine) accessTokenTypeColumn() database.Column {
|
||||
return database.NewColumn(u.user.unqualifiedTableName(), "access_token_type")
|
||||
}
|
||||
|
||||
func (u userMachine) secretColumn() database.Column {
|
||||
return database.NewColumn(u.user.unqualifiedTableName(), "secret")
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type machineKey struct{}
|
||||
|
||||
// AddKey implements [domain.MachineUserRepository].
|
||||
func (u machineKey) AddKey(key *domain.MachineKey) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("INSERT INTO zitadel.machine_keys (" +
|
||||
"instance_id, user_id, id, created_at, expires_at, type, public_key" +
|
||||
") SELECT instance_id, id, ",
|
||||
)
|
||||
var createdAt any = database.NowInstruction
|
||||
if !key.CreatedAt.IsZero() {
|
||||
createdAt = key.CreatedAt
|
||||
}
|
||||
var expiresAt any = database.NullInstruction
|
||||
if !key.ExpiresAt.IsZero() {
|
||||
expiresAt = key.ExpiresAt
|
||||
}
|
||||
builder.WriteArgs(key.ID, createdAt, expiresAt, key.Type, key.PublicKey)
|
||||
builder.WriteString(" FROM existing_user")
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// RemoveKey implements [domain.MachineUserRepository].
|
||||
func (u machineKey) RemoveKey(id string) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM zitadel.machine_keys WHERE " +
|
||||
"(instance_id, user_id, id) = (SELECT instance_id, id, ")
|
||||
builder.WriteArg(id)
|
||||
builder.WriteString(" FROM existing_user)")
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func (u machineKey) qualifiedTableName() string {
|
||||
return "zitadel.machine_keys"
|
||||
}
|
||||
|
||||
func (u machineKey) unqualifiedTableName() string {
|
||||
return "machine_keys"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u machineKey) instanceIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
|
||||
func (u machineKey) userIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "user_id")
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
package repository_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
)
|
||||
|
||||
func Test_machineUser_create(t *testing.T) {
|
||||
tx, rollback := transactionForRollback(t)
|
||||
t.Cleanup(rollback)
|
||||
|
||||
userRepo := repository.UserRepository()
|
||||
|
||||
instanceID := createInstance(t, tx)
|
||||
orgID := createOrganization(t, tx, instanceID)
|
||||
createdAt := time.Now().Round(time.Second)
|
||||
|
||||
existingUserID := createMachineUser(t, tx, instanceID, orgID)
|
||||
|
||||
type args struct {
|
||||
user *domain.User
|
||||
}
|
||||
type want struct {
|
||||
err error
|
||||
user *domain.User
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
args args
|
||||
want want
|
||||
}
|
||||
tests := []test{
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
return test{
|
||||
name: "minimal representation",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
return test{
|
||||
name: "with secret",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
Secret: "secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
Secret: "secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
return test{
|
||||
name: "with access token type",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
AccessTokenType: domain.AccessTokenTypeBearer,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
AccessTokenType: domain.AccessTokenTypeBearer,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
keys := []*domain.MachineKey{
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
PublicKey: []byte("public key"),
|
||||
CreatedAt: createdAt,
|
||||
ExpiresAt: createdAt.Add(24 * time.Hour),
|
||||
Type: domain.MachineKeyTypeJSON,
|
||||
},
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
PublicKey: []byte("public key"),
|
||||
CreatedAt: createdAt,
|
||||
ExpiresAt: createdAt.Add(24 * time.Hour),
|
||||
Type: domain.MachineKeyTypeJSON,
|
||||
},
|
||||
}
|
||||
return test{
|
||||
name: "with keys",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
Keys: keys,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
Keys: keys,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
pats := []*domain.PersonalAccessToken{
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
CreatedAt: createdAt,
|
||||
ExpiresAt: createdAt.Add(24 * time.Hour),
|
||||
},
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
CreatedAt: createdAt,
|
||||
ExpiresAt: createdAt.Add(24 * time.Hour),
|
||||
Scopes: []string{"some", "scopes"},
|
||||
},
|
||||
}
|
||||
return test{
|
||||
name: "with keys",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
PATs: pats,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
PATs: pats,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
id := gofakeit.UUID()
|
||||
pats := []*domain.PersonalAccessToken{
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
CreatedAt: createdAt,
|
||||
ExpiresAt: createdAt.Add(24 * time.Hour),
|
||||
},
|
||||
}
|
||||
keys := []*domain.MachineKey{
|
||||
{
|
||||
ID: gofakeit.UUID(),
|
||||
PublicKey: []byte("public key"),
|
||||
CreatedAt: createdAt,
|
||||
ExpiresAt: createdAt.Add(24 * time.Hour),
|
||||
Type: domain.MachineKeyTypeJSON,
|
||||
},
|
||||
}
|
||||
return test{
|
||||
name: "all fields set",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Metadata: []*domain.Metadata{
|
||||
{
|
||||
Key: "meta1",
|
||||
Value: []byte("value1"),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
},
|
||||
{
|
||||
Key: "meta2",
|
||||
Value: []byte("123"),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
},
|
||||
},
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
PATs: pats,
|
||||
Keys: keys,
|
||||
Secret: "secret",
|
||||
AccessTokenType: domain.AccessTokenTypeJWT,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: id,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
Metadata: []*domain.Metadata{
|
||||
{
|
||||
InstanceID: instanceID,
|
||||
Key: "meta1",
|
||||
Value: []byte("value1"),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
},
|
||||
{
|
||||
InstanceID: instanceID,
|
||||
Key: "meta2",
|
||||
Value: []byte("123"),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
},
|
||||
},
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
Description: "description",
|
||||
PATs: pats,
|
||||
Keys: keys,
|
||||
Secret: "secret",
|
||||
AccessTokenType: domain.AccessTokenTypeJWT,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}(),
|
||||
func() test {
|
||||
username := gofakeit.Username()
|
||||
return test{
|
||||
name: "already exists",
|
||||
args: args{
|
||||
user: &domain.User{
|
||||
InstanceID: instanceID,
|
||||
OrganizationID: orgID,
|
||||
ID: existingUserID,
|
||||
Username: username,
|
||||
State: domain.UserStateActive,
|
||||
CreatedAt: createdAt,
|
||||
Machine: &domain.MachineUser{
|
||||
Name: "machine",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
err: new(database.UniqueError),
|
||||
},
|
||||
}
|
||||
}(),
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
savepoint, err := tx.Begin(t.Context())
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err := savepoint.Rollback(context.Background())
|
||||
if err != nil {
|
||||
t.Log("rollback savepoint failed", err)
|
||||
}
|
||||
})
|
||||
|
||||
err = userRepo.Create(t.Context(), savepoint, tt.args.user)
|
||||
require.ErrorIs(t, err, tt.want.err)
|
||||
if tt.want.err != nil {
|
||||
return
|
||||
}
|
||||
got, err := userRepo.Get(t.Context(), savepoint, database.WithCondition(
|
||||
userRepo.PrimaryKeyCondition(tt.want.user.InstanceID, tt.want.user.ID),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
assertUser(t, tt.want.user, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type userMetadata struct{}
|
||||
|
||||
func (userMetadata) qualifiedTableName() string {
|
||||
return "zitadel.user_metadata"
|
||||
}
|
||||
|
||||
func (userMetadata) unqualifiedTableName() string {
|
||||
return "user_metadata"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// SetMetadata implements [domain.UserRepository].
|
||||
func (u userMetadata) SetMetadata(metadata ...*domain.Metadata) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("INSERT INTO zitadel.user_metadata(instance_id, user_id, key, value, created_at, updated_at)")
|
||||
builder.WriteString(" SELECT existing_user.instance_id, existing_user.id, md.key::TEXT, md.value::BYTEA, md.created_at::TIMESTAMPTZ, md.updated_at::TIMESTAMPTZ")
|
||||
builder.WriteString(" FROM existing_user CROSS JOIN (VALUES ")
|
||||
for i, md := range metadata {
|
||||
if i > 0 {
|
||||
builder.WriteString(", ")
|
||||
}
|
||||
builder.WriteRune('(')
|
||||
// The complex placeholder handling is needed to append the type casts
|
||||
// if we use WriteArgs directly, pgx resolves all args as TEXT instead of the correct type
|
||||
placeholders := make([]string, 4)
|
||||
placeholders[0] = builder.AppendArg(md.Key)
|
||||
placeholders[1] = builder.AppendArg(md.Value) + "::BYTEA"
|
||||
var createdAt, updatedAt any = database.NowInstruction, database.NullInstruction
|
||||
if !md.CreatedAt.IsZero() {
|
||||
createdAt = md.CreatedAt
|
||||
}
|
||||
if !md.UpdatedAt.IsZero() {
|
||||
updatedAt = md.UpdatedAt
|
||||
}
|
||||
placeholders[2] = builder.AppendArg(createdAt) + "::TIMESTAMPTZ"
|
||||
placeholders[3] = builder.AppendArg(updatedAt) + "::TIMESTAMPTZ"
|
||||
builder.WriteString(strings.Join(placeholders, ", "))
|
||||
builder.WriteRune(')')
|
||||
}
|
||||
builder.WriteString(") AS md(key, value, created_at, updated_at) ON CONFLICT (")
|
||||
database.Columns{
|
||||
u.instanceIDColumn(),
|
||||
u.userIDColumn(),
|
||||
u.keyColumn(),
|
||||
}.WriteUnqualified(builder)
|
||||
builder.WriteString(") DO UPDATE SET value = EXCLUDED.value, updated_at = EXCLUDED.updated_at WHERE ")
|
||||
u.valueColumn().WriteQualified(builder)
|
||||
builder.WriteString(" IS DISTINCT FROM EXCLUDED.value")
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// RemoveMetadata implements [domain.UserRepository].
|
||||
func (u userMetadata) RemoveMetadata(condition database.Condition) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM zitadel.user_metadata USING ")
|
||||
builder.WriteString(existingUser.unqualifiedTableName())
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(existingUser.InstanceIDColumn(), u.instanceIDColumn()),
|
||||
database.NewColumnCondition(existingUser.IDColumn(), u.userIDColumn()),
|
||||
condition,
|
||||
))
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userMetadata) MetadataConditions() domain.UserMetadataConditions {
|
||||
return u
|
||||
}
|
||||
|
||||
// MetadataKeyCondition implements [domain.UserMetadataConditions].
|
||||
func (u userMetadata) MetadataKeyCondition(op database.TextOperation, key string) database.Condition {
|
||||
return database.NewTextCondition(u.keyColumn(), op, key)
|
||||
}
|
||||
|
||||
// MetadataValueCondition implements [domain.UserMetadataConditions].
|
||||
func (u userMetadata) MetadataValueCondition(op database.BytesOperation, value []byte) database.Condition {
|
||||
return database.NewBytesCondition[[]byte](database.SHA256Column(u.valueColumn()), op, database.SHA256Value(value))
|
||||
}
|
||||
|
||||
var _ domain.UserMetadataConditions = (*userMetadata)(nil)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userMetadata) instanceIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
|
||||
func (u userMetadata) userIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "user_id")
|
||||
}
|
||||
|
||||
func (u userMetadata) keyColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "key")
|
||||
}
|
||||
|
||||
func (u userMetadata) valueColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "value")
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/instrumentation/logging"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type userPasskey struct{}
|
||||
|
||||
func (u userPasskey) unqualifiedTableName() string {
|
||||
return "user_passkeys"
|
||||
}
|
||||
|
||||
func (u userPasskey) qualifiedTableName() string {
|
||||
return "zitadel.user_passkeys"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// changes
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// AddPasskey implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) AddPasskey(passkey *domain.Passkey) database.Change {
|
||||
var (
|
||||
createdAt any = database.NowInstruction
|
||||
updatedAt any = database.NowInstruction
|
||||
verifiedAt any = database.NowInstruction
|
||||
)
|
||||
if !passkey.CreatedAt.IsZero() {
|
||||
createdAt = passkey.CreatedAt
|
||||
}
|
||||
if !passkey.UpdatedAt.IsZero() {
|
||||
updatedAt = passkey.UpdatedAt
|
||||
}
|
||||
if !passkey.VerifiedAt.IsZero() {
|
||||
verifiedAt = passkey.VerifiedAt
|
||||
}
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("INSERT INTO ")
|
||||
builder.WriteString(u.qualifiedTableName())
|
||||
builder.WriteString(" (")
|
||||
database.Columns{
|
||||
u.instanceIDColumn(),
|
||||
u.userIDColumn(),
|
||||
u.tokenIDColumn(),
|
||||
u.keyIDColumn(),
|
||||
u.createdAtColumn(),
|
||||
u.updatedAtColumn(),
|
||||
u.verifiedAtColumn(),
|
||||
u.typeColumn(),
|
||||
u.nameColumn(),
|
||||
u.signCountColumn(),
|
||||
u.challengeColumn(),
|
||||
u.publicKeyColumn(),
|
||||
u.attestationTypeColumn(),
|
||||
u.authenticatorAttestationGUIDColumn(),
|
||||
u.relyingPartyIDColumn(),
|
||||
}.WriteUnqualified(builder)
|
||||
builder.WriteString(") SELECT ")
|
||||
database.Columns{
|
||||
existingHumanUser.InstanceIDColumn(),
|
||||
existingHumanUser.IDColumn(),
|
||||
}.WriteQualified(builder)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteArgs(
|
||||
passkey.ID,
|
||||
passkey.KeyID,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
verifiedAt,
|
||||
passkey.Type,
|
||||
passkey.Name,
|
||||
passkey.SignCount,
|
||||
passkey.Challenge,
|
||||
passkey.PublicKey,
|
||||
passkey.AttestationType,
|
||||
passkey.AuthenticatorAttestationGUID,
|
||||
passkey.RelyingPartyID,
|
||||
)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
}, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// RemovePasskey implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) RemovePasskey(condition database.Condition) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM ")
|
||||
builder.WriteString(u.qualifiedTableName())
|
||||
builder.WriteString(" USING ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(existingHumanUser.InstanceIDColumn(), u.instanceIDColumn()),
|
||||
database.NewColumnCondition(existingHumanUser.IDColumn(), u.userIDColumn()),
|
||||
condition,
|
||||
))
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// UpdatePasskey implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) UpdatePasskey(condition database.Condition, changes ...database.Change) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("UPDATE ")
|
||||
builder.WriteString(u.qualifiedTableName())
|
||||
builder.WriteString(" SET ")
|
||||
err := database.Changes(changes).Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write changes in cte failed", "error", err)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingHumanUser.unqualifiedTableName())
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(existingHumanUser.InstanceIDColumn(), u.instanceIDColumn()),
|
||||
database.NewColumnCondition(existingHumanUser.IDColumn(), u.userIDColumn()),
|
||||
condition,
|
||||
))
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// SetPasskeyAttestationType implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyAttestationType(attestationType string) database.Change {
|
||||
return database.NewChange(u.attestationTypeColumn(), attestationType)
|
||||
}
|
||||
|
||||
// SetPasskeyAuthenticatorAttestationGUID implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyAuthenticatorAttestationGUID(aaguid []byte) database.Change {
|
||||
return database.NewChange(u.authenticatorAttestationGUIDColumn(), aaguid)
|
||||
}
|
||||
|
||||
// SetPasskeyKeyID implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyKeyID(keyID []byte) database.Change {
|
||||
return database.NewChange(u.keyIDColumn(), keyID)
|
||||
}
|
||||
|
||||
// SetPasskeyName implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyName(name string) database.Change {
|
||||
return database.NewChange(u.nameColumn(), name)
|
||||
}
|
||||
|
||||
// SetPasskeyPublicKey implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyPublicKey(publicKey []byte) database.Change {
|
||||
return database.NewChange(u.publicKeyColumn(), publicKey)
|
||||
}
|
||||
|
||||
// SetPasskeySignCount implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeySignCount(signCount uint32) database.Change {
|
||||
return database.NewChange(u.signCountColumn(), signCount)
|
||||
}
|
||||
|
||||
// SetPasskeyUpdatedAt implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyUpdatedAt(updatedAt time.Time) database.Change {
|
||||
return database.NewChange(u.updatedAtColumn(), updatedAt)
|
||||
}
|
||||
|
||||
// SetPasskeyVerifiedAt implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) SetPasskeyVerifiedAt(verifiedAt time.Time) database.Change {
|
||||
verifiedAtChange := database.NewChange(u.verifiedAtColumn(), database.NowInstruction)
|
||||
if !verifiedAt.IsZero() {
|
||||
verifiedAtChange = database.NewChange(u.verifiedAtColumn(), verifiedAt)
|
||||
}
|
||||
return verifiedAtChange
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// conditions
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// PasskeyConditions implements [domain.HumanUserRepository].
|
||||
func (u userPasskey) PasskeyConditions() domain.HumanPasskeyConditions {
|
||||
return u
|
||||
}
|
||||
|
||||
// ChallengeCondition implements [domain.HumanPasskeyConditions].
|
||||
func (u userPasskey) ChallengeCondition(challenge []byte) database.Condition {
|
||||
return database.NewBytesCondition[[]byte](database.SHA256Column(u.challengeColumn()), database.BytesOperationEqual, database.SHA256Value(challenge))
|
||||
}
|
||||
|
||||
// IDCondition implements [domain.HumanPasskeyConditions].
|
||||
func (u userPasskey) IDCondition(passkeyID string) database.Condition {
|
||||
return database.NewTextCondition(u.tokenIDColumn(), database.TextOperationEqual, passkeyID)
|
||||
}
|
||||
|
||||
// KeyIDCondition implements [domain.HumanPasskeyConditions].
|
||||
func (u userPasskey) KeyIDCondition(keyID string) database.Condition {
|
||||
return database.NewTextCondition(u.keyIDColumn(), database.TextOperationEqual, keyID)
|
||||
}
|
||||
|
||||
// TypeCondition implements [domain.HumanPasskeyConditions].
|
||||
func (u userPasskey) TypeCondition(passkeyType domain.PasskeyType) database.Condition {
|
||||
return database.NewTextCondition(u.typeColumn(), database.TextOperationEqual, passkeyType.String())
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (u userPasskey) tokenIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "token_id")
|
||||
}
|
||||
|
||||
func (u userPasskey) keyIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "key_id")
|
||||
}
|
||||
|
||||
func (u userPasskey) instanceIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
|
||||
func (u userPasskey) userIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "user_id")
|
||||
}
|
||||
|
||||
func (u userPasskey) relyingPartyIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "relying_party_id")
|
||||
}
|
||||
|
||||
func (u userPasskey) authenticatorAttestationGUIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "authenticator_attestation_guid")
|
||||
}
|
||||
|
||||
func (u userPasskey) attestationTypeColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "attestation_type")
|
||||
}
|
||||
|
||||
func (u userPasskey) publicKeyColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "public_key")
|
||||
}
|
||||
|
||||
func (u userPasskey) challengeColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "challenge")
|
||||
}
|
||||
|
||||
func (u userPasskey) signCountColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "sign_count")
|
||||
}
|
||||
|
||||
func (u userPasskey) nameColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "name")
|
||||
}
|
||||
|
||||
func (u userPasskey) typeColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "type")
|
||||
}
|
||||
|
||||
func (u userPasskey) verifiedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "verified_at")
|
||||
}
|
||||
|
||||
func (u userPasskey) updatedAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "updated_at")
|
||||
}
|
||||
|
||||
func (u userPasskey) createdAtColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "created_at")
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type userPersonalAccessToken struct{}
|
||||
|
||||
// AddPersonalAccessToken implements [domain.MachineUserRepository].
|
||||
func (userPersonalAccessToken) AddPersonalAccessToken(pat *domain.PersonalAccessToken) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("INSERT INTO zitadel.user_personal_access_tokens (" +
|
||||
"instance_id, user_id, id, created_at, expires_at, scopes" +
|
||||
") SELECT instance_id, id, ",
|
||||
)
|
||||
var createdAt any = database.NowInstruction
|
||||
if !pat.CreatedAt.IsZero() {
|
||||
createdAt = pat.CreatedAt
|
||||
}
|
||||
var expiresAt any = database.NullInstruction
|
||||
if !pat.ExpiresAt.IsZero() {
|
||||
expiresAt = pat.ExpiresAt
|
||||
}
|
||||
builder.WriteArgs(pat.ID, createdAt, expiresAt, pat.Scopes)
|
||||
builder.WriteString(" FROM existing_user")
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// RemovePersonalAccessToken implements [domain.MachineUserRepository].
|
||||
func (userPersonalAccessToken) RemovePersonalAccessToken(id string) database.Change {
|
||||
return database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM zitadel.user_personal_access_tokens WHERE " +
|
||||
"(instance_id, user_id, id) = (SELECT instance_id, id, ")
|
||||
builder.WriteArg(id)
|
||||
builder.WriteString(" FROM existing_user)")
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func (userPersonalAccessToken) qualifiedTableName() string {
|
||||
return "zitadel.user_personal_access_tokens"
|
||||
}
|
||||
|
||||
func (userPersonalAccessToken) unqualifiedTableName() string {
|
||||
return "user_personal_access_tokens"
|
||||
}
|
||||
|
||||
func (u userPersonalAccessToken) instanceIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
|
||||
func (u userPersonalAccessToken) userIDColumn() database.Column {
|
||||
return database.NewColumn(u.unqualifiedTableName(), "user_id")
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/instrumentation/logging"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
)
|
||||
|
||||
type verification struct{}
|
||||
|
||||
func (v verification) unqualifiedTableName() string {
|
||||
return "verifications"
|
||||
}
|
||||
|
||||
func (v verification) qualifiedTableName() string {
|
||||
return "zitadel." + v.unqualifiedTableName()
|
||||
}
|
||||
|
||||
// init creates a new verification
|
||||
func (v verification) init(init *domain.VerificationTypeInit, existingTableName string, verificationID database.Column) database.CTEChange {
|
||||
return database.NewCTEChange(func(builder *database.StatementBuilder) {
|
||||
var (
|
||||
createdAt any = database.NowInstruction
|
||||
expiry any = database.NullInstruction
|
||||
id any = database.GenRandomUUIDInstruction
|
||||
)
|
||||
if !init.CreatedAt.IsZero() {
|
||||
createdAt = init.CreatedAt
|
||||
}
|
||||
if init.Expiry != nil {
|
||||
expiry = *init.Expiry
|
||||
}
|
||||
if init.ID != nil {
|
||||
id = *init.ID
|
||||
}
|
||||
builder.WriteString("INSERT INTO zitadel.verifications(instance_id, user_id, id, code, created_at, updated_at, expiry) SELECT instance_id, id, ")
|
||||
builder.WriteArgs(id, init.Code, createdAt, createdAt, expiry)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingTableName)
|
||||
builder.WriteString(" RETURNING id")
|
||||
}, func(name string) database.Change {
|
||||
return database.NewChangeToStatement(verificationID, func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("SELECT id FROM ")
|
||||
builder.WriteString(name)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// updates the given fields of the verification with the given ID. Only non-nil fields get updated.
|
||||
func (v verification) update(update *domain.VerificationTypeUpdate, existingTableName string, instanceID, verificationID database.Column) database.CTEChange {
|
||||
changes := make(database.Changes, 0, 3)
|
||||
if update.Code != nil {
|
||||
changes = append(changes, database.NewChange(v.codeColumn(), update.Code))
|
||||
}
|
||||
if update.Expiry != nil {
|
||||
changes = append(changes, database.NewChange(v.expiryColumn(), *update.Expiry))
|
||||
}
|
||||
if update.UpdatedAt.IsZero() {
|
||||
changes = append(changes, database.NewChange(v.updatedAtColumn(), database.NowInstruction))
|
||||
} else {
|
||||
changes = append(changes, database.NewChange(v.updatedAtColumn(), update.UpdatedAt))
|
||||
}
|
||||
return database.NewCTEChange(func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("UPDATE ")
|
||||
builder.WriteString(v.qualifiedTableName())
|
||||
builder.WriteString(" SET ")
|
||||
err := changes.Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write changes in cte failed", "error", err)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingTableName)
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(v.instanceIDColumn(), instanceID),
|
||||
database.NewColumnCondition(v.idColumn(), verificationID),
|
||||
))
|
||||
}, nil)
|
||||
}
|
||||
|
||||
// verified constructs the following changes:
|
||||
// - sets the verifiedAt column to the current time or the provided time
|
||||
// - clears the pending verification ID
|
||||
// - deletes the verification
|
||||
// - resets the failed attempts counter
|
||||
func (v verification) verified(verified *domain.VerificationTypeSucceeded, existingTableName string, instanceID, pendingVerificationID, verifiedAt, failedAttempts database.Column) database.Changes {
|
||||
verifiedAtChange := database.NewChange(verifiedAt, database.NowInstruction)
|
||||
if !verified.VerifiedAt.IsZero() {
|
||||
verifiedAtChange = database.NewChange(verifiedAt, verified.VerifiedAt)
|
||||
}
|
||||
|
||||
return database.NewChanges(
|
||||
verifiedAtChange,
|
||||
database.NewChangeToNull(pendingVerificationID),
|
||||
database.NewChange(failedAttempts, 0),
|
||||
database.NewCTEChange(
|
||||
func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("DELETE FROM ")
|
||||
builder.WriteString(v.qualifiedTableName())
|
||||
builder.WriteString(" USING ")
|
||||
builder.WriteString(existingTableName)
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(v.instanceIDColumn(), instanceID),
|
||||
database.NewColumnCondition(v.idColumn(), pendingVerificationID),
|
||||
))
|
||||
}, nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// skipped constructs the following changes:
|
||||
// - sets the verifiedAt column to the current time or the provided time
|
||||
// - clears the pending verification ID
|
||||
// - resets the failed attempts counter
|
||||
func (v verification) skipped(skipped *domain.VerificationTypeSkipped, verifiedAt, pendingVerificationID, failedAttempts database.Column) database.Changes {
|
||||
verifiedAtChange := database.NewChange(verifiedAt, database.NowInstruction)
|
||||
if !skipped.SkippedAt.IsZero() {
|
||||
verifiedAtChange = database.NewChange(verifiedAt, skipped.SkippedAt)
|
||||
}
|
||||
return database.NewChanges(
|
||||
verifiedAtChange,
|
||||
database.NewChange(failedAttempts, 0),
|
||||
database.NewChangeToNull(pendingVerificationID),
|
||||
)
|
||||
}
|
||||
|
||||
// failed increments the failed attempts counter.
|
||||
func (v verification) failed(existingTableName string, instanceID, verificationID database.Column) database.CTEChange {
|
||||
return database.NewCTEChange(func(builder *database.StatementBuilder) {
|
||||
builder.WriteString("UPDATE ")
|
||||
builder.WriteString(v.qualifiedTableName())
|
||||
builder.WriteString(" SET ")
|
||||
err := database.NewIncrementColumnChange(v.failedAttemptsColumn(), database.Coalesce(v.failedAttemptsColumn(), 0)).Write(builder)
|
||||
logging.New(logging.StreamRuntime).Debug("write cte failed", "error", err)
|
||||
builder.WriteString(" FROM ")
|
||||
builder.WriteString(existingTableName)
|
||||
writeCondition(builder, database.And(
|
||||
database.NewColumnCondition(v.instanceIDColumn(), instanceID),
|
||||
database.NewColumnCondition(v.idColumn(), verificationID),
|
||||
))
|
||||
}, nil)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// columns
|
||||
// -------------------------------------------------------------
|
||||
|
||||
func (v verification) instanceIDColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "instance_id")
|
||||
}
|
||||
|
||||
func (v verification) idColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "id")
|
||||
}
|
||||
|
||||
func (v verification) codeColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "code")
|
||||
}
|
||||
|
||||
func (v verification) expiryColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "expiry")
|
||||
}
|
||||
|
||||
func (v verification) failedAttemptsColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "failed_attempts")
|
||||
}
|
||||
|
||||
func (v verification) userIDColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "user_id")
|
||||
}
|
||||
|
||||
func (v verification) updatedAtColumn() database.Column {
|
||||
return database.NewColumn(v.unqualifiedTableName(), "updated_at")
|
||||
}
|
||||
@@ -8,9 +8,10 @@ import (
|
||||
type Instruction string
|
||||
|
||||
const (
|
||||
DefaultInstruction Instruction = "DEFAULT"
|
||||
NowInstruction Instruction = "NOW()"
|
||||
NullInstruction Instruction = "NULL"
|
||||
DefaultInstruction Instruction = "DEFAULT"
|
||||
NowInstruction Instruction = "NOW()"
|
||||
NullInstruction Instruction = "NULL"
|
||||
GenRandomUUIDInstruction Instruction = "gen_random_uuid()"
|
||||
)
|
||||
|
||||
// StatementBuilder is a helper to build SQL statement.
|
||||
|
||||
Reference in New Issue
Block a user