fixup! feat(db): Adding identity_providers table for relational database

This commit is contained in:
Iraq Jaber
2025-07-18 11:02:50 +01:00
parent 9c94f2744a
commit d951a8b13e
7 changed files with 563 additions and 1 deletions

View File

@@ -0,0 +1,103 @@
package domain
import (
"context"
"time"
"github.com/zitadel/zitadel/backend/v3/storage/database"
)
//go:generate enumer -type IDPType -transform lower -trimprefix IDPType
type IDPType uint8
const (
IDPTypeOIDC IDPType = iota
IDPTypeOAUTH
IDPTypeSAML
IDPTypeLDAP
IDPTypeGithub
IDPTypeGoogle
IDPTypeMicrosoft
IDPTypeApple
)
//go:generate enumer -type IDPState -transform lower -trimprefix IDPState
type IDPState uint8
const (
IDPStateActive IDPState = iota
IDPStateInactive
)
type IdentityProvider struct {
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrgID string `json:"org_id,omitempty" db:"org_id"`
ID string `json:"id,omitempty" db:"id"`
State string `json:"state,omitempty" db:"state"`
Name string `json:"name,omitempty" db:"name"`
Type string `json:"type,omitempty" db:"type"`
AllowCreation bool `json:"allow_creation,omitempty" db:"allow_creation"`
AllowAutoCreation bool `json:"allow_auto_creation,omitempty" db:"allow_auto_creation"`
AllowAutoUpdate bool `json:"allow_auto_update,omitempty" db:"allow_auto_update"`
AllowLinking bool `json:"allow_linking,omitempty" db:"allow_linking"`
StylingType int16 `json:"styling_type,omitempty" db:"styling_type"`
Payload string `json:"payload,omitempty" db:"payload"`
CreatedAt time.Time `json:"createdAt,omitempty" db:"created_at"`
UpdatedAt time.Time `json:"updatedAt,omitempty" db:"updated_at"`
}
type idProviderColumns interface {
InstanceIDColumn() database.Column
OrgIDColumn() database.Column
IDColumn() database.Column
StateColumn() database.Column
NameColumn() database.Column
TypeColumn() database.Column
AllowCreationColumn() database.Column
AllowAutoCreationColumn() database.Column
AllowAutoUpdateColumn() database.Column
AllowLinkingColumn() database.Column
StylingTypeColumn() database.Column
PayloadColumn() database.Column
CreatedAtColumn() database.Column
UpdatedAtColumn() database.Column
}
type idProviderConditions interface {
InstanceIDCondition(id string) database.Condition
OrgIDCondition(id string) database.Condition
IDCondition(id string) database.Condition
StateCondition(state IDPState) database.Condition
NameCondition(name string) database.Condition
TypeCondition(typee IDPType) database.Condition
AllowCreationCondition(allow bool) database.Condition
AllowAutoCreationCondition(allow bool) database.Condition
AllowAutoUpdateCondition(allow bool) database.Condition
AllowLinkingCondition(allow bool) database.Condition
StylingTypeCondition(style int16) database.Condition
PayloadCondition(payload string) database.Condition
}
type idProviderChanges interface {
SetName(name string) database.Change
SetState(state IDPState) database.Change
SetAllowCreation(allow bool) database.Change
SetAllowAutoCreation(allow bool) database.Change
SetAllowAutoUpdate(allow bool) database.Change
SetAllowLinking(allow bool) database.Change
SetStylingType(stylingType int16) database.Change
SetPayload(payload string) database.Change
}
type IDProviderRepository interface {
idProviderColumns
idProviderConditions
idProviderChanges
Get(ctx context.Context, id string) (*IdentityProvider, error)
List(ctx context.Context, conditions ...database.Condition) ([]*IdentityProvider, error)
Create(ctx context.Context, idp *IdentityProvider) error
Update(ctx context.Context, id string, changes ...database.Change) (int64, error)
Delete(ctx context.Context, id string) (int64, error)
}

View File

@@ -0,0 +1,78 @@
// Code generated by "enumer -type IDPState -transform lower -trimprefix IDPState"; DO NOT EDIT.
package domain
import (
"fmt"
"strings"
)
const _IDPStateName = "activeinactive"
var _IDPStateIndex = [...]uint8{0, 6, 14}
const _IDPStateLowerName = "activeinactive"
func (i IDPState) String() string {
if i >= IDPState(len(_IDPStateIndex)-1) {
return fmt.Sprintf("IDPState(%d)", i)
}
return _IDPStateName[_IDPStateIndex[i]:_IDPStateIndex[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 _IDPStateNoOp() {
var x [1]struct{}
_ = x[IDPStateActive-(0)]
_ = x[IDPStateInactive-(1)]
}
var _IDPStateValues = []IDPState{IDPStateActive, IDPStateInactive}
var _IDPStateNameToValueMap = map[string]IDPState{
_IDPStateName[0:6]: IDPStateActive,
_IDPStateLowerName[0:6]: IDPStateActive,
_IDPStateName[6:14]: IDPStateInactive,
_IDPStateLowerName[6:14]: IDPStateInactive,
}
var _IDPStateNames = []string{
_IDPStateName[0:6],
_IDPStateName[6:14],
}
// IDPStateString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func IDPStateString(s string) (IDPState, error) {
if val, ok := _IDPStateNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _IDPStateNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to IDPState values", s)
}
// IDPStateValues returns all values of the enum
func IDPStateValues() []IDPState {
return _IDPStateValues
}
// IDPStateStrings returns a slice of all String values of the enum
func IDPStateStrings() []string {
strs := make([]string, len(_IDPStateNames))
copy(strs, _IDPStateNames)
return strs
}
// IsAIDPState returns "true" if the value is listed in the enum definition. "false" otherwise
func (i IDPState) IsAIDPState() bool {
for _, v := range _IDPStateValues {
if i == v {
return true
}
}
return false
}

View File

@@ -0,0 +1,102 @@
// Code generated by "enumer -type IDPType -transform lower -trimprefix IDPType"; DO NOT EDIT.
package domain
import (
"fmt"
"strings"
)
const _IDPTypeName = "oidcoauthsamlldapgithubgooglemicrosoftapple"
var _IDPTypeIndex = [...]uint8{0, 4, 9, 13, 17, 23, 29, 38, 43}
const _IDPTypeLowerName = "oidcoauthsamlldapgithubgooglemicrosoftapple"
func (i IDPType) String() string {
if i >= IDPType(len(_IDPTypeIndex)-1) {
return fmt.Sprintf("IDPType(%d)", i)
}
return _IDPTypeName[_IDPTypeIndex[i]:_IDPTypeIndex[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 _IDPTypeNoOp() {
var x [1]struct{}
_ = x[IDPTypeOIDC-(0)]
_ = x[IDPTypeOAUTH-(1)]
_ = x[IDPTypeSAML-(2)]
_ = x[IDPTypeLDAP-(3)]
_ = x[IDPTypeGithub-(4)]
_ = x[IDPTypeGoogle-(5)]
_ = x[IDPTypeMicrosoft-(6)]
_ = x[IDPTypeApple-(7)]
}
var _IDPTypeValues = []IDPType{IDPTypeOIDC, IDPTypeOAUTH, IDPTypeSAML, IDPTypeLDAP, IDPTypeGithub, IDPTypeGoogle, IDPTypeMicrosoft, IDPTypeApple}
var _IDPTypeNameToValueMap = map[string]IDPType{
_IDPTypeName[0:4]: IDPTypeOIDC,
_IDPTypeLowerName[0:4]: IDPTypeOIDC,
_IDPTypeName[4:9]: IDPTypeOAUTH,
_IDPTypeLowerName[4:9]: IDPTypeOAUTH,
_IDPTypeName[9:13]: IDPTypeSAML,
_IDPTypeLowerName[9:13]: IDPTypeSAML,
_IDPTypeName[13:17]: IDPTypeLDAP,
_IDPTypeLowerName[13:17]: IDPTypeLDAP,
_IDPTypeName[17:23]: IDPTypeGithub,
_IDPTypeLowerName[17:23]: IDPTypeGithub,
_IDPTypeName[23:29]: IDPTypeGoogle,
_IDPTypeLowerName[23:29]: IDPTypeGoogle,
_IDPTypeName[29:38]: IDPTypeMicrosoft,
_IDPTypeLowerName[29:38]: IDPTypeMicrosoft,
_IDPTypeName[38:43]: IDPTypeApple,
_IDPTypeLowerName[38:43]: IDPTypeApple,
}
var _IDPTypeNames = []string{
_IDPTypeName[0:4],
_IDPTypeName[4:9],
_IDPTypeName[9:13],
_IDPTypeName[13:17],
_IDPTypeName[17:23],
_IDPTypeName[23:29],
_IDPTypeName[29:38],
_IDPTypeName[38:43],
}
// IDPTypeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func IDPTypeString(s string) (IDPType, error) {
if val, ok := _IDPTypeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _IDPTypeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to IDPType values", s)
}
// IDPTypeValues returns all values of the enum
func IDPTypeValues() []IDPType {
return _IDPTypeValues
}
// IDPTypeStrings returns a slice of all String values of the enum
func IDPTypeStrings() []string {
strs := make([]string, len(_IDPTypeNames))
copy(strs, _IDPTypeNames)
return strs
}
// IsAIDPType returns "true" if the value is listed in the enum definition. "false" otherwise
func (i IDPType) IsAIDPType() bool {
for _, v := range _IDPTypeValues {
if i == v {
return true
}
}
return false
}

View File

@@ -14,7 +14,7 @@ var _OrgStateIndex = [...]uint8{0, 6, 14}
const _OrgStateLowerName = "activeinactive"
func (i OrgState) String() string {
if i < 0 || i >= OrgState(len(_OrgStateIndex)-1) {
if i >= OrgState(len(_OrgStateIndex)-1) {
return fmt.Sprintf("OrgState(%d)", i)
}
return _OrgStateName[_OrgStateIndex[i]:_OrgStateIndex[i+1]]

View File

@@ -0,0 +1,267 @@
package repository
import (
"context"
"errors"
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
)
var _ domain.IDProviderRepository = (*idProvider)(nil)
type idProvider struct {
repository
}
func IDProviderRepository(client database.QueryExecutor) domain.IDProviderRepository {
return &idProvider{
repository: repository{
client: client,
},
}
}
const queryIDProviderStmt = `instance_id, org_id, id, state, name, type, allow_creation, allow_auto_creation,` +
` allow_auto_update, allow_linking, styling_type, payload, created_at, updated_at` +
` FROM zitadel.identity_providers`
func (i *idProvider) Get(ctx context.Context, id string) (*domain.IdentityProvider, error) {
builder := database.StatementBuilder{}
builder.WriteString(queryIDProviderStmt)
idCondition := i.IDCondition(id)
writeCondition(&builder, idCondition)
return scanIDProvider(ctx, i.client, &builder)
}
func (i *idProvider) List(ctx context.Context, conditions ...database.Condition) ([]*domain.IdentityProvider, error) {
builder := database.StatementBuilder{}
builder.WriteString(queryIDProviderStmt)
if conditions != nil {
writeCondition(&builder, database.And(conditions...))
}
orderBy := database.OrderBy(i.CreatedAtColumn())
orderBy.Write(&builder)
return scanIDProviders(ctx, i.client, &builder)
}
const createIDProviderStmt = `INSERT INTO zitadel.identity_providers` +
` (instance_id, org_id, id, state, name, type, allow_creation, allow_auto_creation,` +
` allow_auto_update, allow_linking, styling_type, payload)` +
` VALUES ($1, $2, $3, $4, $5, $6, $,7, $8, $9, $10, $11, $12)` +
` RETURNING created_at, updated_at`
func (i *idProvider) Create(ctx context.Context, idp *domain.IdentityProvider) error {
builder := database.StatementBuilder{}
builder.AppendArgs(idp.InstanceID, idp.OrgID, idp.ID, idp.State, idp.Name, idp.Type, idp.AllowCreation,
idp.AllowAutoCreation, idp.AllowLinking, idp.StylingType, idp.Payload)
builder.WriteString(createIDProviderStmt)
err := i.client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&idp.CreatedAt, &idp.UpdatedAt)
if err != nil {
return checkCreateOrgErr(err)
}
return nil
}
func (i *idProvider) Update(ctx context.Context, id string, changes ...database.Change) (int64, error) {
if changes == nil {
return 0, errors.New("Update must contain a condition") // (otherwise ALL identity_providers will be updated)
}
builder := database.StatementBuilder{}
builder.WriteString(`UPDATE zitadel.identity_provider SET `)
conditions := []database.Condition{i.IDCondition(id)}
database.Changes(changes).Write(&builder)
writeCondition(&builder, database.And(conditions...))
stmt := builder.String()
rowsAffected, err := i.client.Exec(ctx, stmt, builder.Args()...)
return rowsAffected, err
}
func (i *idProvider) Delete(ctx context.Context, id string) (int64, error) {
builder := database.StatementBuilder{}
builder.WriteString(`DELETE FROM zitadel.identity_providers`)
conditions := []database.Condition{i.IDCondition(id)}
writeCondition(&builder, database.And(conditions...))
return i.client.Exec(ctx, builder.String(), builder.Args()...)
}
// -------------------------------------------------------------
// columns
// -------------------------------------------------------------
func (idProvider) InstanceIDColumn() database.Column {
return database.NewColumn("instance_id")
}
func (idProvider) OrgIDColumn() database.Column {
return database.NewColumn("org_id")
}
func (idProvider) IDColumn() database.Column {
return database.NewColumn("id")
}
func (idProvider) StateColumn() database.Column {
return database.NewColumn("state")
}
func (idProvider) NameColumn() database.Column {
return database.NewColumn("name")
}
func (idProvider) TypeColumn() database.Column {
return database.NewColumn("type")
}
func (idProvider) AllowCreationColumn() database.Column {
return database.NewColumn("allow_creation")
}
func (idProvider) AllowAutoCreationColumn() database.Column {
return database.NewColumn("allow_auto_creation")
}
func (idProvider) AllowAutoUpdateColumn() database.Column {
return database.NewColumn("allow_auto_update")
}
func (idProvider) AllowLinkingColumn() database.Column {
return database.NewColumn("allow_linking")
}
func (idProvider) StylingTypeColumn() database.Column {
return database.NewColumn("styling_type")
}
func (idProvider) PayloadColumn() database.Column {
return database.NewColumn("payload")
}
func (idProvider) CreatedAtColumn() database.Column {
return database.NewColumn("created_at")
}
func (idProvider) UpdatedAtColumn() database.Column {
return database.NewColumn("updated_at")
}
// -------------------------------------------------------------
// conditions
// -------------------------------------------------------------
func (i idProvider) InstanceIDCondition(id string) database.Condition {
return database.NewTextCondition(i.InstanceIDColumn(), database.TextOperationEqual, id)
}
func (i idProvider) OrgIDCondition(id string) database.Condition {
return database.NewTextCondition(i.OrgIDColumn(), database.TextOperationEqual, id)
}
func (i idProvider) IDCondition(id string) database.Condition {
return database.NewTextCondition(i.IDColumn(), database.TextOperationEqual, id)
}
func (i idProvider) StateCondition(state domain.IDPState) database.Condition {
return database.NewTextCondition(i.OrgIDColumn(), database.TextOperationEqual, state.String())
}
func (i idProvider) NameCondition(name string) database.Condition {
return database.NewTextCondition(i.NameColumn(), database.TextOperationEqual, name)
}
func (i idProvider) TypeCondition(typee domain.IDPType) database.Condition {
return database.NewTextCondition(i.TypeColumn(), database.TextOperationEqual, typee.String())
}
func (i idProvider) AllowCreationCondition(allow bool) database.Condition {
return database.NewBooleanCondition(i.AllowCreationColumn(), allow)
}
func (i idProvider) AllowAutoCreationCondition(allow bool) database.Condition {
return database.NewBooleanCondition(i.AllowAutoCreationColumn(), allow)
}
func (i idProvider) AllowAutoUpdateCondition(allow bool) database.Condition {
return database.NewBooleanCondition(i.AllowAutoUpdateColumn(), allow)
}
func (i idProvider) AllowLinkingCondition(allow bool) database.Condition {
return database.NewBooleanCondition(i.AllowLinkingColumn(), allow)
}
func (i idProvider) StylingTypeCondition(style int16) database.Condition {
return database.NewNumberCondition(i.StylingTypeColumn(), database.NumberOperationEqual, style)
}
func (i idProvider) PayloadCondition(payload string) database.Condition {
return database.NewTextCondition(i.PayloadColumn(), database.TextOperationEqual, payload)
}
// -------------------------------------------------------------
// changes
// -------------------------------------------------------------
func (i idProvider) SetName(name string) database.Change {
return database.NewChange(i.NameColumn(), name)
}
func (i idProvider) SetState(state domain.IDPState) database.Change {
return database.NewChange(i.StateColumn(), state)
}
func (i idProvider) SetAllowCreation(allow bool) database.Change {
return database.NewChange(i.AllowCreationColumn(), allow)
}
func (i idProvider) SetAllowAutoCreation(allow bool) database.Change {
return database.NewChange(i.AllowAutoUpdateColumn(), allow)
}
func (i idProvider) SetAllowAutoUpdate(allow bool) database.Change {
return database.NewChange(i.AllowAutoUpdateColumn(), allow)
}
func (i idProvider) SetAllowLinking(allow bool) database.Change {
return database.NewChange(i.AllowLinkingColumn(), allow)
}
func (i idProvider) SetStylingType(stylingType int16) database.Change {
return database.NewChange(i.StylingTypeColumn(), stylingType)
}
func (i idProvider) SetPayload(payload string) database.Change {
return database.NewChange(i.StylingTypeColumn(), payload)
}
func scanIDProvider(ctx context.Context, querier database.Querier, builder *database.StatementBuilder) (*domain.IdentityProvider, error) {
idp := &domain.IdentityProvider{}
err := scan(ctx, querier, builder, idp)
if err != nil {
return nil, err
}
return idp, err
}
func scanIDProviders(ctx context.Context, querier database.Querier, builder *database.StatementBuilder) ([]*domain.IdentityProvider, error) {
idps := []*domain.IdentityProvider{}
err := scanMultiple(ctx, querier, builder, &idps)
if err != nil {
return nil, err
}
return idps, nil
}