fix: create project with the right permission (#10485)

# Which Problems Are Solved

When a user with an `ORG_PROJECT_CREATOR` role tries to create a
project, the request fails with `No matching permissions found
(AUTH-AWfge)` error. This is because `project.write` was set as the
required permission instead of `project.create` during project creation.

# How the Problems Are Solved
By setting the right required permission (`project.create`) while
creating new projects.

# Additional Changes
N/A

# Additional Context
- Closes #10399
This commit is contained in:
Gayathri Vijayan
2025-08-15 11:35:43 +02:00
committed by GitHub
parent 0318edcd3b
commit 0929c4d235
5 changed files with 74 additions and 4 deletions

View File

@@ -10,12 +10,16 @@ import (
"github.com/brianvoe/gofakeit/v6"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/integration"
internal_permission_v2beta "github.com/zitadel/zitadel/pkg/grpc/internal_permission/v2beta"
project "github.com/zitadel/zitadel/pkg/grpc/project/v2beta"
)
func TestServer_CreateProject(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -74,6 +78,7 @@ func TestServer_CreateProject(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
got, err := instance.Client.Projectv2Beta.CreateProject(tt.ctx, tt.req)
changeDate := time.Now().UTC()
@@ -88,6 +93,7 @@ func TestServer_CreateProject(t *testing.T) {
}
func TestServer_CreateProject_Permission(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -129,6 +135,30 @@ func TestServer_CreateProject_Permission(t *testing.T) {
},
wantErr: true,
},
{
name: "with ORG_PROJECT_CREATOR permission, same organization, ok",
ctx: integration.WithAuthorizationToken(CTX, getOrgProjectCreatorToken(t, iamOwnerCtx, orgResp.GetOrganizationId(), orgResp.GetOrganizationId())),
req: &project.CreateProjectRequest{
Name: integration.ProjectName(),
OrganizationId: orgResp.GetOrganizationId(),
},
want: want{
id: true,
creationDate: true,
},
},
{
name: "with ORG_PROJECT_CREATOR permission, other organization, ok",
ctx: integration.WithAuthorizationToken(CTX, getOrgProjectCreatorToken(t, iamOwnerCtx, orgResp.GetOrganizationId(), instance.DefaultOrg.GetId())),
req: &project.CreateProjectRequest{
Name: integration.ProjectName(),
OrganizationId: instance.DefaultOrg.GetId(),
},
want: want{
id: true,
creationDate: true,
},
},
{
name: "organization owner, ok",
ctx: instance.WithAuthorizationToken(CTX, integration.UserTypeOrgOwner),
@@ -156,6 +186,7 @@ func TestServer_CreateProject_Permission(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
got, err := instance.Client.Projectv2Beta.CreateProject(tt.ctx, tt.req)
changeDate := time.Now().UTC()
@@ -169,6 +200,23 @@ func TestServer_CreateProject_Permission(t *testing.T) {
}
}
func getOrgProjectCreatorToken(t *testing.T, ctx context.Context, orgId1, orgId2 string) string {
// create a machine user in Org 1
userResp := instance.CreateUserTypeMachine(ctx, orgId1)
// assign ORG_PROJECT_CREATOR role in Org 2
_, err := instance.Client.InternalPermissionv2Beta.CreateAdministrator(ctx, &internal_permission_v2beta.CreateAdministratorRequest{
Resource: &internal_permission_v2beta.ResourceType{
Resource: &internal_permission_v2beta.ResourceType_OrganizationId{OrganizationId: orgId2},
},
UserId: userResp.GetId(),
Roles: []string{domain.RoleOrgProjectCreator},
})
require.NoError(t, err)
return instance.CreatePersonalAccessToken(ctx, userResp.GetId()).Token
}
func assertCreateProjectResponse(t *testing.T, creationDate, changeDate time.Time, expectedCreationDate, expectedID bool, actualResp *project.CreateProjectResponse) {
if expectedCreationDate {
if !changeDate.IsZero() {
@@ -188,6 +236,7 @@ func assertCreateProjectResponse(t *testing.T, creationDate, changeDate time.Tim
}
func TestServer_UpdateProject(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -210,7 +259,6 @@ func TestServer_UpdateProject(t *testing.T) {
name: "not existing",
prepare: func(request *project.UpdateProjectRequest) {
request.Id = "notexisting"
return
},
args: args{
ctx: iamOwnerCtx,
@@ -278,6 +326,7 @@ func TestServer_UpdateProject(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
tt.prepare(tt.args.req)
@@ -297,6 +346,7 @@ func TestServer_UpdateProject(t *testing.T) {
}
func TestServer_UpdateProject_Permission(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -430,6 +480,7 @@ func TestServer_UpdateProject_Permission(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
tt.prepare(tt.args.req)
@@ -461,6 +512,7 @@ func assertUpdateProjectResponse(t *testing.T, creationDate, changeDate time.Tim
}
func TestServer_DeleteProject(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -516,6 +568,7 @@ func TestServer_DeleteProject(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var creationDate, deletionDate time.Time
if tt.prepare != nil {
creationDate, deletionDate = tt.prepare(tt.req)
@@ -532,6 +585,7 @@ func TestServer_DeleteProject(t *testing.T) {
}
func TestServer_DeleteProject_Permission(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -635,6 +689,7 @@ func TestServer_DeleteProject_Permission(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var creationDate, deletionDate time.Time
if tt.prepare != nil {
creationDate, deletionDate = tt.prepare(tt.req)
@@ -663,6 +718,7 @@ func assertDeleteProjectResponse(t *testing.T, creationDate, deletionDate time.T
}
func TestServer_DeactivateProject(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -685,7 +741,6 @@ func TestServer_DeactivateProject(t *testing.T) {
name: "not existing",
prepare: func(request *project.DeactivateProjectRequest) {
request.Id = "notexisting"
return
},
args: args{
ctx: iamOwnerCtx,
@@ -725,6 +780,7 @@ func TestServer_DeactivateProject(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
tt.prepare(tt.args.req)
@@ -744,6 +800,7 @@ func TestServer_DeactivateProject(t *testing.T) {
}
func TestServer_DeactivateProject_Permission(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -831,6 +888,7 @@ func TestServer_DeactivateProject_Permission(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
tt.prepare(tt.args.req)
@@ -862,6 +920,7 @@ func assertDeactivateProjectResponse(t *testing.T, creationDate, changeDate time
}
func TestServer_ActivateProject(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -936,6 +995,7 @@ func TestServer_ActivateProject(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
tt.prepare(tt.args.req)
@@ -955,6 +1015,7 @@ func TestServer_ActivateProject(t *testing.T) {
}
func TestServer_ActivateProject_Permission(t *testing.T) {
t.Parallel()
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
orgResp := instance.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), gofakeit.Email())
@@ -1047,6 +1108,7 @@ func TestServer_ActivateProject_Permission(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
creationDate := time.Now().UTC()
tt.prepare(tt.args.req)