mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-06 17:22:28 +00:00
fix(project): include an option to add project members during project creation (#10654)
# Which Problems Are Solved When a project is created by a user with only the `PROJECT_CREATOR` role, they can no longer view/manage the created project. Although the project is created, the user sees the following error: `No matching permissions found (AUTH-3jknH)`. This is due to the [removal](https://github.com/zitadel/zitadel/pull/9317) of auto-assignment of the `PROJECT_OWNER` role when a project is newly created. # How the Problems Are Solved By introducing optional fields in the CreateProject API to include a list of users and a list of project member roles to be assigned to the users. When there are no roles mentioned, the `PROJECT_OWNER` role is assigned by default to all the users mentioned in the list. # Additional Changes N/A # Additional Context - Closes #10561 - Closes #10592 - Should be backported as this issue is not specific to v4 --------- Co-authored-by: conblem <mail@conblem.me> Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com> Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
@@ -96,6 +96,12 @@ func TestServer_CreateProject_Permission(t *testing.T) {
|
||||
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
|
||||
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), integration.Email())
|
||||
|
||||
// user with ORG_PROJECT_CREATOR role in same org
|
||||
user1Id, token1 := getOrgProjectCreator(t, iamOwnerCtx, orgResp.GetOrganizationId(), orgResp.GetOrganizationId())
|
||||
|
||||
// user with ORG_PROJECT_CREATOR role in a different org
|
||||
_, token2 := getOrgProjectCreator(t, iamOwnerCtx, orgResp.GetOrganizationId(), instance.DefaultOrg.GetId())
|
||||
|
||||
type want struct {
|
||||
id bool
|
||||
creationDate bool
|
||||
@@ -136,7 +142,7 @@ func TestServer_CreateProject_Permission(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with ORG_PROJECT_CREATOR permission, same organization, ok",
|
||||
ctx: integration.WithAuthorizationToken(CTX, getOrgProjectCreatorToken(t, iamOwnerCtx, orgResp.GetOrganizationId(), orgResp.GetOrganizationId())),
|
||||
ctx: integration.WithAuthorizationToken(CTX, token1),
|
||||
req: &project.CreateProjectRequest{
|
||||
Name: integration.ProjectName(),
|
||||
OrganizationId: orgResp.GetOrganizationId(),
|
||||
@@ -148,7 +154,7 @@ func TestServer_CreateProject_Permission(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with ORG_PROJECT_CREATOR permission, other organization, ok",
|
||||
ctx: integration.WithAuthorizationToken(CTX, getOrgProjectCreatorToken(t, iamOwnerCtx, orgResp.GetOrganizationId(), instance.DefaultOrg.GetId())),
|
||||
ctx: integration.WithAuthorizationToken(CTX, token2),
|
||||
req: &project.CreateProjectRequest{
|
||||
Name: integration.ProjectName(),
|
||||
OrganizationId: instance.DefaultOrg.GetId(),
|
||||
@@ -158,6 +164,43 @@ func TestServer_CreateProject_Permission(t *testing.T) {
|
||||
creationDate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with ORG_PROJECT_CREATOR permission, with admins and roles, ok",
|
||||
ctx: integration.WithAuthorizationToken(CTX, token1),
|
||||
req: &project.CreateProjectRequest{
|
||||
Name: integration.ProjectName(),
|
||||
OrganizationId: orgResp.GetOrganizationId(),
|
||||
Admins: []*project.CreateProjectRequest_Admin{
|
||||
{
|
||||
UserId: user1Id,
|
||||
Roles: []string{"role1", "role2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
id: true,
|
||||
creationDate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with ORG_PROJECT_CREATOR permission, missing user from the admins list, ok",
|
||||
ctx: integration.WithAuthorizationToken(CTX, token1),
|
||||
req: &project.CreateProjectRequest{
|
||||
Name: integration.ProjectName(),
|
||||
OrganizationId: orgResp.GetOrganizationId(),
|
||||
Admins: []*project.CreateProjectRequest_Admin{
|
||||
{
|
||||
UserId: user1Id,
|
||||
Roles: []string{"role1", "role2"},
|
||||
},
|
||||
{
|
||||
UserId: "random_user",
|
||||
Roles: []string{"role1", "role2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "organization owner, ok",
|
||||
ctx: instance.WithAuthorizationToken(CTX, integration.UserTypeOrgOwner),
|
||||
@@ -199,7 +242,7 @@ func TestServer_CreateProject_Permission(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getOrgProjectCreatorToken(t *testing.T, ctx context.Context, orgId1, orgId2 string) string {
|
||||
func getOrgProjectCreator(t *testing.T, ctx context.Context, orgId1, orgId2 string) (string, string) {
|
||||
// create a machine user in Org 1
|
||||
userResp := instance.CreateUserTypeMachine(ctx, orgId1)
|
||||
|
||||
@@ -213,7 +256,7 @@ func getOrgProjectCreatorToken(t *testing.T, ctx context.Context, orgId1, orgId2
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return instance.CreatePersonalAccessToken(ctx, userResp.GetId()).Token
|
||||
return userResp.GetId(), instance.CreatePersonalAccessToken(ctx, userResp.GetId()).Token
|
||||
}
|
||||
|
||||
func assertCreateProjectResponse(t *testing.T, creationDate, changeDate time.Time, expectedCreationDate, expectedID bool, actualResp *project.CreateProjectResponse) {
|
||||
|
||||
@@ -31,6 +31,7 @@ func (s *Server) CreateProject(ctx context.Context, req *connect.Request[project
|
||||
}
|
||||
|
||||
func projectCreateToCommand(req *project_pb.CreateProjectRequest) *command.AddProject {
|
||||
admins := projectCreateAdminsToCommand(req.GetAdmins())
|
||||
var aggregateID string
|
||||
if req.Id != nil {
|
||||
aggregateID = *req.Id
|
||||
@@ -45,9 +46,24 @@ func projectCreateToCommand(req *project_pb.CreateProjectRequest) *command.AddPr
|
||||
ProjectRoleCheck: req.AuthorizationRequired,
|
||||
HasProjectCheck: req.ProjectAccessRequired,
|
||||
PrivateLabelingSetting: privateLabelingSettingToDomain(req.PrivateLabelingSetting),
|
||||
Admins: admins,
|
||||
}
|
||||
}
|
||||
|
||||
func projectCreateAdminsToCommand(requestAdmins []*project_pb.CreateProjectRequest_Admin) []*command.AddProjectAdmin {
|
||||
if len(requestAdmins) == 0 {
|
||||
return nil
|
||||
}
|
||||
admins := make([]*command.AddProjectAdmin, len(requestAdmins))
|
||||
for i, admin := range requestAdmins {
|
||||
admins[i] = &command.AddProjectAdmin{
|
||||
ID: admin.GetUserId(),
|
||||
Roles: admin.GetRoles(),
|
||||
}
|
||||
}
|
||||
return admins
|
||||
}
|
||||
|
||||
func privateLabelingSettingToDomain(setting project_pb.PrivateLabelingSetting) domain.PrivateLabelingSetting {
|
||||
switch setting {
|
||||
case project_pb.PrivateLabelingSetting_PRIVATE_LABELING_SETTING_ALLOW_LOGIN_USER_RESOURCE_OWNER_POLICY:
|
||||
|
||||
Reference in New Issue
Block a user