mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-04 23:45:07 +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
|
||||
AllowRegister: true
|
||||
AllowExternalIdp: true
|
||||
# Orgs:
|
||||
# - Name: 'Global'
|
||||
# Domain: 'global.caos.ch'
|
||||
# Default: true
|
||||
# OrgIamPolicy: true
|
||||
# Users:
|
||||
# - FirstName: 'Global Org'
|
||||
# LastName: 'Administrator'
|
||||
# UserName: 'zitadel-global-org-admin@caos.ch'
|
||||
# Email: 'zitadel-global-org-admin@caos.ch'
|
||||
# Password: 'Password1!'
|
||||
# Owners:
|
||||
# - 'zitadel-global-org-admin@caos.ch'
|
||||
# - Name: 'CAOS AG'
|
||||
# Domain: 'caos.ch'
|
||||
# Users:
|
||||
# - FirstName: 'Zitadel'
|
||||
# LastName: 'Administrator'
|
||||
# UserName: 'zitadel-admin'
|
||||
# Email: 'zitadel-admin@caos.ch'
|
||||
# Password: 'Password1!'
|
||||
# Owners:
|
||||
# - 'zitadel-admin@caos.ch'
|
||||
# Projects:
|
||||
# - Name: 'Zitadel'
|
||||
# OIDCApps:
|
||||
# - Name: 'Management-API'
|
||||
# - Name: 'Auth-API'
|
||||
# - Name: 'Admin-API'
|
||||
# - Name: 'Zitadel Console'
|
||||
# RedirectUris:
|
||||
# - '$ZITADEL_CONSOLE/auth/callback'
|
||||
# PostLogoutRedirectUris:
|
||||
# - '$ZITADEL_CONSOLE/signedout'
|
||||
# ResponseTypes:
|
||||
# - $ZITADEL_CONSOLE_RESPONSE_TYPE
|
||||
# GrantTypes:
|
||||
# - $ZITADEL_CONSOLE_GRANT_TYPE
|
||||
# ApplicationType: 'USER_AGENT'
|
||||
# AuthMethodType: 'NONE'
|
||||
# DevMode: $ZITADEL_CONSOLE_DEV_MODE
|
||||
# Owners:
|
||||
# - 'zitadel-admin@caos.ch'
|
||||
Orgs:
|
||||
- Name: 'Global'
|
||||
Domain: 'global.caos.ch'
|
||||
Default: true
|
||||
OrgIamPolicy: true
|
||||
Owner:
|
||||
FirstName: 'Global Org'
|
||||
LastName: 'Administrator'
|
||||
UserName: 'zitadel-global-org-admin@caos.ch'
|
||||
Email: 'zitadel-global-org-admin@caos.ch'
|
||||
Password: 'Password1!'
|
||||
- Name: 'CAOS AG'
|
||||
Domain: 'caos.ch'
|
||||
Owner:
|
||||
FirstName: 'Zitadel'
|
||||
LastName: 'Administrator'
|
||||
UserName: 'zitadel-admin'
|
||||
Email: 'zitadel-admin@caos.ch'
|
||||
Password: 'Password1!'
|
||||
Projects:
|
||||
- Name: 'Zitadel'
|
||||
OIDCApps:
|
||||
- Name: 'Management-API'
|
||||
- Name: 'Auth-API'
|
||||
- Name: 'Admin-API'
|
||||
- Name: 'Zitadel Console'
|
||||
RedirectUris:
|
||||
- '$ZITADEL_CONSOLE/auth/callback'
|
||||
PostLogoutRedirectUris:
|
||||
- '$ZITADEL_CONSOLE/signedout'
|
||||
ResponseTypes:
|
||||
- $ZITADEL_CONSOLE_RESPONSE_TYPE
|
||||
GrantTypes:
|
||||
- $ZITADEL_CONSOLE_GRANT_TYPE
|
||||
ApplicationType: 'USER_AGENT'
|
||||
AuthMethodType: 'NONE'
|
||||
DevMode: $ZITADEL_CONSOLE_DEV_MODE
|
||||
Owners:
|
||||
- 'zitadel-admin@caos.ch'
|
||||
Step2:
|
||||
DefaultPasswordComplexityPolicy:
|
||||
MinLength: 8
|
||||
|
@ -2,21 +2,17 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
type OrgRepository interface {
|
||||
SetUpOrg(context.Context, *admin_model.SetupOrg) (*admin_model.SetupOrg, error)
|
||||
IsOrgUnique(ctx context.Context, name, domain string) (bool, error)
|
||||
OrgByID(ctx context.Context, id string) (*org_model.Org, error)
|
||||
SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, 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
|
||||
}
|
||||
|
@ -10,21 +10,21 @@ import (
|
||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func addIamMemberToDomain(member *admin.AddIamMemberRequest) *domain.IAMMember {
|
||||
return &domain.IAMMember{
|
||||
func addIamMemberToDomain(member *admin.AddIamMemberRequest) *domain.Member {
|
||||
return &domain.Member{
|
||||
UserID: member.UserId,
|
||||
Roles: member.Roles,
|
||||
}
|
||||
}
|
||||
|
||||
func changeIamMemberToDomain(member *admin.ChangeIamMemberRequest) *domain.IAMMember {
|
||||
return &domain.IAMMember{
|
||||
func changeIamMemberToDomain(member *admin.ChangeIamMemberRequest) *domain.Member {
|
||||
return &domain.Member{
|
||||
UserID: member.UserId,
|
||||
Roles: member.Roles,
|
||||
}
|
||||
}
|
||||
|
||||
func iamMemberFromDomain(member *domain.IAMMember) *admin.IamMember {
|
||||
func iamMemberFromDomain(member *domain.Member) *admin.IamMember {
|
||||
creationDate, err := ptypes.TimestampProto(member.CreationDate)
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Server) SetUpOrg(ctx context.Context, orgSetUp *admin.OrgSetUpRequest) (_ *admin.OrgSetUpResponse, err error) {
|
||||
setUp, err := s.org.SetUpOrg(ctx, setUpRequestToModel(orgSetUp))
|
||||
func (s *Server) SetUpOrg(ctx context.Context, orgSetUp *admin.OrgSetUpRequest) (_ *empty.Empty, err error) {
|
||||
err = s.command.SetUpOrg(ctx, orgCreateRequestToDomain(orgSetUp.Org), userCreateRequestToDomain(orgSetUp.User))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return setUpOrgResponseFromModel(setUp), err
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultOrgIamPolicy(ctx context.Context, _ *empty.Empty) (_ *admin.OrgIamPolicyView, err error) {
|
||||
|
@ -2,9 +2,10 @@ package admin
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
|
||||
admin_model "github.com/caos/zitadel/internal/admin/model"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
@ -14,20 +15,13 @@ import (
|
||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func setUpRequestToModel(setUp *admin.OrgSetUpRequest) *admin_model.SetupOrg {
|
||||
return &admin_model.SetupOrg{
|
||||
Org: orgCreateRequestToModel(setUp.Org),
|
||||
User: userCreateRequestToModel(setUp.User),
|
||||
}
|
||||
}
|
||||
|
||||
func orgCreateRequestToModel(org *admin.CreateOrgRequest) *org_model.Org {
|
||||
o := &org_model.Org{
|
||||
Domains: []*org_model.OrgDomain{},
|
||||
func orgCreateRequestToDomain(org *admin.CreateOrgRequest) *domain.Org {
|
||||
o := &domain.Org{
|
||||
Domains: []*domain.OrgDomain{},
|
||||
Name: org.Name,
|
||||
}
|
||||
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
|
||||
|
@ -3,11 +3,83 @@ package admin
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
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/golang/protobuf/ptypes"
|
||||
"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 {
|
||||
var human *usr_model.Human
|
||||
var machine *usr_model.Machine
|
||||
|
@ -1,6 +1,6 @@
|
||||
package eventstore
|
||||
|
||||
type aggregater interface {
|
||||
type Aggregater interface {
|
||||
//ID returns the aggreagte id
|
||||
ID() string
|
||||
//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 {
|
||||
id string `json:"-"`
|
||||
typ AggregateType `json:"-"`
|
||||
@ -69,32 +69,32 @@ func (a *Aggregate) PushEvents(events ...EventPusher) *Aggregate {
|
||||
return a
|
||||
}
|
||||
|
||||
//ID implements aggregater
|
||||
//ID implements Aggregater
|
||||
func (a *Aggregate) ID() string {
|
||||
return a.id
|
||||
}
|
||||
|
||||
//KeyType implements aggregater
|
||||
//KeyType implements Aggregater
|
||||
func (a *Aggregate) Type() AggregateType {
|
||||
return a.typ
|
||||
}
|
||||
|
||||
//Events implements aggregater
|
||||
//Events implements Aggregater
|
||||
func (a *Aggregate) Events() []EventPusher {
|
||||
return a.events
|
||||
}
|
||||
|
||||
//ResourceOwner implements aggregater
|
||||
//ResourceOwner implements Aggregater
|
||||
func (a *Aggregate) ResourceOwner() string {
|
||||
return a.resourceOwner
|
||||
}
|
||||
|
||||
//Version implements aggregater
|
||||
//Version implements Aggregater
|
||||
func (a *Aggregate) Version() Version {
|
||||
return a.version
|
||||
}
|
||||
|
||||
//PreviousSequence implements aggregater
|
||||
//PreviousSequence implements Aggregater
|
||||
func (a *Aggregate) PreviousSequence() uint64 {
|
||||
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
|
||||
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)
|
||||
if err != nil {
|
||||
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
|
||||
// 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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -63,7 +63,7 @@ func (es *Eventstore) PushAggregates(ctx context.Context, aggregates ...aggregat
|
||||
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))
|
||||
for _, aggregate := range aggregates {
|
||||
var previousEvent *repository.Event
|
||||
|
@ -356,7 +356,7 @@ func Test_eventData(t *testing.T) {
|
||||
|
||||
func TestEventstore_aggregatesToEvents(t *testing.T) {
|
||||
type args struct {
|
||||
aggregates []aggregater
|
||||
aggregates []Aggregater
|
||||
}
|
||||
type res struct {
|
||||
wantErr bool
|
||||
@ -370,7 +370,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
||||
{
|
||||
name: "one aggregate one event",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -403,7 +403,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
||||
{
|
||||
name: "one aggregate multiple events",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -452,7 +452,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
||||
{
|
||||
name: "invalid data",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -473,7 +473,7 @@ func TestEventstore_aggregatesToEvents(t *testing.T) {
|
||||
{
|
||||
name: "multiple aggregates",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -614,7 +614,7 @@ func (repo *testRepo) LatestSequence(ctx context.Context, queryFactory *reposito
|
||||
|
||||
func TestEventstore_Push(t *testing.T) {
|
||||
type args struct {
|
||||
aggregates []aggregater
|
||||
aggregates []Aggregater
|
||||
}
|
||||
type fields struct {
|
||||
repo *testRepo
|
||||
@ -632,7 +632,7 @@ func TestEventstore_Push(t *testing.T) {
|
||||
{
|
||||
name: "one aggregate one event",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -672,7 +672,7 @@ func TestEventstore_Push(t *testing.T) {
|
||||
{
|
||||
name: "one aggregate multiple events",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -731,7 +731,7 @@ func TestEventstore_Push(t *testing.T) {
|
||||
{
|
||||
name: "multiple aggregates",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -815,7 +815,7 @@ func TestEventstore_Push(t *testing.T) {
|
||||
{
|
||||
name: "push fails",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
@ -842,7 +842,7 @@ func TestEventstore_Push(t *testing.T) {
|
||||
{
|
||||
name: "aggreagtes to events mapping fails",
|
||||
args: args{
|
||||
aggregates: []aggregater{
|
||||
aggregates: []Aggregater{
|
||||
&testAggregate{
|
||||
id: "1",
|
||||
events: []EventPusher{
|
||||
|
@ -109,6 +109,8 @@ Errors:
|
||||
IdpNotExisting: IDP Konfiguration existiert nicht
|
||||
OIDCConfigInvalid: OIDC IDP Konfiguration ist ungültig
|
||||
IdpIsNotOIDC: IDP Konfiguration ist nicht vom Typ OIDC
|
||||
Domain:
|
||||
AlreadyExists: Domäne existiert bereits
|
||||
IDP:
|
||||
InvalidSearchQuery: Ungültiger Suchparameter
|
||||
LoginPolicy:
|
||||
|
@ -109,6 +109,8 @@ Errors:
|
||||
IdpNotExisting: IDP configuration does not exist
|
||||
OIDCConfigInvalid: OIDC IDP configuration is invalid
|
||||
IdpIsNotOIDC: IDP configuration is not of type oidc
|
||||
Domain:
|
||||
AlreadyExists: Domain already exists
|
||||
IDP:
|
||||
InvalidSearchQuery: Ungültiger Suchparameter
|
||||
LoginPolicy:
|
||||
|
@ -15,6 +15,7 @@ type CommandSide struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
iamID string
|
||||
iamDomain string
|
||||
|
||||
idpConfigSecretCrypto crypto.Crypto
|
||||
|
||||
@ -37,6 +38,7 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
||||
eventstore: config.Eventstore,
|
||||
idGenerator: id.SonyFlakeGenerator,
|
||||
iamID: config.SystemDefaults.IamID,
|
||||
iamDomain: config.SystemDefaults.Domain,
|
||||
}
|
||||
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
//TODO: private
|
||||
func (r *CommandSide) GetIAM(ctx context.Context, aggregateID string) (*domain.IAM, error) {
|
||||
iamWriteModel := NewIAMWriteModel(aggregateID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
||||
|
@ -25,9 +25,9 @@ func writeModelToIAM(wm *IAMWriteModel) *domain.IAM {
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToMember(writeModel *IAMMemberWriteModel) *domain.IAMMember {
|
||||
return &domain.IAMMember{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.MemberWriteModel.WriteModel),
|
||||
func memberWriteModelToMember(writeModel *MemberWriteModel) *domain.Member {
|
||||
return &domain.Member{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
Roles: writeModel.Roles,
|
||||
UserID: writeModel.UserID,
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
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
|
||||
|
||||
if !member.IsValid() {
|
||||
@ -35,11 +35,11 @@ func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.IAMMember
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToMember(addedMember), nil
|
||||
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
if !member.IsValid() {
|
||||
@ -67,7 +67,7 @@ func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.IAMMem
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToMember(existingMember), nil
|
||||
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
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) {
|
||||
policy.AggregateID = r.iamID
|
||||
addedPolicy := NewIAMOrgIAMPolicyWriteModel(policy.AggregateID)
|
||||
@ -75,6 +64,16 @@ func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *dom
|
||||
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) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
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"
|
||||
)
|
||||
|
||||
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 {
|
||||
return &domain.OrgIAMPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
||||
@ -21,3 +29,14 @@ func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWrit
|
||||
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
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgMemberWriteModel struct {
|
||||
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 (
|
||||
"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"
|
||||
)
|
||||
|
||||
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{
|
||||
Aggregate: *eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion),
|
||||
}
|
||||
|
@ -5,32 +5,20 @@ import (
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"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) {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||
}
|
||||
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
orgAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||
orgAgg.PushEvents(org.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||
|
||||
err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg)
|
||||
if err != nil {
|
||||
@ -40,6 +28,18 @@ func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAM
|
||||
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) {
|
||||
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
|
||||
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")
|
||||
}
|
||||
|
||||
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
orgAgg.PushEvents(changedEvent)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
@ -48,8 +49,7 @@ type Org struct {
|
||||
Name string
|
||||
Domain string
|
||||
OrgIamPolicy bool
|
||||
Users []User
|
||||
Owners []string
|
||||
Owner User
|
||||
Projects []Project
|
||||
}
|
||||
|
||||
@ -84,25 +84,60 @@ func (r *CommandSide) SetupStep1(ctx context.Context, iamID string, step1 *Step1
|
||||
return err
|
||||
}
|
||||
//create orgs
|
||||
//create projects
|
||||
//create applications
|
||||
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
|
||||
}
|
||||
|
||||
//set iam owners
|
||||
//set global org
|
||||
//set iam project id
|
||||
|
||||
/*aggregates:
|
||||
iam:
|
||||
default login policy
|
||||
iam owner
|
||||
org:
|
||||
default
|
||||
caos
|
||||
zitadel
|
||||
iam:
|
||||
default login policy
|
||||
iam owner
|
||||
org:
|
||||
default
|
||||
caos
|
||||
zitadel
|
||||
|
||||
*/
|
||||
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 {
|
||||
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")
|
||||
}
|
||||
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,37 +2,51 @@ 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/user"
|
||||
)
|
||||
|
||||
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() {
|
||||
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()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
human.AggregateID = userID
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
addedHuman := NewHumanWriteModel(human.AggregateID)
|
||||
//TODO: Check Unique Username
|
||||
if err := human.CheckOrgIAMPolicy(username, orgIAMPolicy); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
human.SetNamesAsDisplayname()
|
||||
if err := human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||
@ -66,7 +80,7 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma
|
||||
if human.IsInitialState() {
|
||||
initCode, err := domain.NewInitUserCode(r.initializeUserCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
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 {
|
||||
phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry)
|
||||
} else if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
|
||||
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
|
||||
}
|
||||
|
||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToHuman(addedHuman), nil
|
||||
return userAgg, addedHuman, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
human.AggregateID = userID
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func (r *CommandSide) AddMachine(ctx context.Context, orgID, username string, ma
|
||||
}
|
||||
//TODO: Check Unique username
|
||||
machine.AggregateID = userID
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -15,6 +15,12 @@ type Password struct {
|
||||
ChangeRequired bool
|
||||
}
|
||||
|
||||
func NewPassword(password string) *Password {
|
||||
return &Password{
|
||||
SecretString: password,
|
||||
}
|
||||
}
|
||||
|
||||
type PasswordCode struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
|
@ -11,7 +11,7 @@ type IAM struct {
|
||||
IAMProjectID string
|
||||
SetUpDone Step
|
||||
SetUpStarted Step
|
||||
Members []*IAMMember
|
||||
Members []*Member
|
||||
IDPs []*IDPConfig
|
||||
DefaultLoginPolicy *LoginPolicy
|
||||
DefaultLabelPolicy *LabelPolicy
|
||||
|
@ -4,14 +4,24 @@ import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type IAMMember struct {
|
||||
type Member struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
UserID 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
|
||||
}
|
||||
|
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 (
|
||||
OrgIAMPolicyAddedEventType = orgEventTypePrefix + policy.OrgIAMPolicyAddedEventType
|
||||
OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType
|
||||
//TODO: enable when possible
|
||||
//OrgIAMPolicyAddedEventType = orgEventTypePrefix + policy.OrgIAMPolicyAddedEventType
|
||||
//OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType
|
||||
OrgIAMPolicyAddedEventType = orgEventTypePrefix + "iam.policy.added"
|
||||
OrgIAMPolicyChangedEventType = orgEventTypePrefix + "iam.policy.changed"
|
||||
)
|
||||
|
||||
type OrgIAMPolicyAddedEvent struct {
|
||||
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 {
|
||||
policy.OrgIAMPolicyChangedEvent
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
//TODO: use for org events as suffix (when possible)
|
||||
OrgIAMPolicyAddedEventType = "policy.org.iam.added"
|
||||
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) = {
|
||||
post: "/orgs/_setup"
|
||||
body: "*"
|
||||
|
Loading…
Reference in New Issue
Block a user