mirror of
https://github.com/zitadel/zitadel.git
synced 2025-06-02 13:08:21 +00:00
feat: set up org (#1157)
* add setup steps * refactoring * omitempty * cleanup * begin org * create org * setup org * setup org * merge * fixes * fixes * fixes
This commit is contained in:
parent
26c8113930
commit
ff87264f95
@ -30,49 +30,45 @@ SetUp:
|
|||||||
AllowUsernamePassword: true
|
AllowUsernamePassword: true
|
||||||
AllowRegister: true
|
AllowRegister: true
|
||||||
AllowExternalIdp: true
|
AllowExternalIdp: true
|
||||||
# Orgs:
|
Orgs:
|
||||||
# - Name: 'Global'
|
- Name: 'Global'
|
||||||
# Domain: 'global.caos.ch'
|
Domain: 'global.caos.ch'
|
||||||
# Default: true
|
Default: true
|
||||||
# OrgIamPolicy: true
|
OrgIamPolicy: true
|
||||||
# Users:
|
Owner:
|
||||||
# - FirstName: 'Global Org'
|
FirstName: 'Global Org'
|
||||||
# LastName: 'Administrator'
|
LastName: 'Administrator'
|
||||||
# UserName: 'zitadel-global-org-admin@caos.ch'
|
UserName: 'zitadel-global-org-admin@caos.ch'
|
||||||
# Email: 'zitadel-global-org-admin@caos.ch'
|
Email: 'zitadel-global-org-admin@caos.ch'
|
||||||
# Password: 'Password1!'
|
Password: 'Password1!'
|
||||||
# Owners:
|
- Name: 'CAOS AG'
|
||||||
# - 'zitadel-global-org-admin@caos.ch'
|
Domain: 'caos.ch'
|
||||||
# - Name: 'CAOS AG'
|
Owner:
|
||||||
# Domain: 'caos.ch'
|
FirstName: 'Zitadel'
|
||||||
# Users:
|
LastName: 'Administrator'
|
||||||
# - FirstName: 'Zitadel'
|
UserName: 'zitadel-admin'
|
||||||
# LastName: 'Administrator'
|
Email: 'zitadel-admin@caos.ch'
|
||||||
# UserName: 'zitadel-admin'
|
Password: 'Password1!'
|
||||||
# Email: 'zitadel-admin@caos.ch'
|
Projects:
|
||||||
# Password: 'Password1!'
|
- Name: 'Zitadel'
|
||||||
# Owners:
|
OIDCApps:
|
||||||
# - 'zitadel-admin@caos.ch'
|
- Name: 'Management-API'
|
||||||
# Projects:
|
- Name: 'Auth-API'
|
||||||
# - Name: 'Zitadel'
|
- Name: 'Admin-API'
|
||||||
# OIDCApps:
|
- Name: 'Zitadel Console'
|
||||||
# - Name: 'Management-API'
|
RedirectUris:
|
||||||
# - Name: 'Auth-API'
|
- '$ZITADEL_CONSOLE/auth/callback'
|
||||||
# - Name: 'Admin-API'
|
PostLogoutRedirectUris:
|
||||||
# - Name: 'Zitadel Console'
|
- '$ZITADEL_CONSOLE/signedout'
|
||||||
# RedirectUris:
|
ResponseTypes:
|
||||||
# - '$ZITADEL_CONSOLE/auth/callback'
|
- $ZITADEL_CONSOLE_RESPONSE_TYPE
|
||||||
# PostLogoutRedirectUris:
|
GrantTypes:
|
||||||
# - '$ZITADEL_CONSOLE/signedout'
|
- $ZITADEL_CONSOLE_GRANT_TYPE
|
||||||
# ResponseTypes:
|
ApplicationType: 'USER_AGENT'
|
||||||
# - $ZITADEL_CONSOLE_RESPONSE_TYPE
|
AuthMethodType: 'NONE'
|
||||||
# GrantTypes:
|
DevMode: $ZITADEL_CONSOLE_DEV_MODE
|
||||||
# - $ZITADEL_CONSOLE_GRANT_TYPE
|
Owners:
|
||||||
# ApplicationType: 'USER_AGENT'
|
- 'zitadel-admin@caos.ch'
|
||||||
# AuthMethodType: 'NONE'
|
|
||||||
# DevMode: $ZITADEL_CONSOLE_DEV_MODE
|
|
||||||
# Owners:
|
|
||||||
# - 'zitadel-admin@caos.ch'
|
|
||||||
Step2:
|
Step2:
|
||||||
DefaultPasswordComplexityPolicy:
|
DefaultPasswordComplexityPolicy:
|
||||||
MinLength: 8
|
MinLength: 8
|
||||||
|
@ -2,21 +2,17 @@ package repository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
|
|
||||||
admin_model "github.com/caos/zitadel/internal/admin/model"
|
|
||||||
org_model "github.com/caos/zitadel/internal/org/model"
|
org_model "github.com/caos/zitadel/internal/org/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrgRepository interface {
|
type OrgRepository interface {
|
||||||
SetUpOrg(context.Context, *admin_model.SetupOrg) (*admin_model.SetupOrg, error)
|
|
||||||
IsOrgUnique(ctx context.Context, name, domain string) (bool, error)
|
IsOrgUnique(ctx context.Context, name, domain string) (bool, error)
|
||||||
OrgByID(ctx context.Context, id string) (*org_model.Org, error)
|
OrgByID(ctx context.Context, id string) (*org_model.Org, error)
|
||||||
SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error)
|
SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error)
|
||||||
|
|
||||||
GetOrgIAMPolicyByID(ctx context.Context, id string) (*iam_model.OrgIAMPolicyView, error)
|
GetOrgIAMPolicyByID(ctx context.Context, id string) (*iam_model.OrgIAMPolicyView, error)
|
||||||
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
|
|
||||||
CreateOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error)
|
|
||||||
ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error)
|
|
||||||
RemoveOrgIAMPolicy(ctx context.Context, id string) error
|
RemoveOrgIAMPolicy(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
@ -10,21 +10,21 @@ import (
|
|||||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addIamMemberToDomain(member *admin.AddIamMemberRequest) *domain.IAMMember {
|
func addIamMemberToDomain(member *admin.AddIamMemberRequest) *domain.Member {
|
||||||
return &domain.IAMMember{
|
return &domain.Member{
|
||||||
UserID: member.UserId,
|
UserID: member.UserId,
|
||||||
Roles: member.Roles,
|
Roles: member.Roles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func changeIamMemberToDomain(member *admin.ChangeIamMemberRequest) *domain.IAMMember {
|
func changeIamMemberToDomain(member *admin.ChangeIamMemberRequest) *domain.Member {
|
||||||
return &domain.IAMMember{
|
return &domain.Member{
|
||||||
UserID: member.UserId,
|
UserID: member.UserId,
|
||||||
Roles: member.Roles,
|
Roles: member.Roles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func iamMemberFromDomain(member *domain.IAMMember) *admin.IamMember {
|
func iamMemberFromDomain(member *domain.Member) *admin.IamMember {
|
||||||
creationDate, err := ptypes.TimestampProto(member.CreationDate)
|
creationDate, err := ptypes.TimestampProto(member.CreationDate)
|
||||||
logging.Log("GRPC-Lsp76").OnError(err).Debug("date parse failed")
|
logging.Log("GRPC-Lsp76").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ func (s *Server) IsOrgUnique(ctx context.Context, request *admin.UniqueOrgReques
|
|||||||
return &admin.UniqueOrgResponse{IsUnique: isUnique}, err
|
return &admin.UniqueOrgResponse{IsUnique: isUnique}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetUpOrg(ctx context.Context, orgSetUp *admin.OrgSetUpRequest) (_ *admin.OrgSetUpResponse, err error) {
|
func (s *Server) SetUpOrg(ctx context.Context, orgSetUp *admin.OrgSetUpRequest) (_ *empty.Empty, err error) {
|
||||||
setUp, err := s.org.SetUpOrg(ctx, setUpRequestToModel(orgSetUp))
|
err = s.command.SetUpOrg(ctx, orgCreateRequestToDomain(orgSetUp.Org), userCreateRequestToDomain(orgSetUp.User))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return setUpOrgResponseFromModel(setUp), err
|
return &empty.Empty{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetDefaultOrgIamPolicy(ctx context.Context, _ *empty.Empty) (_ *admin.OrgIamPolicyView, err error) {
|
func (s *Server) GetDefaultOrgIamPolicy(ctx context.Context, _ *empty.Empty) (_ *admin.OrgIamPolicyView, err error) {
|
||||||
|
@ -2,9 +2,10 @@ package admin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
"github.com/golang/protobuf/ptypes"
|
||||||
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/golang/protobuf/ptypes"
|
|
||||||
|
|
||||||
admin_model "github.com/caos/zitadel/internal/admin/model"
|
admin_model "github.com/caos/zitadel/internal/admin/model"
|
||||||
"github.com/caos/zitadel/internal/eventstore/models"
|
"github.com/caos/zitadel/internal/eventstore/models"
|
||||||
@ -14,20 +15,13 @@ import (
|
|||||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setUpRequestToModel(setUp *admin.OrgSetUpRequest) *admin_model.SetupOrg {
|
func orgCreateRequestToDomain(org *admin.CreateOrgRequest) *domain.Org {
|
||||||
return &admin_model.SetupOrg{
|
o := &domain.Org{
|
||||||
Org: orgCreateRequestToModel(setUp.Org),
|
Domains: []*domain.OrgDomain{},
|
||||||
User: userCreateRequestToModel(setUp.User),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func orgCreateRequestToModel(org *admin.CreateOrgRequest) *org_model.Org {
|
|
||||||
o := &org_model.Org{
|
|
||||||
Domains: []*org_model.OrgDomain{},
|
|
||||||
Name: org.Name,
|
Name: org.Name,
|
||||||
}
|
}
|
||||||
if org.Domain != "" {
|
if org.Domain != "" {
|
||||||
o.Domains = append(o.Domains, &org_model.OrgDomain{Domain: org.Domain})
|
o.Domains = append(o.Domains, &domain.OrgDomain{Domain: org.Domain})
|
||||||
}
|
}
|
||||||
|
|
||||||
return o
|
return o
|
||||||
|
@ -3,11 +3,83 @@ package admin
|
|||||||
import (
|
import (
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
usr_model "github.com/caos/zitadel/internal/user/model"
|
usr_model "github.com/caos/zitadel/internal/user/model"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||||
"github.com/golang/protobuf/ptypes"
|
"github.com/golang/protobuf/ptypes"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func userCreateRequestToDomain(user *admin.CreateUserRequest) *domain.User {
|
||||||
|
var human *domain.Human
|
||||||
|
var machine *domain.Machine
|
||||||
|
|
||||||
|
if h := user.GetHuman(); h != nil {
|
||||||
|
human = humanCreateToDomain(h)
|
||||||
|
}
|
||||||
|
if m := user.GetMachine(); m != nil {
|
||||||
|
machine = machineCreateToDomain(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &domain.User{
|
||||||
|
UserName: user.UserName,
|
||||||
|
Human: human,
|
||||||
|
Machine: machine,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func humanCreateToDomain(u *admin.CreateHumanRequest) *domain.Human {
|
||||||
|
preferredLanguage, err := language.Parse(u.PreferredLanguage)
|
||||||
|
logging.Log("GRPC-1ouQc").OnError(err).Debug("language malformed")
|
||||||
|
|
||||||
|
human := &domain.Human{
|
||||||
|
Profile: &domain.Profile{
|
||||||
|
FirstName: u.FirstName,
|
||||||
|
LastName: u.LastName,
|
||||||
|
NickName: u.NickName,
|
||||||
|
PreferredLanguage: preferredLanguage,
|
||||||
|
Gender: genderToDomain(u.Gender),
|
||||||
|
},
|
||||||
|
Email: &domain.Email{
|
||||||
|
EmailAddress: u.Email,
|
||||||
|
IsEmailVerified: u.IsEmailVerified,
|
||||||
|
},
|
||||||
|
Address: &domain.Address{
|
||||||
|
Country: u.Country,
|
||||||
|
Locality: u.Locality,
|
||||||
|
PostalCode: u.PostalCode,
|
||||||
|
Region: u.Region,
|
||||||
|
StreetAddress: u.StreetAddress,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if u.Password != "" {
|
||||||
|
human.Password = &domain.Password{SecretString: u.Password}
|
||||||
|
}
|
||||||
|
if u.Phone != "" {
|
||||||
|
human.Phone = &domain.Phone{PhoneNumber: u.Phone, IsPhoneVerified: u.IsPhoneVerified}
|
||||||
|
}
|
||||||
|
return human
|
||||||
|
}
|
||||||
|
|
||||||
|
func genderToDomain(gender admin.Gender) domain.Gender {
|
||||||
|
switch gender {
|
||||||
|
case admin.Gender_GENDER_FEMALE:
|
||||||
|
return domain.GenderFemale
|
||||||
|
case admin.Gender_GENDER_MALE:
|
||||||
|
return domain.GenderMale
|
||||||
|
case admin.Gender_GENDER_DIVERSE:
|
||||||
|
return domain.GenderDiverse
|
||||||
|
default:
|
||||||
|
return domain.GenderUnspecified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func machineCreateToDomain(machine *admin.CreateMachineRequest) *domain.Machine {
|
||||||
|
return &domain.Machine{
|
||||||
|
Name: machine.Name,
|
||||||
|
Description: machine.Description,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func userCreateRequestToModel(user *admin.CreateUserRequest) *usr_model.User {
|
func userCreateRequestToModel(user *admin.CreateUserRequest) *usr_model.User {
|
||||||
var human *usr_model.Human
|
var human *usr_model.Human
|
||||||
var machine *usr_model.Machine
|
var machine *usr_model.Machine
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eventstore
|
package eventstore
|
||||||
|
|
||||||
type aggregater interface {
|
type Aggregater interface {
|
||||||
//ID returns the aggreagte id
|
//ID returns the aggreagte id
|
||||||
ID() string
|
ID() string
|
||||||
//KeyType returns the aggregate type
|
//KeyType returns the aggregate type
|
||||||
@ -52,7 +52,7 @@ func AggregateFromWriteModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Aggregate is the basic implementation of aggregater
|
//Aggregate is the basic implementation of Aggregater
|
||||||
type Aggregate struct {
|
type Aggregate struct {
|
||||||
id string `json:"-"`
|
id string `json:"-"`
|
||||||
typ AggregateType `json:"-"`
|
typ AggregateType `json:"-"`
|
||||||
@ -69,32 +69,32 @@ func (a *Aggregate) PushEvents(events ...EventPusher) *Aggregate {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
//ID implements aggregater
|
//ID implements Aggregater
|
||||||
func (a *Aggregate) ID() string {
|
func (a *Aggregate) ID() string {
|
||||||
return a.id
|
return a.id
|
||||||
}
|
}
|
||||||
|
|
||||||
//KeyType implements aggregater
|
//KeyType implements Aggregater
|
||||||
func (a *Aggregate) Type() AggregateType {
|
func (a *Aggregate) Type() AggregateType {
|
||||||
return a.typ
|
return a.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
//Events implements aggregater
|
//Events implements Aggregater
|
||||||
func (a *Aggregate) Events() []EventPusher {
|
func (a *Aggregate) Events() []EventPusher {
|
||||||
return a.events
|
return a.events
|
||||||
}
|
}
|
||||||
|
|
||||||
//ResourceOwner implements aggregater
|
//ResourceOwner implements Aggregater
|
||||||
func (a *Aggregate) ResourceOwner() string {
|
func (a *Aggregate) ResourceOwner() string {
|
||||||
return a.resourceOwner
|
return a.resourceOwner
|
||||||
}
|
}
|
||||||
|
|
||||||
//Version implements aggregater
|
//Version implements Aggregater
|
||||||
func (a *Aggregate) Version() Version {
|
func (a *Aggregate) Version() Version {
|
||||||
return a.version
|
return a.version
|
||||||
}
|
}
|
||||||
|
|
||||||
//PreviousSequence implements aggregater
|
//PreviousSequence implements Aggregater
|
||||||
func (a *Aggregate) PreviousSequence() uint64 {
|
func (a *Aggregate) PreviousSequence() uint64 {
|
||||||
return a.previousSequence
|
return a.previousSequence
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func (es *Eventstore) Health(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//PushAggregate pushes the aggregate and reduces the new events on the aggregate
|
//PushAggregate pushes the aggregate and reduces the new events on the aggregate
|
||||||
func (es *Eventstore) PushAggregate(ctx context.Context, writeModel queryReducer, aggregate aggregater) error {
|
func (es *Eventstore) PushAggregate(ctx context.Context, writeModel queryReducer, aggregate Aggregater) error {
|
||||||
events, err := es.PushAggregates(ctx, aggregate)
|
events, err := es.PushAggregates(ctx, aggregate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -49,7 +49,7 @@ func (es *Eventstore) PushAggregate(ctx context.Context, writeModel queryReducer
|
|||||||
|
|
||||||
//PushAggregates maps the events of all aggregates to an eventstore event
|
//PushAggregates maps the events of all aggregates to an eventstore event
|
||||||
// based on the pushMapper
|
// based on the pushMapper
|
||||||
func (es *Eventstore) PushAggregates(ctx context.Context, aggregates ...aggregater) ([]EventReader, error) {
|
func (es *Eventstore) PushAggregates(ctx context.Context, aggregates ...Aggregater) ([]EventReader, error) {
|
||||||
events, err := es.aggregatesToEvents(aggregates)
|
events, err := es.aggregatesToEvents(aggregates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -63,7 +63,7 @@ func (es *Eventstore) PushAggregates(ctx context.Context, aggregates ...aggregat
|
|||||||
return es.mapEvents(events)
|
return es.mapEvents(events)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Eventstore) aggregatesToEvents(aggregates []aggregater) ([]*repository.Event, error) {
|
func (es *Eventstore) aggregatesToEvents(aggregates []Aggregater) ([]*repository.Event, error) {
|
||||||
events := make([]*repository.Event, 0, len(aggregates))
|
events := make([]*repository.Event, 0, len(aggregates))
|
||||||
for _, aggregate := range aggregates {
|
for _, aggregate := range aggregates {
|
||||||
var previousEvent *repository.Event
|
var previousEvent *repository.Event
|
||||||
|
@ -356,7 +356,7 @@ func Test_eventData(t *testing.T) {
|
|||||||
|
|
||||||
func TestEventstore_aggregatesToEvents(t *testing.T) {
|
func TestEventstore_aggregatesToEvents(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
aggregates []aggregater
|
aggregates []Aggregater
|
||||||
}
|
}
|
||||||
type res struct {
|
type res struct {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
@ -370,7 +370,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one aggregate one event",
|
name: "one aggregate one event",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -403,7 +403,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one aggregate multiple events",
|
name: "one aggregate multiple events",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -452,7 +452,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "invalid data",
|
name: "invalid data",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -473,7 +473,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "multiple aggregates",
|
name: "multiple aggregates",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -614,7 +614,7 @@ func (repo *testRepo) LatestSequence(ctx context.Context, queryFactory *reposito
|
|||||||
|
|
||||||
func TestEventstore_Push(t *testing.T) {
|
func TestEventstore_Push(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
aggregates []aggregater
|
aggregates []Aggregater
|
||||||
}
|
}
|
||||||
type fields struct {
|
type fields struct {
|
||||||
repo *testRepo
|
repo *testRepo
|
||||||
@ -632,7 +632,7 @@ func TestEventstore_Push(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one aggregate one event",
|
name: "one aggregate one event",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -672,7 +672,7 @@ func TestEventstore_Push(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one aggregate multiple events",
|
name: "one aggregate multiple events",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -731,7 +731,7 @@ func TestEventstore_Push(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "multiple aggregates",
|
name: "multiple aggregates",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -815,7 +815,7 @@ func TestEventstore_Push(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "push fails",
|
name: "push fails",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
@ -842,7 +842,7 @@ func TestEventstore_Push(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "aggreagtes to events mapping fails",
|
name: "aggreagtes to events mapping fails",
|
||||||
args: args{
|
args: args{
|
||||||
aggregates: []aggregater{
|
aggregates: []Aggregater{
|
||||||
&testAggregate{
|
&testAggregate{
|
||||||
id: "1",
|
id: "1",
|
||||||
events: []EventPusher{
|
events: []EventPusher{
|
||||||
|
@ -109,6 +109,8 @@ Errors:
|
|||||||
IdpNotExisting: IDP Konfiguration existiert nicht
|
IdpNotExisting: IDP Konfiguration existiert nicht
|
||||||
OIDCConfigInvalid: OIDC IDP Konfiguration ist ungültig
|
OIDCConfigInvalid: OIDC IDP Konfiguration ist ungültig
|
||||||
IdpIsNotOIDC: IDP Konfiguration ist nicht vom Typ OIDC
|
IdpIsNotOIDC: IDP Konfiguration ist nicht vom Typ OIDC
|
||||||
|
Domain:
|
||||||
|
AlreadyExists: Domäne existiert bereits
|
||||||
IDP:
|
IDP:
|
||||||
InvalidSearchQuery: Ungültiger Suchparameter
|
InvalidSearchQuery: Ungültiger Suchparameter
|
||||||
LoginPolicy:
|
LoginPolicy:
|
||||||
|
@ -109,6 +109,8 @@ Errors:
|
|||||||
IdpNotExisting: IDP configuration does not exist
|
IdpNotExisting: IDP configuration does not exist
|
||||||
OIDCConfigInvalid: OIDC IDP configuration is invalid
|
OIDCConfigInvalid: OIDC IDP configuration is invalid
|
||||||
IdpIsNotOIDC: IDP configuration is not of type oidc
|
IdpIsNotOIDC: IDP configuration is not of type oidc
|
||||||
|
Domain:
|
||||||
|
AlreadyExists: Domain already exists
|
||||||
IDP:
|
IDP:
|
||||||
InvalidSearchQuery: Ungültiger Suchparameter
|
InvalidSearchQuery: Ungültiger Suchparameter
|
||||||
LoginPolicy:
|
LoginPolicy:
|
||||||
|
@ -15,6 +15,7 @@ type CommandSide struct {
|
|||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
idGenerator id.Generator
|
idGenerator id.Generator
|
||||||
iamID string
|
iamID string
|
||||||
|
iamDomain string
|
||||||
|
|
||||||
idpConfigSecretCrypto crypto.Crypto
|
idpConfigSecretCrypto crypto.Crypto
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
|||||||
eventstore: config.Eventstore,
|
eventstore: config.Eventstore,
|
||||||
idGenerator: id.SonyFlakeGenerator,
|
idGenerator: id.SonyFlakeGenerator,
|
||||||
iamID: config.SystemDefaults.IamID,
|
iamID: config.SystemDefaults.IamID,
|
||||||
|
iamDomain: config.SystemDefaults.Domain,
|
||||||
}
|
}
|
||||||
iam_repo.RegisterEventMappers(repo.eventstore)
|
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//TODO: private
|
||||||
func (r *CommandSide) GetIAM(ctx context.Context, aggregateID string) (*domain.IAM, error) {
|
func (r *CommandSide) GetIAM(ctx context.Context, aggregateID string) (*domain.IAM, error) {
|
||||||
iamWriteModel := NewIAMWriteModel(aggregateID)
|
iamWriteModel := NewIAMWriteModel(aggregateID)
|
||||||
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
||||||
|
@ -25,9 +25,9 @@ func writeModelToIAM(wm *IAMWriteModel) *domain.IAM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeModelToMember(writeModel *IAMMemberWriteModel) *domain.IAMMember {
|
func memberWriteModelToMember(writeModel *MemberWriteModel) *domain.Member {
|
||||||
return &domain.IAMMember{
|
return &domain.Member{
|
||||||
ObjectRoot: writeModelToObjectRoot(writeModel.MemberWriteModel.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||||
Roles: writeModel.Roles,
|
Roles: writeModel.Roles,
|
||||||
UserID: writeModel.UserID,
|
UserID: writeModel.UserID,
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.IAMMember) (*domain.IAMMember, error) {
|
func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||||
//TODO: check if roles valid
|
//TODO: check if roles valid
|
||||||
|
|
||||||
if !member.IsValid() {
|
if !member.IsValid() {
|
||||||
@ -35,11 +35,11 @@ func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.IAMMember
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeModelToMember(addedMember), nil
|
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ChangeIAMMember updates an existing member
|
//ChangeIAMMember updates an existing member
|
||||||
func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.IAMMember) (*domain.IAMMember, error) {
|
func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||||
//TODO: check if roles valid
|
//TODO: check if roles valid
|
||||||
|
|
||||||
if !member.IsValid() {
|
if !member.IsValid() {
|
||||||
@ -67,7 +67,7 @@ func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.IAMMem
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeModelToMember(existingMember), nil
|
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) RemoveIAMMember(ctx context.Context, userID string) error {
|
func (r *CommandSide) RemoveIAMMember(ctx context.Context, userID string) error {
|
||||||
|
@ -8,17 +8,6 @@ import (
|
|||||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) GetDefaultOrgIAMPolicy(ctx context.Context) (*domain.OrgIAMPolicy, error) {
|
|
||||||
policyWriteModel := NewIAMOrgIAMPolicyWriteModel(r.iamID)
|
|
||||||
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
policy := writeModelToOrgIAMPolicy(policyWriteModel)
|
|
||||||
policy.Default = true
|
|
||||||
return policy, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *CommandSide) AddDefaultOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
func (r *CommandSide) AddDefaultOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||||
policy.AggregateID = r.iamID
|
policy.AggregateID = r.iamID
|
||||||
addedPolicy := NewIAMOrgIAMPolicyWriteModel(policy.AggregateID)
|
addedPolicy := NewIAMOrgIAMPolicyWriteModel(policy.AggregateID)
|
||||||
@ -75,6 +64,16 @@ func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *dom
|
|||||||
return writeModelToOrgIAMPolicy(existingPolicy), nil
|
return writeModelToOrgIAMPolicy(existingPolicy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) getDefaultOrgIAMPolicy(ctx context.Context) (*domain.OrgIAMPolicy, error) {
|
||||||
|
policyWriteModel, err := r.defaultOrgIAMPolicyWriteModelByID(ctx, r.iamID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
policy := writeModelToOrgIAMPolicy(policyWriteModel)
|
||||||
|
policy.Default = true
|
||||||
|
return policy, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *CommandSide) defaultOrgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMOrgIAMPolicyWriteModel, err error) {
|
func (r *CommandSide) defaultOrgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMOrgIAMPolicyWriteModel, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
72
internal/v2/command/org.go
Normal file
72
internal/v2/command/org.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) SetUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.User) error {
|
||||||
|
orgAgg, userAgg, orgMemberAgg, err := r.setUpOrg(ctx, organisation, admin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.eventstore.PushAggregates(ctx, orgAgg, userAgg, orgMemberAgg)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) setUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.User) (*org.Aggregate, *user.Aggregate, *org.Aggregate, error) {
|
||||||
|
orgAgg, _, err := r.addOrg(ctx, organisation)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userAgg, _, err := r.addHuman(ctx, orgAgg.ID(), admin.UserName, admin.Human)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addedMember := NewOrgMemberWriteModel(orgAgg.ID(), userAgg.ID())
|
||||||
|
orgMemberAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
|
||||||
|
err = r.addOrgMember(ctx, orgMemberAgg, addedMember, domain.NewMember(orgMemberAgg.ID(), userAgg.ID(), domain.OrgOwnerRole)) //TODO: correct?
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
return orgAgg, userAgg, orgMemberAgg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) addOrg(ctx context.Context, organisation *domain.Org) (_ *org.Aggregate, _ *OrgWriteModel, err error) {
|
||||||
|
if organisation == nil || !organisation.IsValid() {
|
||||||
|
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMM-deLSk", "Errors.Org.Invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
organisation.AggregateID, err = r.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, caos_errs.ThrowInternal(err, "COMMA-OwciI", "Errors.Internal")
|
||||||
|
}
|
||||||
|
organisation.AddIAMDomain(r.iamDomain)
|
||||||
|
addedOrg := NewOrgWriteModel(organisation.AggregateID)
|
||||||
|
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&addedOrg.WriteModel)
|
||||||
|
//TODO: uniqueness org name
|
||||||
|
orgAgg.PushEvents(org.NewOrgAddedEvent(ctx, organisation.Name))
|
||||||
|
for _, orgDomain := range organisation.Domains {
|
||||||
|
if err := r.addOrgDomain(ctx, orgAgg, NewOrgDomainWriteModel(orgAgg.ID(), orgDomain.Domain), orgDomain); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return orgAgg, addedOrg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) getOrgWriteModelByID(ctx context.Context, orgID string) (*OrgWriteModel, error) {
|
||||||
|
orgWriteModel := NewOrgWriteModel(orgID)
|
||||||
|
err := r.eventstore.FilterToQueryReducer(ctx, orgWriteModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return orgWriteModel, nil
|
||||||
|
}
|
@ -4,6 +4,14 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func orgWriteModelToOrg(wm *OrgWriteModel) *domain.Org {
|
||||||
|
return &domain.Org{
|
||||||
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
|
Name: wm.Name,
|
||||||
|
State: wm.State,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func orgWriteModelToOrgIAMPolicy(wm *ORGOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
func orgWriteModelToOrgIAMPolicy(wm *ORGOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
||||||
return &domain.OrgIAMPolicy{
|
return &domain.OrgIAMPolicy{
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
||||||
@ -21,3 +29,14 @@ func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWrit
|
|||||||
HasSymbol: wm.HasSymbol,
|
HasSymbol: wm.HasSymbol,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func orgDomainWriteModelToOrgDomain(wm *OrgDomainWriteModel) *domain.OrgDomain {
|
||||||
|
return &domain.OrgDomain{
|
||||||
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
|
Domain: wm.Domain,
|
||||||
|
Primary: wm.Primary,
|
||||||
|
Verified: wm.Verified,
|
||||||
|
ValidationType: wm.ValidationType,
|
||||||
|
ValidationCode: wm.ValidationCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
43
internal/v2/command/org_domain.go
Normal file
43
internal/v2/command/org_domain.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) AddOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) (*domain.OrgDomain, error) {
|
||||||
|
domainWriteModel := NewOrgDomainWriteModel(orgDomain.AggregateID, orgDomain.Domain)
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||||
|
err := r.addOrgDomain(ctx, orgAgg, domainWriteModel, orgDomain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return orgDomainWriteModelToOrgDomain(domainWriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *org.Aggregate, addedDomain *OrgDomainWriteModel, orgDomain *domain.OrgDomain) error {
|
||||||
|
err := r.eventstore.FilterToQueryReducer(ctx, addedDomain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if addedDomain.State == domain.OrgDomainStateActive {
|
||||||
|
return caos_errs.ThrowAlreadyExists(nil, "COMMA-Bd2jj", "Errors.Org.Domain.AlreadyExists")
|
||||||
|
}
|
||||||
|
orgAgg.PushEvents(org.NewDomainAddedEvent(ctx, orgDomain.Domain))
|
||||||
|
if orgDomain.Verified {
|
||||||
|
//TODO: uniqueness verified domain
|
||||||
|
//TODO: users with verified domain -> domain claimed
|
||||||
|
orgAgg.PushEvents(org.NewDomainVerifiedEvent(ctx, orgDomain.Domain))
|
||||||
|
}
|
||||||
|
if orgDomain.Primary {
|
||||||
|
orgAgg.PushEvents(org.NewDomainPrimarySetEvent(ctx, orgDomain.Domain))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
90
internal/v2/command/org_domain_model.go
Normal file
90
internal/v2/command/org_domain_model.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrgDomainWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Domain string
|
||||||
|
ValidationType domain.OrgDomainValidationType
|
||||||
|
ValidationCode *crypto.CryptoValue
|
||||||
|
Primary bool
|
||||||
|
Verified bool
|
||||||
|
|
||||||
|
State domain.OrgDomainState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgDomainWriteModel(orgID string, domain string) *OrgDomainWriteModel {
|
||||||
|
return &OrgDomainWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
},
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgDomainWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.DomainAddedEvent:
|
||||||
|
if e.Domain != wm.Domain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
case *org.DomainVerificationAddedEvent:
|
||||||
|
if e.Domain != wm.Domain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
case *org.DomainVerificationFailedEvent:
|
||||||
|
if e.Domain != wm.Domain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
case *org.DomainVerifiedEvent:
|
||||||
|
if e.Domain != wm.Domain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
case *org.DomainPrimarySetEvent:
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
case *org.DomainRemovedEvent:
|
||||||
|
if e.Domain != wm.Domain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgDomainWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.DomainAddedEvent:
|
||||||
|
wm.Domain = e.Domain
|
||||||
|
wm.State = domain.OrgDomainStateActive
|
||||||
|
case *org.DomainVerificationAddedEvent:
|
||||||
|
wm.ValidationType = e.ValidationType
|
||||||
|
wm.ValidationCode = e.ValidationCode
|
||||||
|
case *org.DomainVerificationFailedEvent:
|
||||||
|
//TODO: not handled in v1
|
||||||
|
case *org.DomainVerifiedEvent:
|
||||||
|
wm.Verified = true
|
||||||
|
case *org.DomainPrimarySetEvent:
|
||||||
|
wm.Primary = e.Domain == wm.Domain
|
||||||
|
case *org.DomainRemovedEvent:
|
||||||
|
wm.State = domain.OrgDomainStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgDomainWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
112
internal/v2/command/org_member.go
Normal file
112
internal/v2/command/org_member.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) AddOrgMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||||
|
addedMember := NewOrgMemberWriteModel(member.AggregateID, member.UserID)
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
|
||||||
|
err := r.addOrgMember(ctx, orgAgg, addedMember, member)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.eventstore.PushAggregate(ctx, addedMember, orgAgg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) addOrgMember(ctx context.Context, orgAgg *org.Aggregate, addedMember *OrgMemberWriteModel, member *domain.Member) error {
|
||||||
|
//TODO: check if roles valid
|
||||||
|
|
||||||
|
if !member.IsValid() {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "Org-W8m4l", "Errors.Org.MemberInvalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.eventstore.FilterToQueryReducer(ctx, addedMember)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if addedMember.State == domain.MemberStateActive {
|
||||||
|
return errors.ThrowAlreadyExists(nil, "Org-PtXi1", "Errors.Org.Member.AlreadyExists")
|
||||||
|
}
|
||||||
|
|
||||||
|
orgAgg.PushEvents(org.NewMemberAddedEvent(ctx, member.UserID, member.Roles...))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//ChangeOrgMember updates an existing member
|
||||||
|
func (r *CommandSide) ChangeOrgMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||||
|
//TODO: check if roles valid
|
||||||
|
|
||||||
|
if !member.IsValid() {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-LiaZi", "Errors.Org.MemberInvalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingMember, err := r.orgMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-LiaZi", "Errors.Org.Member.RolesNotChanged")
|
||||||
|
}
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
|
||||||
|
orgAgg.PushEvents(org.NewMemberChangedEvent(ctx, member.UserID, member.Roles...))
|
||||||
|
|
||||||
|
events, err := r.eventstore.PushAggregates(ctx, orgAgg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
existingMember.AppendEvents(events...)
|
||||||
|
if err = existingMember.Reduce(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) RemoveOrgMember(ctx context.Context, orgID, userID string) error {
|
||||||
|
m, err := r.orgMemberWriteModelByID(ctx, orgID, userID)
|
||||||
|
if err != nil && !errors.IsNotFound(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
|
||||||
|
orgAgg.PushEvents(org.NewMemberRemovedEvent(ctx, userID))
|
||||||
|
|
||||||
|
return r.eventstore.PushAggregate(ctx, m, orgAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) orgMemberWriteModelByID(ctx context.Context, orgID, userID string) (member *OrgMemberWriteModel, err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
writeModel := NewOrgMemberWriteModel(orgID, userID)
|
||||||
|
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||||
|
return nil, errors.ThrowNotFound(nil, "Org-D8JxR", "Errors.NotFound")
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
@ -1,5 +1,52 @@
|
|||||||
package command
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
type OrgMemberWriteModel struct {
|
type OrgMemberWriteModel struct {
|
||||||
MemberWriteModel
|
MemberWriteModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewOrgMemberWriteModel(orgID, userID string) *OrgMemberWriteModel {
|
||||||
|
return &OrgMemberWriteModel{
|
||||||
|
MemberWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
},
|
||||||
|
UserID: userID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.MemberAddedEvent:
|
||||||
|
if e.UserID != wm.MemberWriteModel.UserID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
|
||||||
|
case *org.MemberChangedEvent:
|
||||||
|
if e.UserID != wm.MemberWriteModel.UserID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
|
||||||
|
case *org.MemberRemovedEvent:
|
||||||
|
if e.UserID != wm.MemberWriteModel.UserID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgMemberWriteModel) Reduce() error {
|
||||||
|
return wm.MemberWriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||||
|
AggregateIDs(wm.MemberWriteModel.AggregateID)
|
||||||
|
}
|
||||||
|
@ -2,10 +2,56 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ORGAggregateFromWriteModel(wm *eventstore.WriteModel) *org.Aggregate {
|
type OrgWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Name string
|
||||||
|
State domain.OrgState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgWriteModel(orgID string) *OrgWriteModel {
|
||||||
|
return &OrgWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
wm.WriteModel.AppendEvents(events...)
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.OrgAddedEvent,
|
||||||
|
*iam.LabelPolicyChangedEvent:
|
||||||
|
wm.WriteModel.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.OrgAddedEvent:
|
||||||
|
wm.Name = e.Name
|
||||||
|
wm.State = domain.OrgStateActive
|
||||||
|
case *org.OrgChangedEvent:
|
||||||
|
wm.Name = e.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OrgAggregateFromWriteModel(wm *eventstore.WriteModel) *org.Aggregate {
|
||||||
return &org.Aggregate{
|
return &org.Aggregate{
|
||||||
Aggregate: *eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion),
|
Aggregate: *eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion),
|
||||||
}
|
}
|
||||||
|
@ -5,32 +5,20 @@ import (
|
|||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) GetOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error) {
|
|
||||||
policy := NewORGOrgIAMPolicyWriteModel(orgID)
|
|
||||||
err := r.eventstore.FilterToQueryReducer(ctx, policy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if policy.State == domain.PolicyStateActive {
|
|
||||||
return orgWriteModelToOrgIAMPolicy(policy), nil
|
|
||||||
}
|
|
||||||
return r.GetDefaultOrgIAMPolicy(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||||
addedPolicy := NewORGOrgIAMPolicyWriteModel(policy.AggregateID)
|
addedPolicy := NewORGOrgIAMPolicyWriteModel(policy.AggregateID)
|
||||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||||
|
err := r.addOrgIAMPolicy(ctx, orgAgg, addedPolicy, policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if addedPolicy.State == domain.PolicyStateActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
orgAgg.PushEvents(org.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||||
orgAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
|
||||||
|
|
||||||
err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg)
|
err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,6 +28,18 @@ func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAM
|
|||||||
return orgWriteModelToOrgIAMPolicy(addedPolicy), nil
|
return orgWriteModelToOrgIAMPolicy(addedPolicy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) addOrgIAMPolicy(ctx context.Context, orgAgg *org.Aggregate, addedPolicy *ORGOrgIAMPolicyWriteModel, policy *domain.OrgIAMPolicy) error {
|
||||||
|
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
|
return caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||||
|
}
|
||||||
|
orgAgg.PushEvents(org.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||||
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
|
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -54,7 +54,7 @@ func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.Org
|
|||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||||
orgAgg.PushEvents(changedEvent)
|
orgAgg.PushEvents(changedEvent)
|
||||||
|
|
||||||
err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg)
|
err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg)
|
||||||
@ -65,6 +65,17 @@ func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.Org
|
|||||||
return orgWriteModelToOrgIAMPolicy(existingPolicy), nil
|
return orgWriteModelToOrgIAMPolicy(existingPolicy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) getOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error) {
|
||||||
|
policy, err := r.orgIAMPolicyWriteModelByID(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if policy.State == domain.PolicyStateActive {
|
||||||
|
return orgWriteModelToOrgIAMPolicy(policy), nil
|
||||||
|
}
|
||||||
|
return r.getDefaultOrgIAMPolicy(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *CommandSide) orgIAMPolicyWriteModelByID(ctx context.Context, orgID string) (policy *ORGOrgIAMPolicyWriteModel, err error) {
|
func (r *CommandSide) orgIAMPolicyWriteModelByID(ctx context.Context, orgID string) (policy *ORGOrgIAMPolicyWriteModel, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||||
)
|
)
|
||||||
@ -48,8 +49,7 @@ type Org struct {
|
|||||||
Name string
|
Name string
|
||||||
Domain string
|
Domain string
|
||||||
OrgIamPolicy bool
|
OrgIamPolicy bool
|
||||||
Users []User
|
Owner User
|
||||||
Owners []string
|
|
||||||
Projects []Project
|
Projects []Project
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,8 +84,43 @@ func (r *CommandSide) SetupStep1(ctx context.Context, iamID string, step1 *Step1
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//create orgs
|
//create orgs
|
||||||
//create projects
|
aggregates := make([]eventstore.Aggregater, 0)
|
||||||
|
for _, organisation := range step1.Orgs {
|
||||||
|
orgAgg, userAgg, orgMemberAgg, err := r.setUpOrg(ctx,
|
||||||
|
&domain.Org{
|
||||||
|
Name: organisation.Name,
|
||||||
|
Domains: []*domain.OrgDomain{{Domain: organisation.Domain}},
|
||||||
|
},
|
||||||
|
&domain.User{
|
||||||
|
UserName: organisation.Owner.UserName,
|
||||||
|
Human: &domain.Human{
|
||||||
|
Profile: &domain.Profile{
|
||||||
|
FirstName: organisation.Owner.FirstName,
|
||||||
|
LastName: organisation.Owner.LastName,
|
||||||
|
},
|
||||||
|
Password: &domain.Password{
|
||||||
|
SecretString: organisation.Owner.Password,
|
||||||
|
},
|
||||||
|
Email: &domain.Email{
|
||||||
|
EmailAddress: organisation.Owner.Email,
|
||||||
|
IsEmailVerified: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if organisation.OrgIamPolicy {
|
||||||
|
err = r.addOrgIAMPolicy(ctx, orgAgg, NewORGOrgIAMPolicyWriteModel(orgAgg.ID()), &domain.OrgIAMPolicy{UserLoginMustBeDomain: false})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aggregates = append(aggregates, orgAgg, userAgg, orgMemberAgg)
|
||||||
|
//projects
|
||||||
//create applications
|
//create applications
|
||||||
|
}
|
||||||
|
|
||||||
//set iam owners
|
//set iam owners
|
||||||
//set global org
|
//set global org
|
||||||
//set iam project id
|
//set iam project id
|
||||||
@ -102,7 +137,7 @@ func (r *CommandSide) SetupStep1(ctx context.Context, iamID string, step1 *Step1
|
|||||||
*/
|
*/
|
||||||
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
|
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
|
||||||
|
|
||||||
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
|
_, err = r.eventstore.PushAggregates(ctx, append(aggregates, iamAgg)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Gr2hh", "Setup Step1 failed")
|
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Gr2hh", "Setup Step1 failed")
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ func (r *CommandSide) ChangeUsername(ctx context.Context, orgID, userID, userNam
|
|||||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.UsernameNotChanged")
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.UsernameNotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2,37 +2,51 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/user"
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, human *domain.Human) (*domain.Human, error) {
|
func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, human *domain.Human) (*domain.Human, error) {
|
||||||
|
userAgg, addedHuman, err := r.addHuman(ctx, orgID, username, human)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeModelToHuman(addedHuman), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) addHuman(ctx context.Context, orgID, username string, human *domain.Human) (*user.Aggregate, *HumanWriteModel, error) {
|
||||||
if !human.IsValid() {
|
if !human.IsValid() {
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
userID, err := r.idGenerator.Next()
|
userID, err := r.idGenerator.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
human.AggregateID = userID
|
human.AggregateID = userID
|
||||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
|
pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
addedHuman := NewHumanWriteModel(human.AggregateID)
|
addedHuman := NewHumanWriteModel(human.AggregateID)
|
||||||
//TODO: Check Unique Username
|
//TODO: Check Unique Username
|
||||||
if err := human.CheckOrgIAMPolicy(username, orgIAMPolicy); err != nil {
|
if err := human.CheckOrgIAMPolicy(username, orgIAMPolicy); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
human.SetNamesAsDisplayname()
|
human.SetNamesAsDisplayname()
|
||||||
if err := human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true); err != nil {
|
if err := human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||||
@ -66,7 +80,7 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma
|
|||||||
if human.IsInitialState() {
|
if human.IsInitialState() {
|
||||||
initCode, err := domain.NewInitUserCode(r.initializeUserCode)
|
initCode, err := domain.NewInitUserCode(r.initializeUserCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry)
|
user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry)
|
||||||
}
|
}
|
||||||
@ -76,19 +90,14 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma
|
|||||||
if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified {
|
if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified {
|
||||||
phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode)
|
phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry)
|
user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry)
|
||||||
} else if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
|
} else if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
|
||||||
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
|
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
return userAgg, addedHuman, nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return writeModelToHuman(addedHuman), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string, human *domain.Human, externalIDP *domain.ExternalIDP) (*domain.Human, error) {
|
func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string, human *domain.Human, externalIDP *domain.ExternalIDP) (*domain.Human, error) {
|
||||||
@ -100,7 +109,7 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
human.AggregateID = userID
|
human.AggregateID = userID
|
||||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ func (r *CommandSide) AddMachine(ctx context.Context, orgID, username string, ma
|
|||||||
}
|
}
|
||||||
//TODO: Check Unique username
|
//TODO: Check Unique username
|
||||||
machine.AggregateID = userID
|
machine.AggregateID = userID
|
||||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,12 @@ type Password struct {
|
|||||||
ChangeRequired bool
|
ChangeRequired bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPassword(password string) *Password {
|
||||||
|
return &Password{
|
||||||
|
SecretString: password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type PasswordCode struct {
|
type PasswordCode struct {
|
||||||
es_models.ObjectRoot
|
es_models.ObjectRoot
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ type IAM struct {
|
|||||||
IAMProjectID string
|
IAMProjectID string
|
||||||
SetUpDone Step
|
SetUpDone Step
|
||||||
SetUpStarted Step
|
SetUpStarted Step
|
||||||
Members []*IAMMember
|
Members []*Member
|
||||||
IDPs []*IDPConfig
|
IDPs []*IDPConfig
|
||||||
DefaultLoginPolicy *LoginPolicy
|
DefaultLoginPolicy *LoginPolicy
|
||||||
DefaultLabelPolicy *LabelPolicy
|
DefaultLabelPolicy *LabelPolicy
|
||||||
|
@ -4,14 +4,24 @@ import (
|
|||||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IAMMember struct {
|
type Member struct {
|
||||||
es_models.ObjectRoot
|
es_models.ObjectRoot
|
||||||
|
|
||||||
UserID string
|
UserID string
|
||||||
Roles []string
|
Roles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IAMMember) IsValid() bool {
|
func NewMember(aggregateID, userID string, roles ...string) *Member {
|
||||||
|
return &Member{
|
||||||
|
ObjectRoot: es_models.ObjectRoot{
|
||||||
|
AggregateID: aggregateID,
|
||||||
|
},
|
||||||
|
UserID: userID,
|
||||||
|
Roles: roles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Member) IsValid() bool {
|
||||||
return i.AggregateID != "" && i.UserID != "" && len(i.Roles) != 0
|
return i.AggregateID != "" && i.UserID != "" && len(i.Roles) != 0
|
||||||
}
|
}
|
||||||
|
|
43
internal/v2/domain/org.go
Normal file
43
internal/v2/domain/org.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Org struct {
|
||||||
|
models.ObjectRoot
|
||||||
|
|
||||||
|
State OrgState
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Domains []*OrgDomain
|
||||||
|
Members []*Member
|
||||||
|
OrgIamPolicy *OrgIAMPolicy
|
||||||
|
LoginPolicy *LoginPolicy
|
||||||
|
LabelPolicy *LabelPolicy
|
||||||
|
PasswordComplexityPolicy *PasswordComplexityPolicy
|
||||||
|
PasswordAgePolicy *PasswordAgePolicy
|
||||||
|
PasswordLockoutPolicy *PasswordLockoutPolicy
|
||||||
|
IDPs []*IDPConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Org) IsValid() bool {
|
||||||
|
return o.Name != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Org) AddIAMDomain(iamDomain string) {
|
||||||
|
o.Domains = append(o.Domains, &OrgDomain{Domain: o.nameForDomain(iamDomain), Verified: true, Primary: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Org) nameForDomain(iamDomain string) string {
|
||||||
|
return strings.ToLower(strings.ReplaceAll(o.Name, " ", "-") + "." + iamDomain)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrgState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrgStateActive OrgState = iota
|
||||||
|
OrgStateInactive
|
||||||
|
)
|
38
internal/v2/domain/org_domain.go
Normal file
38
internal/v2/domain/org_domain.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrgDomain struct {
|
||||||
|
models.ObjectRoot
|
||||||
|
|
||||||
|
Domain string
|
||||||
|
Primary bool
|
||||||
|
Verified bool
|
||||||
|
ValidationType OrgDomainValidationType
|
||||||
|
ValidationCode *crypto.CryptoValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrgDomainValidationType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrgDomainValidationTypeUnspecified OrgDomainValidationType = iota
|
||||||
|
OrgDomainValidationTypeHTTP
|
||||||
|
OrgDomainValidationTypeDNS
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrgDomainState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrgDomainStateUnspecified OrgDomainState = iota
|
||||||
|
OrgDomainStateActive
|
||||||
|
OrgDomainStateRemoved
|
||||||
|
|
||||||
|
orgDomainStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f OrgDomainState) Valid() bool {
|
||||||
|
return f >= 0 && f < orgDomainStateCount
|
||||||
|
}
|
5
internal/v2/domain/roles.go
Normal file
5
internal/v2/domain/roles.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrgOwnerRole = "ORG_OWNER"
|
||||||
|
)
|
222
internal/v2/repository/org/domain.go
Normal file
222
internal/v2/repository/org/domain.go
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
package org
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
domainEventPrefix = orgEventTypePrefix + "domain."
|
||||||
|
OrgDomainAdded = domainEventPrefix + "added"
|
||||||
|
OrgDomainVerificationAdded = domainEventPrefix + "verification.added"
|
||||||
|
OrgDomainVerificationFailed = domainEventPrefix + "verification.failed"
|
||||||
|
OrgDomainVerified = domainEventPrefix + "verified"
|
||||||
|
OrgDomainPrimarySet = domainEventPrefix + "primary.set"
|
||||||
|
OrgDomainRemoved = domainEventPrefix + "removed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DomainAddedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Domain string `json:"domain,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DomainAddedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainAddedEvent(ctx context.Context, domain string) *DomainAddedEvent {
|
||||||
|
return &DomainAddedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgDomainAdded,
|
||||||
|
),
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgDomainAdded := &DomainAddedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgDomainAdded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-GBr52", "unable to unmarshal org domain added")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgDomainAdded, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainVerificationAddedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Domain string `json:"domain,omitempty"`
|
||||||
|
ValidationType domain.OrgDomainValidationType `json:"validationType,omitempty"`
|
||||||
|
ValidationCode *crypto.CryptoValue `json:"validationCode,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DomainVerificationAddedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainVerificationAddedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
domain string,
|
||||||
|
validationType domain.OrgDomainValidationType,
|
||||||
|
validationCode *crypto.CryptoValue) *DomainVerificationAddedEvent {
|
||||||
|
return &DomainVerificationAddedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgDomainVerificationAdded,
|
||||||
|
),
|
||||||
|
Domain: domain,
|
||||||
|
ValidationType: validationType,
|
||||||
|
ValidationCode: validationCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainVerificationAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgDomainVerificationAdded := &DomainVerificationAddedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgDomainVerificationAdded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-NRN32", "unable to unmarshal org domain verification added")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgDomainVerificationAdded, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainVerificationFailedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Domain string `json:"domain,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DomainVerificationFailedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainVerificationFailedEvent(ctx context.Context, domain string) *DomainVerificationFailedEvent {
|
||||||
|
return &DomainVerificationFailedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgDomainVerificationFailed,
|
||||||
|
),
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainVerificationFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgDomainVerificationFailed := &DomainVerificationFailedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgDomainVerificationFailed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-Bhm37", "unable to unmarshal org domain verification failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgDomainVerificationFailed, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainVerifiedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Domain string `json:"domain,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DomainVerifiedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainVerifiedEvent(ctx context.Context, domain string) *DomainVerifiedEvent {
|
||||||
|
return &DomainVerifiedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgDomainVerified,
|
||||||
|
),
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainVerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgDomainVerified := &DomainVerifiedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgDomainVerified)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-BFSwt", "unable to unmarshal org domain verified")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgDomainVerified, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainPrimarySetEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Domain string `json:"domain,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DomainPrimarySetEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainPrimarySetEvent(ctx context.Context, domain string) *DomainPrimarySetEvent {
|
||||||
|
return &DomainPrimarySetEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgDomainPrimarySet,
|
||||||
|
),
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainPrimarySetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgDomainPrimarySet := &DomainPrimarySetEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgDomainPrimarySet)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-N5787", "unable to unmarshal org domain primary set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgDomainPrimarySet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainRemovedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Domain string `json:"domain,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DomainRemovedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainRemovedEvent(ctx context.Context, domain string) *DomainRemovedEvent {
|
||||||
|
return &DomainRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgDomainRemoved,
|
||||||
|
),
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgDomainRemoved := &DomainRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgDomainRemoved)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-BngB2", "unable to unmarshal org domain removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgDomainRemoved, nil
|
||||||
|
}
|
19
internal/v2/repository/org/eventstore.go
Normal file
19
internal/v2/repository/org/eventstore.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package org
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||||
|
es.RegisterFilterEventMapper(OrgAdded, OrgAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgChanged, OrgChangedEventMapper).
|
||||||
|
//RegisterFilterEventMapper(OrgDeactivated, OrgChangedEventMapper). TODO: !
|
||||||
|
//RegisterFilterEventMapper(OrgReactivated, OrgChangedEventMapper).
|
||||||
|
//RegisterFilterEventMapper(OrgRemoved, OrgChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgDomainAdded, DomainAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgDomainVerificationAdded, DomainVerificationAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgDomainVerificationFailed, DomainVerificationFailedEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgDomainVerified, DomainVerifiedEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgDomainPrimarySet, DomainPrimarySetEventMapper).
|
||||||
|
RegisterFilterEventMapper(OrgDomainRemoved, DomainRemovedEventMapper)
|
||||||
|
}
|
82
internal/v2/repository/org/org.go
Normal file
82
internal/v2/repository/org/org.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package org
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrgAdded = orgEventTypePrefix + "added"
|
||||||
|
OrgChanged = orgEventTypePrefix + "changed"
|
||||||
|
OrgDeactivated = orgEventTypePrefix + "deactivated"
|
||||||
|
OrgReactivated = orgEventTypePrefix + "reactivated"
|
||||||
|
OrgRemoved = orgEventTypePrefix + "removed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrgAddedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *OrgAddedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgAddedEvent(ctx context.Context, name string) *OrgAddedEvent {
|
||||||
|
return &OrgAddedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgAdded,
|
||||||
|
),
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OrgAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgAdded := &OrgAddedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgAdded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-Bren2", "unable to unmarshal org added")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgAdded, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrgChangedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *OrgChangedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgChangedEvent(ctx context.Context, name string) *OrgChangedEvent {
|
||||||
|
return &OrgChangedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
OrgChanged,
|
||||||
|
),
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OrgChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
orgChanged := &OrgChangedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, orgChanged)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "ORG-Bren2", "unable to unmarshal org added")
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgChanged, nil
|
||||||
|
}
|
@ -8,14 +8,38 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
OrgIAMPolicyAddedEventType = orgEventTypePrefix + policy.OrgIAMPolicyAddedEventType
|
//TODO: enable when possible
|
||||||
OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType
|
//OrgIAMPolicyAddedEventType = orgEventTypePrefix + policy.OrgIAMPolicyAddedEventType
|
||||||
|
//OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType
|
||||||
|
OrgIAMPolicyAddedEventType = orgEventTypePrefix + "iam.policy.added"
|
||||||
|
OrgIAMPolicyChangedEventType = orgEventTypePrefix + "iam.policy.changed"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrgIAMPolicyAddedEvent struct {
|
type OrgIAMPolicyAddedEvent struct {
|
||||||
policy.OrgIAMPolicyAddedEvent
|
policy.OrgIAMPolicyAddedEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewOrgIAMPolicyAddedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
userLoginMustBeDomain bool,
|
||||||
|
) *OrgIAMPolicyAddedEvent {
|
||||||
|
return &OrgIAMPolicyAddedEvent{
|
||||||
|
OrgIAMPolicyAddedEvent: *policy.NewOrgIAMPolicyAddedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyAddedEventType),
|
||||||
|
userLoginMustBeDomain,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OrgIAMPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e, err := policy.OrgIAMPolicyAddedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OrgIAMPolicyAddedEvent{OrgIAMPolicyAddedEvent: *e.(*policy.OrgIAMPolicyAddedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type OrgIAMPolicyChangedEvent struct {
|
type OrgIAMPolicyChangedEvent struct {
|
||||||
policy.OrgIAMPolicyChangedEvent
|
policy.OrgIAMPolicyChangedEvent
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
//TODO: use for org events as suffix (when possible)
|
||||||
OrgIAMPolicyAddedEventType = "policy.org.iam.added"
|
OrgIAMPolicyAddedEventType = "policy.org.iam.added"
|
||||||
OrgIAMPolicyChangedEventType = "policy.org.iam.changed"
|
OrgIAMPolicyChangedEventType = "policy.org.iam.changed"
|
||||||
)
|
)
|
||||||
|
@ -74,7 +74,7 @@ service AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc SetUpOrg(OrgSetUpRequest) returns (OrgSetUpResponse) {
|
rpc SetUpOrg(OrgSetUpRequest) returns (google.protobuf.Empty) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
post: "/orgs/_setup"
|
post: "/orgs/_setup"
|
||||||
body: "*"
|
body: "*"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user