mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 20:27:23 +00:00
feat(queries): login policy idp links (#2767)
* fix(idp): set type in projection * correct table * user idp links * refactor: user idp link query * add not null constraint * refactor: idp user links * rename file * fix(idp): correct resource owner * refactor: rename test * fix(query): implement idp login policy links * unify naming of idp links * test prepare * fix(api): convert idp type * rename migration
This commit is contained in:
parent
7bf7379a05
commit
c9face4ea4
@ -3,14 +3,14 @@ package admin
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
idp_grpc "github.com/caos/zitadel/internal/api/grpc/idp"
|
||||
object_pb "github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func (s *Server) GetIDPByID(ctx context.Context, req *admin_pb.GetIDPByIDRequest) (*admin_pb.GetIDPByIDResponse, error) {
|
||||
idp, err := s.query.IDPByIDAndResourceOwner(ctx, req.Id, authz.GetCtxData(ctx).OrgID)
|
||||
idp, err := s.query.IDPByIDAndResourceOwner(ctx, req.Id, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -22,7 +22,7 @@ func (s *Server) ListIDPs(ctx context.Context, req *admin_pb.ListIDPsRequest) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := s.query.SearchIDPs(ctx, authz.GetCtxData(ctx).OrgID, queries)
|
||||
resp, err := s.query.SearchIDPs(ctx, domain.IAMID, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -35,18 +35,18 @@ func (s *Server) UpdateLoginPolicy(ctx context.Context, p *admin_pb.UpdateLoginP
|
||||
}
|
||||
|
||||
func (s *Server) ListLoginPolicyIDPs(ctx context.Context, req *admin_pb.ListLoginPolicyIDPsRequest) (*admin_pb.ListLoginPolicyIDPsResponse, error) {
|
||||
res, err := s.iam.SearchDefaultIDPProviders(ctx, ListLoginPolicyIDPsRequestToModel(req))
|
||||
res, err := s.query.IDPLoginPolicyLinks(ctx, domain.IAMID, ListLoginPolicyIDPsRequestToQuery(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.ListLoginPolicyIDPsResponse{
|
||||
Result: idp.ExternalIDPViewsToLoginPolicyLinkPb(res.Result),
|
||||
Details: object.ToListDetails(res.TotalResult, res.Sequence, res.Timestamp),
|
||||
Result: idp.IDPLoginPolicyLinksToPb(res.Links),
|
||||
Details: object.ToListDetails(res.Count, res.Sequence, res.Timestamp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddIDPToLoginPolicy(ctx context.Context, req *admin_pb.AddIDPToLoginPolicyRequest) (*admin_pb.AddIDPToLoginPolicyResponse, error) {
|
||||
idp, err := s.command.AddIDPProviderToDefaultLoginPolicy(ctx, &domain.IDPProvider{IDPConfigID: req.IdpId}) //TODO: old way was to also add type but this doesnt make sense in my point of view
|
||||
idp, err := s.command.AddIDPProviderToDefaultLoginPolicy(ctx, &domain.IDPProvider{IDPConfigID: req.IdpId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/caos/zitadel/internal/api/grpc/policy"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
@ -19,13 +19,13 @@ func updateLoginPolicyToDomain(p *admin_pb.UpdateLoginPolicyRequest) *domain.Log
|
||||
}
|
||||
}
|
||||
|
||||
func ListLoginPolicyIDPsRequestToModel(req *admin_pb.ListLoginPolicyIDPsRequest) *model.IDPProviderSearchRequest {
|
||||
func ListLoginPolicyIDPsRequestToQuery(req *admin_pb.ListLoginPolicyIDPsRequest) *query.IDPLoginPolicyLinksSearchQuery {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
return &model.IDPProviderSearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
// SortingColumn: model.IDPProviderSearchKey, //TODO: not in proto
|
||||
// Queries: []*model.IDPProviderSearchQuery, //TODO: not in proto
|
||||
return &query.IDPLoginPolicyLinksSearchQuery{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,16 @@ func (s *Server) ListMyLinkedIDPs(ctx context.Context, req *auth_pb.ListMyLinked
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idps, err := s.query.UserIDPLinks(ctx, q)
|
||||
links, err := s.query.IDPUserLinks(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &auth_pb.ListMyLinkedIDPsResponse{
|
||||
Result: idp_grpc.IDPUserLinksToPb(idps.Links),
|
||||
Result: idp_grpc.IDPUserLinksToPb(links.Links),
|
||||
Details: object.ToListDetails(
|
||||
idps.Count,
|
||||
idps.Sequence,
|
||||
idps.Timestamp,
|
||||
links.Count,
|
||||
links.Sequence,
|
||||
links.Timestamp,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
@ -10,13 +10,13 @@ import (
|
||||
auth_pb "github.com/caos/zitadel/pkg/grpc/auth"
|
||||
)
|
||||
|
||||
func ListMyLinkedIDPsRequestToQuery(ctx context.Context, req *auth_pb.ListMyLinkedIDPsRequest) (*query.UserIDPLinksSearchQuery, error) {
|
||||
func ListMyLinkedIDPsRequestToQuery(ctx context.Context, req *auth_pb.ListMyLinkedIDPsRequest) (*query.IDPUserLinksSearchQuery, error) {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
q, err := query.NewUserIDPLinksUserIDSearchQuery(authz.GetCtxData(ctx).UserID)
|
||||
q, err := query.NewIDPUserLinksUserIDSearchQuery(authz.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &query.UserIDPLinksSearchQuery{
|
||||
return &query.IDPUserLinksSearchQuery{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
|
@ -48,23 +48,23 @@ func IDPViewToPb(idp *query.IDP) *idp_pb.IDP {
|
||||
return mapped
|
||||
}
|
||||
|
||||
func ExternalIDPViewsToLoginPolicyLinkPb(links []*iam_model.IDPProviderView) []*idp_pb.IDPLoginPolicyLink {
|
||||
func IDPLoginPolicyLinksToPb(links []*query.IDPLoginPolicyLink) []*idp_pb.IDPLoginPolicyLink {
|
||||
l := make([]*idp_pb.IDPLoginPolicyLink, len(links))
|
||||
for i, link := range links {
|
||||
l[i] = ExternalIDPViewToLoginPolicyLinkPb(link)
|
||||
l[i] = IDPLoginPolicyLinkToPb(link)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func ExternalIDPViewToLoginPolicyLinkPb(link *iam_model.IDPProviderView) *idp_pb.IDPLoginPolicyLink {
|
||||
func IDPLoginPolicyLinkToPb(link *query.IDPLoginPolicyLink) *idp_pb.IDPLoginPolicyLink {
|
||||
return &idp_pb.IDPLoginPolicyLink{
|
||||
IdpId: link.IDPConfigID,
|
||||
IdpName: link.Name,
|
||||
IdpType: IDPTypeViewToPb(link.IDPConfigType),
|
||||
IdpId: link.IDPID,
|
||||
IdpName: link.IDPName,
|
||||
IdpType: IDPTypeToPb(link.IDPType),
|
||||
}
|
||||
}
|
||||
|
||||
func IDPUserLinksToPb(res []*query.UserIDPLink) []*idp_pb.IDPUserLink {
|
||||
func IDPUserLinksToPb(res []*query.IDPUserLink) []*idp_pb.IDPUserLink {
|
||||
links := make([]*idp_pb.IDPUserLink, len(res))
|
||||
for i, link := range res {
|
||||
links[i] = IDPUserLinkToPb(link)
|
||||
@ -72,7 +72,7 @@ func IDPUserLinksToPb(res []*query.UserIDPLink) []*idp_pb.IDPUserLink {
|
||||
return links
|
||||
}
|
||||
|
||||
func IDPUserLinkToPb(link *query.UserIDPLink) *idp_pb.IDPUserLink {
|
||||
func IDPUserLinkToPb(link *query.IDPUserLink) *idp_pb.IDPUserLink {
|
||||
return &idp_pb.IDPUserLink{
|
||||
UserId: link.UserID,
|
||||
IdpId: link.IDPID,
|
||||
@ -83,19 +83,6 @@ func IDPUserLinkToPb(link *query.UserIDPLink) *idp_pb.IDPUserLink {
|
||||
}
|
||||
}
|
||||
|
||||
func IDPTypeViewToPb(idpType iam_model.IdpConfigType) idp_pb.IDPType {
|
||||
switch idpType {
|
||||
case iam_model.IDPConfigTypeOIDC:
|
||||
return idp_pb.IDPType_IDP_TYPE_OIDC
|
||||
case iam_model.IDPConfigTypeSAML:
|
||||
return idp_pb.IDPType_IDP_TYPE_UNSPECIFIED
|
||||
case iam_model.IDPConfigTypeJWT:
|
||||
return idp_pb.IDPType_IDP_TYPE_JWT
|
||||
default:
|
||||
return idp_pb.IDPType_IDP_TYPE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func IDPTypeToPb(idpType domain.IDPConfigType) idp_pb.IDPType {
|
||||
switch idpType {
|
||||
case domain.IDPConfigTypeOIDC:
|
||||
|
@ -31,6 +31,7 @@ func (s *Server) ListOrgIDPs(ctx context.Context, req *mgmt_pb.ListOrgIDPsReques
|
||||
Details: object_pb.ToListDetails(resp.Count, resp.Sequence, resp.Timestamp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddOrgOIDCIDP(ctx context.Context, req *mgmt_pb.AddOrgOIDCIDPRequest) (*mgmt_pb.AddOrgOIDCIDPResponse, error) {
|
||||
config, err := s.command.AddIDPConfig(ctx, addOIDCIDPRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
@ -68,6 +69,7 @@ func (s *Server) DeactivateOrgIDP(ctx context.Context, req *mgmt_pb.DeactivateOr
|
||||
}
|
||||
return &mgmt_pb.DeactivateOrgIDPResponse{Details: object_pb.DomainToChangeDetailsPb(objectDetails)}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ReactivateOrgIDP(ctx context.Context, req *mgmt_pb.ReactivateOrgIDPRequest) (*mgmt_pb.ReactivateOrgIDPResponse, error) {
|
||||
objectDetails, err := s.command.ReactivateIDPConfig(ctx, req.IdpId, authz.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
@ -75,6 +77,7 @@ func (s *Server) ReactivateOrgIDP(ctx context.Context, req *mgmt_pb.ReactivateOr
|
||||
}
|
||||
return &mgmt_pb.ReactivateOrgIDPResponse{Details: object_pb.DomainToChangeDetailsPb(objectDetails)}, nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveOrgIDP(ctx context.Context, req *mgmt_pb.RemoveOrgIDPRequest) (*mgmt_pb.RemoveOrgIDPResponse, error) {
|
||||
idpProviders, err := s.org.GetIDPProvidersByIDPConfigID(ctx, authz.GetCtxData(ctx).OrgID, req.IdpId)
|
||||
if err != nil {
|
||||
@ -90,6 +93,7 @@ func (s *Server) RemoveOrgIDP(ctx context.Context, req *mgmt_pb.RemoveOrgIDPRequ
|
||||
}
|
||||
return &mgmt_pb.RemoveOrgIDPResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateOrgIDP(ctx context.Context, req *mgmt_pb.UpdateOrgIDPRequest) (*mgmt_pb.UpdateOrgIDPResponse, error) {
|
||||
config, err := s.command.ChangeIDPConfig(ctx, updateIDPToDomain(req), authz.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
|
@ -68,13 +68,13 @@ func (s *Server) ResetLoginPolicyToDefault(ctx context.Context, req *mgmt_pb.Res
|
||||
}
|
||||
|
||||
func (s *Server) ListLoginPolicyIDPs(ctx context.Context, req *mgmt_pb.ListLoginPolicyIDPsRequest) (*mgmt_pb.ListLoginPolicyIDPsResponse, error) {
|
||||
res, err := s.org.SearchIDPProviders(ctx, ListLoginPolicyIDPsRequestToModel(req))
|
||||
res, err := s.query.IDPLoginPolicyLinks(ctx, authz.GetCtxData(ctx).OrgID, ListLoginPolicyIDPsRequestToQuery(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.ListLoginPolicyIDPsResponse{
|
||||
Result: idp.ExternalIDPViewsToLoginPolicyLinkPb(res.Result),
|
||||
Details: object.ToListDetails(res.TotalResult, res.Sequence, res.Timestamp),
|
||||
Result: idp.IDPLoginPolicyLinksToPb(res.Links),
|
||||
Details: object.ToListDetails(res.Count, res.Sequence, res.Timestamp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/caos/zitadel/internal/api/grpc/policy"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
@ -30,13 +30,13 @@ func updateLoginPolicyToDomain(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *domai
|
||||
}
|
||||
}
|
||||
|
||||
func ListLoginPolicyIDPsRequestToModel(req *mgmt_pb.ListLoginPolicyIDPsRequest) *model.IDPProviderSearchRequest {
|
||||
func ListLoginPolicyIDPsRequestToQuery(req *mgmt_pb.ListLoginPolicyIDPsRequest) *query.IDPLoginPolicyLinksSearchQuery {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
return &model.IDPProviderSearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
// SortingColumn: model.IDPProviderSearchKey, //TODO: not in proto
|
||||
// Queries: []*model.IDPProviderSearchQuery, //TODO: not in proto
|
||||
return &query.IDPLoginPolicyLinksSearchQuery{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -610,7 +610,7 @@ func (s *Server) ListHumanLinkedIDPs(ctx context.Context, req *mgmt_pb.ListHuman
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := s.query.UserIDPLinks(ctx, queries)
|
||||
res, err := s.query.IDPUserLinks(ctx, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -235,17 +235,17 @@ func RemoveHumanLinkedIDPRequestToDomain(ctx context.Context, req *mgmt_pb.Remov
|
||||
}
|
||||
}
|
||||
|
||||
func ListHumanLinkedIDPsRequestToQuery(ctx context.Context, req *mgmt_pb.ListHumanLinkedIDPsRequest) (*query.UserIDPLinksSearchQuery, error) {
|
||||
func ListHumanLinkedIDPsRequestToQuery(ctx context.Context, req *mgmt_pb.ListHumanLinkedIDPsRequest) (*query.IDPUserLinksSearchQuery, error) {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
userQuery, err := query.NewUserIDPLinksUserIDSearchQuery(req.UserId)
|
||||
userQuery, err := query.NewIDPUserLinksUserIDSearchQuery(req.UserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceOwnerQuery, err := query.NewUserIDPLinksResourceOwnerSearchQuery(authz.GetCtxData(ctx).OrgID)
|
||||
resourceOwnerQuery, err := query.NewIDPUserLinksResourceOwnerSearchQuery(authz.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &query.UserIDPLinksSearchQuery{
|
||||
return &query.IDPUserLinksSearchQuery{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
|
135
internal/query/idp_login_policy_link.go
Normal file
135
internal/query/idp_login_policy_link.go
Normal file
@ -0,0 +1,135 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/query/projection"
|
||||
)
|
||||
|
||||
type IDPLoginPolicyLink struct {
|
||||
IDPID string
|
||||
IDPName string
|
||||
IDPType domain.IDPConfigType
|
||||
}
|
||||
|
||||
type IDPLoginPolicyLinks struct {
|
||||
SearchResponse
|
||||
Links []*IDPLoginPolicyLink
|
||||
}
|
||||
|
||||
type IDPLoginPolicyLinksSearchQuery struct {
|
||||
SearchRequest
|
||||
Queries []SearchQuery
|
||||
}
|
||||
|
||||
func (q *IDPLoginPolicyLinksSearchQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||
query = q.SearchRequest.toQuery(query)
|
||||
for _, q := range q.Queries {
|
||||
query = q.toQuery(query)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
var (
|
||||
idpLoginPolicyLinkTable = table{
|
||||
name: projection.IDPLoginPolicyLinkTable,
|
||||
}
|
||||
IDPLoginPolicyLinkIDPIDCol = Column{
|
||||
name: projection.IDPLoginPolicyLinkIDPIDCol,
|
||||
table: idpLoginPolicyLinkTable,
|
||||
}
|
||||
IDPLoginPolicyLinkCreationDateCol = Column{
|
||||
name: projection.IDPLoginPolicyLinkCreationDateCol,
|
||||
table: idpLoginPolicyLinkTable,
|
||||
}
|
||||
IDPLoginPolicyLinkChangeDateCol = Column{
|
||||
name: projection.IDPLoginPolicyLinkChangeDateCol,
|
||||
table: idpLoginPolicyLinkTable,
|
||||
}
|
||||
IDPLoginPolicyLinkSequenceCol = Column{
|
||||
name: projection.IDPLoginPolicyLinkSequenceCol,
|
||||
table: idpLoginPolicyLinkTable,
|
||||
}
|
||||
IDPLoginPolicyLinkResourceOwnerCol = Column{
|
||||
name: projection.IDPLoginPolicyLinkResourceOwnerCol,
|
||||
table: idpLoginPolicyLinkTable,
|
||||
}
|
||||
IDPLoginPolicyLinkProviderTypeCol = Column{
|
||||
name: projection.IDPLoginPolicyLinkProviderTypeCol,
|
||||
table: idpLoginPolicyLinkTable,
|
||||
}
|
||||
)
|
||||
|
||||
func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string, queries *IDPLoginPolicyLinksSearchQuery) (idps *IDPLoginPolicyLinks, err error) {
|
||||
query, scan := prepareIDPLoginPolicyLinksQuery()
|
||||
stmt, args, err := queries.toQuery(query).Where(
|
||||
sq.Eq{IDPLoginPolicyLinkResourceOwnerCol.identifier(): resourceOwner},
|
||||
).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInvalidArgument(err, "QUERY-FDbKW", "Errors.Query.InvalidRequest")
|
||||
}
|
||||
|
||||
rows, err := q.client.QueryContext(ctx, stmt, args...)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-ZkKUc", "Errors.Internal")
|
||||
}
|
||||
idps, err = scan(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idps.LatestSequence, err = q.latestSequence(ctx, idpLoginPolicyLinkTable)
|
||||
return idps, err
|
||||
}
|
||||
|
||||
func prepareIDPLoginPolicyLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
|
||||
return sq.Select(
|
||||
IDPLoginPolicyLinkIDPIDCol.identifier(),
|
||||
IDPNameCol.identifier(),
|
||||
IDPTypeCol.identifier(),
|
||||
countColumn.identifier()).
|
||||
From(idpLoginPolicyLinkTable.identifier()).
|
||||
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol)).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)
|
||||
)
|
||||
err := rows.Scan(
|
||||
&link.IDPID,
|
||||
&idpName,
|
||||
&idpType,
|
||||
&count,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
link.IDPName = idpName.String
|
||||
//IDPType 0 is oidc so we have to set unspecified manually
|
||||
if idpType.Valid {
|
||||
link.IDPType = domain.IDPConfigType(idpType.Int16)
|
||||
} else {
|
||||
link.IDPType = domain.IDPConfigTypeUnspecified
|
||||
}
|
||||
links = append(links, link)
|
||||
}
|
||||
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-vOLFG", "Errors.Query.CloseRows")
|
||||
}
|
||||
|
||||
return &IDPLoginPolicyLinks{
|
||||
Links: links,
|
||||
SearchResponse: SearchResponse{
|
||||
Count: count,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
121
internal/query/idp_login_policy_link_test.go
Normal file
121
internal/query/idp_login_policy_link_test.go
Normal file
@ -0,0 +1,121 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
var (
|
||||
loginPolicyIDPLinksQuery = regexp.QuoteMeta(`SELECT zitadel.projections.idp_login_policy_links.idp_id,` +
|
||||
` zitadel.projections.idps.name,` +
|
||||
` zitadel.projections.idps.type,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM zitadel.projections.idp_login_policy_links` +
|
||||
` LEFT JOIN zitadel.projections.idps ON zitadel.projections.idp_login_policy_links.idp_id = zitadel.projections.idps.id`)
|
||||
loginPolicyIDPLinksCols = []string{
|
||||
"idp_id",
|
||||
"name",
|
||||
"type",
|
||||
"count",
|
||||
}
|
||||
)
|
||||
|
||||
func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
|
||||
type want struct {
|
||||
sqlExpectations sqlExpectation
|
||||
err checkErr
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare interface{}
|
||||
want want
|
||||
object interface{}
|
||||
}{
|
||||
{
|
||||
name: "prepareIDPsQuery found",
|
||||
prepare: prepareIDPLoginPolicyLinksQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
loginPolicyIDPLinksQuery,
|
||||
loginPolicyIDPLinksCols,
|
||||
[][]driver.Value{
|
||||
{
|
||||
"idp-id",
|
||||
"idp-name",
|
||||
domain.IDPConfigTypeJWT,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &IDPLoginPolicyLinks{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 1,
|
||||
},
|
||||
Links: []*IDPLoginPolicyLink{
|
||||
{
|
||||
IDPID: "idp-id",
|
||||
IDPName: "idp-name",
|
||||
IDPType: domain.IDPConfigTypeJWT,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareIDPsQuery no idp",
|
||||
prepare: prepareIDPLoginPolicyLinksQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
loginPolicyIDPLinksQuery,
|
||||
loginPolicyIDPLinksCols,
|
||||
[][]driver.Value{
|
||||
{
|
||||
"idp-id",
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &IDPLoginPolicyLinks{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 1,
|
||||
},
|
||||
Links: []*IDPLoginPolicyLink{
|
||||
{
|
||||
IDPID: "idp-id",
|
||||
IDPName: "",
|
||||
IDPType: domain.IDPConfigTypeUnspecified,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareIDPsQuery sql err",
|
||||
prepare: prepareIDPLoginPolicyLinksQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
loginPolicyIDPLinksQuery,
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
if !errors.Is(err, sql.ErrConnDone) {
|
||||
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
|
||||
}
|
||||
return nil, true
|
||||
},
|
||||
},
|
||||
object: nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
||||
})
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/query/projection"
|
||||
)
|
||||
|
||||
type UserIDPLink struct {
|
||||
type IDPUserLink struct {
|
||||
IDPID string
|
||||
UserID string
|
||||
IDPName string
|
||||
@ -19,17 +19,17 @@ type UserIDPLink struct {
|
||||
IDPType domain.IDPConfigType
|
||||
}
|
||||
|
||||
type UserIDPLinks struct {
|
||||
type IDPUserLinks struct {
|
||||
SearchResponse
|
||||
Links []*UserIDPLink
|
||||
Links []*IDPUserLink
|
||||
}
|
||||
|
||||
type UserIDPLinksSearchQuery struct {
|
||||
type IDPUserLinksSearchQuery struct {
|
||||
SearchRequest
|
||||
Queries []SearchQuery
|
||||
}
|
||||
|
||||
func (q *UserIDPLinksSearchQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||
func (q *IDPUserLinksSearchQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||
query = q.SearchRequest.toQuery(query)
|
||||
for _, q := range q.Queries {
|
||||
query = q.toQuery(query)
|
||||
@ -75,8 +75,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (q *Queries) UserIDPLinks(ctx context.Context, queries *UserIDPLinksSearchQuery) (idps *UserIDPLinks, err error) {
|
||||
query, scan := prepareUserIDPLinksQuery()
|
||||
func (q *Queries) IDPUserLinks(ctx context.Context, queries *IDPUserLinksSearchQuery) (idps *IDPUserLinks, err error) {
|
||||
query, scan := prepareIDPUserLinksQuery()
|
||||
stmt, args, err := queries.toQuery(query).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInvalidArgument(err, "QUERY-4zzFK", "Errors.Query.InvalidRequest")
|
||||
@ -94,15 +94,15 @@ func (q *Queries) UserIDPLinks(ctx context.Context, queries *UserIDPLinksSearchQ
|
||||
return idps, err
|
||||
}
|
||||
|
||||
func NewUserIDPLinksUserIDSearchQuery(value string) (SearchQuery, error) {
|
||||
func NewIDPUserLinksUserIDSearchQuery(value string) (SearchQuery, error) {
|
||||
return NewTextQuery(IDPUserLinkUserIDCol, value, TextEquals)
|
||||
}
|
||||
|
||||
func NewUserIDPLinksResourceOwnerSearchQuery(value string) (SearchQuery, error) {
|
||||
func NewIDPUserLinksResourceOwnerSearchQuery(value string) (SearchQuery, error) {
|
||||
return NewTextQuery(IDPUserLinkResourceOwnerCol, value, TextEquals)
|
||||
}
|
||||
|
||||
func prepareUserIDPLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserIDPLinks, error)) {
|
||||
func prepareIDPUserLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
|
||||
return sq.Select(
|
||||
IDPUserLinkIDPIDCol.identifier(),
|
||||
IDPUserLinkUserIDCol.identifier(),
|
||||
@ -113,14 +113,14 @@ func prepareUserIDPLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserIDPLink
|
||||
countColumn.identifier()).
|
||||
From(idpUserLinkTable.identifier()).
|
||||
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol)).PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*UserIDPLinks, error) {
|
||||
idps := make([]*UserIDPLink, 0)
|
||||
func(rows *sql.Rows) (*IDPUserLinks, error) {
|
||||
idps := make([]*IDPUserLink, 0)
|
||||
var count uint64
|
||||
for rows.Next() {
|
||||
var (
|
||||
idpName = sql.NullString{}
|
||||
idpType = sql.NullInt16{}
|
||||
idp = new(UserIDPLink)
|
||||
idp = new(IDPUserLink)
|
||||
)
|
||||
err := rows.Scan(
|
||||
&idp.IDPID,
|
||||
@ -148,7 +148,7 @@ func prepareUserIDPLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserIDPLink
|
||||
return nil, errors.ThrowInternal(err, "QUERY-nwx6U", "Errors.Query.CloseRows")
|
||||
}
|
||||
|
||||
return &UserIDPLinks{
|
||||
return &IDPUserLinks{
|
||||
Links: idps,
|
||||
SearchResponse: SearchResponse{
|
||||
Count: count,
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
userIDPLinksQuery = regexp.QuoteMeta(`SELECT zitadel.projections.idp_user_links.idp_id,` +
|
||||
idpUserLinksQuery = regexp.QuoteMeta(`SELECT zitadel.projections.idp_user_links.idp_id,` +
|
||||
` zitadel.projections.idp_user_links.user_id,` +
|
||||
` zitadel.projections.idps.name,` +
|
||||
` zitadel.projections.idp_user_links.external_user_id,` +
|
||||
@ -21,7 +21,7 @@ var (
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM zitadel.projections.idp_user_links` +
|
||||
` LEFT JOIN zitadel.projections.idps ON zitadel.projections.idp_user_links.idp_id = zitadel.projections.idps.id`)
|
||||
userIDPLinksCols = []string{
|
||||
idpUserLinksCols = []string{
|
||||
"idp_id",
|
||||
"user_id",
|
||||
"name",
|
||||
@ -32,7 +32,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func Test_UserIDPLinkPrepares(t *testing.T) {
|
||||
func Test_IDPUserLinkPrepares(t *testing.T) {
|
||||
type want struct {
|
||||
sqlExpectations sqlExpectation
|
||||
err checkErr
|
||||
@ -45,11 +45,11 @@ func Test_UserIDPLinkPrepares(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "prepareIDPsQuery found",
|
||||
prepare: prepareUserIDPLinksQuery,
|
||||
prepare: prepareIDPUserLinksQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
userIDPLinksQuery,
|
||||
userIDPLinksCols,
|
||||
idpUserLinksQuery,
|
||||
idpUserLinksCols,
|
||||
[][]driver.Value{
|
||||
{
|
||||
"idp-id",
|
||||
@ -62,11 +62,11 @@ func Test_UserIDPLinkPrepares(t *testing.T) {
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &UserIDPLinks{
|
||||
object: &IDPUserLinks{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 1,
|
||||
},
|
||||
Links: []*UserIDPLink{
|
||||
Links: []*IDPUserLink{
|
||||
{
|
||||
IDPID: "idp-id",
|
||||
UserID: "user-id",
|
||||
@ -80,11 +80,11 @@ func Test_UserIDPLinkPrepares(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "prepareIDPsQuery no idp",
|
||||
prepare: prepareUserIDPLinksQuery,
|
||||
prepare: prepareIDPUserLinksQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
userIDPLinksQuery,
|
||||
userIDPLinksCols,
|
||||
idpUserLinksQuery,
|
||||
idpUserLinksCols,
|
||||
[][]driver.Value{
|
||||
{
|
||||
"idp-id",
|
||||
@ -97,11 +97,11 @@ func Test_UserIDPLinkPrepares(t *testing.T) {
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &UserIDPLinks{
|
||||
object: &IDPUserLinks{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 1,
|
||||
},
|
||||
Links: []*UserIDPLink{
|
||||
Links: []*IDPUserLink{
|
||||
{
|
||||
IDPID: "idp-id",
|
||||
UserID: "user-id",
|
||||
@ -115,10 +115,10 @@ func Test_UserIDPLinkPrepares(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "prepareIDPsQuery sql err",
|
||||
prepare: prepareUserIDPLinksQuery,
|
||||
prepare: prepareIDPUserLinksQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
userIDPLinksQuery,
|
||||
idpUserLinksQuery,
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
Loading…
x
Reference in New Issue
Block a user