alfa-alex 6889d6a1da
feat: add custom org ID to AddOrganizationRequest (#9720)
# Which Problems Are Solved

- It is not possible to specify a custom organization ID when creating
an organization. According to
https://github.com/zitadel/zitadel/discussions/9202#discussioncomment-11929464
this is "an inconsistency in the V2 API".

# How the Problems Are Solved

- Adds the `org_id` as an optional parameter to the
`AddOrganizationRequest` in the `v2beta` API.

# Additional Changes

None. 

# Additional Context

- Discussion
[#9202](https://github.com/zitadel/zitadel/discussions/9202)
- I was mostly interested in how much work it'd be to add this field.
Then after completing this, I thought I'd submit this PR. I won't be
angry if you just close this PR with the reasoning "we didn't ask for
it". 😄
- Even though I don't think this is a breaking change, I didn't add this
to the `v2` API yet (don't know what the process for this is TBH). The
changes should be analogous, so if you want me to, just request it.

---------

Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
2025-05-21 12:55:40 +02:00

188 lines
4.2 KiB
Go

package org
import (
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
user "github.com/zitadel/zitadel/pkg/grpc/user/v2beta"
)
func Test_addOrganizationRequestToCommand(t *testing.T) {
type args struct {
request *org.AddOrganizationRequest
}
tests := []struct {
name string
args args
want *command.OrgSetup
wantErr error
}{
{
name: "nil user",
args: args{
request: &org.AddOrganizationRequest{
Name: "name",
Admins: []*org.AddOrganizationRequest_Admin{
{},
},
},
},
wantErr: zerrors.ThrowUnimplementedf(nil, "ORGv2-SD2r1", "userType oneOf %T in method AddOrganization not implemented", nil),
},
{
name: "custom org ID",
args: args{
request: &org.AddOrganizationRequest{
Name: "custom org ID",
OrgId: gu.Ptr("org-ID"),
},
},
want: &command.OrgSetup{
Name: "custom org ID",
CustomDomain: "",
Admins: []*command.OrgSetupAdmin{},
OrgID: "org-ID",
},
},
{
name: "user ID",
args: args{
request: &org.AddOrganizationRequest{
Name: "name",
Admins: []*org.AddOrganizationRequest_Admin{
{
UserType: &org.AddOrganizationRequest_Admin_UserId{
UserId: "userID",
},
Roles: nil,
},
},
},
},
want: &command.OrgSetup{
Name: "name",
CustomDomain: "",
Admins: []*command.OrgSetupAdmin{
{
ID: "userID",
},
},
},
},
{
name: "human user",
args: args{
request: &org.AddOrganizationRequest{
Name: "name",
Admins: []*org.AddOrganizationRequest_Admin{
{
UserType: &org.AddOrganizationRequest_Admin_Human{
Human: &user.AddHumanUserRequest{
Profile: &user.SetHumanProfile{
GivenName: "firstname",
FamilyName: "lastname",
},
Email: &user.SetHumanEmail{
Email: "email@test.com",
},
},
},
Roles: nil,
},
},
},
},
want: &command.OrgSetup{
Name: "name",
CustomDomain: "",
Admins: []*command.OrgSetupAdmin{
{
Human: &command.AddHuman{
Username: "email@test.com",
FirstName: "firstname",
LastName: "lastname",
Email: command.Email{
Address: "email@test.com",
},
Metadata: make([]*command.AddMetadataEntry, 0),
Links: make([]*command.AddLink, 0),
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := addOrganizationRequestToCommand(tt.args.request)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, tt.want, got)
})
}
}
func Test_createdOrganizationToPb(t *testing.T) {
now := time.Now()
type args struct {
createdOrg *command.CreatedOrg
}
tests := []struct {
name string
args args
want *org.AddOrganizationResponse
wantErr error
}{
{
name: "human user with phone and email code",
args: args{
createdOrg: &command.CreatedOrg{
ObjectDetails: &domain.ObjectDetails{
Sequence: 1,
EventDate: now,
ResourceOwner: "orgID",
},
CreatedAdmins: []*command.CreatedOrgAdmin{
{
ID: "id",
EmailCode: gu.Ptr("emailCode"),
PhoneCode: gu.Ptr("phoneCode"),
},
},
},
},
want: &org.AddOrganizationResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.New(now),
ResourceOwner: "orgID",
},
OrganizationId: "orgID",
CreatedAdmins: []*org.AddOrganizationResponse_CreatedAdmin{
{
UserId: "id",
EmailCode: gu.Ptr("emailCode"),
PhoneCode: gu.Ptr("phoneCode"),
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := createdOrganizationToPb(tt.args.createdOrg)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, tt.want, got)
})
}
}