diff --git a/docs/docs/apis/openidoauth/scopes.md b/docs/docs/apis/openidoauth/scopes.md index ec930d6b30..05f57dad1a 100644 --- a/docs/docs/apis/openidoauth/scopes.md +++ b/docs/docs/apis/openidoauth/scopes.md @@ -22,11 +22,11 @@ ZITADEL supports the usage of scopes as way of requesting information from the I In addition to the standard compliant scopes we utilize the following scopes. -| Scopes | Example | Description | -|:------------------------------------------------|:-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| urn:zitadel:iam:org:project:role:{rolename} | `urn:zitadel:iam:org:project:role:user` | By using this scope a client can request the claim urn:zitadel:iam:roles:rolename} to be asserted when possible. As an alternative approach you can enable all roles to be asserted from the [project](../../guides/usage/projects) a client belongs to. | -| urn:zitadel:iam:org:domain:primary:{domainname} | `urn:zitadel:iam:org:domain:primary:acme.ch` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization. If the organization does not exist a failure is displayed | -| urn:zitadel:iam:role:{rolename} | | | -| `urn:zitadel:iam:org:project:id:{projectid}:aud` | ZITADEL's Project id is `urn:zitadel:iam:org:project:id:69234237810729019:aud` | By adding this scope, the requested projectid will be added to the audience of the access and id token | +| Scopes | Example | Description | +|:-------------------------------------------------|:-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| urn:zitadel:iam:org:project:role:{rolename} | `urn:zitadel:iam:org:project:role:user` | By using this scope a client can request the claim urn:zitadel:iam:roles:rolename} to be asserted when possible. As an alternative approach you can enable all roles to be asserted from the [project](../../guides/usage/projects) a client belongs to. | +| urn:zitadel:iam:org:domain:primary:{domainname} | `urn:zitadel:iam:org:domain:primary:acme.ch` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization. If the organization does not exist a failure is displayed | +| urn:zitadel:iam:role:{rolename} | | | +| `urn:zitadel:iam:org:project:id:{projectid}:aud` | ZITADEL's Project id is `urn:zitadel:iam:org:project:id:69234237810729019:aud` | By adding this scope, the requested projectid will be added to the audience of the access and id token | > If access to ZITADEL's API's is needed with a service user the scope `urn:zitadel:iam:org:project:id:69234237810729019:aud` needs to be used with the JWT Profile request diff --git a/docs/docs/apis/proto/management.md b/docs/docs/apis/proto/management.md index 2d8ffd2633..bb12511c75 100644 --- a/docs/docs/apis/proto/management.md +++ b/docs/docs/apis/proto/management.md @@ -3277,6 +3277,7 @@ This is an empty request | project_role_assertion | bool | - | | | project_role_check | bool | - | | | has_project_check | bool | - | | +| private_labeling_setting | zitadel.project.v1.PrivateLabelingSetting | - | enum.defined_only: true
| @@ -7522,6 +7523,7 @@ This is an empty request | project_role_assertion | bool | - | | | project_role_check | bool | - | | | has_project_check | bool | - | | +| private_labeling_setting | zitadel.project.v1.PrivateLabelingSetting | - | enum.defined_only: true
| diff --git a/docs/docs/apis/proto/project.md b/docs/docs/apis/proto/project.md index d925165017..48066cd951 100644 --- a/docs/docs/apis/proto/project.md +++ b/docs/docs/apis/proto/project.md @@ -66,6 +66,7 @@ title: zitadel/project.proto | project_role_assertion | bool | describes if roles of user should be added in token | | | project_role_check | bool | ZITADEL checks if the user has at least one on this project | | | has_project_check | bool | ZITADEL checks if the org of the user has permission to this project | | +| private_labeling_setting | PrivateLabelingSetting | Defines from where the private labeling should be triggered | | @@ -160,6 +161,18 @@ title: zitadel/project.proto ## Enums +### PrivateLabelingSetting {#privatelabelingsetting} + + +| Name | Number | Description | +| ---- | ------ | ----------- | +| PRIVATE_LABELING_SETTING_UNSPECIFIED | 0 | - | +| PRIVATE_LABELING_SETTING_ENFORCE_PROJECT_RESOURCE_OWNER_POLICY | 1 | - | +| PRIVATE_LABELING_SETTING_ALLOW_LOGIN_USER_RESOURCE_OWNER_POLICY | 2 | - | + + + + ### ProjectGrantState {#projectgrantstate} diff --git a/internal/api/grpc/management/project_converter.go b/internal/api/grpc/management/project_converter.go index ba18827009..084ec6b685 100644 --- a/internal/api/grpc/management/project_converter.go +++ b/internal/api/grpc/management/project_converter.go @@ -8,14 +8,16 @@ import ( "github.com/caos/zitadel/internal/eventstore/v1/models" proj_model "github.com/caos/zitadel/internal/project/model" mgmt_pb "github.com/caos/zitadel/pkg/grpc/management" + proj_pb "github.com/caos/zitadel/pkg/grpc/project" ) func ProjectCreateToDomain(req *mgmt_pb.AddProjectRequest) *domain.Project { return &domain.Project{ - Name: req.Name, - ProjectRoleAssertion: req.ProjectRoleAssertion, - ProjectRoleCheck: req.ProjectRoleCheck, - HasProjectCheck: req.HasProjectCheck, + Name: req.Name, + ProjectRoleAssertion: req.ProjectRoleAssertion, + ProjectRoleCheck: req.ProjectRoleCheck, + HasProjectCheck: req.HasProjectCheck, + PrivateLabelingSetting: privateLabelingSettingToDomain(req.PrivateLabelingSetting), } } @@ -24,10 +26,22 @@ func ProjectUpdateToDomain(req *mgmt_pb.UpdateProjectRequest) *domain.Project { ObjectRoot: models.ObjectRoot{ AggregateID: req.Id, }, - Name: req.Name, - ProjectRoleAssertion: req.ProjectRoleAssertion, - ProjectRoleCheck: req.ProjectRoleCheck, - HasProjectCheck: req.HasProjectCheck, + Name: req.Name, + ProjectRoleAssertion: req.ProjectRoleAssertion, + ProjectRoleCheck: req.ProjectRoleCheck, + HasProjectCheck: req.HasProjectCheck, + PrivateLabelingSetting: privateLabelingSettingToDomain(req.PrivateLabelingSetting), + } +} + +func privateLabelingSettingToDomain(setting proj_pb.PrivateLabelingSetting) domain.PrivateLabelingSetting { + switch setting { + case proj_pb.PrivateLabelingSetting_PRIVATE_LABELING_SETTING_ALLOW_LOGIN_USER_RESOURCE_OWNER_POLICY: + return domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy + case proj_pb.PrivateLabelingSetting_PRIVATE_LABELING_SETTING_ENFORCE_PROJECT_RESOURCE_OWNER_POLICY: + return domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy + default: + return domain.PrivateLabelingSettingUnspecified } } diff --git a/internal/api/grpc/project/application.go b/internal/api/grpc/project/application.go index efcf57689b..f72ce352b8 100644 --- a/internal/api/grpc/project/application.go +++ b/internal/api/grpc/project/application.go @@ -22,7 +22,7 @@ func AppsToPb(apps []*proj_model.ApplicationView) []*app_pb.App { func AppToPb(app *proj_model.ApplicationView) *app_pb.App { return &app_pb.App{ Id: app.ID, - Details: object_grpc.ToViewDetailsPb(app.Sequence, app.CreationDate, app.ChangeDate, ""), //TODO: RO + Details: object_grpc.ToViewDetailsPb(app.Sequence, app.CreationDate, app.ChangeDate, app.ResourceOwner), State: AppStateToPb(app.State), Name: app.Name, Config: AppConfigToPb(app), diff --git a/internal/api/grpc/project/converter.go b/internal/api/grpc/project/converter.go index 28420e707b..3176527651 100644 --- a/internal/api/grpc/project/converter.go +++ b/internal/api/grpc/project/converter.go @@ -2,6 +2,7 @@ package project import ( object_grpc "github.com/caos/zitadel/internal/api/grpc/object" + "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/errors" proj_model "github.com/caos/zitadel/internal/project/model" proj_pb "github.com/caos/zitadel/pkg/grpc/project" @@ -9,13 +10,14 @@ import ( func ProjectToPb(project *proj_model.ProjectView) *proj_pb.Project { return &proj_pb.Project{ - Id: project.ProjectID, - Details: object_grpc.ToViewDetailsPb(project.Sequence, project.CreationDate, project.ChangeDate, project.ResourceOwner), - Name: project.Name, - State: projectStateToPb(project.State), - ProjectRoleAssertion: project.ProjectRoleAssertion, - ProjectRoleCheck: project.ProjectRoleCheck, - HasProjectCheck: project.HasProjectCheck, + Id: project.ProjectID, + Details: object_grpc.ToViewDetailsPb(project.Sequence, project.CreationDate, project.ChangeDate, project.ResourceOwner), + Name: project.Name, + State: projectStateToPb(project.State), + ProjectRoleAssertion: project.ProjectRoleAssertion, + ProjectRoleCheck: project.ProjectRoleCheck, + HasProjectCheck: project.HasProjectCheck, + PrivateLabelingSetting: privateLabelingSettingToPb(project.PrivateLabelingSetting), } } @@ -61,6 +63,17 @@ func projectStateToPb(state proj_model.ProjectState) proj_pb.ProjectState { } } +func privateLabelingSettingToPb(setting domain.PrivateLabelingSetting) proj_pb.PrivateLabelingSetting { + switch setting { + case domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy: + return proj_pb.PrivateLabelingSetting_PRIVATE_LABELING_SETTING_ALLOW_LOGIN_USER_RESOURCE_OWNER_POLICY + case domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy: + return proj_pb.PrivateLabelingSetting_PRIVATE_LABELING_SETTING_ENFORCE_PROJECT_RESOURCE_OWNER_POLICY + default: + return proj_pb.PrivateLabelingSetting_PRIVATE_LABELING_SETTING_UNSPECIFIED + } +} + func grantedProjectStateToPb(state proj_model.ProjectState) proj_pb.ProjectGrantState { switch state { case proj_model.ProjectStateActive: diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go index f5fa340ace..30266c579f 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go @@ -124,6 +124,8 @@ func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *dom } request.Audience = appIDs request.AppendAudIfNotExisting(app.ProjectID) + request.ApplicationResourceOwner = app.ResourceOwner + request.PrivateLabelingSetting = app.PrivateLabelingSetting if err := setOrgID(repo.OrgViewProvider, request); err != nil { return nil, err } @@ -510,7 +512,16 @@ func (repo *AuthRequestRepo) fillPolicies(ctx context.Context, request *domain.A return err } request.PrivacyPolicy = privacyPolicy - labelPolicy, err := repo.getLabelPolicy(ctx, orgID) + privateLabelingOrgID := domain.IAMID + if request.PrivateLabelingSetting != domain.PrivateLabelingSettingUnspecified { + privateLabelingOrgID = request.ApplicationResourceOwner + } + if request.PrivateLabelingSetting == domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy || request.PrivateLabelingSetting == domain.PrivateLabelingSettingUnspecified { + if request.UserOrgID != "" { + privateLabelingOrgID = request.UserOrgID + } + } + labelPolicy, err := repo.getLabelPolicy(ctx, privateLabelingOrgID) if err != nil { return err } diff --git a/internal/auth/repository/eventsourcing/handler/application.go b/internal/auth/repository/eventsourcing/handler/application.go index 65e75bdf71..7632180abc 100644 --- a/internal/auth/repository/eventsourcing/handler/application.go +++ b/internal/auth/repository/eventsourcing/handler/application.go @@ -84,6 +84,7 @@ func (a *Application) Reduce(event *models.Event) (err error) { app.ProjectRoleCheck = project.ProjectRoleCheck app.HasProjectCheck = project.HasProjectCheck app.ProjectRoleAssertion = project.ProjectRoleAssertion + app.PrivateLabelingSetting = project.PrivateLabelingSetting err = app.AppendEvent(event) case es_model.ApplicationChanged, diff --git a/internal/command/project.go b/internal/command/project.go index 2257d9feb1..91283a9d34 100644 --- a/internal/command/project.go +++ b/internal/command/project.go @@ -45,7 +45,14 @@ func (c *Commands) addProject(ctx context.Context, projectAdd *domain.Project, r projectRole = domain.RoleProjectOwnerGlobal } events := []eventstore.EventPusher{ - project.NewProjectAddedEvent(ctx, projectAgg, projectAdd.Name, projectAdd.ProjectRoleAssertion, projectAdd.ProjectRoleCheck, projectAdd.HasProjectCheck), + project.NewProjectAddedEvent( + ctx, + projectAgg, + projectAdd.Name, + projectAdd.ProjectRoleAssertion, + projectAdd.ProjectRoleCheck, + projectAdd.HasProjectCheck, + projectAdd.PrivateLabelingSetting), project.NewProjectMemberAddedEvent(ctx, projectAgg, ownerUserID, projectRole), } return events, addedProject, nil @@ -93,7 +100,8 @@ func (c *Commands) ChangeProject(ctx context.Context, projectChange *domain.Proj projectChange.Name, projectChange.ProjectRoleAssertion, projectChange.ProjectRoleCheck, - projectChange.HasProjectCheck) + projectChange.HasProjectCheck, + projectChange.PrivateLabelingSetting) if err != nil { return nil, err } diff --git a/internal/command/project_application_api_test.go b/internal/command/project_application_api_test.go index 507f0fe249..6de1636741 100644 --- a/internal/command/project_application_api_test.go +++ b/internal/command/project_application_api_test.go @@ -84,7 +84,8 @@ func TestCommandSide_AddAPIApplication(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingUnspecified), ), ), ), @@ -113,7 +114,8 @@ func TestCommandSide_AddAPIApplication(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingUnspecified), ), ), expectPush( @@ -180,7 +182,8 @@ func TestCommandSide_AddAPIApplication(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingUnspecified), ), ), expectPush( diff --git a/internal/command/project_application_oidc_test.go b/internal/command/project_application_oidc_test.go index ecfef9ebb0..d690bbe8da 100644 --- a/internal/command/project_application_oidc_test.go +++ b/internal/command/project_application_oidc_test.go @@ -87,7 +87,8 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingUnspecified), ), ), ), @@ -116,7 +117,8 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingUnspecified), ), ), expectPush( diff --git a/internal/command/project_converter.go b/internal/command/project_converter.go index 4af0418c1a..aca37def6d 100644 --- a/internal/command/project_converter.go +++ b/internal/command/project_converter.go @@ -6,11 +6,12 @@ import ( func projectWriteModelToProject(writeModel *ProjectWriteModel) *domain.Project { return &domain.Project{ - ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel), - Name: writeModel.Name, - ProjectRoleAssertion: writeModel.ProjectRoleAssertion, - ProjectRoleCheck: writeModel.ProjectRoleCheck, - HasProjectCheck: writeModel.HasProjectCheck, + ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel), + Name: writeModel.Name, + ProjectRoleAssertion: writeModel.ProjectRoleAssertion, + ProjectRoleCheck: writeModel.ProjectRoleCheck, + HasProjectCheck: writeModel.HasProjectCheck, + PrivateLabelingSetting: writeModel.PrivateLabelingSetting, } } diff --git a/internal/command/project_grant_test.go b/internal/command/project_grant_test.go index 15f28a2cc9..67bd94189e 100644 --- a/internal/command/project_grant_test.go +++ b/internal/command/project_grant_test.go @@ -88,6 +88,7 @@ func TestCommandSide_AddProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -117,6 +118,7 @@ func TestCommandSide_AddProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -153,6 +155,7 @@ func TestCommandSide_AddProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -342,6 +345,7 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -380,6 +384,7 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -425,6 +430,7 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -478,6 +484,7 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -557,6 +564,7 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -638,6 +646,7 @@ func TestCommandSide_ChangeProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -814,6 +823,7 @@ func TestCommandSide_DeactivateProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -840,6 +850,7 @@ func TestCommandSide_DeactivateProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -877,6 +888,7 @@ func TestCommandSide_DeactivateProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1010,6 +1022,7 @@ func TestCommandSide_ReactivateProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1036,6 +1049,7 @@ func TestCommandSide_ReactivateProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1069,6 +1083,7 @@ func TestCommandSide_ReactivateProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1207,6 +1222,7 @@ func TestCommandSide_RemoveProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1233,6 +1249,7 @@ func TestCommandSide_RemoveProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1278,6 +1295,7 @@ func TestCommandSide_RemoveProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -1325,6 +1343,7 @@ func TestCommandSide_RemoveProjectGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), diff --git a/internal/command/project_model.go b/internal/command/project_model.go index 8655f3d9b8..1dbf4ecec9 100644 --- a/internal/command/project_model.go +++ b/internal/command/project_model.go @@ -11,11 +11,12 @@ import ( type ProjectWriteModel struct { eventstore.WriteModel - Name string - ProjectRoleAssertion bool - ProjectRoleCheck bool - HasProjectCheck bool - State domain.ProjectState + Name string + ProjectRoleAssertion bool + ProjectRoleCheck bool + HasProjectCheck bool + PrivateLabelingSetting domain.PrivateLabelingSetting + State domain.ProjectState } func NewProjectWriteModel(projectID string, resourceOwner string) *ProjectWriteModel { @@ -35,6 +36,7 @@ func (wm *ProjectWriteModel) Reduce() error { wm.ProjectRoleAssertion = e.ProjectRoleAssertion wm.ProjectRoleCheck = e.ProjectRoleCheck wm.HasProjectCheck = e.HasProjectCheck + wm.PrivateLabelingSetting = e.PrivateLabelingSetting wm.State = domain.ProjectStateActive case *project.ProjectChangeEvent: if e.Name != nil { @@ -49,6 +51,9 @@ func (wm *ProjectWriteModel) Reduce() error { if e.HasProjectCheck != nil { wm.HasProjectCheck = *e.HasProjectCheck } + if e.PrivateLabelingSetting != nil { + wm.PrivateLabelingSetting = *e.PrivateLabelingSetting + } case *project.ProjectDeactivatedEvent: if wm.State == domain.ProjectStateRemoved { continue @@ -87,6 +92,7 @@ func (wm *ProjectWriteModel) NewChangedEvent( projectRoleAssertion, projectRoleCheck, hasProjectCheck bool, + privateLabelingSetting domain.PrivateLabelingSetting, ) (*project.ProjectChangeEvent, bool, error) { changes := make([]project.ProjectChanges, 0) var err error @@ -105,6 +111,9 @@ func (wm *ProjectWriteModel) NewChangedEvent( if wm.HasProjectCheck != hasProjectCheck { changes = append(changes, project.ChangeHasProjectCheck(hasProjectCheck)) } + if wm.PrivateLabelingSetting != privateLabelingSetting { + changes = append(changes, project.ChangePrivateLabelingSetting(privateLabelingSetting)) + } if len(changes) == 0 { return nil, false, nil } diff --git a/internal/command/project_role_test.go b/internal/command/project_role_test.go index 80a13c8577..7d70c9be80 100644 --- a/internal/command/project_role_test.go +++ b/internal/command/project_role_test.go @@ -42,6 +42,7 @@ func TestCommandSide_AddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -77,6 +78,7 @@ func TestCommandSide_AddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -105,6 +107,7 @@ func TestCommandSide_AddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -149,6 +152,7 @@ func TestCommandSide_AddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -241,6 +245,7 @@ func TestCommandSide_BulkAddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -278,6 +283,7 @@ func TestCommandSide_BulkAddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -310,6 +316,7 @@ func TestCommandSide_BulkAddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -368,6 +375,7 @@ func TestCommandSide_BulkAddProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -487,6 +495,7 @@ func TestCommandSide_ChangeProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -522,6 +531,7 @@ func TestCommandSide_ChangeProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -569,6 +579,7 @@ func TestCommandSide_ChangeProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -610,6 +621,7 @@ func TestCommandSide_ChangeProjectRole(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), diff --git a/internal/command/project_test.go b/internal/command/project_test.go index 63d99d8251..1671e37ef1 100644 --- a/internal/command/project_test.go +++ b/internal/command/project_test.go @@ -74,6 +74,7 @@ func TestCommandSide_AddProject(t *testing.T) { context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, ), ), eventFromEventPusher(project.NewProjectMemberAddedEvent( @@ -93,10 +94,11 @@ func TestCommandSide_AddProject(t *testing.T) { args: args{ ctx: context.Background(), project: &domain.Project{ - Name: "project", - ProjectRoleAssertion: true, - ProjectRoleCheck: true, - HasProjectCheck: true, + Name: "project", + ProjectRoleAssertion: true, + ProjectRoleCheck: true, + HasProjectCheck: true, + PrivateLabelingSetting: domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, }, resourceOwner: "org1", ownerID: "user1", @@ -124,6 +126,7 @@ func TestCommandSide_AddProject(t *testing.T) { context.Background(), &project.NewAggregate("project1", "globalorg").Aggregate, "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, ), ), eventFromEventPusher(project.NewProjectMemberAddedEvent( @@ -143,10 +146,11 @@ func TestCommandSide_AddProject(t *testing.T) { args: args{ ctx: context.Background(), project: &domain.Project{ - Name: "project", - ProjectRoleAssertion: true, - ProjectRoleCheck: true, - HasProjectCheck: true, + Name: "project", + ProjectRoleAssertion: true, + ProjectRoleCheck: true, + HasProjectCheck: true, + PrivateLabelingSetting: domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, }, resourceOwner: "globalorg", ownerID: "user1", @@ -157,10 +161,11 @@ func TestCommandSide_AddProject(t *testing.T) { ResourceOwner: "globalorg", AggregateID: "project1", }, - Name: "project", - ProjectRoleAssertion: true, - ProjectRoleCheck: true, - HasProjectCheck: true, + Name: "project", + ProjectRoleAssertion: true, + ProjectRoleCheck: true, + HasProjectCheck: true, + PrivateLabelingSetting: domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, }, }, }, @@ -183,6 +188,7 @@ func TestCommandSide_AddProject(t *testing.T) { context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, ), ), eventFromEventPusher(project.NewProjectMemberAddedEvent( @@ -202,10 +208,11 @@ func TestCommandSide_AddProject(t *testing.T) { args: args{ ctx: context.Background(), project: &domain.Project{ - Name: "project", - ProjectRoleAssertion: true, - ProjectRoleCheck: true, - HasProjectCheck: true, + Name: "project", + ProjectRoleAssertion: true, + ProjectRoleCheck: true, + HasProjectCheck: true, + PrivateLabelingSetting: domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, }, resourceOwner: "org1", ownerID: "user1", @@ -216,10 +223,11 @@ func TestCommandSide_AddProject(t *testing.T) { ResourceOwner: "org1", AggregateID: "project1", }, - Name: "project", - ProjectRoleAssertion: true, - ProjectRoleCheck: true, - HasProjectCheck: true, + Name: "project", + ProjectRoleAssertion: true, + ProjectRoleCheck: true, + HasProjectCheck: true, + PrivateLabelingSetting: domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, }, }, }, @@ -332,7 +340,8 @@ func TestCommandSide_ChangeProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), eventFromEventPusher( project.NewProjectRemovedEvent(context.Background(), @@ -365,7 +374,8 @@ func TestCommandSide_ChangeProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), ), ), @@ -376,10 +386,11 @@ func TestCommandSide_ChangeProject(t *testing.T) { ObjectRoot: models.ObjectRoot{ AggregateID: "project1", }, - Name: "project", - ProjectRoleAssertion: true, - ProjectRoleCheck: true, - HasProjectCheck: true, + Name: "project", + ProjectRoleAssertion: true, + ProjectRoleCheck: true, + HasProjectCheck: true, + PrivateLabelingSetting: domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy, }, resourceOwner: "org1", }, @@ -396,7 +407,8 @@ func TestCommandSide_ChangeProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), ), expectPush( @@ -409,7 +421,8 @@ func TestCommandSide_ChangeProject(t *testing.T) { "project-new", false, false, - false), + false, + domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy), ), }, uniqueConstraintsFromEventConstraint(project.NewRemoveProjectNameUniqueConstraint("project", "org1")), @@ -423,10 +436,11 @@ func TestCommandSide_ChangeProject(t *testing.T) { ObjectRoot: models.ObjectRoot{ AggregateID: "project1", }, - Name: "project-new", - ProjectRoleAssertion: false, - ProjectRoleCheck: false, - HasProjectCheck: false, + Name: "project-new", + ProjectRoleAssertion: false, + ProjectRoleCheck: false, + HasProjectCheck: false, + PrivateLabelingSetting: domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy, }, resourceOwner: "org1", }, @@ -436,10 +450,11 @@ func TestCommandSide_ChangeProject(t *testing.T) { AggregateID: "project1", ResourceOwner: "org1", }, - Name: "project-new", - ProjectRoleAssertion: false, - ProjectRoleCheck: false, - HasProjectCheck: false, + Name: "project-new", + ProjectRoleAssertion: false, + ProjectRoleCheck: false, + HasProjectCheck: false, + PrivateLabelingSetting: domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy, }, }, }, @@ -452,7 +467,8 @@ func TestCommandSide_ChangeProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), ), expectPush( @@ -465,7 +481,8 @@ func TestCommandSide_ChangeProject(t *testing.T) { "", false, false, - false), + false, + domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy), ), }, ), @@ -477,10 +494,11 @@ func TestCommandSide_ChangeProject(t *testing.T) { ObjectRoot: models.ObjectRoot{ AggregateID: "project1", }, - Name: "project", - ProjectRoleAssertion: false, - ProjectRoleCheck: false, - HasProjectCheck: false, + Name: "project", + ProjectRoleAssertion: false, + ProjectRoleCheck: false, + HasProjectCheck: false, + PrivateLabelingSetting: domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy, }, resourceOwner: "org1", }, @@ -490,10 +508,11 @@ func TestCommandSide_ChangeProject(t *testing.T) { AggregateID: "project1", ResourceOwner: "org1", }, - Name: "project", - ProjectRoleAssertion: false, - ProjectRoleCheck: false, - HasProjectCheck: false, + Name: "project", + ProjectRoleAssertion: false, + ProjectRoleCheck: false, + HasProjectCheck: false, + PrivateLabelingSetting: domain.PrivateLabelingSettingEnforceProjectResourceOwnerPolicy, }, }, }, @@ -594,7 +613,8 @@ func TestCommandSide_DeactivateProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), eventFromEventPusher( project.NewProjectRemovedEvent(context.Background(), @@ -622,7 +642,8 @@ func TestCommandSide_DeactivateProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), eventFromEventPusher( project.NewProjectDeactivatedEvent(context.Background(), @@ -649,7 +670,8 @@ func TestCommandSide_DeactivateProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), ), expectPush( @@ -770,7 +792,8 @@ func TestCommandSide_ReactivateProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), eventFromEventPusher( project.NewProjectRemovedEvent(context.Background(), @@ -798,7 +821,8 @@ func TestCommandSide_ReactivateProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), ), ), @@ -821,7 +845,8 @@ func TestCommandSide_ReactivateProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), eventFromEventPusher( project.NewProjectDeactivatedEvent(context.Background(), @@ -946,7 +971,8 @@ func TestCommandSide_RemoveProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), eventFromEventPusher( project.NewProjectRemovedEvent(context.Background(), @@ -974,7 +1000,8 @@ func TestCommandSide_RemoveProject(t *testing.T) { eventFromEventPusher( project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, - "project", true, true, true), + "project", true, true, true, + domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy), ), ), expectPush( @@ -1020,11 +1047,12 @@ func TestCommandSide_RemoveProject(t *testing.T) { } } -func newProjectChangedEvent(ctx context.Context, projectID, resourceOwner, oldName, newName string, roleAssertion, roleCheck, hasProjectCheck bool) *project.ProjectChangeEvent { +func newProjectChangedEvent(ctx context.Context, projectID, resourceOwner, oldName, newName string, roleAssertion, roleCheck, hasProjectCheck bool, privateLabelingSetting domain.PrivateLabelingSetting) *project.ProjectChangeEvent { changes := []project.ProjectChanges{ project.ChangeProjectRoleAssertion(roleAssertion), project.ChangeProjectRoleCheck(roleCheck), project.ChangeHasProjectCheck(hasProjectCheck), + project.ChangePrivateLabelingSetting(privateLabelingSetting), } if newName != "" { changes = append(changes, project.ChangeName(newName)) diff --git a/internal/command/user_grant_test.go b/internal/command/user_grant_test.go index a3ce1a7a2b..f9f4f521a1 100644 --- a/internal/command/user_grant_test.go +++ b/internal/command/user_grant_test.go @@ -141,6 +141,7 @@ func TestCommandSide_AddUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -188,6 +189,7 @@ func TestCommandSide_AddUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -230,6 +232,7 @@ func TestCommandSide_AddUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -273,6 +276,7 @@ func TestCommandSide_AddUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -332,6 +336,7 @@ func TestCommandSide_AddUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -404,6 +409,7 @@ func TestCommandSide_AddUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -718,6 +724,7 @@ func TestCommandSide_ChangeUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -777,6 +784,7 @@ func TestCommandSide_ChangeUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -831,6 +839,7 @@ func TestCommandSide_ChangeUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), ), @@ -886,6 +895,7 @@ func TestCommandSide_ChangeUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -957,6 +967,7 @@ func TestCommandSide_ChangeUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( @@ -1044,6 +1055,7 @@ func TestCommandSide_ChangeUserGrant(t *testing.T) { project.NewProjectAddedEvent(context.Background(), &project.NewAggregate("project1", "org1").Aggregate, "projectname1", true, true, true, + domain.PrivateLabelingSettingUnspecified, ), ), eventFromEventPusher( diff --git a/internal/domain/auth_request.go b/internal/domain/auth_request.go index 53bf58e552..77f56d07e7 100644 --- a/internal/domain/auth_request.go +++ b/internal/domain/auth_request.go @@ -25,32 +25,34 @@ type AuthRequest struct { MaxAuthAge *time.Duration Request Request - levelOfAssurance LevelOfAssurance - UserID string - UserName string - LoginName string - DisplayName string - AvatarKey string - PresignedAvatar string - UserOrgID string - RequestedOrgID string - RequestedOrgName string - RequestedPrimaryDomain string - SelectedIDPConfigID string - LinkingUsers []*ExternalUser - PossibleSteps []NextStep - PasswordVerified bool - MFAsVerified []MFAType - Audience []string - AuthTime time.Time - Code string - LoginPolicy *LoginPolicy - AllowedExternalIDPs []*IDPProvider - LabelPolicy *LabelPolicy - PrivacyPolicy *PrivacyPolicy - LockoutPolicy *LockoutPolicy - DefaultTranslations []*CustomText - OrgTranslations []*CustomText + levelOfAssurance LevelOfAssurance + UserID string + UserName string + LoginName string + DisplayName string + AvatarKey string + PresignedAvatar string + UserOrgID string + RequestedOrgID string + RequestedOrgName string + RequestedPrimaryDomain string + ApplicationResourceOwner string + PrivateLabelingSetting PrivateLabelingSetting + SelectedIDPConfigID string + LinkingUsers []*ExternalUser + PossibleSteps []NextStep + PasswordVerified bool + MFAsVerified []MFAType + Audience []string + AuthTime time.Time + Code string + LoginPolicy *LoginPolicy + AllowedExternalIDPs []*IDPProvider + LabelPolicy *LabelPolicy + PrivacyPolicy *PrivacyPolicy + LockoutPolicy *LockoutPolicy + DefaultTranslations []*CustomText + OrgTranslations []*CustomText } type ExternalUser struct { diff --git a/internal/domain/project.go b/internal/domain/project.go index fb8262ebbc..84fe9fafa1 100644 --- a/internal/domain/project.go +++ b/internal/domain/project.go @@ -7,11 +7,12 @@ import ( type Project struct { models.ObjectRoot - State ProjectState - Name string - ProjectRoleAssertion bool - ProjectRoleCheck bool - HasProjectCheck bool + State ProjectState + Name string + ProjectRoleAssertion bool + ProjectRoleCheck bool + HasProjectCheck bool + PrivateLabelingSetting PrivateLabelingSetting } type ProjectState int32 @@ -23,6 +24,14 @@ const ( ProjectStateRemoved ) +type PrivateLabelingSetting int32 + +const ( + PrivateLabelingSettingUnspecified PrivateLabelingSetting = iota + PrivateLabelingSettingEnforceProjectResourceOwnerPolicy + PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy +) + func (o *Project) IsValid() bool { return o.Name != "" } diff --git a/internal/management/repository/eventsourcing/handler/application.go b/internal/management/repository/eventsourcing/handler/application.go index dd45a94586..7e3ac7a519 100644 --- a/internal/management/repository/eventsourcing/handler/application.go +++ b/internal/management/repository/eventsourcing/handler/application.go @@ -86,6 +86,7 @@ func (a *Application) Reduce(event *models.Event) (err error) { app.ProjectRoleCheck = project.ProjectRoleCheck app.HasProjectCheck = project.HasProjectCheck app.ProjectRoleAssertion = project.ProjectRoleAssertion + app.PrivateLabelingSetting = project.PrivateLabelingSetting err = app.AppendEvent(event) case es_model.ApplicationChanged, diff --git a/internal/project/model/application_view.go b/internal/project/model/application_view.go index 20bfc20624..a2f554603c 100644 --- a/internal/project/model/application_view.go +++ b/internal/project/model/application_view.go @@ -8,14 +8,17 @@ import ( ) type ApplicationView struct { - ID string - ProjectID string - Name string - CreationDate time.Time - ChangeDate time.Time - State AppState - ProjectRoleAssertion bool - ProjectRoleCheck bool + ID string + ProjectID string + Name string + CreationDate time.Time + ChangeDate time.Time + ResourceOwner string + State AppState + ProjectRoleAssertion bool + ProjectRoleCheck bool + HasProjectCheck bool + PrivateLabelingSetting domain.PrivateLabelingSetting IsOIDC bool OIDCVersion OIDCVersion diff --git a/internal/project/model/project.go b/internal/project/model/project.go index 3a6e3e95f9..e999f24dcf 100644 --- a/internal/project/model/project.go +++ b/internal/project/model/project.go @@ -3,21 +3,23 @@ package model import ( "github.com/golang/protobuf/ptypes/timestamp" + "github.com/caos/zitadel/internal/domain" es_models "github.com/caos/zitadel/internal/eventstore/v1/models" ) type Project struct { es_models.ObjectRoot - State ProjectState - Name string - Members []*ProjectMember - Roles []*ProjectRole - Applications []*Application - Grants []*ProjectGrant - ProjectRoleAssertion bool - ProjectRoleCheck bool - HasProjectCheck bool + State ProjectState + Name string + Members []*ProjectMember + Roles []*ProjectRole + Applications []*Application + Grants []*ProjectGrant + ProjectRoleAssertion bool + ProjectRoleCheck bool + HasProjectCheck bool + PrivateLabelingSetting domain.PrivateLabelingSetting } type ProjectChanges struct { Changes []*ProjectChange @@ -55,15 +57,6 @@ func (p *Project) IsValid() bool { return p.Name != "" } -func (p *Project) GetMember(userID string) (int, *ProjectMember) { - for i, m := range p.Members { - if m.UserID == userID { - return i, m - } - } - return -1, nil -} - func (p *Project) ContainsRole(role *ProjectRole) bool { for _, r := range p.Roles { if r.Key == role.Key { diff --git a/internal/project/model/project_view.go b/internal/project/model/project_view.go index e1f2f52360..9834d26434 100644 --- a/internal/project/model/project_view.go +++ b/internal/project/model/project_view.go @@ -8,16 +8,17 @@ import ( ) type ProjectView struct { - ProjectID string - Name string - CreationDate time.Time - ChangeDate time.Time - State ProjectState - ResourceOwner string - ProjectRoleAssertion bool - ProjectRoleCheck bool - HasProjectCheck bool - Sequence uint64 + ProjectID string + Name string + CreationDate time.Time + ChangeDate time.Time + State ProjectState + ResourceOwner string + ProjectRoleAssertion bool + ProjectRoleCheck bool + HasProjectCheck bool + PrivateLabelingSetting domain.PrivateLabelingSetting + Sequence uint64 } type ProjectViewSearchRequest struct { diff --git a/internal/project/repository/eventsourcing/cache.go b/internal/project/repository/eventsourcing/cache.go deleted file mode 100644 index 28d1b521bc..0000000000 --- a/internal/project/repository/eventsourcing/cache.go +++ /dev/null @@ -1,35 +0,0 @@ -package eventsourcing - -import ( - "github.com/caos/logging" - "github.com/caos/zitadel/internal/cache" - "github.com/caos/zitadel/internal/cache/config" - "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" -) - -type ProjectCache struct { - projectCache cache.Cache -} - -func StartCache(conf *config.CacheConfig) (*ProjectCache, error) { - projectCache, err := conf.Config.NewCache() - logging.Log("EVENT-CsHdo").OnError(err).Panic("unable to create project cache") - - return &ProjectCache{projectCache: projectCache}, nil -} - -func (c *ProjectCache) getProject(ID string) (project *model.Project) { - project = &model.Project{ObjectRoot: models.ObjectRoot{AggregateID: ID}} - if err := c.projectCache.Get(ID, project); err != nil { - logging.Log("EVENT-tMydV").WithError(err).Debug("error in getting cache") - } - return project -} - -func (c *ProjectCache) cacheProject(project *model.Project) { - err := c.projectCache.Set(project.AggregateID, project) - if err != nil { - logging.Log("EVENT-3wKzj").WithError(err).Debug("error in setting project cache") - } -} diff --git a/internal/project/repository/eventsourcing/eventstore.go b/internal/project/repository/eventsourcing/eventstore.go deleted file mode 100644 index 4c1161b49b..0000000000 --- a/internal/project/repository/eventsourcing/eventstore.go +++ /dev/null @@ -1,46 +0,0 @@ -package eventsourcing - -// -//import ( -// "github.com/caos/zitadel/internal/cache/config" -// sd "github.com/caos/zitadel/internal/config/systemdefaults" -// "github.com/caos/zitadel/internal/crypto" -// es_int "github.com/caos/zitadel/internal/eventstore" -// "github.com/caos/zitadel/internal/id" -//) -// -//const ( -// projectOwnerRole = "PROJECT_OWNER" -// projectOwnerGlobalRole = "PROJECT_OWNER_GLOBAL" -//) -// -//type ProjectEventstore struct { -// es_int.Eventstore -// projectCache *ProjectCache -// passwordAlg crypto.HashAlgorithm -// pwGenerator crypto.Generator -// idGenerator id.Generator -// ClientKeySize int -//} -// -//type ProjectConfig struct { -// es_int.Eventstore -// Cache *config.CacheConfig -//} -// -//func StartProject(conf ProjectConfig, systemDefaults sd.SystemDefaults) (*ProjectEventstore, error) { -// projectCache, err := StartCache(conf.Cache) -// if err != nil { -// return nil, err -// } -// passwordAlg := crypto.NewBCrypt(systemDefaults.SecretGenerators.PasswordSaltCost) -// pwGenerator := crypto.NewHashGenerator(systemDefaults.SecretGenerators.ClientSecretGenerator, passwordAlg) -// return &ProjectEventstore{ -// Eventstore: conf.Eventstore, -// projectCache: projectCache, -// passwordAlg: passwordAlg, -// pwGenerator: pwGenerator, -// idGenerator: id.SonyFlakeGenerator, -// ClientKeySize: int(systemDefaults.SecretGenerators.ApplicationKeySize), -// }, nil -//} diff --git a/internal/project/repository/eventsourcing/model/api_config.go b/internal/project/repository/eventsourcing/model/api_config.go index 06aae490a3..77a64ab8b7 100644 --- a/internal/project/repository/eventsourcing/model/api_config.go +++ b/internal/project/repository/eventsourcing/model/api_config.go @@ -6,7 +6,6 @@ import ( "github.com/caos/logging" "github.com/caos/zitadel/internal/crypto" - "github.com/caos/zitadel/internal/errors" es_models "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/project/model" ) @@ -51,36 +50,6 @@ func APIConfigToModel(config *APIConfig) *model.APIConfig { return oidcConfig } -func (p *Project) appendAddAPIConfigEvent(event *es_models.Event) error { - config := new(APIConfig) - err := config.setData(event) - if err != nil { - return err - } - config.ObjectRoot.CreationDate = event.CreationDate - if i, a := GetApplication(p.Applications, config.AppID); a != nil { - p.Applications[i].Type = int32(model.AppTypeAPI) - p.Applications[i].APIConfig = config - } - return nil -} - -func (p *Project) appendChangeAPIConfigEvent(event *es_models.Event) error { - config := new(APIConfig) - err := config.setData(event) - if err != nil { - return err - } - - if i, a := GetApplication(p.Applications, config.AppID); a != nil { - if p.Applications[i].APIConfig == nil { - return errors.ThrowInvalidArgument(nil, "MODEL-ADbsd", "api config is nil") - } - return p.Applications[i].APIConfig.setData(event) - } - return nil -} - func (o *APIConfig) setData(event *es_models.Event) error { o.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, o); err != nil { diff --git a/internal/project/repository/eventsourcing/model/application.go b/internal/project/repository/eventsourcing/model/application.go index 2b72268940..7ac0d3be61 100644 --- a/internal/project/repository/eventsourcing/model/application.go +++ b/internal/project/repository/eventsourcing/model/application.go @@ -6,7 +6,6 @@ import ( "github.com/caos/logging" es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/model" ) type Application struct { @@ -33,116 +32,6 @@ func GetApplication(apps []*Application, id string) (int, *Application) { return -1, nil } -func (a *Application) Changes(changed *Application) map[string]interface{} { - changes := make(map[string]interface{}, 1) - changes["appId"] = a.AppID - if changed.Name != "" && a.Name != changed.Name { - changes["name"] = changed.Name - } - return changes -} - -func AppsToModel(apps []*Application) []*model.Application { - convertedApps := make([]*model.Application, len(apps)) - for i, a := range apps { - convertedApps[i] = AppToModel(a) - } - return convertedApps -} - -func AppsFromModel(apps []*model.Application) []*Application { - convertedApps := make([]*Application, len(apps)) - for i, a := range apps { - convertedApps[i] = AppFromModel(a) - } - return convertedApps -} - -func AppFromModel(app *model.Application) *Application { - converted := &Application{ - ObjectRoot: app.ObjectRoot, - AppID: app.AppID, - Name: app.Name, - State: int32(app.State), - Type: int32(app.Type), - } - if app.OIDCConfig != nil { - converted.OIDCConfig = OIDCConfigFromModel(app.OIDCConfig) - } - if app.APIConfig != nil { - converted.APIConfig = APIConfigFromModel(app.APIConfig) - } - return converted -} - -func AppToModel(app *Application) *model.Application { - converted := &model.Application{ - ObjectRoot: app.ObjectRoot, - AppID: app.AppID, - Name: app.Name, - State: model.AppState(app.State), - Type: model.AppType(app.Type), - } - if app.OIDCConfig != nil { - converted.OIDCConfig = OIDCConfigToModel(app.OIDCConfig) - } - if app.APIConfig != nil { - converted.APIConfig = APIConfigToModel(app.APIConfig) - } - return converted -} - -func (p *Project) appendAddAppEvent(event *es_models.Event) error { - app := new(Application) - err := app.setData(event) - if err != nil { - return err - } - app.ObjectRoot.CreationDate = event.CreationDate - p.Applications = append(p.Applications, app) - return nil -} - -func (p *Project) appendChangeAppEvent(event *es_models.Event) error { - app := new(Application) - err := app.setData(event) - if err != nil { - return err - } - if i, a := GetApplication(p.Applications, app.AppID); a != nil { - return p.Applications[i].setData(event) - } - return nil -} - -func (p *Project) appendRemoveAppEvent(event *es_models.Event) error { - app := new(Application) - err := app.setData(event) - if err != nil { - return err - } - if i, a := GetApplication(p.Applications, app.AppID); a != nil { - p.Applications[i] = p.Applications[len(p.Applications)-1] - p.Applications[len(p.Applications)-1] = nil - p.Applications = p.Applications[:len(p.Applications)-1] - } - return nil -} - -func (p *Project) appendAppStateEvent(event *es_models.Event, state model.AppState) error { - app := new(Application) - err := app.setData(event) - if err != nil { - return err - } - - if i, a := GetApplication(p.Applications, app.AppID); a != nil { - a.State = int32(state) - p.Applications[i] = a - } - return nil -} - func (a *Application) setData(event *es_models.Event) error { a.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, a); err != nil { diff --git a/internal/project/repository/eventsourcing/model/application_test.go b/internal/project/repository/eventsourcing/model/application_test.go deleted file mode 100644 index b2a1c731db..0000000000 --- a/internal/project/repository/eventsourcing/model/application_test.go +++ /dev/null @@ -1,246 +0,0 @@ -package model - -import ( - "encoding/json" - "testing" - - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/model" -) - -func TestApplicationChanges(t *testing.T) { - type args struct { - existingProject *Application - newProject *Application - } - type res struct { - changesLen int - } - tests := []struct { - name string - args args - res res - }{ - { - name: "application name changes", - args: args{ - existingProject: &Application{AppID: "AppID", Name: "Name"}, - newProject: &Application{AppID: "AppID", Name: "NameChanged"}, - }, - res: res{ - changesLen: 2, - }, - }, - { - name: "no changes", - args: args{ - existingProject: &Application{AppID: "AppID", Name: "Name"}, - newProject: &Application{AppID: "AppID", Name: "Name"}, - }, - res: res{ - changesLen: 1, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - changes := tt.args.existingProject.Changes(tt.args.newProject) - if len(changes) != tt.res.changesLen { - t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes)) - } - }) - } -} - -func TestAppendAddAppEvent(t *testing.T) { - type args struct { - project *Project - app *Application - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append add application event", - args: args{ - project: &Project{}, - app: &Application{Name: "Application"}, - event: &es_models.Event{}, - }, - result: &Project{ - Applications: []*Application{ - {Name: "Application"}, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.app != nil { - data, _ := json.Marshal(tt.args.app) - tt.args.event.Data = data - } - tt.args.project.appendAddAppEvent(tt.args.event) - if len(tt.args.project.Applications) != 1 { - t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications)) - } - if tt.args.project.Applications[0] == tt.result.Applications[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0]) - } - }) - } -} - -func TestAppendChangeAppEvent(t *testing.T) { - type args struct { - project *Project - app *Application - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append change application event", - args: args{ - project: &Project{ - Applications: []*Application{ - {Name: "Application"}, - }, - }, - app: &Application{Name: "Application Change"}, - event: &es_models.Event{}, - }, - result: &Project{ - Applications: []*Application{ - {Name: "Application Change"}, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.app != nil { - data, _ := json.Marshal(tt.args.app) - tt.args.event.Data = data - } - tt.args.project.appendChangeAppEvent(tt.args.event) - if len(tt.args.project.Applications) != 1 { - t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications)) - } - if tt.args.project.Applications[0] == tt.result.Applications[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0]) - } - }) - } -} - -func TestAppendRemoveAppEvent(t *testing.T) { - type args struct { - project *Project - app *Application - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append remove application event", - args: args{ - project: &Project{ - Applications: []*Application{ - {AppID: "AppID", Name: "Application"}, - }, - }, - app: &Application{AppID: "AppID", Name: "Application"}, - event: &es_models.Event{}, - }, - result: &Project{Applications: []*Application{}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.app != nil { - data, _ := json.Marshal(tt.args.app) - tt.args.event.Data = data - } - tt.args.project.appendRemoveAppEvent(tt.args.event) - if len(tt.args.project.Applications) != 0 { - t.Errorf("got wrong result should have no apps actual: %v ", len(tt.args.project.Applications)) - } - }) - } -} - -func TestAppendAppStateEvent(t *testing.T) { - type args struct { - project *Project - app *ApplicationID - event *es_models.Event - state model.AppState - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append deactivate application event", - args: args{ - project: &Project{ - Applications: []*Application{ - {AppID: "AppID", Name: "Application", State: int32(model.AppStateActive)}, - }, - }, - app: &ApplicationID{AppID: "AppID"}, - event: &es_models.Event{}, - state: model.AppStateInactive, - }, - result: &Project{ - Applications: []*Application{ - {AppID: "AppID", Name: "Application", State: int32(model.AppStateInactive)}, - }, - }, - }, - { - name: "append reactivate application event", - args: args{ - project: &Project{ - Applications: []*Application{ - {AppID: "AppID", Name: "Application", State: int32(model.AppStateInactive)}, - }, - }, - app: &ApplicationID{AppID: "AppID"}, - event: &es_models.Event{}, - state: model.AppStateActive, - }, - result: &Project{ - Applications: []*Application{ - {AppID: "AppID", Name: "Application", State: int32(model.AppStateActive)}, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.app != nil { - data, _ := json.Marshal(tt.args.app) - tt.args.event.Data = data - } - tt.args.project.appendAppStateEvent(tt.args.event, tt.args.state) - if len(tt.args.project.Applications) != 1 { - t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications)) - } - if tt.args.project.Applications[0] == tt.result.Applications[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0]) - } - }) - } -} diff --git a/internal/project/repository/eventsourcing/model/oidc_config.go b/internal/project/repository/eventsourcing/model/oidc_config.go index f7cc7c3f29..27831edc8b 100644 --- a/internal/project/repository/eventsourcing/model/oidc_config.go +++ b/internal/project/repository/eventsourcing/model/oidc_config.go @@ -2,7 +2,6 @@ package model import ( "encoding/json" - "reflect" "time" "github.com/caos/logging" @@ -35,187 +34,6 @@ type OIDCConfig struct { ClientKeys []*ClientKey `json:"-"` } -func (c *OIDCConfig) Changes(changed *OIDCConfig) map[string]interface{} { - changes := make(map[string]interface{}, 1) - changes["appId"] = c.AppID - if !reflect.DeepEqual(c.RedirectUris, changed.RedirectUris) { - changes["redirectUris"] = changed.RedirectUris - } - if !reflect.DeepEqual(c.ResponseTypes, changed.ResponseTypes) { - changes["responseTypes"] = changed.ResponseTypes - } - if !reflect.DeepEqual(c.GrantTypes, changed.GrantTypes) { - changes["grantTypes"] = changed.GrantTypes - } - if c.ApplicationType != changed.ApplicationType { - changes["applicationType"] = changed.ApplicationType - } - if c.AuthMethodType != changed.AuthMethodType { - changes["authMethodType"] = changed.AuthMethodType - } - if c.Version != changed.Version { - changes["oidcVersion"] = changed.Version - } - if !reflect.DeepEqual(c.PostLogoutRedirectUris, changed.PostLogoutRedirectUris) { - changes["postLogoutRedirectUris"] = changed.PostLogoutRedirectUris - } - if c.DevMode != changed.DevMode { - changes["devMode"] = changed.DevMode - } - if c.AccessTokenType != changed.AccessTokenType { - changes["accessTokenType"] = changed.AccessTokenType - } - if c.AccessTokenRoleAssertion != changed.AccessTokenRoleAssertion { - changes["accessTokenRoleAssertion"] = changed.AccessTokenRoleAssertion - } - if c.IDTokenRoleAssertion != changed.IDTokenRoleAssertion { - changes["idTokenRoleAssertion"] = changed.IDTokenRoleAssertion - } - if c.IDTokenUserinfoAssertion != changed.IDTokenUserinfoAssertion { - changes["idTokenUserinfoAssertion"] = changed.IDTokenUserinfoAssertion - } - if c.ClockSkew != changed.ClockSkew { - changes["clockSkew"] = changed.ClockSkew - } - return changes -} - -func OIDCConfigFromModel(config *model.OIDCConfig) *OIDCConfig { - responseTypes := make([]int32, len(config.ResponseTypes)) - for i, rt := range config.ResponseTypes { - responseTypes[i] = int32(rt) - } - grantTypes := make([]int32, len(config.GrantTypes)) - for i, rt := range config.GrantTypes { - grantTypes[i] = int32(rt) - } - return &OIDCConfig{ - ObjectRoot: config.ObjectRoot, - AppID: config.AppID, - Version: int32(config.OIDCVersion), - ClientID: config.ClientID, - ClientSecret: config.ClientSecret, - RedirectUris: config.RedirectUris, - ResponseTypes: responseTypes, - GrantTypes: grantTypes, - ApplicationType: int32(config.ApplicationType), - AuthMethodType: int32(config.AuthMethodType), - PostLogoutRedirectUris: config.PostLogoutRedirectUris, - DevMode: config.DevMode, - AccessTokenType: int32(config.AccessTokenType), - AccessTokenRoleAssertion: config.AccessTokenRoleAssertion, - IDTokenRoleAssertion: config.IDTokenRoleAssertion, - IDTokenUserinfoAssertion: config.IDTokenUserinfoAssertion, - ClockSkew: config.ClockSkew, - } -} - -func OIDCConfigToModel(config *OIDCConfig) *model.OIDCConfig { - responseTypes := make([]model.OIDCResponseType, len(config.ResponseTypes)) - for i, rt := range config.ResponseTypes { - responseTypes[i] = model.OIDCResponseType(rt) - } - grantTypes := make([]model.OIDCGrantType, len(config.GrantTypes)) - for i, rt := range config.GrantTypes { - grantTypes[i] = model.OIDCGrantType(rt) - } - oidcConfig := &model.OIDCConfig{ - ObjectRoot: config.ObjectRoot, - AppID: config.AppID, - OIDCVersion: model.OIDCVersion(config.Version), - ClientID: config.ClientID, - ClientSecret: config.ClientSecret, - RedirectUris: config.RedirectUris, - ResponseTypes: responseTypes, - GrantTypes: grantTypes, - ApplicationType: model.OIDCApplicationType(config.ApplicationType), - AuthMethodType: model.OIDCAuthMethodType(config.AuthMethodType), - PostLogoutRedirectUris: config.PostLogoutRedirectUris, - DevMode: config.DevMode, - AccessTokenType: model.OIDCTokenType(config.AccessTokenType), - AccessTokenRoleAssertion: config.AccessTokenRoleAssertion, - IDTokenRoleAssertion: config.IDTokenRoleAssertion, - IDTokenUserinfoAssertion: config.IDTokenUserinfoAssertion, - ClockSkew: config.ClockSkew, - ClientKeys: ClientKeysToModel(config.ClientKeys), - } - oidcConfig.FillCompliance() - return oidcConfig -} - -func (p *Project) appendAddOIDCConfigEvent(event *es_models.Event) error { - config := new(OIDCConfig) - err := config.setData(event) - if err != nil { - return err - } - config.ObjectRoot.CreationDate = event.CreationDate - if i, a := GetApplication(p.Applications, config.AppID); a != nil { - p.Applications[i].Type = int32(model.AppTypeOIDC) - p.Applications[i].OIDCConfig = config - } - return nil -} - -func (p *Project) appendChangeOIDCConfigEvent(event *es_models.Event) error { - config := new(OIDCConfig) - err := config.setData(event) - if err != nil { - return err - } - - if i, a := GetApplication(p.Applications, config.AppID); a != nil { - if p.Applications[i].OIDCConfig == nil { - return errors.ThrowInvalidArgument(nil, "MODEL-aBR5G", "oidc config is nil") - } - return p.Applications[i].OIDCConfig.setData(event) - } - return nil -} - -func (p *Project) appendAddClientKeyEvent(event *es_models.Event) error { - key := new(ClientKey) - err := key.SetData(event) - if err != nil { - return err - } - - if i, a := GetApplication(p.Applications, key.ApplicationID); a != nil { - if a.OIDCConfig != nil { - p.Applications[i].OIDCConfig.ClientKeys = append(p.Applications[i].OIDCConfig.ClientKeys, key) - } - if a.APIConfig != nil { - p.Applications[i].APIConfig.ClientKeys = append(p.Applications[i].APIConfig.ClientKeys, key) - } - } - return nil -} - -func (p *Project) appendRemoveClientKeyEvent(event *es_models.Event) error { - key := new(ClientKey) - err := key.SetData(event) - if err != nil { - return err - } - if i, a := GetApplication(p.Applications, key.ApplicationID); a != nil { - if a.OIDCConfig != nil { - if j, k := GetClientKey(p.Applications[i].OIDCConfig.ClientKeys, key.KeyID); k != nil { - p.Applications[i].OIDCConfig.ClientKeys[j] = p.Applications[i].OIDCConfig.ClientKeys[len(p.Applications[i].OIDCConfig.ClientKeys)-1] - p.Applications[i].OIDCConfig.ClientKeys[len(p.Applications[i].OIDCConfig.ClientKeys)-1] = nil - p.Applications[i].OIDCConfig.ClientKeys = p.Applications[i].OIDCConfig.ClientKeys[:len(p.Applications[i].OIDCConfig.ClientKeys)-1] - } - } - if a.APIConfig != nil { - if j, k := GetClientKey(p.Applications[i].APIConfig.ClientKeys, key.KeyID); k != nil { - p.Applications[i].APIConfig.ClientKeys[j] = p.Applications[i].APIConfig.ClientKeys[len(p.Applications[i].APIConfig.ClientKeys)-1] - p.Applications[i].APIConfig.ClientKeys[len(p.Applications[i].APIConfig.ClientKeys)-1] = nil - p.Applications[i].APIConfig.ClientKeys = p.Applications[i].APIConfig.ClientKeys[:len(p.Applications[i].APIConfig.ClientKeys)-1] - } - } - } - return nil -} - func (o *OIDCConfig) setData(event *es_models.Event) error { o.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, o); err != nil { @@ -225,15 +43,6 @@ func (o *OIDCConfig) setData(event *es_models.Event) error { return nil } -func GetClientKey(keys []*ClientKey, id string) (int, *ClientKey) { - for i, k := range keys { - if k.KeyID == id { - return i, k - } - } - return -1, nil -} - type ClientKey struct { es_models.ObjectRoot `json:"-"` ApplicationID string `json:"applicationId,omitempty"` @@ -278,17 +87,6 @@ func (key *ClientKey) AppendEvent(event *es_models.Event) (err error) { return err } -func ClientKeyFromModel(key *model.ClientKey) *ClientKey { - return &ClientKey{ - ObjectRoot: key.ObjectRoot, - ExpirationDate: key.ExpirationDate, - ApplicationID: key.ApplicationID, - ClientID: key.ClientID, - KeyID: key.KeyID, - Type: int32(key.Type), - } -} - func ClientKeysToModel(keys []*ClientKey) []*model.ClientKey { clientKeys := make([]*model.ClientKey, len(keys)) for i, key := range keys { diff --git a/internal/project/repository/eventsourcing/model/oidc_config_test.go b/internal/project/repository/eventsourcing/model/oidc_config_test.go deleted file mode 100644 index b07eaea44d..0000000000 --- a/internal/project/repository/eventsourcing/model/oidc_config_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package model - -import ( - "encoding/json" - "testing" - - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" -) - -func TestOIDCConfigChanges(t *testing.T) { - type args struct { - existingConfig *OIDCConfig - newConfig *OIDCConfig - } - type res struct { - changesLen int - } - tests := []struct { - name string - args args - res res - }{ - { - name: "all possible values change", - args: args{ - existingConfig: &OIDCConfig{ - AppID: "AppID", - RedirectUris: []string{"RedirectUris"}, - ResponseTypes: []int32{1}, - GrantTypes: []int32{1}, - ApplicationType: 1, - AuthMethodType: 1, - PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"}, - }, - newConfig: &OIDCConfig{ - AppID: "AppID", - RedirectUris: []string{"RedirectUrisChanged"}, - ResponseTypes: []int32{2}, - GrantTypes: []int32{2}, - ApplicationType: 2, - AuthMethodType: 2, - PostLogoutRedirectUris: []string{"PostLogoutRedirectUrisChanged"}, - }, - }, - res: res{ - changesLen: 7, - }, - }, - { - name: "no changes", - args: args{ - existingConfig: &OIDCConfig{ - AppID: "AppID", - RedirectUris: []string{"RedirectUris"}, - ResponseTypes: []int32{1}, - GrantTypes: []int32{1}, - ApplicationType: 1, - AuthMethodType: 1, - PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"}, - }, - newConfig: &OIDCConfig{ - AppID: "AppID", - RedirectUris: []string{"RedirectUris"}, - ResponseTypes: []int32{1}, - GrantTypes: []int32{1}, - ApplicationType: 1, - AuthMethodType: 1, - PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"}, - }, - }, - res: res{ - changesLen: 1, - }, - }, - { - name: "change not changeable attributes", - args: args{ - existingConfig: &OIDCConfig{ - AppID: "AppID", - ClientID: "ClientID", - }, - newConfig: &OIDCConfig{ - AppID: "AppIDChange", - ClientID: "ClientIDChange", - }, - }, - res: res{ - changesLen: 1, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - changes := tt.args.existingConfig.Changes(tt.args.newConfig) - if len(changes) != tt.res.changesLen { - t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes)) - } - }) - } -} - -func TestAppendAddOIDCConfigEvent(t *testing.T) { - type args struct { - project *Project - config *OIDCConfig - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append add application event", - args: args{ - project: &Project{ - Applications: []*Application{ - {AppID: "AppID"}, - }, - }, - config: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"}, - event: &es_models.Event{}, - }, - result: &Project{ - Applications: []*Application{ - {AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"}}, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.config != nil { - data, _ := json.Marshal(tt.args.config) - tt.args.event.Data = data - } - tt.args.project.appendAddOIDCConfigEvent(tt.args.event) - if len(tt.args.project.Applications) != 1 { - t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications)) - } - if tt.args.project.Applications[0].OIDCConfig == nil { - t.Errorf("got wrong result should have oidc config actual: %v ", tt.args.project.Applications[0].OIDCConfig) - } - if tt.args.project.Applications[0] == tt.result.Applications[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0]) - } - }) - } -} - -func TestAppendChangeOIDCConfigEvent(t *testing.T) { - type args struct { - project *Project - config *OIDCConfig - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append change application event", - args: args{ - project: &Project{ - Applications: []*Application{ - {AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"}}, - }, - }, - config: &OIDCConfig{AppID: "AppID", ClientID: "ClientID Changed"}, - event: &es_models.Event{}, - }, - result: &Project{ - Applications: []*Application{ - {AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID Changed"}}, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.config != nil { - data, _ := json.Marshal(tt.args.config) - tt.args.event.Data = data - } - tt.args.project.appendChangeOIDCConfigEvent(tt.args.event) - if len(tt.args.project.Applications) != 1 { - t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications)) - } - if tt.args.project.Applications[0].OIDCConfig == nil { - t.Errorf("got wrong result should have oidc config actual: %v ", tt.args.project.Applications[0].OIDCConfig) - } - if tt.args.project.Applications[0] == tt.result.Applications[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0]) - } - }) - } -} diff --git a/internal/project/repository/eventsourcing/model/project.go b/internal/project/repository/eventsourcing/model/project.go index 80f8e611fd..37797b3288 100644 --- a/internal/project/repository/eventsourcing/model/project.go +++ b/internal/project/repository/eventsourcing/model/project.go @@ -15,32 +15,20 @@ const ( type Project struct { es_models.ObjectRoot - Name string `json:"name,omitempty"` - ProjectRoleAssertion bool `json:"projectRoleAssertion,omitempty"` - ProjectRoleCheck bool `json:"projectRoleCheck,omitempty"` - HasProjectCheck bool `json:"hasProjectCheck,omitempty"` - State int32 `json:"-"` - Members []*ProjectMember `json:"-"` - Roles []*ProjectRole `json:"-"` - Applications []*Application `json:"-"` - Grants []*ProjectGrant `json:"-"` + Name string `json:"name,omitempty"` + ProjectRoleAssertion bool `json:"projectRoleAssertion,omitempty"` + ProjectRoleCheck bool `json:"projectRoleCheck,omitempty"` + HasProjectCheck bool `json:"hasProjectCheck,omitempty"` + State int32 `json:"-"` } func ProjectToModel(project *Project) *model.Project { - members := ProjectMembersToModel(project.Members) - roles := ProjectRolesToModel(project.Roles) - apps := AppsToModel(project.Applications) - grants := GrantsToModel(project.Grants) return &model.Project{ ObjectRoot: project.ObjectRoot, Name: project.Name, ProjectRoleAssertion: project.ProjectRoleAssertion, ProjectRoleCheck: project.ProjectRoleCheck, State: model.ProjectState(project.State), - Members: members, - Roles: roles, - Applications: apps, - Grants: grants, } } @@ -73,60 +61,6 @@ func (p *Project) AppendEvent(event *es_models.Event) error { return p.appendReactivatedEvent() case ProjectRemoved: return p.appendRemovedEvent() - case ProjectMemberAdded: - return p.appendAddMemberEvent(event) - case ProjectMemberChanged: - return p.appendChangeMemberEvent(event) - case ProjectMemberRemoved: - return p.appendRemoveMemberEvent(event) - case ProjectMemberCascadeRemoved: - return p.appendRemoveMemberEvent(event) - case ProjectRoleAdded: - return p.appendAddRoleEvent(event) - case ProjectRoleChanged: - return p.appendChangeRoleEvent(event) - case ProjectRoleRemoved: - return p.appendRemoveRoleEvent(event) - case ApplicationAdded: - return p.appendAddAppEvent(event) - case ApplicationChanged: - return p.appendChangeAppEvent(event) - case ApplicationRemoved: - return p.appendRemoveAppEvent(event) - case ApplicationDeactivated: - return p.appendAppStateEvent(event, model.AppStateInactive) - case ApplicationReactivated: - return p.appendAppStateEvent(event, model.AppStateActive) - case OIDCConfigAdded: - return p.appendAddOIDCConfigEvent(event) - case OIDCConfigChanged, OIDCConfigSecretChanged: - return p.appendChangeOIDCConfigEvent(event) - case APIConfigAdded: - return p.appendAddAPIConfigEvent(event) - case APIConfigChanged, APIConfigSecretChanged: - return p.appendChangeAPIConfigEvent(event) - case ClientKeyAdded: - return p.appendAddClientKeyEvent(event) - case ClientKeyRemoved: - return p.appendRemoveClientKeyEvent(event) - case ProjectGrantAdded: - return p.appendAddGrantEvent(event) - case ProjectGrantChanged, ProjectGrantCascadeChanged: - return p.appendChangeGrantEvent(event) - case ProjectGrantDeactivated: - return p.appendGrantStateEvent(event, model.ProjectGrantStateInactive) - case ProjectGrantReactivated: - return p.appendGrantStateEvent(event, model.ProjectGrantStateActive) - case ProjectGrantRemoved: - return p.appendRemoveGrantEvent(event) - case ProjectGrantMemberAdded: - return p.appendAddGrantMemberEvent(event) - case ProjectGrantMemberChanged: - return p.appendChangeGrantMemberEvent(event) - case ProjectGrantMemberRemoved: - return p.appendRemoveGrantMemberEvent(event) - case ProjectGrantMemberCascadeRemoved: - return p.appendRemoveGrantMemberEvent(event) } return nil } diff --git a/internal/project/repository/eventsourcing/model/project_grant.go b/internal/project/repository/eventsourcing/model/project_grant.go index ce95190e31..8b753dfa94 100644 --- a/internal/project/repository/eventsourcing/model/project_grant.go +++ b/internal/project/repository/eventsourcing/model/project_grant.go @@ -2,10 +2,11 @@ package model import ( "encoding/json" - "github.com/caos/logging" - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/model" "reflect" + + "github.com/caos/logging" + + es_models "github.com/caos/zitadel/internal/eventstore/v1/models" ) type ProjectGrant struct { @@ -31,15 +32,6 @@ func GetProjectGrant(grants []*ProjectGrant, id string) (int, *ProjectGrant) { return -1, nil } -func GetProjectGrantByOrgID(grants []*ProjectGrant, resourceOwner string) (int, *ProjectGrant) { - for i, g := range grants { - if g.GrantedOrgID == resourceOwner { - return i, g - } - } - return -1, nil -} - func (g *ProjectGrant) Changes(changed *ProjectGrant) map[string]interface{} { changes := make(map[string]interface{}, 1) changes["grantId"] = g.GrantID @@ -49,97 +41,6 @@ func (g *ProjectGrant) Changes(changed *ProjectGrant) map[string]interface{} { return changes } -func GrantsToModel(grants []*ProjectGrant) []*model.ProjectGrant { - convertedGrants := make([]*model.ProjectGrant, len(grants)) - for i, g := range grants { - convertedGrants[i] = GrantToModel(g) - } - return convertedGrants -} - -func GrantsFromModel(grants []*model.ProjectGrant) []*ProjectGrant { - convertedGrants := make([]*ProjectGrant, len(grants)) - for i, g := range grants { - convertedGrants[i] = GrantFromModel(g) - } - return convertedGrants -} - -func GrantFromModel(grant *model.ProjectGrant) *ProjectGrant { - members := GrantMembersFromModel(grant.Members) - return &ProjectGrant{ - ObjectRoot: grant.ObjectRoot, - GrantID: grant.GrantID, - GrantedOrgID: grant.GrantedOrgID, - State: int32(grant.State), - RoleKeys: grant.RoleKeys, - Members: members, - } -} - -func GrantToModel(grant *ProjectGrant) *model.ProjectGrant { - members := GrantMembersToModel(grant.Members) - return &model.ProjectGrant{ - ObjectRoot: grant.ObjectRoot, - GrantID: grant.GrantID, - GrantedOrgID: grant.GrantedOrgID, - State: model.ProjectGrantState(grant.State), - RoleKeys: grant.RoleKeys, - Members: members, - } -} - -func (p *Project) appendAddGrantEvent(event *es_models.Event) error { - grant := new(ProjectGrant) - err := grant.getData(event) - if err != nil { - return err - } - grant.ObjectRoot.CreationDate = event.CreationDate - p.Grants = append(p.Grants, grant) - return nil -} - -func (p *Project) appendChangeGrantEvent(event *es_models.Event) error { - grant := new(ProjectGrant) - err := grant.getData(event) - if err != nil { - return err - } - if i, g := GetProjectGrant(p.Grants, grant.GrantID); g != nil { - p.Grants[i].getData(event) - } - return nil -} - -func (p *Project) appendGrantStateEvent(event *es_models.Event, state model.ProjectGrantState) error { - grant := new(ProjectGrant) - err := grant.getData(event) - if err != nil { - return err - } - if i, g := GetProjectGrant(p.Grants, grant.GrantID); g != nil { - g.State = int32(state) - p.Grants[i] = g - } - return nil -} - -func (p *Project) appendRemoveGrantEvent(event *es_models.Event) error { - grant := new(ProjectGrant) - err := grant.getData(event) - if err != nil { - return err - } - - if i, g := GetProjectGrant(p.Grants, grant.GrantID); g != nil { - p.Grants[i] = p.Grants[len(p.Grants)-1] - p.Grants[len(p.Grants)-1] = nil - p.Grants = p.Grants[:len(p.Grants)-1] - } - return nil -} - func (g *ProjectGrant) getData(event *es_models.Event) error { g.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, g); err != nil { diff --git a/internal/project/repository/eventsourcing/model/project_grant_member.go b/internal/project/repository/eventsourcing/model/project_grant_member.go index df0c3829a3..1fb4a2c8b7 100644 --- a/internal/project/repository/eventsourcing/model/project_grant_member.go +++ b/internal/project/repository/eventsourcing/model/project_grant_member.go @@ -2,9 +2,10 @@ package model import ( "encoding/json" + "github.com/caos/logging" + es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/model" ) type ProjectGrantMember struct { @@ -14,94 +15,6 @@ type ProjectGrantMember struct { Roles []string `json:"roles,omitempty"` } -func GetProjectGrantMember(members []*ProjectGrantMember, id string) (int, *ProjectGrantMember) { - for i, m := range members { - if m.UserID == id { - return i, m - } - } - return -1, nil -} - -func GrantMembersToModel(members []*ProjectGrantMember) []*model.ProjectGrantMember { - convertedMembers := make([]*model.ProjectGrantMember, len(members)) - for i, g := range members { - convertedMembers[i] = GrantMemberToModel(g) - } - return convertedMembers -} - -func GrantMembersFromModel(members []*model.ProjectGrantMember) []*ProjectGrantMember { - convertedMembers := make([]*ProjectGrantMember, len(members)) - for i, g := range members { - convertedMembers[i] = GrantMemberFromModel(g) - } - return convertedMembers -} - -func GrantMemberFromModel(member *model.ProjectGrantMember) *ProjectGrantMember { - return &ProjectGrantMember{ - ObjectRoot: member.ObjectRoot, - GrantID: member.GrantID, - UserID: member.UserID, - Roles: member.Roles, - } -} - -func GrantMemberToModel(member *ProjectGrantMember) *model.ProjectGrantMember { - return &model.ProjectGrantMember{ - ObjectRoot: member.ObjectRoot, - GrantID: member.GrantID, - UserID: member.UserID, - Roles: member.Roles, - } -} - -func (p *Project) appendAddGrantMemberEvent(event *es_models.Event) error { - member := &ProjectGrantMember{} - err := member.SetData(event) - if err != nil { - return err - } - member.ObjectRoot.CreationDate = event.CreationDate - - if _, g := GetProjectGrant(p.Grants, member.GrantID); g != nil { - g.Members = append(g.Members, member) - } - return nil -} - -func (p *Project) appendChangeGrantMemberEvent(event *es_models.Event) error { - member := &ProjectGrantMember{} - err := member.SetData(event) - if err != nil { - return err - } - if _, g := GetProjectGrant(p.Grants, member.GrantID); g != nil { - if i, m := GetProjectGrantMember(g.Members, member.UserID); m != nil { - g.Members[i].SetData(event) - } - } - return nil -} - -func (p *Project) appendRemoveGrantMemberEvent(event *es_models.Event) error { - member := &ProjectGrantMember{} - err := member.SetData(event) - if err != nil { - return err - } - - if _, g := GetProjectGrant(p.Grants, member.GrantID); g != nil { - if i, member := GetProjectGrantMember(g.Members, member.UserID); member != nil { - g.Members[i] = g.Members[len(g.Members)-1] - g.Members[len(g.Members)-1] = nil - g.Members = g.Members[:len(g.Members)-1] - } - } - return nil -} - func (m *ProjectGrantMember) SetData(event *es_models.Event) error { m.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, m); err != nil { diff --git a/internal/project/repository/eventsourcing/model/project_grant_member_test.go b/internal/project/repository/eventsourcing/model/project_grant_member_test.go deleted file mode 100644 index 6794f1b514..0000000000 --- a/internal/project/repository/eventsourcing/model/project_grant_member_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package model - -import ( - "encoding/json" - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "testing" -) - -func TestAppendAddGrantMemberEvent(t *testing.T) { - type args struct { - project *Project - member *ProjectGrantMember - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append add grant member", - args: args{ - project: &Project{Grants: []*ProjectGrant{ - &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}}, - member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}, - event: &es_models.Event{}, - }, - result: &Project{ - Grants: []*ProjectGrant{ - &ProjectGrant{ - GrantID: "ProjectGrantID", - GrantedOrgID: "OrgID", - RoleKeys: []string{"Key"}, - Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.member != nil { - data, _ := json.Marshal(tt.args.member) - tt.args.event.Data = data - } - tt.args.project.appendAddGrantMemberEvent(tt.args.event) - if len(tt.args.project.Grants[0].Members) != 1 { - t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants[0].Members)) - } - if tt.args.project.Grants[0].Members[0] == tt.result.Grants[0].Members[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0].Members[0], tt.args.project.Grants[0].Members[0]) - } - }) - } -} - -func TestAppendChangeGrantMemberEvent(t *testing.T) { - type args struct { - project *Project - member *ProjectGrantMember - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append change grant member", - args: args{ - project: &Project{ - Grants: []*ProjectGrant{ - &ProjectGrant{ - GrantID: "ProjectGrantID", - GrantedOrgID: "OrgID", - RoleKeys: []string{"Key"}, - Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}}, - }, - member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}}, - event: &es_models.Event{}, - }, - result: &Project{ - Grants: []*ProjectGrant{ - &ProjectGrant{ - GrantID: "ProjectGrantID", - GrantedOrgID: "OrgID", - RoleKeys: []string{"Key"}, - Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}}}}}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.member != nil { - data, _ := json.Marshal(tt.args.member) - tt.args.event.Data = data - } - tt.args.project.appendChangeGrantMemberEvent(tt.args.event) - if len(tt.args.project.Grants[0].Members) != 1 { - t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants[0].Members)) - } - if tt.args.project.Grants[0].Members[0] == tt.result.Grants[0].Members[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0].Members[0], tt.args.project.Grants[0].Members[0]) - } - }) - } -} - -func TestAppendRemoveGrantMemberEvent(t *testing.T) { - type args struct { - project *Project - member *ProjectGrantMember - event *es_models.Event - } - tests := []struct { - name string - args args - }{ - { - name: "append remove grant member", - args: args{ - project: &Project{ - Grants: []*ProjectGrant{ - &ProjectGrant{ - GrantID: "ProjectGrantID", - GrantedOrgID: "OrgID", - RoleKeys: []string{"Key"}, - Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}}, - }, - member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}}, - event: &es_models.Event{}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.member != nil { - data, _ := json.Marshal(tt.args.member) - tt.args.event.Data = data - } - tt.args.project.appendRemoveGrantMemberEvent(tt.args.event) - if len(tt.args.project.Grants[0].Members) != 0 { - t.Errorf("got wrong result should have no members actual: %v ", len(tt.args.project.Grants[0].Members)) - } - }) - } -} diff --git a/internal/project/repository/eventsourcing/model/project_grant_test.go b/internal/project/repository/eventsourcing/model/project_grant_test.go deleted file mode 100644 index 44b76c49b8..0000000000 --- a/internal/project/repository/eventsourcing/model/project_grant_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package model - -import ( - "encoding/json" - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/model" - "testing" -) - -func TestAppendAddGrantEvent(t *testing.T) { - type args struct { - project *Project - role *ProjectGrant - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append add grant event", - args: args{ - project: &Project{}, - role: &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}, - event: &es_models.Event{}, - }, - result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.role != nil { - data, _ := json.Marshal(tt.args.role) - tt.args.event.Data = data - } - tt.args.project.appendAddGrantEvent(tt.args.event) - if len(tt.args.project.Grants) != 1 { - t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants)) - } - if tt.args.project.Grants[0] == tt.result.Grants[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0], tt.args.project.Grants[0]) - } - }) - } -} - -func TestAppendChangeGrantEvent(t *testing.T) { - type args struct { - project *Project - grant *ProjectGrant - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append change grant event", - args: args{ - project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}}, - grant: &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}}, - event: &es_models.Event{}, - }, - result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}}}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.grant != nil { - data, _ := json.Marshal(tt.args.grant) - tt.args.event.Data = data - } - tt.args.project.appendChangeGrantEvent(tt.args.event) - if len(tt.args.project.Grants) != 1 { - t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants)) - } - if tt.args.project.Grants[0] == tt.result.Grants[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0], tt.args.project.Grants[0]) - } - }) - } -} - -func TestAppendRemoveGrantEvent(t *testing.T) { - type args struct { - project *Project - grant *ProjectGrant - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append remove role event", - args: args{ - project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}}, - grant: &ProjectGrant{GrantID: "ProjectGrantID"}, - event: &es_models.Event{}, - }, - result: &Project{Grants: []*ProjectGrant{}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.grant != nil { - data, _ := json.Marshal(tt.args.grant) - tt.args.event.Data = data - } - tt.args.project.appendRemoveGrantEvent(tt.args.event) - if len(tt.args.project.Grants) != 0 { - t.Errorf("got wrong result should have no grant actual: %v ", len(tt.args.project.Grants)) - } - }) - } -} - -func TestAppendGrantStateEvent(t *testing.T) { - type args struct { - project *Project - grant *ProjectGrantID - event *es_models.Event - state model.ProjectGrantState - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append deactivate grant event", - args: args{ - project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}}, - grant: &ProjectGrantID{GrantID: "ProjectGrantID"}, - event: &es_models.Event{}, - state: model.ProjectGrantStateInactive, - }, - result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateInactive)}}}, - }, - { - name: "append reactivate grant event", - args: args{ - project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}}, - grant: &ProjectGrantID{GrantID: "ProjectGrantID"}, - event: &es_models.Event{}, - state: model.ProjectGrantStateActive, - }, - result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateActive)}}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.grant != nil { - data, _ := json.Marshal(tt.args.grant) - tt.args.event.Data = data - } - tt.args.project.appendGrantStateEvent(tt.args.event, tt.args.state) - if len(tt.args.project.Grants) != 1 { - t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants)) - } - if tt.args.project.Grants[0] == tt.result.Grants[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0], tt.args.project.Grants[0]) - } - }) - } -} diff --git a/internal/project/repository/eventsourcing/model/project_member.go b/internal/project/repository/eventsourcing/model/project_member.go index 1473653d5a..2c9682269b 100644 --- a/internal/project/repository/eventsourcing/model/project_member.go +++ b/internal/project/repository/eventsourcing/model/project_member.go @@ -2,9 +2,10 @@ package model import ( "encoding/json" + "github.com/caos/logging" + es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/project/model" ) type ProjectMember struct { @@ -13,84 +14,6 @@ type ProjectMember struct { Roles []string `json:"roles,omitempty"` } -func GetProjectMember(members []*ProjectMember, id string) (int, *ProjectMember) { - for i, m := range members { - if m.UserID == id { - return i, m - } - } - return -1, nil -} - -func ProjectMembersToModel(members []*ProjectMember) []*model.ProjectMember { - convertedMembers := make([]*model.ProjectMember, len(members)) - for i, m := range members { - convertedMembers[i] = ProjectMemberToModel(m) - } - return convertedMembers -} - -func ProjectMembersFromModel(members []*model.ProjectMember) []*ProjectMember { - convertedMembers := make([]*ProjectMember, len(members)) - for i, m := range members { - convertedMembers[i] = ProjectMemberFromModel(m) - } - return convertedMembers -} - -func ProjectMemberFromModel(member *model.ProjectMember) *ProjectMember { - return &ProjectMember{ - ObjectRoot: member.ObjectRoot, - UserID: member.UserID, - Roles: member.Roles, - } -} - -func ProjectMemberToModel(member *ProjectMember) *model.ProjectMember { - return &model.ProjectMember{ - ObjectRoot: member.ObjectRoot, - UserID: member.UserID, - Roles: member.Roles, - } -} - -func (p *Project) appendAddMemberEvent(event *es_models.Event) error { - member := &ProjectMember{} - err := member.SetData(event) - if err != nil { - return err - } - member.ObjectRoot.CreationDate = event.CreationDate - p.Members = append(p.Members, member) - return nil -} - -func (p *Project) appendChangeMemberEvent(event *es_models.Event) error { - member := &ProjectMember{} - err := member.SetData(event) - if err != nil { - return err - } - if i, m := GetProjectMember(p.Members, member.UserID); m != nil { - p.Members[i] = member - } - return nil -} - -func (p *Project) appendRemoveMemberEvent(event *es_models.Event) error { - member := &ProjectMember{} - err := member.SetData(event) - if err != nil { - return err - } - if i, m := GetProjectMember(p.Members, member.UserID); m != nil { - p.Members[i] = p.Members[len(p.Members)-1] - p.Members[len(p.Members)-1] = nil - p.Members = p.Members[:len(p.Members)-1] - } - return nil -} - func (m *ProjectMember) SetData(event *es_models.Event) error { m.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, m); err != nil { diff --git a/internal/project/repository/eventsourcing/model/project_member_test.go b/internal/project/repository/eventsourcing/model/project_member_test.go deleted file mode 100644 index ce18b86e6c..0000000000 --- a/internal/project/repository/eventsourcing/model/project_member_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package model - -import ( - "encoding/json" - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "testing" -) - -func TestAppendAddMemberEvent(t *testing.T) { - type args struct { - project *Project - member *ProjectMember - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append add member event", - args: args{ - project: &Project{}, - member: &ProjectMember{UserID: "UserID", Roles: []string{"Role"}}, - event: &es_models.Event{}, - }, - result: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"Role"}}}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.member != nil { - data, _ := json.Marshal(tt.args.member) - tt.args.event.Data = data - } - tt.args.project.appendAddMemberEvent(tt.args.event) - if len(tt.args.project.Members) != 1 { - t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.project.Members)) - } - if tt.args.project.Members[0] == tt.result.Members[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Members[0], tt.args.project.Members[0]) - } - }) - } -} - -func TestAppendChangeMemberEvent(t *testing.T) { - type args struct { - project *Project - member *ProjectMember - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append change member event", - args: args{ - project: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"Role"}}}}, - member: &ProjectMember{UserID: "UserID", Roles: []string{"ChangedRole"}}, - event: &es_models.Event{}, - }, - result: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"ChangedRole"}}}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.member != nil { - data, _ := json.Marshal(tt.args.member) - tt.args.event.Data = data - } - tt.args.project.appendChangeMemberEvent(tt.args.event) - if len(tt.args.project.Members) != 1 { - t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.project.Members)) - } - if tt.args.project.Members[0] == tt.result.Members[0] { - t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Members[0], tt.args.project.Members[0]) - } - }) - } -} - -func TestAppendRemoveMemberEvent(t *testing.T) { - type args struct { - project *Project - member *ProjectMember - event *es_models.Event - } - tests := []struct { - name string - args args - result *Project - }{ - { - name: "append remove member event", - args: args{ - project: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"Role"}}}}, - member: &ProjectMember{UserID: "UserID"}, - event: &es_models.Event{}, - }, - result: &Project{Members: []*ProjectMember{}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.args.member != nil { - data, _ := json.Marshal(tt.args.member) - tt.args.event.Data = data - } - tt.args.project.appendRemoveMemberEvent(tt.args.event) - if len(tt.args.project.Members) != 0 { - t.Errorf("got wrong result should have no member actual: %v ", len(tt.args.project.Members)) - } - }) - } -} diff --git a/internal/project/repository/eventsourcing/model/project_role.go b/internal/project/repository/eventsourcing/model/project_role.go index 15295ace36..ec019afdbf 100644 --- a/internal/project/repository/eventsourcing/model/project_role.go +++ b/internal/project/repository/eventsourcing/model/project_role.go @@ -57,43 +57,6 @@ func ProjectRoleToModel(role *ProjectRole) *model.ProjectRole { } } -func (p *Project) appendAddRoleEvent(event *es_models.Event) error { - role := new(ProjectRole) - err := role.setData(event) - if err != nil { - return err - } - role.ObjectRoot.CreationDate = event.CreationDate - p.Roles = append(p.Roles, role) - return nil -} - -func (p *Project) appendChangeRoleEvent(event *es_models.Event) error { - role := new(ProjectRole) - err := role.setData(event) - if err != nil { - return err - } - if i, r := GetProjectRole(p.Roles, role.Key); r != nil { - p.Roles[i] = role - } - return nil -} - -func (p *Project) appendRemoveRoleEvent(event *es_models.Event) error { - role := new(ProjectRole) - err := role.setData(event) - if err != nil { - return err - } - if i, r := GetProjectRole(p.Roles, role.Key); r != nil { - p.Roles[i] = p.Roles[len(p.Roles)-1] - p.Roles[len(p.Roles)-1] = nil - p.Roles = p.Roles[:len(p.Roles)-1] - } - return nil -} - func (r *ProjectRole) setData(event *es_models.Event) error { r.ObjectRoot.AppendEvent(event) if err := json.Unmarshal(event.Data, r); err != nil { diff --git a/internal/project/repository/eventsourcing/project.go b/internal/project/repository/eventsourcing/project.go deleted file mode 100644 index 2493865809..0000000000 --- a/internal/project/repository/eventsourcing/project.go +++ /dev/null @@ -1,150 +0,0 @@ -package eventsourcing - -import ( - "context" - - "github.com/caos/zitadel/internal/crypto" - "github.com/caos/zitadel/internal/errors" - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" - "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" -) - -func ProjectAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, project *model.Project) (*es_models.Aggregate, error) { - if project == nil { - return nil, errors.ThrowPreconditionFailed(nil, "EVENT-doe93", "Errors.Internal") - } - return aggCreator.NewAggregate(ctx, project.AggregateID, model.ProjectAggregate, model.ProjectVersion, project.Sequence) -} - -func ApplicationAddedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, app *model.Application) func(ctx context.Context) (*es_models.Aggregate, error) { - return func(ctx context.Context) (*es_models.Aggregate, error) { - if app == nil { - return nil, errors.ThrowPreconditionFailed(nil, "EVENT-09du7", "Errors.Internal") - } - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - agg.AppendEvent(model.ApplicationAdded, app) - if app.OIDCConfig != nil { - agg.AppendEvent(model.OIDCConfigAdded, app.OIDCConfig) - } - if app.APIConfig != nil { - agg.AppendEvent(model.APIConfigAdded, app.APIConfig) - } - return agg, nil - } -} - -func APIConfigChangedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, config *model.APIConfig) func(ctx context.Context) (*es_models.Aggregate, error) { - return func(ctx context.Context) (*es_models.Aggregate, error) { - if config == nil { - return nil, errors.ThrowPreconditionFailed(nil, "EVENT-slf32", "Errors.Internal") - } - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - var changes map[string]interface{} - for _, a := range existingProject.Applications { - if a.AppID == config.AppID { - if a.APIConfig != nil { - changes = a.APIConfig.Changes(config) - } - } - } - agg.AppendEvent(model.APIConfigChanged, changes) - - return agg, nil - } -} - -func OIDCConfigSecretChangedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string, secret *crypto.CryptoValue) func(ctx context.Context) (*es_models.Aggregate, error) { - return func(ctx context.Context) (*es_models.Aggregate, error) { - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - changes := make(map[string]interface{}, 2) - changes["appId"] = appID - changes["clientSecret"] = secret - - agg.AppendEvent(model.OIDCConfigSecretChanged, changes) - - return agg, nil - } -} - -func APIConfigSecretChangedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string, secret *crypto.CryptoValue) func(ctx context.Context) (*es_models.Aggregate, error) { - return func(ctx context.Context) (*es_models.Aggregate, error) { - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - changes := make(map[string]interface{}, 2) - changes["appId"] = appID - changes["clientSecret"] = secret - - agg.AppendEvent(model.APIConfigSecretChanged, changes) - - return agg, nil - } -} - -func OIDCClientSecretCheckSucceededAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string) es_sdk.AggregateFunc { - return func(ctx context.Context) (*es_models.Aggregate, error) { - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - changes := make(map[string]interface{}, 1) - changes["appId"] = appID - - agg.AppendEvent(model.OIDCClientSecretCheckSucceeded, changes) - - return agg, nil - } -} - -func OIDCClientSecretCheckFailedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string) es_sdk.AggregateFunc { - return func(ctx context.Context) (*es_models.Aggregate, error) { - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - changes := make(map[string]interface{}, 1) - changes["appId"] = appID - - agg.AppendEvent(model.OIDCClientSecretCheckFailed, changes) - - return agg, nil - } -} - -func OIDCApplicationKeyAddedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, key *model.ClientKey) es_sdk.AggregateFunc { - return func(ctx context.Context) (*es_models.Aggregate, error) { - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - agg.AppendEvent(model.ClientKeyAdded, key) - - return agg, nil - } -} - -func OIDCApplicationKeyRemovedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, keyID string) es_sdk.AggregateFunc { - return func(ctx context.Context) (*es_models.Aggregate, error) { - agg, err := ProjectAggregate(ctx, aggCreator, existingProject) - if err != nil { - return nil, err - } - changes := make(map[string]interface{}, 1) - changes["keyId"] = keyID - - agg.AppendEvent(model.ClientKeyRemoved, changes) - - return agg, nil - } -} diff --git a/internal/project/repository/view/model/application.go b/internal/project/repository/view/model/application.go index 4ca3473ead..23458a05d8 100644 --- a/internal/project/repository/view/model/application.go +++ b/internal/project/repository/view/model/application.go @@ -8,6 +8,7 @@ import ( "github.com/lib/pq" http_util "github.com/caos/zitadel/internal/api/http" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/project/model" @@ -23,15 +24,17 @@ const ( ) type ApplicationView struct { - ID string `json:"appId" gorm:"column:id;primary_key"` - ProjectID string `json:"-" gorm:"column:project_id"` - Name string `json:"name" gorm:"column:app_name"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - State int32 `json:"-" gorm:"column:app_state"` - ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"` - ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"` - HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"` + ID string `json:"appId" gorm:"column:id;primary_key"` + ProjectID string `json:"-" gorm:"column:project_id"` + Name string `json:"name" gorm:"column:app_name"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + State int32 `json:"-" gorm:"column:app_state"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"` + ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"` + HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"` + PrivateLabelingSetting domain.PrivateLabelingSetting `json:"privateLabelingSetting" gorm:"column:private_labeling_setting"` IsOIDC bool `json:"-" gorm:"column:is_oidc"` OIDCVersion int32 `json:"oidcVersion" gorm:"column:oidc_version"` @@ -58,15 +61,18 @@ type ApplicationView struct { func ApplicationViewToModel(app *ApplicationView) *model.ApplicationView { return &model.ApplicationView{ - ID: app.ID, - ProjectID: app.ProjectID, - Name: app.Name, - State: model.AppState(app.State), - Sequence: app.Sequence, - CreationDate: app.CreationDate, - ChangeDate: app.ChangeDate, - ProjectRoleAssertion: app.ProjectRoleAssertion, - ProjectRoleCheck: app.ProjectRoleCheck, + ID: app.ID, + ProjectID: app.ProjectID, + Name: app.Name, + State: model.AppState(app.State), + Sequence: app.Sequence, + CreationDate: app.CreationDate, + ChangeDate: app.ChangeDate, + ResourceOwner: app.ResourceOwner, + ProjectRoleAssertion: app.ProjectRoleAssertion, + ProjectRoleCheck: app.ProjectRoleCheck, + HasProjectCheck: app.HasProjectCheck, + PrivateLabelingSetting: app.PrivateLabelingSetting, IsOIDC: app.IsOIDC, OIDCVersion: model.OIDCVersion(app.OIDCVersion), @@ -158,6 +164,7 @@ func (a *ApplicationView) AppendEvent(event *models.Event) (err error) { case es_model.ApplicationAdded: a.setRootData(event) a.CreationDate = event.CreationDate + a.ResourceOwner = event.ResourceOwner err = a.SetData(event) case es_model.OIDCConfigAdded: a.IsOIDC = true @@ -233,9 +240,10 @@ func (a *ApplicationView) setCompliance() { func (a *ApplicationView) setProjectChanges(event *models.Event) error { changes := struct { - ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"` - ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"` - HasProjectCheck *bool `json:"hasProjectCheck,omitempty"` + ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"` + ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"` + HasProjectCheck *bool `json:"hasProjectCheck,omitempty"` + PrivateLabelingSetting *domain.PrivateLabelingSetting `json:"privateLabelingSetting,omitempty"` }{} if err := json.Unmarshal(event.Data, &changes); err != nil { logging.Log("EVEN-DFbfg").WithError(err).Error("could not unmarshal event data") @@ -250,5 +258,8 @@ func (a *ApplicationView) setProjectChanges(event *models.Event) error { if changes.HasProjectCheck != nil { a.HasProjectCheck = *changes.HasProjectCheck } + if changes.PrivateLabelingSetting != nil { + a.PrivateLabelingSetting = *changes.PrivateLabelingSetting + } return nil } diff --git a/internal/project/repository/view/model/project.go b/internal/project/repository/view/model/project.go index 81a62c7026..ae2999b837 100644 --- a/internal/project/repository/view/model/project.go +++ b/internal/project/repository/view/model/project.go @@ -6,6 +6,7 @@ import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/project/model" @@ -19,30 +20,32 @@ const ( ) type ProjectView struct { - ProjectID string `json:"-" gorm:"column:project_id;primary_key"` - Name string `json:"name" gorm:"column:project_name"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - State int32 `json:"-" gorm:"column:project_state"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"` - ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"` - HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"` - Sequence uint64 `json:"-" gorm:"column:sequence"` + ProjectID string `json:"-" gorm:"column:project_id;primary_key"` + Name string `json:"name" gorm:"column:project_name"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + State int32 `json:"-" gorm:"column:project_state"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"` + ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"` + HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"` + PrivateLabelingSetting domain.PrivateLabelingSetting `json:"privateLabelingSetting" gorm:"column:private_labeling_setting"` + Sequence uint64 `json:"-" gorm:"column:sequence"` } func ProjectToModel(project *ProjectView) *model.ProjectView { return &model.ProjectView{ - ProjectID: project.ProjectID, - Name: project.Name, - ChangeDate: project.ChangeDate, - CreationDate: project.CreationDate, - State: model.ProjectState(project.State), - ResourceOwner: project.ResourceOwner, - ProjectRoleAssertion: project.ProjectRoleAssertion, - ProjectRoleCheck: project.ProjectRoleCheck, - HasProjectCheck: project.HasProjectCheck, - Sequence: project.Sequence, + ProjectID: project.ProjectID, + Name: project.Name, + ChangeDate: project.ChangeDate, + CreationDate: project.CreationDate, + State: model.ProjectState(project.State), + ResourceOwner: project.ResourceOwner, + ProjectRoleAssertion: project.ProjectRoleAssertion, + ProjectRoleCheck: project.ProjectRoleCheck, + HasProjectCheck: project.HasProjectCheck, + PrivateLabelingSetting: project.PrivateLabelingSetting, + Sequence: project.Sequence, } } diff --git a/internal/repository/project/project.go b/internal/repository/project/project.go index c63c0d06e9..ae7de2f28f 100644 --- a/internal/repository/project/project.go +++ b/internal/repository/project/project.go @@ -3,6 +3,8 @@ package project import ( "context" "encoding/json" + + "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/errors" @@ -35,10 +37,11 @@ func NewRemoveProjectNameUniqueConstraint(projectName, resourceOwner string) *ev type ProjectAddedEvent struct { eventstore.BaseEvent `json:"-"` - Name string `json:"name,omitempty"` - ProjectRoleAssertion bool `json:"projectRoleAssertion,omitempty"` - ProjectRoleCheck bool `json:"projectRoleCheck,omitempty"` - HasProjectCheck bool `json:"hasProjectCheck,omitempty"` + Name string `json:"name,omitempty"` + ProjectRoleAssertion bool `json:"projectRoleAssertion,omitempty"` + ProjectRoleCheck bool `json:"projectRoleCheck,omitempty"` + HasProjectCheck bool `json:"hasProjectCheck,omitempty"` + PrivateLabelingSetting domain.PrivateLabelingSetting `json:"privateLabelingSetting,omitempty"` } func (e *ProjectAddedEvent) Data() interface{} { @@ -56,6 +59,7 @@ func NewProjectAddedEvent( projectRoleAssertion, projectRoleCheck, hasProjectCheck bool, + privateLabelingSetting domain.PrivateLabelingSetting, ) *ProjectAddedEvent { return &ProjectAddedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( @@ -63,10 +67,11 @@ func NewProjectAddedEvent( aggregate, ProjectAddedType, ), - Name: name, - ProjectRoleAssertion: projectRoleAssertion, - ProjectRoleCheck: projectRoleCheck, - HasProjectCheck: hasProjectCheck, + Name: name, + ProjectRoleAssertion: projectRoleAssertion, + ProjectRoleCheck: projectRoleCheck, + HasProjectCheck: hasProjectCheck, + PrivateLabelingSetting: privateLabelingSetting, } } @@ -86,11 +91,12 @@ func ProjectAddedEventMapper(event *repository.Event) (eventstore.EventReader, e type ProjectChangeEvent struct { eventstore.BaseEvent `json:"-"` - Name *string `json:"name,omitempty"` - ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"` - ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"` - HasProjectCheck *bool `json:"hasProjectCheck,omitempty"` - oldName string + Name *string `json:"name,omitempty"` + ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"` + ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"` + HasProjectCheck *bool `json:"hasProjectCheck,omitempty"` + PrivateLabelingSetting *domain.PrivateLabelingSetting `json:"privateLabelingSetting,omitempty"` + oldName string } func (e *ProjectChangeEvent) Data() interface{} { @@ -156,6 +162,12 @@ func ChangeHasProjectCheck(ChangeHasProjectCheck bool) func(event *ProjectChange } } +func ChangePrivateLabelingSetting(ChangePrivateLabelingSetting domain.PrivateLabelingSetting) func(event *ProjectChangeEvent) { + return func(e *ProjectChangeEvent) { + e.PrivateLabelingSetting = &ChangePrivateLabelingSetting + } +} + func ProjectChangeEventMapper(event *repository.Event) (eventstore.EventReader, error) { e := &ProjectChangeEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), diff --git a/internal/ui/login/handler/renderer.go b/internal/ui/login/handler/renderer.go index 4d3b1d9cbf..11f835a4bd 100644 --- a/internal/ui/login/handler/renderer.go +++ b/internal/ui/login/handler/renderer.go @@ -329,6 +329,7 @@ func (l *Login) getBaseData(r *http.Request, authReq *domain.AuthRequest, title Theme: l.getTheme(r), ThemeMode: l.getThemeMode(r), DarkMode: l.isDarkMode(r), + PrivateLabelingOrgID: l.getPrivateLabelingID(authReq), OrgID: l.getOrgID(authReq), OrgName: l.getOrgName(authReq), PrimaryDomain: l.getOrgPrimaryDomain(authReq), @@ -423,6 +424,19 @@ func (l *Login) getOrgID(authReq *domain.AuthRequest) string { return authReq.UserOrgID } +func (l *Login) getPrivateLabelingID(authReq *domain.AuthRequest) string { + privateLabelingOrgID := domain.IAMID + if authReq.PrivateLabelingSetting != domain.PrivateLabelingSettingUnspecified { + privateLabelingOrgID = authReq.ApplicationResourceOwner + } + if authReq.PrivateLabelingSetting == domain.PrivateLabelingSettingAllowLoginUserResourceOwnerPolicy || authReq.PrivateLabelingSetting == domain.PrivateLabelingSettingUnspecified { + if authReq.UserOrgID != "" { + privateLabelingOrgID = authReq.UserOrgID + } + } + return privateLabelingOrgID +} + func (l *Login) getOrgName(authReq *domain.AuthRequest) string { if authReq == nil { return "" @@ -485,6 +499,7 @@ type baseData struct { Theme string ThemeMode string DarkMode bool + PrivateLabelingOrgID string OrgID string OrgName string PrimaryDomain string diff --git a/internal/ui/login/static/templates/main.html b/internal/ui/login/static/templates/main.html index 229bac6d5b..aa9956bc37 100644 --- a/internal/ui/login/static/templates/main.html +++ b/internal/ui/login/static/templates/main.html @@ -10,7 +10,7 @@ {{ if hasCustomPolicy .LabelPolicy }} - + {{ end}} diff --git a/migrations/cockroach/V1.67__project_private_labeling.sql b/migrations/cockroach/V1.67__project_private_labeling.sql new file mode 100644 index 0000000000..13cf69c237 --- /dev/null +++ b/migrations/cockroach/V1.67__project_private_labeling.sql @@ -0,0 +1,5 @@ +ALTER TABLE management.projects ADD COLUMN private_labeling_setting SMALLINT; + +ALTER TABLE authz.applications ADD COLUMN private_labeling_setting SMALLINT; +ALTER TABLE auth.applications ADD COLUMN private_labeling_setting SMALLINT; +ALTER TABLE management.applications ADD COLUMN private_labeling_setting SMALLINT; diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto index 23fcf9203e..ffe0ab1e29 100644 --- a/proto/zitadel/management.proto +++ b/proto/zitadel/management.proto @@ -3453,6 +3453,7 @@ message AddProjectRequest { bool project_role_assertion = 2; bool project_role_check = 3; bool has_project_check = 4; + zitadel.project.v1.PrivateLabelingSetting private_labeling_setting = 5 [(validate.rules).enum = {defined_only: true}]; } message AddProjectResponse { @@ -3466,6 +3467,7 @@ message UpdateProjectRequest { bool project_role_assertion = 3; bool project_role_check = 4; bool has_project_check = 5; + zitadel.project.v1.PrivateLabelingSetting private_labeling_setting = 6 [(validate.rules).enum = {defined_only: true}]; } message UpdateProjectResponse { diff --git a/proto/zitadel/project.proto b/proto/zitadel/project.proto index 01222a1c23..4ae408b0b6 100644 --- a/proto/zitadel/project.proto +++ b/proto/zitadel/project.proto @@ -31,6 +31,8 @@ message Project { bool project_role_check = 6; // ZITADEL checks if the org of the user has permission to this project bool has_project_check = 7; + // Defines from where the private labeling should be triggered + PrivateLabelingSetting private_labeling_setting = 8; } message GrantedProject { @@ -90,6 +92,12 @@ enum ProjectState { PROJECT_STATE_INACTIVE = 2; } +enum PrivateLabelingSetting { + PRIVATE_LABELING_SETTING_UNSPECIFIED = 0; + PRIVATE_LABELING_SETTING_ENFORCE_PROJECT_RESOURCE_OWNER_POLICY = 1; + PRIVATE_LABELING_SETTING_ALLOW_LOGIN_USER_RESOURCE_OWNER_POLICY = 2; +} + enum ProjectGrantState { PROJECT_GRANT_STATE_UNSPECIFIED = 0; PROJECT_GRANT_STATE_ACTIVE = 1;