mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-14 00:17:34 +00:00
fix: project grants (#4031)
* fix: filter granted memberships correctly * fix: only show changes of granted project * Apply suggestions from code review Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update internal/query/user_membership.go Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com>
This commit is contained in:
@@ -177,8 +177,12 @@ func (s *Server) ListMyProjectOrgs(ctx context.Context, req *auth_pb.ListMyProje
|
||||
|
||||
if !isIAMAdmin(memberships.Memberships) {
|
||||
ids := make([]string, 0, len(memberships.Memberships))
|
||||
for _, grant := range memberships.Memberships {
|
||||
ids = appendIfNotExists(ids, grant.ResourceOwner)
|
||||
for _, membership := range memberships.Memberships {
|
||||
orgID := membership.ResourceOwner
|
||||
if membership.ProjectGrant != nil && membership.ProjectGrant.GrantedOrgID != "" {
|
||||
orgID = membership.ProjectGrant.GrantedOrgID
|
||||
}
|
||||
ids = appendIfNotExists(ids, orgID)
|
||||
}
|
||||
|
||||
idsQuery, err := query.NewOrgIDsSearchQuery(ids...)
|
||||
|
@@ -55,6 +55,17 @@ func (s *Server) ListProjects(ctx context.Context, req *mgmt_pb.ListProjectsRequ
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ListProjectGrantChanges(ctx context.Context, req *mgmt_pb.ListProjectGrantChangesRequest) (*mgmt_pb.ListProjectGrantChangesResponse, error) {
|
||||
sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query)
|
||||
res, err := s.query.ProjectGrantChanges(ctx, req.ProjectId, req.GrantId, sequence, limit, asc, s.auditLogRetention)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.ListProjectGrantChangesResponse{
|
||||
Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix(ctx)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ListGrantedProjects(ctx context.Context, req *mgmt_pb.ListGrantedProjectsRequest) (*mgmt_pb.ListGrantedProjectsResponse, error) {
|
||||
queries, err := listGrantedProjectsRequestToModel(req)
|
||||
if err != nil {
|
||||
|
@@ -34,8 +34,12 @@ func (repo *UserMembershipRepo) searchUserMemberships(ctx context.Context) (_ []
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
grantedIDQuery, err := query.NewMembershipGrantedOrgIDSearchQuery(ctxData.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
memberships, err := repo.Queries.Memberships(ctx, &query.MembershipSearchQuery{
|
||||
Queries: []query.SearchQuery{userIDQuery, orgIDsQuery},
|
||||
Queries: []query.SearchQuery{userIDQuery, query.Or(orgIDsQuery, grantedIDQuery)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -50,6 +50,17 @@ func (q *Queries) ProjectChanges(ctx context.Context, projectID string, lastSequ
|
||||
return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention)
|
||||
}
|
||||
|
||||
func (q *Queries) ProjectGrantChanges(ctx context.Context, projectID, grantID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) {
|
||||
query := func(query *eventstore.SearchQuery) {
|
||||
query.AggregateTypes(project.AggregateType).
|
||||
AggregateIDs(projectID).
|
||||
EventData(map[string]interface{}{
|
||||
"grantId": grantID,
|
||||
})
|
||||
}
|
||||
return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention)
|
||||
}
|
||||
|
||||
func (q *Queries) ApplicationChanges(ctx context.Context, projectID, appID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) {
|
||||
query := func(query *eventstore.SearchQuery) {
|
||||
query.AggregateTypes(project.AggregateType).
|
||||
|
@@ -312,6 +312,28 @@ func ListComparisonFromMethod(m domain.SearchMethod) ListComparison {
|
||||
}
|
||||
}
|
||||
|
||||
type or struct {
|
||||
queries []SearchQuery
|
||||
}
|
||||
|
||||
func Or(queries ...SearchQuery) *or {
|
||||
return &or{
|
||||
queries: queries,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *or) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||
return query.Where(q.comp())
|
||||
}
|
||||
|
||||
func (q *or) comp() sq.Sqlizer {
|
||||
queries := make([]sq.Sqlizer, 0)
|
||||
for _, query := range q.queries {
|
||||
queries = append(queries, query.comp())
|
||||
}
|
||||
return sq.Or(queries)
|
||||
}
|
||||
|
||||
type BoolQuery struct {
|
||||
Column Column
|
||||
Value bool
|
||||
|
@@ -48,9 +48,10 @@ type ProjectMembership struct {
|
||||
}
|
||||
|
||||
type ProjectGrantMembership struct {
|
||||
ProjectID string
|
||||
ProjectName string
|
||||
GrantID string
|
||||
ProjectID string
|
||||
ProjectName string
|
||||
GrantID string
|
||||
GrantedOrgID string
|
||||
}
|
||||
|
||||
type MembershipSearchQuery struct {
|
||||
@@ -78,6 +79,10 @@ func NewMembershipResourceOwnersSearchQuery(ids ...string) (SearchQuery, error)
|
||||
return NewListQuery(membershipResourceOwner, list, ListIn)
|
||||
}
|
||||
|
||||
func NewMembershipGrantedOrgIDSearchQuery(id string) (SearchQuery, error) {
|
||||
return NewTextQuery(ProjectGrantColumnGrantedOrgID, id, TextEquals)
|
||||
}
|
||||
|
||||
func NewMembershipProjectIDQuery(value string) (SearchQuery, error) {
|
||||
return NewTextQuery(membershipProjectID, value, TextEquals)
|
||||
}
|
||||
@@ -173,6 +178,10 @@ var (
|
||||
name: projection.ProjectGrantMemberGrantIDCol,
|
||||
table: membershipAlias,
|
||||
}
|
||||
membershipGrantGrantedOrgID = Column{
|
||||
name: projection.ProjectGrantColumnGrantedOrgID,
|
||||
table: membershipAlias,
|
||||
}
|
||||
|
||||
membershipFrom = "(" +
|
||||
prepareOrgMember() +
|
||||
@@ -197,12 +206,14 @@ func prepareMembershipsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memberships,
|
||||
membershipIAMID.identifier(),
|
||||
membershipProjectID.identifier(),
|
||||
membershipGrantID.identifier(),
|
||||
ProjectGrantColumnGrantedOrgID.identifier(),
|
||||
ProjectColumnName.identifier(),
|
||||
OrgColumnName.identifier(),
|
||||
countColumn.identifier(),
|
||||
).From(membershipFrom).
|
||||
LeftJoin(join(ProjectColumnID, membershipProjectID)).
|
||||
LeftJoin(join(OrgColumnID, membershipOrgID)).
|
||||
LeftJoin(join(ProjectGrantColumnGrantID, membershipGrantID)).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*Memberships, error) {
|
||||
memberships := make([]*Membership, 0)
|
||||
@@ -210,14 +221,15 @@ func prepareMembershipsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memberships,
|
||||
for rows.Next() {
|
||||
|
||||
var (
|
||||
membership = new(Membership)
|
||||
orgID = sql.NullString{}
|
||||
iamID = sql.NullString{}
|
||||
projectID = sql.NullString{}
|
||||
grantID = sql.NullString{}
|
||||
roles = pq.StringArray{}
|
||||
projectName = sql.NullString{}
|
||||
orgName = sql.NullString{}
|
||||
membership = new(Membership)
|
||||
orgID = sql.NullString{}
|
||||
iamID = sql.NullString{}
|
||||
projectID = sql.NullString{}
|
||||
grantID = sql.NullString{}
|
||||
grantedOrgID = sql.NullString{}
|
||||
roles = pq.StringArray{}
|
||||
projectName = sql.NullString{}
|
||||
orgName = sql.NullString{}
|
||||
)
|
||||
|
||||
err := rows.Scan(
|
||||
@@ -231,6 +243,7 @@ func prepareMembershipsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memberships,
|
||||
&iamID,
|
||||
&projectID,
|
||||
&grantID,
|
||||
&grantedOrgID,
|
||||
&projectName,
|
||||
&orgName,
|
||||
&count,
|
||||
@@ -252,11 +265,12 @@ func prepareMembershipsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memberships,
|
||||
IAMID: iamID.String,
|
||||
Name: iamID.String,
|
||||
}
|
||||
} else if projectID.Valid && grantID.Valid {
|
||||
} else if projectID.Valid && grantID.Valid && grantedOrgID.Valid {
|
||||
membership.ProjectGrant = &ProjectGrantMembership{
|
||||
ProjectID: projectID.String,
|
||||
ProjectName: projectName.String,
|
||||
GrantID: grantID.String,
|
||||
ProjectID: projectID.String,
|
||||
ProjectName: projectName.String,
|
||||
GrantID: grantID.String,
|
||||
GrantedOrgID: grantedOrgID.String,
|
||||
}
|
||||
} else if projectID.Valid {
|
||||
membership.Project = &ProjectMembership{
|
||||
@@ -346,7 +360,8 @@ func prepareProjectGrantMember() string {
|
||||
"NULL::STRING AS "+membershipIAMID.name,
|
||||
ProjectGrantMemberProjectID.identifier(),
|
||||
ProjectGrantMemberGrantID.identifier(),
|
||||
).From(projectGrantMemberTable.identifier()).MustSql()
|
||||
).From(projectGrantMemberTable.identifier()).
|
||||
MustSql()
|
||||
|
||||
return stmt
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ var (
|
||||
", memberships.id" +
|
||||
", memberships.project_id" +
|
||||
", memberships.grant_id" +
|
||||
", projections.project_grants.granted_org_id" +
|
||||
", projections.projects.name" +
|
||||
", projections.orgs.name" +
|
||||
", COUNT(*) OVER ()" +
|
||||
@@ -80,7 +81,8 @@ var (
|
||||
" FROM projections.project_grant_members as members" +
|
||||
") AS memberships" +
|
||||
" LEFT JOIN projections.projects ON memberships.project_id = projections.projects.id" +
|
||||
" LEFT JOIN projections.orgs ON memberships.org_id = projections.orgs.id")
|
||||
" LEFT JOIN projections.orgs ON memberships.org_id = projections.orgs.id" +
|
||||
" LEFT JOIN projections.project_grants ON memberships.grant_id = projections.project_grants.grant_id")
|
||||
membershipCols = []string{
|
||||
"user_id",
|
||||
"roles",
|
||||
@@ -92,6 +94,7 @@ var (
|
||||
"instance_id",
|
||||
"project_id",
|
||||
"grant_id",
|
||||
"granted_org_id",
|
||||
"name", //project name
|
||||
"name", //org name
|
||||
"count",
|
||||
@@ -141,6 +144,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
"org-name",
|
||||
},
|
||||
},
|
||||
@@ -184,6 +188,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -224,6 +229,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
"project-id",
|
||||
nil,
|
||||
nil,
|
||||
"project-name",
|
||||
nil,
|
||||
},
|
||||
@@ -266,6 +272,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
"project-id",
|
||||
"grant-id",
|
||||
"granted-org-id",
|
||||
"project-name",
|
||||
nil,
|
||||
},
|
||||
@@ -285,9 +292,10 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
Sequence: 20211202,
|
||||
ResourceOwner: "ro",
|
||||
ProjectGrant: &ProjectGrantMembership{
|
||||
GrantID: "grant-id",
|
||||
ProjectID: "project-id",
|
||||
ProjectName: "project-name",
|
||||
GrantID: "grant-id",
|
||||
ProjectID: "project-id",
|
||||
ProjectName: "project-name",
|
||||
GrantedOrgID: "granted-org-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -313,6 +321,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
"org-name",
|
||||
},
|
||||
{
|
||||
@@ -328,6 +337,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user-id",
|
||||
@@ -340,6 +350,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
"project-id",
|
||||
nil,
|
||||
nil,
|
||||
"project-name",
|
||||
nil,
|
||||
},
|
||||
@@ -354,6 +365,7 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
nil,
|
||||
"project-id",
|
||||
"grant-id",
|
||||
"granted-org-id",
|
||||
"project-name",
|
||||
nil,
|
||||
},
|
||||
@@ -400,9 +412,10 @@ func Test_MembershipPrepares(t *testing.T) {
|
||||
Sequence: 20211202,
|
||||
ResourceOwner: "ro",
|
||||
ProjectGrant: &ProjectGrantMembership{
|
||||
ProjectID: "project-id",
|
||||
GrantID: "grant-id",
|
||||
ProjectName: "project-name",
|
||||
ProjectID: "project-id",
|
||||
GrantID: "grant-id",
|
||||
ProjectName: "project-name",
|
||||
GrantedOrgID: "granted-org-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -16,8 +16,12 @@ func (q *Queries) MyZitadelPermissions(ctx context.Context, orgID, userID string
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
grantedOrgIDQuery, err := NewMembershipGrantedOrgIDSearchQuery(orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
memberships, err := q.Memberships(ctx, &MembershipSearchQuery{
|
||||
Queries: []SearchQuery{userIDQuery, orgIDsQuery},
|
||||
Queries: []SearchQuery{userIDQuery, Or(orgIDsQuery, grantedOrgIDQuery)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
Reference in New Issue
Block a user