mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-31 03:22:15 +00:00
fix: generated project grant id (#10747)
# Which Problems Are Solved Project Grant ID would have needed to be unique to be handled properly on the projections, but was defined as the organization ID the project was granted to, so could be non-unique. # How the Problems Are Solved Generate the Project Grant ID even in the v2 APIs, which also includes fixes in the integration tests. Additionally to that, the logic for some functionality had to be extended as the Project Grant ID is not provided anymore in the API, so had to be queried before creating events for Project Grants. # Additional Changes Included fix for authorizations, when an authorization was intended to be created for a project, without providing any organization information, which also showed some faulty integration tests. # Additional Context Partially closes #10745 --------- Co-authored-by: Livio Spring <[email protected]> Co-authored-by: Silvan <[email protected]>
This commit is contained in:
co-authored by
Livio Spring
Silvan
parent
adc8fb2013
commit
b6ff4ff16c
@@ -133,19 +133,11 @@ func (c *Commands) checkPermissionDeleteProjectMember(ctx context.Context, resou
|
||||
}
|
||||
|
||||
func (c *Commands) checkPermissionUpdateProjectGrantMember(ctx context.Context, grantedOrgID, projectGrantID string) (err error) {
|
||||
// TODO: add permission check for project grant owners
|
||||
//if err := c.newPermissionCheck(ctx, domain.PermissionProjectGrantMemberWrite, project.AggregateType)(resourceOwner, projectGrantID); err != nil {
|
||||
return c.newPermissionCheck(ctx, domain.PermissionProjectGrantMemberWrite, project.AggregateType)(grantedOrgID, projectGrantID)
|
||||
//}
|
||||
//return nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkPermissionDeleteProjectGrantMember(ctx context.Context, grantedOrgID, projectGrantID string) (err error) {
|
||||
// TODO: add permission check for project grant owners
|
||||
//if err := c.newPermissionCheck(ctx, domain.PermissionProjectGrantMemberDelete, project.AggregateType)(resourceOwner, projectGrantID); err != nil {
|
||||
return c.newPermissionCheck(ctx, domain.PermissionProjectGrantMemberDelete, project.AggregateType)(grantedOrgID, projectGrantID)
|
||||
//}
|
||||
//return nil
|
||||
}
|
||||
|
||||
func (c *Commands) newUserGrantPermissionCheck(ctx context.Context, permission string) UserGrantPermissionCheck {
|
||||
|
||||
@@ -234,15 +234,15 @@ func (c *Commands) DeactivateProjectGrant(ctx context.Context, projectID, grantI
|
||||
return writeModelToObjectDetails(&existingGrant.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkProjectGrantExists(ctx context.Context, grantID, grantedOrgID, projectID, resourceOwner string) (string, string, error) {
|
||||
func (c *Commands) checkProjectGrantExists(ctx context.Context, grantID, grantedOrgID, projectID, resourceOwner string) (string, string, string, error) {
|
||||
existingGrant, err := c.projectGrantWriteModelByID(ctx, grantID, grantedOrgID, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return "", "", "", err
|
||||
}
|
||||
if !existingGrant.State.Exists() {
|
||||
return "", "", zerrors.ThrowNotFound(nil, "PROJECT-D8JxR", "Errors.Project.Grant.NotFound")
|
||||
return "", "", "", zerrors.ThrowNotFound(nil, "PROJECT-D8JxR", "Errors.Project.Grant.NotFound")
|
||||
}
|
||||
return existingGrant.GrantedOrgID, existingGrant.ResourceOwner, nil
|
||||
return existingGrant.FoundGrantID, existingGrant.GrantedOrgID, existingGrant.ResourceOwner, nil
|
||||
}
|
||||
|
||||
func (c *Commands) ReactivateProjectGrant(ctx context.Context, projectID, grantID, grantedOrgID, resourceOwner string) (details *domain.ObjectDetails, err error) {
|
||||
|
||||
@@ -13,15 +13,16 @@ import (
|
||||
)
|
||||
|
||||
type AddProjectGrantMember struct {
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
GrantID string
|
||||
ProjectID string
|
||||
Roles []string
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
OrganizationID string
|
||||
ProjectGrantID string
|
||||
ProjectID string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func (i *AddProjectGrantMember) IsValid(zitadelRoles []authz.RoleMapping) error {
|
||||
if i.ProjectID == "" || i.GrantID == "" || i.UserID == "" || len(i.Roles) == 0 {
|
||||
if i.ProjectID == "" || (i.OrganizationID == "" && i.ProjectGrantID == "") || i.UserID == "" || len(i.Roles) == 0 {
|
||||
return zerrors.ThrowInvalidArgument(nil, "PROJECT-8fi7G", "Errors.Project.Grant.Member.Invalid")
|
||||
}
|
||||
if len(domain.CheckForInvalidRoles(i.Roles, domain.ProjectGrantRolePrefix, zitadelRoles)) > 0 {
|
||||
@@ -41,14 +42,18 @@ func (c *Commands) AddProjectGrantMember(ctx context.Context, member *AddProject
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
grantedOrgID, projectGrantResourceOwner, err := c.checkProjectGrantExists(ctx, member.GrantID, "", member.ProjectID, "")
|
||||
projectGrantID, grantedOrgID, projectGrantResourceOwner, err := c.checkProjectGrantExists(ctx, member.ProjectGrantID, member.OrganizationID, member.ProjectID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if member.ResourceOwner == "" {
|
||||
member.ResourceOwner = projectGrantResourceOwner
|
||||
}
|
||||
addedMember, err := c.projectGrantMemberWriteModelByID(ctx, member.ProjectID, member.UserID, member.GrantID, member.ResourceOwner)
|
||||
// if projectGrantID is not provided, organizationID has to be provided, but we still need the projectGrantID which we query
|
||||
if member.ProjectGrantID == "" {
|
||||
member.ProjectGrantID = projectGrantID
|
||||
}
|
||||
addedMember, err := c.projectGrantMemberWriteModelByID(ctx, member.ProjectID, member.UserID, member.ProjectGrantID, member.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -69,7 +74,7 @@ func (c *Commands) AddProjectGrantMember(ctx context.Context, member *AddProject
|
||||
project.NewProjectGrantMemberAddedEvent(ctx,
|
||||
ProjectAggregateFromWriteModelWithCTX(ctx, &addedMember.WriteModel),
|
||||
member.UserID,
|
||||
member.GrantID,
|
||||
member.ProjectGrantID,
|
||||
member.Roles...,
|
||||
))
|
||||
if err != nil {
|
||||
@@ -84,14 +89,15 @@ func (c *Commands) AddProjectGrantMember(ctx context.Context, member *AddProject
|
||||
}
|
||||
|
||||
type ChangeProjectGrantMember struct {
|
||||
UserID string
|
||||
GrantID string
|
||||
ProjectID string
|
||||
Roles []string
|
||||
UserID string
|
||||
ProjectGrantID string
|
||||
OrganizationID string
|
||||
ProjectID string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func (i *ChangeProjectGrantMember) IsValid(zitadelRoles []authz.RoleMapping) error {
|
||||
if i.ProjectID == "" || i.GrantID == "" || i.UserID == "" || len(i.Roles) == 0 {
|
||||
if i.ProjectID == "" || (i.ProjectGrantID == "" && i.OrganizationID == "") || i.UserID == "" || len(i.Roles) == 0 {
|
||||
return zerrors.ThrowInvalidArgument(nil, "PROJECT-109fs", "Errors.Project.Grant.Member.Invalid")
|
||||
}
|
||||
if len(domain.CheckForInvalidRoles(i.Roles, domain.ProjectGrantRolePrefix, zitadelRoles)) > 0 {
|
||||
@@ -105,11 +111,14 @@ func (c *Commands) ChangeProjectGrantMember(ctx context.Context, member *ChangeP
|
||||
if err := member.IsValid(c.zitadelRoles); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingGrant, err := c.projectGrantWriteModelByID(ctx, member.GrantID, "", member.ProjectID, "")
|
||||
existingGrant, err := c.projectGrantWriteModelByID(ctx, member.ProjectGrantID, member.OrganizationID, member.ProjectID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingMember, err := c.projectGrantMemberWriteModelByID(ctx, member.ProjectID, member.UserID, member.GrantID, existingGrant.ResourceOwner)
|
||||
if member.ProjectGrantID == "" {
|
||||
member.ProjectGrantID = existingGrant.GrantID
|
||||
}
|
||||
existingMember, err := c.projectGrantMemberWriteModelByID(ctx, member.ProjectID, member.UserID, member.ProjectGrantID, existingGrant.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -129,7 +138,7 @@ func (c *Commands) ChangeProjectGrantMember(ctx context.Context, member *ChangeP
|
||||
project.NewProjectGrantMemberChangedEvent(ctx,
|
||||
ProjectAggregateFromWriteModelWithCTX(ctx, &existingMember.WriteModel),
|
||||
member.UserID,
|
||||
member.GrantID,
|
||||
member.ProjectGrantID,
|
||||
member.Roles...,
|
||||
))
|
||||
if err != nil {
|
||||
@@ -143,15 +152,16 @@ func (c *Commands) ChangeProjectGrantMember(ctx context.Context, member *ChangeP
|
||||
return writeModelToObjectDetails(&existingMember.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveProjectGrantMember(ctx context.Context, projectID, userID, grantID string) (*domain.ObjectDetails, error) {
|
||||
if projectID == "" || userID == "" || grantID == "" {
|
||||
func (c *Commands) RemoveProjectGrantMember(ctx context.Context, projectID, userID, grantID, organizationID string) (*domain.ObjectDetails, error) {
|
||||
if projectID == "" || userID == "" || (grantID == "" && organizationID == "") {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "PROJECT-66mHd", "Errors.Project.Member.Invalid")
|
||||
}
|
||||
existingGrant, err := c.projectGrantWriteModelByID(ctx, grantID, "", projectID, "")
|
||||
existingGrant, err := c.projectGrantWriteModelByID(ctx, grantID, organizationID, projectID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingMember, err := c.projectGrantMemberWriteModelByID(ctx, projectID, userID, grantID, existingGrant.ResourceOwner)
|
||||
|
||||
existingMember, err := c.projectGrantMemberWriteModelByID(ctx, existingGrant.AggregateID, userID, existingGrant.FoundGrantID, existingGrant.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -165,7 +175,7 @@ func (c *Commands) RemoveProjectGrantMember(ctx context.Context, projectID, user
|
||||
removeEvent := c.removeProjectGrantMember(ctx,
|
||||
ProjectAggregateFromWriteModelWithCTX(ctx, &existingMember.WriteModel),
|
||||
userID,
|
||||
grantID,
|
||||
existingGrant.FoundGrantID,
|
||||
false,
|
||||
)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, removeEvent)
|
||||
|
||||
@@ -57,10 +57,10 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &AddProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -82,10 +82,10 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &AddProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -142,10 +142,10 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &AddProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -202,10 +202,10 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &AddProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -257,10 +257,10 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &AddProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -331,10 +331,10 @@ func TestCommandSide_ChangeProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &ChangeProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -366,10 +366,10 @@ func TestCommandSide_ChangeProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &ChangeProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -410,10 +410,10 @@ func TestCommandSide_ChangeProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &ChangeProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -467,10 +467,10 @@ func TestCommandSide_ChangeProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &ChangeProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER", "PROJECT_GRANT_VIEWER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER", "PROJECT_GRANT_VIEWER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -516,10 +516,10 @@ func TestCommandSide_ChangeProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
member: &ChangeProjectGrantMember{
|
||||
ProjectID: "project1",
|
||||
GrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER", "PROJECT_GRANT_VIEWER"},
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
UserID: "user1",
|
||||
Roles: []string{"PROJECT_GRANT_OWNER", "PROJECT_GRANT_VIEWER"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -554,10 +554,11 @@ func TestCommandSide_RemoveProjectGrantMember(t *testing.T) {
|
||||
checkPermission domain.PermissionCheck
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
projectID string
|
||||
grantID string
|
||||
userID string
|
||||
ctx context.Context
|
||||
projectID string
|
||||
grantID string
|
||||
organizationID string
|
||||
userID string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@@ -693,6 +694,52 @@ func TestCommandSide_RemoveProjectGrantMember(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "member remove, organizationID, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewGrantAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectgrant1",
|
||||
"org2",
|
||||
[]string{"rol1", "role2"},
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewProjectGrantMemberAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"user1",
|
||||
"projectgrant1",
|
||||
[]string{"PROJECT_OWNER"}...,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
project.NewProjectGrantMemberRemovedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"user1",
|
||||
"projectgrant1",
|
||||
),
|
||||
),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
projectID: "project1",
|
||||
userID: "user1",
|
||||
organizationID: "org2",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "member remove, no permission",
|
||||
fields: fields{
|
||||
@@ -737,7 +784,7 @@ func TestCommandSide_RemoveProjectGrantMember(t *testing.T) {
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
}
|
||||
got, err := r.RemoveProjectGrantMember(tt.args.ctx, tt.args.projectID, tt.args.userID, tt.args.grantID)
|
||||
got, err := r.RemoveProjectGrantMember(tt.args.ctx, tt.args.projectID, tt.args.userID, tt.args.grantID, tt.args.organizationID)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
@@ -14,6 +16,8 @@ type ProjectGrantWriteModel struct {
|
||||
GrantedOrgID string
|
||||
RoleKeys []string
|
||||
State domain.ProjectGrantState
|
||||
|
||||
FoundGrantID string
|
||||
}
|
||||
|
||||
func NewProjectGrantWriteModel(grantID, grantedOrgID, projectID, resourceOwner string) *ProjectGrantWriteModel {
|
||||
@@ -22,6 +26,7 @@ func NewProjectGrantWriteModel(grantID, grantedOrgID, projectID, resourceOwner s
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
// Always either the grantID or the grantedOrgID is provided
|
||||
GrantID: grantID,
|
||||
GrantedOrgID: grantedOrgID,
|
||||
}
|
||||
@@ -31,28 +36,29 @@ func (wm *ProjectGrantWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.GrantAddedEvent:
|
||||
if (wm.GrantID != "" && e.GrantID == wm.GrantID) ||
|
||||
(wm.GrantedOrgID != "" && e.GrantedOrgID == wm.GrantedOrgID) {
|
||||
if projectGrantExists(wm.GrantID, wm.GrantedOrgID, e.GrantID, e.GrantedOrgID) {
|
||||
wm.FoundGrantID = e.GrantID
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantChangedEvent:
|
||||
if wm.GrantID != "" && e.GrantID == wm.GrantID {
|
||||
if projectGrantEqual(wm.FoundGrantID, e.GrantID) {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantCascadeChangedEvent:
|
||||
if wm.GrantID != "" && e.GrantID == wm.GrantID {
|
||||
if projectGrantEqual(wm.FoundGrantID, e.GrantID) {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantDeactivateEvent:
|
||||
if wm.GrantID != "" && e.GrantID == wm.GrantID {
|
||||
if projectGrantEqual(wm.FoundGrantID, e.GrantID) {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantReactivatedEvent:
|
||||
if wm.GrantID != "" && e.GrantID == wm.GrantID {
|
||||
if projectGrantEqual(wm.FoundGrantID, e.GrantID) {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantRemovedEvent:
|
||||
if wm.GrantID != "" && e.GrantID == wm.GrantID {
|
||||
if projectGrantEqual(wm.FoundGrantID, e.GrantID) {
|
||||
wm.FoundGrantID = ""
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.ProjectRemovedEvent:
|
||||
@@ -61,6 +67,17 @@ func (wm *ProjectGrantWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
}
|
||||
}
|
||||
|
||||
func projectGrantExists(requiredGrantID, requiredGrantedOrgID, grantID, grantedOrgID string) bool {
|
||||
// either grantID or grantedOrgID is provided and equal
|
||||
return projectGrantEqual(requiredGrantID, grantID) ||
|
||||
(requiredGrantedOrgID != "" && grantedOrgID == requiredGrantedOrgID)
|
||||
}
|
||||
|
||||
func projectGrantEqual(requiredGrantID, grantID string) bool {
|
||||
// grantID is provided and equal
|
||||
return requiredGrantID != "" && grantID == requiredGrantID
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
@@ -93,7 +110,8 @@ func (wm *ProjectGrantWriteModel) Reduce() error {
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
@@ -106,11 +124,6 @@ func (wm *ProjectGrantWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
project.GrantRemovedType,
|
||||
project.ProjectRemovedType).
|
||||
Builder()
|
||||
|
||||
if wm.ResourceOwner != "" {
|
||||
query.ResourceOwner(wm.ResourceOwner)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
type ProjectGrantPreConditionReadModel struct {
|
||||
@@ -159,14 +172,9 @@ func (wm *ProjectGrantPreConditionReadModel) Reduce() error {
|
||||
if e.Aggregate().ResourceOwner != wm.ProjectResourceOwner {
|
||||
continue
|
||||
}
|
||||
for i, key := range wm.ExistingRoleKeys {
|
||||
if key == e.Key {
|
||||
copy(wm.ExistingRoleKeys[i:], wm.ExistingRoleKeys[i+1:])
|
||||
wm.ExistingRoleKeys[len(wm.ExistingRoleKeys)-1] = ""
|
||||
wm.ExistingRoleKeys = wm.ExistingRoleKeys[:len(wm.ExistingRoleKeys)-1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
wm.ExistingRoleKeys = slices.DeleteFunc(wm.ExistingRoleKeys, func(key string) bool {
|
||||
return key == e.Key
|
||||
})
|
||||
case *org.OrgAddedEvent:
|
||||
wm.GrantedOrgExists = true
|
||||
case *org.OrgRemovedEvent:
|
||||
|
||||
@@ -352,6 +352,61 @@ func TestCommandSide_AddProjectGrant(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "grant for project, only granted org, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewProjectAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectname1", true, true, true,
|
||||
domain.PrivateLabelingSettingUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewOrgAddedEvent(context.Background(),
|
||||
&org.NewAggregate("grantedorg1").Aggregate,
|
||||
"granted org",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewRoleAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"key1",
|
||||
"key",
|
||||
"",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
project.NewGrantAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectgrant1",
|
||||
"grantedorg1",
|
||||
[]string{"key1"},
|
||||
),
|
||||
),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "projectgrant1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
projectGrant: &AddProjectGrant{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "project1",
|
||||
},
|
||||
GrantedOrgID: "grantedorg1",
|
||||
RoleKeys: []string{"key1"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -790,6 +845,75 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "projectgrant only added roles,no resourceowner, grantedOrgID, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(project.NewGrantAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectgrant1",
|
||||
"grantedorg1",
|
||||
[]string{"key1"},
|
||||
)),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewProjectAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectname1", true, true, true,
|
||||
domain.PrivateLabelingSettingUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewOrgAddedEvent(context.Background(),
|
||||
&org.NewAggregate("grantedorg1").Aggregate,
|
||||
"granted org",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewRoleAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"key1",
|
||||
"key",
|
||||
"",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewRoleAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"key2",
|
||||
"key2",
|
||||
"",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
project.NewGrantChangedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectgrant1",
|
||||
[]string{"key1", "key2"},
|
||||
),
|
||||
),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
projectGrant: &ChangeProjectGrant{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "project1",
|
||||
},
|
||||
GrantedOrgID: "grantedorg1",
|
||||
RoleKeys: []string{"key1", "key2"},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "projectgrant remove roles, usergrant not found, ok",
|
||||
fields: fields{
|
||||
|
||||
@@ -171,7 +171,8 @@ func projectExistsOnOrganization(requiredOrganization, projectResourceOwner stri
|
||||
func projectGrantExistsOnOrganization(requiredGrantID, requiredOrganization, projectGrantID, grantedOrganization string) bool {
|
||||
// Depending on the API, a request can either require a project grant (ID) and/or an organization (ID),
|
||||
// where the project must be granted to.
|
||||
return (requiredGrantID == "" || requiredGrantID == projectGrantID) &&
|
||||
return (requiredGrantID != "" || requiredOrganization != "") &&
|
||||
(requiredGrantID == "" || requiredGrantID == projectGrantID) &&
|
||||
(requiredOrganization == "" || requiredOrganization == grantedOrganization)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user