feat(login): use new IDP templates (#5315)

The login uses the new template based IDPs with backwards compatibility for old IDPs
This commit is contained in:
Livio Spring
2023-02-28 21:20:58 +01:00
committed by GitHub
parent abacb6c5aa
commit 48f9815b7c
62 changed files with 1254 additions and 2165 deletions

View File

@@ -15,9 +15,10 @@ import (
)
type IDPLoginPolicyLink struct {
IDPID string
IDPName string
IDPType domain.IDPConfigType
IDPID string
IDPName string
IDPType domain.IDPType
OwnerType domain.IdentityProviderType
}
type IDPLoginPolicyLinks struct {
@@ -113,25 +114,28 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string,
func prepareIDPLoginPolicyLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
return sq.Select(
IDPLoginPolicyLinkIDPIDCol.identifier(),
IDPNameCol.identifier(),
IDPTypeCol.identifier(),
IDPTemplateNameCol.identifier(),
IDPTemplateTypeCol.identifier(),
IDPTemplateOwnerTypeCol.identifier(),
countColumn.identifier()).
From(idpLoginPolicyLinkTable.identifier()).
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
LeftJoin(join(IDPTemplateIDCol, IDPLoginPolicyLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*IDPLoginPolicyLinks, error) {
links := make([]*IDPLoginPolicyLink, 0)
var count uint64
for rows.Next() {
var (
idpName = sql.NullString{}
idpType = sql.NullInt16{}
link = new(IDPLoginPolicyLink)
idpName = sql.NullString{}
idpType = sql.NullInt16{}
idpOwnerType = sql.NullInt16{}
link = new(IDPLoginPolicyLink)
)
err := rows.Scan(
&link.IDPID,
&idpName,
&idpType,
&idpOwnerType,
&count,
)
if err != nil {
@@ -140,10 +144,11 @@ func prepareIDPLoginPolicyLinksQuery(ctx context.Context, db prepareDatabase) (s
link.IDPName = idpName.String
//IDPType 0 is oidc so we have to set unspecified manually
if idpType.Valid {
link.IDPType = domain.IDPConfigType(idpType.Int16)
link.IDPType = domain.IDPType(idpType.Int16)
} else {
link.IDPType = domain.IDPConfigTypeUnspecified
link.IDPType = domain.IDPTypeUnspecified
}
link.OwnerType = domain.IdentityProviderType(idpOwnerType.Int16)
links = append(links, link)
}

View File

@@ -13,16 +13,18 @@ import (
var (
loginPolicyIDPLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_login_policy_links4.idp_id,` +
` projections.idps3.name,` +
` projections.idps3.type,` +
` projections.idp_templates2.name,` +
` projections.idp_templates2.type,` +
` projections.idp_templates2.owner_type,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_login_policy_links4` +
` LEFT JOIN projections.idps3 ON projections.idp_login_policy_links4.idp_id = projections.idps3.id AND projections.idp_login_policy_links4.instance_id = projections.idps3.instance_id` +
` LEFT JOIN projections.idp_templates2 ON projections.idp_login_policy_links4.idp_id = projections.idp_templates2.id AND projections.idp_login_policy_links4.instance_id = projections.idp_templates2.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
loginPolicyIDPLinksCols = []string{
"idp_id",
"name",
"type",
"owner_type",
"count",
}
)
@@ -49,7 +51,8 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
{
"idp-id",
"idp-name",
domain.IDPConfigTypeJWT,
domain.IDPTypeJWT,
domain.IdentityProviderTypeSystem,
},
},
),
@@ -60,9 +63,10 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
},
Links: []*IDPLoginPolicyLink{
{
IDPID: "idp-id",
IDPName: "idp-name",
IDPType: domain.IDPConfigTypeJWT,
IDPID: "idp-id",
IDPName: "idp-name",
IDPType: domain.IDPTypeJWT,
OwnerType: domain.IdentityProviderTypeSystem,
},
},
},
@@ -79,6 +83,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
"idp-id",
nil,
nil,
nil,
},
},
),
@@ -91,7 +96,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
{
IDPID: "idp-id",
IDPName: "",
IDPType: domain.IDPConfigTypeUnspecified,
IDPType: domain.IDPTypeUnspecified,
},
},
},

View File

@@ -386,8 +386,8 @@ var (
}
)
// IDPTemplateByIDAndResourceOwner searches for the requested id in the context of the resource owner and IAM
func (q *Queries) IDPTemplateByIDAndResourceOwner(ctx context.Context, shouldTriggerBulk bool, id, resourceOwner string, withOwnerRemoved bool) (_ *IDPTemplate, err error) {
// IDPTemplateByID searches for the requested id
func (q *Queries) IDPTemplateByID(ctx context.Context, shouldTriggerBulk bool, id string, withOwnerRemoved bool, queries ...SearchQuery) (_ *IDPTemplate, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
@@ -403,20 +403,16 @@ func (q *Queries) IDPTemplateByIDAndResourceOwner(ctx context.Context, shouldTri
if !withOwnerRemoved {
eq[IDPTemplateOwnerRemovedCol.identifier()] = false
}
where := sq.And{
eq,
sq.Or{
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): resourceOwner},
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
},
query, scan := prepareIDPTemplateByIDQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
stmt, scan := prepareIDPTemplateByIDQuery(ctx, q.client)
query, args, err := stmt.Where(where).ToSql()
stmt, args, err := query.Where(eq).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-SFAew", "Errors.Query.SQLStatement")
return nil, errors.ThrowInternal(err, "QUERY-SFefg", "Errors.Query.SQLStatement")
}
row := q.client.QueryRowContext(ctx, query, args...)
row := q.client.QueryRowContext(ctx, stmt, args...)
return scan(row)
}

View File

@@ -21,7 +21,7 @@ type IDPUserLink struct {
ProvidedUserID string
ProvidedUsername string
ResourceOwner string
IDPType domain.IDPConfigType
IDPType domain.IDPType
}
type IDPUserLinks struct {
@@ -127,18 +127,22 @@ func NewIDPUserLinksResourceOwnerSearchQuery(value string) (SearchQuery, error)
return NewTextQuery(IDPUserLinkResourceOwnerCol, value, TextEquals)
}
func NewIDPUserLinksExternalIDSearchQuery(value string) (SearchQuery, error) {
return NewTextQuery(IDPUserLinkExternalUserIDCol, value, TextEquals)
}
func prepareIDPUserLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
return sq.Select(
IDPUserLinkIDPIDCol.identifier(),
IDPUserLinkUserIDCol.identifier(),
IDPNameCol.identifier(),
IDPTemplateNameCol.identifier(),
IDPUserLinkExternalUserIDCol.identifier(),
IDPUserLinkDisplayNameCol.identifier(),
IDPTypeCol.identifier(),
IDPTemplateTypeCol.identifier(),
IDPUserLinkResourceOwnerCol.identifier(),
countColumn.identifier()).
From(idpUserLinkTable.identifier()).
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
LeftJoin(join(IDPTemplateIDCol, IDPUserLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*IDPUserLinks, error) {
idps := make([]*IDPUserLink, 0)
@@ -165,9 +169,9 @@ func prepareIDPUserLinksQuery(ctx context.Context, db prepareDatabase) (sq.Selec
idp.IDPName = idpName.String
//IDPType 0 is oidc so we have to set unspecified manually
if idpType.Valid {
idp.IDPType = domain.IDPConfigType(idpType.Int16)
idp.IDPType = domain.IDPType(idpType.Int16)
} else {
idp.IDPType = domain.IDPConfigTypeUnspecified
idp.IDPType = domain.IDPTypeUnspecified
}
idps = append(idps, idp)
}

View File

@@ -14,14 +14,14 @@ import (
var (
idpUserLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_user_links3.idp_id,` +
` projections.idp_user_links3.user_id,` +
` projections.idps3.name,` +
` projections.idp_templates2.name,` +
` projections.idp_user_links3.external_user_id,` +
` projections.idp_user_links3.display_name,` +
` projections.idps3.type,` +
` projections.idp_templates2.type,` +
` projections.idp_user_links3.resource_owner,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_user_links3` +
` LEFT JOIN projections.idps3 ON projections.idp_user_links3.idp_id = projections.idps3.id AND projections.idp_user_links3.instance_id = projections.idps3.instance_id` +
` LEFT JOIN projections.idp_templates2 ON projections.idp_user_links3.idp_id = projections.idp_templates2.id AND projections.idp_user_links3.instance_id = projections.idp_templates2.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
idpUserLinksCols = []string{
"idp_id",
@@ -60,7 +60,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
"idp-name",
"external-user-id",
"display-name",
domain.IDPConfigTypeJWT,
domain.IDPTypeJWT,
"ro",
},
},
@@ -77,7 +77,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
IDPName: "idp-name",
ProvidedUserID: "external-user-id",
ProvidedUsername: "display-name",
IDPType: domain.IDPConfigTypeJWT,
IDPType: domain.IDPTypeJWT,
ResourceOwner: "ro",
},
},
@@ -114,7 +114,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
IDPName: "",
ProvidedUserID: "external-user-id",
ProvidedUsername: "display-name",
IDPType: domain.IDPConfigTypeUnspecified,
IDPType: domain.IDPTypeUnspecified,
ResourceOwner: "ro",
},
},

View File

@@ -668,7 +668,7 @@ func (p *idpTemplateProjection) reduceOldConfigAdded(event eventstore.Event) (*h
handler.NewCol(IDPTemplateStateCol, domain.IDPStateActive),
handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
handler.NewCol(IDPTemplateOwnerTypeCol, idpOwnerType),
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeOIDC),
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeUnspecified),
handler.NewCol(IDPTemplateIsCreationAllowedCol, true),
handler.NewCol(IDPTemplateIsLinkingAllowedCol, true),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.AutoRegister),
@@ -727,6 +727,7 @@ func (p *idpTemplateProjection) reduceOldOIDCConfigAdded(event eventstore.Event)
[]handler.Column{
handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeOIDC),
},
[]handler.Condition{
handler.NewCond(IDPTemplateIDCol, idpEvent.IDPConfigID),
@@ -820,6 +821,7 @@ func (p *idpTemplateProjection) reduceOldJWTConfigAdded(event eventstore.Event)
[]handler.Column{
handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeJWT),
},
[]handler.Condition{
handler.NewCond(IDPTemplateIDCol, idpEvent.IDPConfigID),