feat: set private labeling setting on project (#2184)

* docs: add scope to request private labeling

* feat: add enum to project

* fix: remove unused code, add private labeling setting to query side

* fix: set private labeling depending on setting

* fix: private labeling depending on project setting

* Update proto/zitadel/management.proto

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: rename sql file

* fix: private labeling setting

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Fabi
2021-08-24 08:34:10 +02:00
committed by GitHub
parent 7993d92907
commit 74688394d8
47 changed files with 443 additions and 2047 deletions

View File

@@ -8,14 +8,17 @@ import (
)
type ApplicationView struct {
ID string
ProjectID string
Name string
CreationDate time.Time
ChangeDate time.Time
State AppState
ProjectRoleAssertion bool
ProjectRoleCheck bool
ID string
ProjectID string
Name string
CreationDate time.Time
ChangeDate time.Time
ResourceOwner string
State AppState
ProjectRoleAssertion bool
ProjectRoleCheck bool
HasProjectCheck bool
PrivateLabelingSetting domain.PrivateLabelingSetting
IsOIDC bool
OIDCVersion OIDCVersion

View File

@@ -3,21 +3,23 @@ package model
import (
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/caos/zitadel/internal/domain"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
type Project struct {
es_models.ObjectRoot
State ProjectState
Name string
Members []*ProjectMember
Roles []*ProjectRole
Applications []*Application
Grants []*ProjectGrant
ProjectRoleAssertion bool
ProjectRoleCheck bool
HasProjectCheck bool
State ProjectState
Name string
Members []*ProjectMember
Roles []*ProjectRole
Applications []*Application
Grants []*ProjectGrant
ProjectRoleAssertion bool
ProjectRoleCheck bool
HasProjectCheck bool
PrivateLabelingSetting domain.PrivateLabelingSetting
}
type ProjectChanges struct {
Changes []*ProjectChange
@@ -55,15 +57,6 @@ func (p *Project) IsValid() bool {
return p.Name != ""
}
func (p *Project) GetMember(userID string) (int, *ProjectMember) {
for i, m := range p.Members {
if m.UserID == userID {
return i, m
}
}
return -1, nil
}
func (p *Project) ContainsRole(role *ProjectRole) bool {
for _, r := range p.Roles {
if r.Key == role.Key {

View File

@@ -8,16 +8,17 @@ import (
)
type ProjectView struct {
ProjectID string
Name string
CreationDate time.Time
ChangeDate time.Time
State ProjectState
ResourceOwner string
ProjectRoleAssertion bool
ProjectRoleCheck bool
HasProjectCheck bool
Sequence uint64
ProjectID string
Name string
CreationDate time.Time
ChangeDate time.Time
State ProjectState
ResourceOwner string
ProjectRoleAssertion bool
ProjectRoleCheck bool
HasProjectCheck bool
PrivateLabelingSetting domain.PrivateLabelingSetting
Sequence uint64
}
type ProjectViewSearchRequest struct {

View File

@@ -1,35 +0,0 @@
package eventsourcing
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/cache"
"github.com/caos/zitadel/internal/cache/config"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
)
type ProjectCache struct {
projectCache cache.Cache
}
func StartCache(conf *config.CacheConfig) (*ProjectCache, error) {
projectCache, err := conf.Config.NewCache()
logging.Log("EVENT-CsHdo").OnError(err).Panic("unable to create project cache")
return &ProjectCache{projectCache: projectCache}, nil
}
func (c *ProjectCache) getProject(ID string) (project *model.Project) {
project = &model.Project{ObjectRoot: models.ObjectRoot{AggregateID: ID}}
if err := c.projectCache.Get(ID, project); err != nil {
logging.Log("EVENT-tMydV").WithError(err).Debug("error in getting cache")
}
return project
}
func (c *ProjectCache) cacheProject(project *model.Project) {
err := c.projectCache.Set(project.AggregateID, project)
if err != nil {
logging.Log("EVENT-3wKzj").WithError(err).Debug("error in setting project cache")
}
}

View File

@@ -1,46 +0,0 @@
package eventsourcing
//
//import (
// "github.com/caos/zitadel/internal/cache/config"
// sd "github.com/caos/zitadel/internal/config/systemdefaults"
// "github.com/caos/zitadel/internal/crypto"
// es_int "github.com/caos/zitadel/internal/eventstore"
// "github.com/caos/zitadel/internal/id"
//)
//
//const (
// projectOwnerRole = "PROJECT_OWNER"
// projectOwnerGlobalRole = "PROJECT_OWNER_GLOBAL"
//)
//
//type ProjectEventstore struct {
// es_int.Eventstore
// projectCache *ProjectCache
// passwordAlg crypto.HashAlgorithm
// pwGenerator crypto.Generator
// idGenerator id.Generator
// ClientKeySize int
//}
//
//type ProjectConfig struct {
// es_int.Eventstore
// Cache *config.CacheConfig
//}
//
//func StartProject(conf ProjectConfig, systemDefaults sd.SystemDefaults) (*ProjectEventstore, error) {
// projectCache, err := StartCache(conf.Cache)
// if err != nil {
// return nil, err
// }
// passwordAlg := crypto.NewBCrypt(systemDefaults.SecretGenerators.PasswordSaltCost)
// pwGenerator := crypto.NewHashGenerator(systemDefaults.SecretGenerators.ClientSecretGenerator, passwordAlg)
// return &ProjectEventstore{
// Eventstore: conf.Eventstore,
// projectCache: projectCache,
// passwordAlg: passwordAlg,
// pwGenerator: pwGenerator,
// idGenerator: id.SonyFlakeGenerator,
// ClientKeySize: int(systemDefaults.SecretGenerators.ApplicationKeySize),
// }, nil
//}

View File

@@ -6,7 +6,6 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
)
@@ -51,36 +50,6 @@ func APIConfigToModel(config *APIConfig) *model.APIConfig {
return oidcConfig
}
func (p *Project) appendAddAPIConfigEvent(event *es_models.Event) error {
config := new(APIConfig)
err := config.setData(event)
if err != nil {
return err
}
config.ObjectRoot.CreationDate = event.CreationDate
if i, a := GetApplication(p.Applications, config.AppID); a != nil {
p.Applications[i].Type = int32(model.AppTypeAPI)
p.Applications[i].APIConfig = config
}
return nil
}
func (p *Project) appendChangeAPIConfigEvent(event *es_models.Event) error {
config := new(APIConfig)
err := config.setData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, config.AppID); a != nil {
if p.Applications[i].APIConfig == nil {
return errors.ThrowInvalidArgument(nil, "MODEL-ADbsd", "api config is nil")
}
return p.Applications[i].APIConfig.setData(event)
}
return nil
}
func (o *APIConfig) setData(event *es_models.Event) error {
o.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, o); err != nil {

View File

@@ -6,7 +6,6 @@ import (
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
)
type Application struct {
@@ -33,116 +32,6 @@ func GetApplication(apps []*Application, id string) (int, *Application) {
return -1, nil
}
func (a *Application) Changes(changed *Application) map[string]interface{} {
changes := make(map[string]interface{}, 1)
changes["appId"] = a.AppID
if changed.Name != "" && a.Name != changed.Name {
changes["name"] = changed.Name
}
return changes
}
func AppsToModel(apps []*Application) []*model.Application {
convertedApps := make([]*model.Application, len(apps))
for i, a := range apps {
convertedApps[i] = AppToModel(a)
}
return convertedApps
}
func AppsFromModel(apps []*model.Application) []*Application {
convertedApps := make([]*Application, len(apps))
for i, a := range apps {
convertedApps[i] = AppFromModel(a)
}
return convertedApps
}
func AppFromModel(app *model.Application) *Application {
converted := &Application{
ObjectRoot: app.ObjectRoot,
AppID: app.AppID,
Name: app.Name,
State: int32(app.State),
Type: int32(app.Type),
}
if app.OIDCConfig != nil {
converted.OIDCConfig = OIDCConfigFromModel(app.OIDCConfig)
}
if app.APIConfig != nil {
converted.APIConfig = APIConfigFromModel(app.APIConfig)
}
return converted
}
func AppToModel(app *Application) *model.Application {
converted := &model.Application{
ObjectRoot: app.ObjectRoot,
AppID: app.AppID,
Name: app.Name,
State: model.AppState(app.State),
Type: model.AppType(app.Type),
}
if app.OIDCConfig != nil {
converted.OIDCConfig = OIDCConfigToModel(app.OIDCConfig)
}
if app.APIConfig != nil {
converted.APIConfig = APIConfigToModel(app.APIConfig)
}
return converted
}
func (p *Project) appendAddAppEvent(event *es_models.Event) error {
app := new(Application)
err := app.setData(event)
if err != nil {
return err
}
app.ObjectRoot.CreationDate = event.CreationDate
p.Applications = append(p.Applications, app)
return nil
}
func (p *Project) appendChangeAppEvent(event *es_models.Event) error {
app := new(Application)
err := app.setData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, app.AppID); a != nil {
return p.Applications[i].setData(event)
}
return nil
}
func (p *Project) appendRemoveAppEvent(event *es_models.Event) error {
app := new(Application)
err := app.setData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, app.AppID); a != nil {
p.Applications[i] = p.Applications[len(p.Applications)-1]
p.Applications[len(p.Applications)-1] = nil
p.Applications = p.Applications[:len(p.Applications)-1]
}
return nil
}
func (p *Project) appendAppStateEvent(event *es_models.Event, state model.AppState) error {
app := new(Application)
err := app.setData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, app.AppID); a != nil {
a.State = int32(state)
p.Applications[i] = a
}
return nil
}
func (a *Application) setData(event *es_models.Event) error {
a.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, a); err != nil {

View File

@@ -1,246 +0,0 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
)
func TestApplicationChanges(t *testing.T) {
type args struct {
existingProject *Application
newProject *Application
}
type res struct {
changesLen int
}
tests := []struct {
name string
args args
res res
}{
{
name: "application name changes",
args: args{
existingProject: &Application{AppID: "AppID", Name: "Name"},
newProject: &Application{AppID: "AppID", Name: "NameChanged"},
},
res: res{
changesLen: 2,
},
},
{
name: "no changes",
args: args{
existingProject: &Application{AppID: "AppID", Name: "Name"},
newProject: &Application{AppID: "AppID", Name: "Name"},
},
res: res{
changesLen: 1,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
changes := tt.args.existingProject.Changes(tt.args.newProject)
if len(changes) != tt.res.changesLen {
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
}
})
}
}
func TestAppendAddAppEvent(t *testing.T) {
type args struct {
project *Project
app *Application
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append add application event",
args: args{
project: &Project{},
app: &Application{Name: "Application"},
event: &es_models.Event{},
},
result: &Project{
Applications: []*Application{
{Name: "Application"},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.app != nil {
data, _ := json.Marshal(tt.args.app)
tt.args.event.Data = data
}
tt.args.project.appendAddAppEvent(tt.args.event)
if len(tt.args.project.Applications) != 1 {
t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications))
}
if tt.args.project.Applications[0] == tt.result.Applications[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0])
}
})
}
}
func TestAppendChangeAppEvent(t *testing.T) {
type args struct {
project *Project
app *Application
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append change application event",
args: args{
project: &Project{
Applications: []*Application{
{Name: "Application"},
},
},
app: &Application{Name: "Application Change"},
event: &es_models.Event{},
},
result: &Project{
Applications: []*Application{
{Name: "Application Change"},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.app != nil {
data, _ := json.Marshal(tt.args.app)
tt.args.event.Data = data
}
tt.args.project.appendChangeAppEvent(tt.args.event)
if len(tt.args.project.Applications) != 1 {
t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications))
}
if tt.args.project.Applications[0] == tt.result.Applications[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0])
}
})
}
}
func TestAppendRemoveAppEvent(t *testing.T) {
type args struct {
project *Project
app *Application
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append remove application event",
args: args{
project: &Project{
Applications: []*Application{
{AppID: "AppID", Name: "Application"},
},
},
app: &Application{AppID: "AppID", Name: "Application"},
event: &es_models.Event{},
},
result: &Project{Applications: []*Application{}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.app != nil {
data, _ := json.Marshal(tt.args.app)
tt.args.event.Data = data
}
tt.args.project.appendRemoveAppEvent(tt.args.event)
if len(tt.args.project.Applications) != 0 {
t.Errorf("got wrong result should have no apps actual: %v ", len(tt.args.project.Applications))
}
})
}
}
func TestAppendAppStateEvent(t *testing.T) {
type args struct {
project *Project
app *ApplicationID
event *es_models.Event
state model.AppState
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append deactivate application event",
args: args{
project: &Project{
Applications: []*Application{
{AppID: "AppID", Name: "Application", State: int32(model.AppStateActive)},
},
},
app: &ApplicationID{AppID: "AppID"},
event: &es_models.Event{},
state: model.AppStateInactive,
},
result: &Project{
Applications: []*Application{
{AppID: "AppID", Name: "Application", State: int32(model.AppStateInactive)},
},
},
},
{
name: "append reactivate application event",
args: args{
project: &Project{
Applications: []*Application{
{AppID: "AppID", Name: "Application", State: int32(model.AppStateInactive)},
},
},
app: &ApplicationID{AppID: "AppID"},
event: &es_models.Event{},
state: model.AppStateActive,
},
result: &Project{
Applications: []*Application{
{AppID: "AppID", Name: "Application", State: int32(model.AppStateActive)},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.app != nil {
data, _ := json.Marshal(tt.args.app)
tt.args.event.Data = data
}
tt.args.project.appendAppStateEvent(tt.args.event, tt.args.state)
if len(tt.args.project.Applications) != 1 {
t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications))
}
if tt.args.project.Applications[0] == tt.result.Applications[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0])
}
})
}
}

View File

@@ -2,7 +2,6 @@ package model
import (
"encoding/json"
"reflect"
"time"
"github.com/caos/logging"
@@ -35,187 +34,6 @@ type OIDCConfig struct {
ClientKeys []*ClientKey `json:"-"`
}
func (c *OIDCConfig) Changes(changed *OIDCConfig) map[string]interface{} {
changes := make(map[string]interface{}, 1)
changes["appId"] = c.AppID
if !reflect.DeepEqual(c.RedirectUris, changed.RedirectUris) {
changes["redirectUris"] = changed.RedirectUris
}
if !reflect.DeepEqual(c.ResponseTypes, changed.ResponseTypes) {
changes["responseTypes"] = changed.ResponseTypes
}
if !reflect.DeepEqual(c.GrantTypes, changed.GrantTypes) {
changes["grantTypes"] = changed.GrantTypes
}
if c.ApplicationType != changed.ApplicationType {
changes["applicationType"] = changed.ApplicationType
}
if c.AuthMethodType != changed.AuthMethodType {
changes["authMethodType"] = changed.AuthMethodType
}
if c.Version != changed.Version {
changes["oidcVersion"] = changed.Version
}
if !reflect.DeepEqual(c.PostLogoutRedirectUris, changed.PostLogoutRedirectUris) {
changes["postLogoutRedirectUris"] = changed.PostLogoutRedirectUris
}
if c.DevMode != changed.DevMode {
changes["devMode"] = changed.DevMode
}
if c.AccessTokenType != changed.AccessTokenType {
changes["accessTokenType"] = changed.AccessTokenType
}
if c.AccessTokenRoleAssertion != changed.AccessTokenRoleAssertion {
changes["accessTokenRoleAssertion"] = changed.AccessTokenRoleAssertion
}
if c.IDTokenRoleAssertion != changed.IDTokenRoleAssertion {
changes["idTokenRoleAssertion"] = changed.IDTokenRoleAssertion
}
if c.IDTokenUserinfoAssertion != changed.IDTokenUserinfoAssertion {
changes["idTokenUserinfoAssertion"] = changed.IDTokenUserinfoAssertion
}
if c.ClockSkew != changed.ClockSkew {
changes["clockSkew"] = changed.ClockSkew
}
return changes
}
func OIDCConfigFromModel(config *model.OIDCConfig) *OIDCConfig {
responseTypes := make([]int32, len(config.ResponseTypes))
for i, rt := range config.ResponseTypes {
responseTypes[i] = int32(rt)
}
grantTypes := make([]int32, len(config.GrantTypes))
for i, rt := range config.GrantTypes {
grantTypes[i] = int32(rt)
}
return &OIDCConfig{
ObjectRoot: config.ObjectRoot,
AppID: config.AppID,
Version: int32(config.OIDCVersion),
ClientID: config.ClientID,
ClientSecret: config.ClientSecret,
RedirectUris: config.RedirectUris,
ResponseTypes: responseTypes,
GrantTypes: grantTypes,
ApplicationType: int32(config.ApplicationType),
AuthMethodType: int32(config.AuthMethodType),
PostLogoutRedirectUris: config.PostLogoutRedirectUris,
DevMode: config.DevMode,
AccessTokenType: int32(config.AccessTokenType),
AccessTokenRoleAssertion: config.AccessTokenRoleAssertion,
IDTokenRoleAssertion: config.IDTokenRoleAssertion,
IDTokenUserinfoAssertion: config.IDTokenUserinfoAssertion,
ClockSkew: config.ClockSkew,
}
}
func OIDCConfigToModel(config *OIDCConfig) *model.OIDCConfig {
responseTypes := make([]model.OIDCResponseType, len(config.ResponseTypes))
for i, rt := range config.ResponseTypes {
responseTypes[i] = model.OIDCResponseType(rt)
}
grantTypes := make([]model.OIDCGrantType, len(config.GrantTypes))
for i, rt := range config.GrantTypes {
grantTypes[i] = model.OIDCGrantType(rt)
}
oidcConfig := &model.OIDCConfig{
ObjectRoot: config.ObjectRoot,
AppID: config.AppID,
OIDCVersion: model.OIDCVersion(config.Version),
ClientID: config.ClientID,
ClientSecret: config.ClientSecret,
RedirectUris: config.RedirectUris,
ResponseTypes: responseTypes,
GrantTypes: grantTypes,
ApplicationType: model.OIDCApplicationType(config.ApplicationType),
AuthMethodType: model.OIDCAuthMethodType(config.AuthMethodType),
PostLogoutRedirectUris: config.PostLogoutRedirectUris,
DevMode: config.DevMode,
AccessTokenType: model.OIDCTokenType(config.AccessTokenType),
AccessTokenRoleAssertion: config.AccessTokenRoleAssertion,
IDTokenRoleAssertion: config.IDTokenRoleAssertion,
IDTokenUserinfoAssertion: config.IDTokenUserinfoAssertion,
ClockSkew: config.ClockSkew,
ClientKeys: ClientKeysToModel(config.ClientKeys),
}
oidcConfig.FillCompliance()
return oidcConfig
}
func (p *Project) appendAddOIDCConfigEvent(event *es_models.Event) error {
config := new(OIDCConfig)
err := config.setData(event)
if err != nil {
return err
}
config.ObjectRoot.CreationDate = event.CreationDate
if i, a := GetApplication(p.Applications, config.AppID); a != nil {
p.Applications[i].Type = int32(model.AppTypeOIDC)
p.Applications[i].OIDCConfig = config
}
return nil
}
func (p *Project) appendChangeOIDCConfigEvent(event *es_models.Event) error {
config := new(OIDCConfig)
err := config.setData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, config.AppID); a != nil {
if p.Applications[i].OIDCConfig == nil {
return errors.ThrowInvalidArgument(nil, "MODEL-aBR5G", "oidc config is nil")
}
return p.Applications[i].OIDCConfig.setData(event)
}
return nil
}
func (p *Project) appendAddClientKeyEvent(event *es_models.Event) error {
key := new(ClientKey)
err := key.SetData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, key.ApplicationID); a != nil {
if a.OIDCConfig != nil {
p.Applications[i].OIDCConfig.ClientKeys = append(p.Applications[i].OIDCConfig.ClientKeys, key)
}
if a.APIConfig != nil {
p.Applications[i].APIConfig.ClientKeys = append(p.Applications[i].APIConfig.ClientKeys, key)
}
}
return nil
}
func (p *Project) appendRemoveClientKeyEvent(event *es_models.Event) error {
key := new(ClientKey)
err := key.SetData(event)
if err != nil {
return err
}
if i, a := GetApplication(p.Applications, key.ApplicationID); a != nil {
if a.OIDCConfig != nil {
if j, k := GetClientKey(p.Applications[i].OIDCConfig.ClientKeys, key.KeyID); k != nil {
p.Applications[i].OIDCConfig.ClientKeys[j] = p.Applications[i].OIDCConfig.ClientKeys[len(p.Applications[i].OIDCConfig.ClientKeys)-1]
p.Applications[i].OIDCConfig.ClientKeys[len(p.Applications[i].OIDCConfig.ClientKeys)-1] = nil
p.Applications[i].OIDCConfig.ClientKeys = p.Applications[i].OIDCConfig.ClientKeys[:len(p.Applications[i].OIDCConfig.ClientKeys)-1]
}
}
if a.APIConfig != nil {
if j, k := GetClientKey(p.Applications[i].APIConfig.ClientKeys, key.KeyID); k != nil {
p.Applications[i].APIConfig.ClientKeys[j] = p.Applications[i].APIConfig.ClientKeys[len(p.Applications[i].APIConfig.ClientKeys)-1]
p.Applications[i].APIConfig.ClientKeys[len(p.Applications[i].APIConfig.ClientKeys)-1] = nil
p.Applications[i].APIConfig.ClientKeys = p.Applications[i].APIConfig.ClientKeys[:len(p.Applications[i].APIConfig.ClientKeys)-1]
}
}
}
return nil
}
func (o *OIDCConfig) setData(event *es_models.Event) error {
o.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, o); err != nil {
@@ -225,15 +43,6 @@ func (o *OIDCConfig) setData(event *es_models.Event) error {
return nil
}
func GetClientKey(keys []*ClientKey, id string) (int, *ClientKey) {
for i, k := range keys {
if k.KeyID == id {
return i, k
}
}
return -1, nil
}
type ClientKey struct {
es_models.ObjectRoot `json:"-"`
ApplicationID string `json:"applicationId,omitempty"`
@@ -278,17 +87,6 @@ func (key *ClientKey) AppendEvent(event *es_models.Event) (err error) {
return err
}
func ClientKeyFromModel(key *model.ClientKey) *ClientKey {
return &ClientKey{
ObjectRoot: key.ObjectRoot,
ExpirationDate: key.ExpirationDate,
ApplicationID: key.ApplicationID,
ClientID: key.ClientID,
KeyID: key.KeyID,
Type: int32(key.Type),
}
}
func ClientKeysToModel(keys []*ClientKey) []*model.ClientKey {
clientKeys := make([]*model.ClientKey, len(keys))
for i, key := range keys {

View File

@@ -1,198 +0,0 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestOIDCConfigChanges(t *testing.T) {
type args struct {
existingConfig *OIDCConfig
newConfig *OIDCConfig
}
type res struct {
changesLen int
}
tests := []struct {
name string
args args
res res
}{
{
name: "all possible values change",
args: args{
existingConfig: &OIDCConfig{
AppID: "AppID",
RedirectUris: []string{"RedirectUris"},
ResponseTypes: []int32{1},
GrantTypes: []int32{1},
ApplicationType: 1,
AuthMethodType: 1,
PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"},
},
newConfig: &OIDCConfig{
AppID: "AppID",
RedirectUris: []string{"RedirectUrisChanged"},
ResponseTypes: []int32{2},
GrantTypes: []int32{2},
ApplicationType: 2,
AuthMethodType: 2,
PostLogoutRedirectUris: []string{"PostLogoutRedirectUrisChanged"},
},
},
res: res{
changesLen: 7,
},
},
{
name: "no changes",
args: args{
existingConfig: &OIDCConfig{
AppID: "AppID",
RedirectUris: []string{"RedirectUris"},
ResponseTypes: []int32{1},
GrantTypes: []int32{1},
ApplicationType: 1,
AuthMethodType: 1,
PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"},
},
newConfig: &OIDCConfig{
AppID: "AppID",
RedirectUris: []string{"RedirectUris"},
ResponseTypes: []int32{1},
GrantTypes: []int32{1},
ApplicationType: 1,
AuthMethodType: 1,
PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"},
},
},
res: res{
changesLen: 1,
},
},
{
name: "change not changeable attributes",
args: args{
existingConfig: &OIDCConfig{
AppID: "AppID",
ClientID: "ClientID",
},
newConfig: &OIDCConfig{
AppID: "AppIDChange",
ClientID: "ClientIDChange",
},
},
res: res{
changesLen: 1,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
changes := tt.args.existingConfig.Changes(tt.args.newConfig)
if len(changes) != tt.res.changesLen {
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
}
})
}
}
func TestAppendAddOIDCConfigEvent(t *testing.T) {
type args struct {
project *Project
config *OIDCConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append add application event",
args: args{
project: &Project{
Applications: []*Application{
{AppID: "AppID"},
},
},
config: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"},
event: &es_models.Event{},
},
result: &Project{
Applications: []*Application{
{AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"}},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.config != nil {
data, _ := json.Marshal(tt.args.config)
tt.args.event.Data = data
}
tt.args.project.appendAddOIDCConfigEvent(tt.args.event)
if len(tt.args.project.Applications) != 1 {
t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications))
}
if tt.args.project.Applications[0].OIDCConfig == nil {
t.Errorf("got wrong result should have oidc config actual: %v ", tt.args.project.Applications[0].OIDCConfig)
}
if tt.args.project.Applications[0] == tt.result.Applications[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0])
}
})
}
}
func TestAppendChangeOIDCConfigEvent(t *testing.T) {
type args struct {
project *Project
config *OIDCConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append change application event",
args: args{
project: &Project{
Applications: []*Application{
{AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"}},
},
},
config: &OIDCConfig{AppID: "AppID", ClientID: "ClientID Changed"},
event: &es_models.Event{},
},
result: &Project{
Applications: []*Application{
{AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID Changed"}},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.config != nil {
data, _ := json.Marshal(tt.args.config)
tt.args.event.Data = data
}
tt.args.project.appendChangeOIDCConfigEvent(tt.args.event)
if len(tt.args.project.Applications) != 1 {
t.Errorf("got wrong result should have one app actual: %v ", len(tt.args.project.Applications))
}
if tt.args.project.Applications[0].OIDCConfig == nil {
t.Errorf("got wrong result should have oidc config actual: %v ", tt.args.project.Applications[0].OIDCConfig)
}
if tt.args.project.Applications[0] == tt.result.Applications[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Applications[0], tt.args.project.Applications[0])
}
})
}
}

View File

@@ -15,32 +15,20 @@ const (
type Project struct {
es_models.ObjectRoot
Name string `json:"name,omitempty"`
ProjectRoleAssertion bool `json:"projectRoleAssertion,omitempty"`
ProjectRoleCheck bool `json:"projectRoleCheck,omitempty"`
HasProjectCheck bool `json:"hasProjectCheck,omitempty"`
State int32 `json:"-"`
Members []*ProjectMember `json:"-"`
Roles []*ProjectRole `json:"-"`
Applications []*Application `json:"-"`
Grants []*ProjectGrant `json:"-"`
Name string `json:"name,omitempty"`
ProjectRoleAssertion bool `json:"projectRoleAssertion,omitempty"`
ProjectRoleCheck bool `json:"projectRoleCheck,omitempty"`
HasProjectCheck bool `json:"hasProjectCheck,omitempty"`
State int32 `json:"-"`
}
func ProjectToModel(project *Project) *model.Project {
members := ProjectMembersToModel(project.Members)
roles := ProjectRolesToModel(project.Roles)
apps := AppsToModel(project.Applications)
grants := GrantsToModel(project.Grants)
return &model.Project{
ObjectRoot: project.ObjectRoot,
Name: project.Name,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
State: model.ProjectState(project.State),
Members: members,
Roles: roles,
Applications: apps,
Grants: grants,
}
}
@@ -73,60 +61,6 @@ func (p *Project) AppendEvent(event *es_models.Event) error {
return p.appendReactivatedEvent()
case ProjectRemoved:
return p.appendRemovedEvent()
case ProjectMemberAdded:
return p.appendAddMemberEvent(event)
case ProjectMemberChanged:
return p.appendChangeMemberEvent(event)
case ProjectMemberRemoved:
return p.appendRemoveMemberEvent(event)
case ProjectMemberCascadeRemoved:
return p.appendRemoveMemberEvent(event)
case ProjectRoleAdded:
return p.appendAddRoleEvent(event)
case ProjectRoleChanged:
return p.appendChangeRoleEvent(event)
case ProjectRoleRemoved:
return p.appendRemoveRoleEvent(event)
case ApplicationAdded:
return p.appendAddAppEvent(event)
case ApplicationChanged:
return p.appendChangeAppEvent(event)
case ApplicationRemoved:
return p.appendRemoveAppEvent(event)
case ApplicationDeactivated:
return p.appendAppStateEvent(event, model.AppStateInactive)
case ApplicationReactivated:
return p.appendAppStateEvent(event, model.AppStateActive)
case OIDCConfigAdded:
return p.appendAddOIDCConfigEvent(event)
case OIDCConfigChanged, OIDCConfigSecretChanged:
return p.appendChangeOIDCConfigEvent(event)
case APIConfigAdded:
return p.appendAddAPIConfigEvent(event)
case APIConfigChanged, APIConfigSecretChanged:
return p.appendChangeAPIConfigEvent(event)
case ClientKeyAdded:
return p.appendAddClientKeyEvent(event)
case ClientKeyRemoved:
return p.appendRemoveClientKeyEvent(event)
case ProjectGrantAdded:
return p.appendAddGrantEvent(event)
case ProjectGrantChanged, ProjectGrantCascadeChanged:
return p.appendChangeGrantEvent(event)
case ProjectGrantDeactivated:
return p.appendGrantStateEvent(event, model.ProjectGrantStateInactive)
case ProjectGrantReactivated:
return p.appendGrantStateEvent(event, model.ProjectGrantStateActive)
case ProjectGrantRemoved:
return p.appendRemoveGrantEvent(event)
case ProjectGrantMemberAdded:
return p.appendAddGrantMemberEvent(event)
case ProjectGrantMemberChanged:
return p.appendChangeGrantMemberEvent(event)
case ProjectGrantMemberRemoved:
return p.appendRemoveGrantMemberEvent(event)
case ProjectGrantMemberCascadeRemoved:
return p.appendRemoveGrantMemberEvent(event)
}
return nil
}

View File

@@ -2,10 +2,11 @@ package model
import (
"encoding/json"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
"reflect"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
type ProjectGrant struct {
@@ -31,15 +32,6 @@ func GetProjectGrant(grants []*ProjectGrant, id string) (int, *ProjectGrant) {
return -1, nil
}
func GetProjectGrantByOrgID(grants []*ProjectGrant, resourceOwner string) (int, *ProjectGrant) {
for i, g := range grants {
if g.GrantedOrgID == resourceOwner {
return i, g
}
}
return -1, nil
}
func (g *ProjectGrant) Changes(changed *ProjectGrant) map[string]interface{} {
changes := make(map[string]interface{}, 1)
changes["grantId"] = g.GrantID
@@ -49,97 +41,6 @@ func (g *ProjectGrant) Changes(changed *ProjectGrant) map[string]interface{} {
return changes
}
func GrantsToModel(grants []*ProjectGrant) []*model.ProjectGrant {
convertedGrants := make([]*model.ProjectGrant, len(grants))
for i, g := range grants {
convertedGrants[i] = GrantToModel(g)
}
return convertedGrants
}
func GrantsFromModel(grants []*model.ProjectGrant) []*ProjectGrant {
convertedGrants := make([]*ProjectGrant, len(grants))
for i, g := range grants {
convertedGrants[i] = GrantFromModel(g)
}
return convertedGrants
}
func GrantFromModel(grant *model.ProjectGrant) *ProjectGrant {
members := GrantMembersFromModel(grant.Members)
return &ProjectGrant{
ObjectRoot: grant.ObjectRoot,
GrantID: grant.GrantID,
GrantedOrgID: grant.GrantedOrgID,
State: int32(grant.State),
RoleKeys: grant.RoleKeys,
Members: members,
}
}
func GrantToModel(grant *ProjectGrant) *model.ProjectGrant {
members := GrantMembersToModel(grant.Members)
return &model.ProjectGrant{
ObjectRoot: grant.ObjectRoot,
GrantID: grant.GrantID,
GrantedOrgID: grant.GrantedOrgID,
State: model.ProjectGrantState(grant.State),
RoleKeys: grant.RoleKeys,
Members: members,
}
}
func (p *Project) appendAddGrantEvent(event *es_models.Event) error {
grant := new(ProjectGrant)
err := grant.getData(event)
if err != nil {
return err
}
grant.ObjectRoot.CreationDate = event.CreationDate
p.Grants = append(p.Grants, grant)
return nil
}
func (p *Project) appendChangeGrantEvent(event *es_models.Event) error {
grant := new(ProjectGrant)
err := grant.getData(event)
if err != nil {
return err
}
if i, g := GetProjectGrant(p.Grants, grant.GrantID); g != nil {
p.Grants[i].getData(event)
}
return nil
}
func (p *Project) appendGrantStateEvent(event *es_models.Event, state model.ProjectGrantState) error {
grant := new(ProjectGrant)
err := grant.getData(event)
if err != nil {
return err
}
if i, g := GetProjectGrant(p.Grants, grant.GrantID); g != nil {
g.State = int32(state)
p.Grants[i] = g
}
return nil
}
func (p *Project) appendRemoveGrantEvent(event *es_models.Event) error {
grant := new(ProjectGrant)
err := grant.getData(event)
if err != nil {
return err
}
if i, g := GetProjectGrant(p.Grants, grant.GrantID); g != nil {
p.Grants[i] = p.Grants[len(p.Grants)-1]
p.Grants[len(p.Grants)-1] = nil
p.Grants = p.Grants[:len(p.Grants)-1]
}
return nil
}
func (g *ProjectGrant) getData(event *es_models.Event) error {
g.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, g); err != nil {

View File

@@ -2,9 +2,10 @@ package model
import (
"encoding/json"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
)
type ProjectGrantMember struct {
@@ -14,94 +15,6 @@ type ProjectGrantMember struct {
Roles []string `json:"roles,omitempty"`
}
func GetProjectGrantMember(members []*ProjectGrantMember, id string) (int, *ProjectGrantMember) {
for i, m := range members {
if m.UserID == id {
return i, m
}
}
return -1, nil
}
func GrantMembersToModel(members []*ProjectGrantMember) []*model.ProjectGrantMember {
convertedMembers := make([]*model.ProjectGrantMember, len(members))
for i, g := range members {
convertedMembers[i] = GrantMemberToModel(g)
}
return convertedMembers
}
func GrantMembersFromModel(members []*model.ProjectGrantMember) []*ProjectGrantMember {
convertedMembers := make([]*ProjectGrantMember, len(members))
for i, g := range members {
convertedMembers[i] = GrantMemberFromModel(g)
}
return convertedMembers
}
func GrantMemberFromModel(member *model.ProjectGrantMember) *ProjectGrantMember {
return &ProjectGrantMember{
ObjectRoot: member.ObjectRoot,
GrantID: member.GrantID,
UserID: member.UserID,
Roles: member.Roles,
}
}
func GrantMemberToModel(member *ProjectGrantMember) *model.ProjectGrantMember {
return &model.ProjectGrantMember{
ObjectRoot: member.ObjectRoot,
GrantID: member.GrantID,
UserID: member.UserID,
Roles: member.Roles,
}
}
func (p *Project) appendAddGrantMemberEvent(event *es_models.Event) error {
member := &ProjectGrantMember{}
err := member.SetData(event)
if err != nil {
return err
}
member.ObjectRoot.CreationDate = event.CreationDate
if _, g := GetProjectGrant(p.Grants, member.GrantID); g != nil {
g.Members = append(g.Members, member)
}
return nil
}
func (p *Project) appendChangeGrantMemberEvent(event *es_models.Event) error {
member := &ProjectGrantMember{}
err := member.SetData(event)
if err != nil {
return err
}
if _, g := GetProjectGrant(p.Grants, member.GrantID); g != nil {
if i, m := GetProjectGrantMember(g.Members, member.UserID); m != nil {
g.Members[i].SetData(event)
}
}
return nil
}
func (p *Project) appendRemoveGrantMemberEvent(event *es_models.Event) error {
member := &ProjectGrantMember{}
err := member.SetData(event)
if err != nil {
return err
}
if _, g := GetProjectGrant(p.Grants, member.GrantID); g != nil {
if i, member := GetProjectGrantMember(g.Members, member.UserID); member != nil {
g.Members[i] = g.Members[len(g.Members)-1]
g.Members[len(g.Members)-1] = nil
g.Members = g.Members[:len(g.Members)-1]
}
}
return nil
}
func (m *ProjectGrantMember) SetData(event *es_models.Event) error {
m.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, m); err != nil {

View File

@@ -1,145 +0,0 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
)
func TestAppendAddGrantMemberEvent(t *testing.T) {
type args struct {
project *Project
member *ProjectGrantMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append add grant member",
args: args{
project: &Project{Grants: []*ProjectGrant{
&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}},
event: &es_models.Event{},
},
result: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.project.appendAddGrantMemberEvent(tt.args.event)
if len(tt.args.project.Grants[0].Members) != 1 {
t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants[0].Members))
}
if tt.args.project.Grants[0].Members[0] == tt.result.Grants[0].Members[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0].Members[0], tt.args.project.Grants[0].Members[0])
}
})
}
}
func TestAppendChangeGrantMemberEvent(t *testing.T) {
type args struct {
project *Project
member *ProjectGrantMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append change grant member",
args: args{
project: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
},
member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}},
event: &es_models.Event{},
},
result: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}}}}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.project.appendChangeGrantMemberEvent(tt.args.event)
if len(tt.args.project.Grants[0].Members) != 1 {
t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants[0].Members))
}
if tt.args.project.Grants[0].Members[0] == tt.result.Grants[0].Members[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0].Members[0], tt.args.project.Grants[0].Members[0])
}
})
}
}
func TestAppendRemoveGrantMemberEvent(t *testing.T) {
type args struct {
project *Project
member *ProjectGrantMember
event *es_models.Event
}
tests := []struct {
name string
args args
}{
{
name: "append remove grant member",
args: args{
project: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
},
member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}},
event: &es_models.Event{},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.project.appendRemoveGrantMemberEvent(tt.args.event)
if len(tt.args.project.Grants[0].Members) != 0 {
t.Errorf("got wrong result should have no members actual: %v ", len(tt.args.project.Grants[0].Members))
}
})
}
}

View File

@@ -1,169 +0,0 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
"testing"
)
func TestAppendAddGrantEvent(t *testing.T) {
type args struct {
project *Project
role *ProjectGrant
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append add grant event",
args: args{
project: &Project{},
role: &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}},
event: &es_models.Event{},
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.role != nil {
data, _ := json.Marshal(tt.args.role)
tt.args.event.Data = data
}
tt.args.project.appendAddGrantEvent(tt.args.event)
if len(tt.args.project.Grants) != 1 {
t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants))
}
if tt.args.project.Grants[0] == tt.result.Grants[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0], tt.args.project.Grants[0])
}
})
}
}
func TestAppendChangeGrantEvent(t *testing.T) {
type args struct {
project *Project
grant *ProjectGrant
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append change grant event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}},
event: &es_models.Event{},
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.grant != nil {
data, _ := json.Marshal(tt.args.grant)
tt.args.event.Data = data
}
tt.args.project.appendChangeGrantEvent(tt.args.event)
if len(tt.args.project.Grants) != 1 {
t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants))
}
if tt.args.project.Grants[0] == tt.result.Grants[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0], tt.args.project.Grants[0])
}
})
}
}
func TestAppendRemoveGrantEvent(t *testing.T) {
type args struct {
project *Project
grant *ProjectGrant
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append remove role event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrant{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
},
result: &Project{Grants: []*ProjectGrant{}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.grant != nil {
data, _ := json.Marshal(tt.args.grant)
tt.args.event.Data = data
}
tt.args.project.appendRemoveGrantEvent(tt.args.event)
if len(tt.args.project.Grants) != 0 {
t.Errorf("got wrong result should have no grant actual: %v ", len(tt.args.project.Grants))
}
})
}
}
func TestAppendGrantStateEvent(t *testing.T) {
type args struct {
project *Project
grant *ProjectGrantID
event *es_models.Event
state model.ProjectGrantState
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append deactivate grant event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.ProjectGrantStateInactive,
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateInactive)}}},
},
{
name: "append reactivate grant event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.ProjectGrantStateActive,
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateActive)}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.grant != nil {
data, _ := json.Marshal(tt.args.grant)
tt.args.event.Data = data
}
tt.args.project.appendGrantStateEvent(tt.args.event, tt.args.state)
if len(tt.args.project.Grants) != 1 {
t.Errorf("got wrong result should have one grant actual: %v ", len(tt.args.project.Grants))
}
if tt.args.project.Grants[0] == tt.result.Grants[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Grants[0], tt.args.project.Grants[0])
}
})
}
}

View File

@@ -2,9 +2,10 @@ package model
import (
"encoding/json"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
)
type ProjectMember struct {
@@ -13,84 +14,6 @@ type ProjectMember struct {
Roles []string `json:"roles,omitempty"`
}
func GetProjectMember(members []*ProjectMember, id string) (int, *ProjectMember) {
for i, m := range members {
if m.UserID == id {
return i, m
}
}
return -1, nil
}
func ProjectMembersToModel(members []*ProjectMember) []*model.ProjectMember {
convertedMembers := make([]*model.ProjectMember, len(members))
for i, m := range members {
convertedMembers[i] = ProjectMemberToModel(m)
}
return convertedMembers
}
func ProjectMembersFromModel(members []*model.ProjectMember) []*ProjectMember {
convertedMembers := make([]*ProjectMember, len(members))
for i, m := range members {
convertedMembers[i] = ProjectMemberFromModel(m)
}
return convertedMembers
}
func ProjectMemberFromModel(member *model.ProjectMember) *ProjectMember {
return &ProjectMember{
ObjectRoot: member.ObjectRoot,
UserID: member.UserID,
Roles: member.Roles,
}
}
func ProjectMemberToModel(member *ProjectMember) *model.ProjectMember {
return &model.ProjectMember{
ObjectRoot: member.ObjectRoot,
UserID: member.UserID,
Roles: member.Roles,
}
}
func (p *Project) appendAddMemberEvent(event *es_models.Event) error {
member := &ProjectMember{}
err := member.SetData(event)
if err != nil {
return err
}
member.ObjectRoot.CreationDate = event.CreationDate
p.Members = append(p.Members, member)
return nil
}
func (p *Project) appendChangeMemberEvent(event *es_models.Event) error {
member := &ProjectMember{}
err := member.SetData(event)
if err != nil {
return err
}
if i, m := GetProjectMember(p.Members, member.UserID); m != nil {
p.Members[i] = member
}
return nil
}
func (p *Project) appendRemoveMemberEvent(event *es_models.Event) error {
member := &ProjectMember{}
err := member.SetData(event)
if err != nil {
return err
}
if i, m := GetProjectMember(p.Members, member.UserID); m != nil {
p.Members[i] = p.Members[len(p.Members)-1]
p.Members[len(p.Members)-1] = nil
p.Members = p.Members[:len(p.Members)-1]
}
return nil
}
func (m *ProjectMember) SetData(event *es_models.Event) error {
m.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, m); err != nil {

View File

@@ -1,118 +0,0 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
)
func TestAppendAddMemberEvent(t *testing.T) {
type args struct {
project *Project
member *ProjectMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append add member event",
args: args{
project: &Project{},
member: &ProjectMember{UserID: "UserID", Roles: []string{"Role"}},
event: &es_models.Event{},
},
result: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"Role"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.project.appendAddMemberEvent(tt.args.event)
if len(tt.args.project.Members) != 1 {
t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.project.Members))
}
if tt.args.project.Members[0] == tt.result.Members[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Members[0], tt.args.project.Members[0])
}
})
}
}
func TestAppendChangeMemberEvent(t *testing.T) {
type args struct {
project *Project
member *ProjectMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append change member event",
args: args{
project: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"Role"}}}},
member: &ProjectMember{UserID: "UserID", Roles: []string{"ChangedRole"}},
event: &es_models.Event{},
},
result: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"ChangedRole"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.project.appendChangeMemberEvent(tt.args.event)
if len(tt.args.project.Members) != 1 {
t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.project.Members))
}
if tt.args.project.Members[0] == tt.result.Members[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Members[0], tt.args.project.Members[0])
}
})
}
}
func TestAppendRemoveMemberEvent(t *testing.T) {
type args struct {
project *Project
member *ProjectMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *Project
}{
{
name: "append remove member event",
args: args{
project: &Project{Members: []*ProjectMember{&ProjectMember{UserID: "UserID", Roles: []string{"Role"}}}},
member: &ProjectMember{UserID: "UserID"},
event: &es_models.Event{},
},
result: &Project{Members: []*ProjectMember{}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.project.appendRemoveMemberEvent(tt.args.event)
if len(tt.args.project.Members) != 0 {
t.Errorf("got wrong result should have no member actual: %v ", len(tt.args.project.Members))
}
})
}
}

View File

@@ -57,43 +57,6 @@ func ProjectRoleToModel(role *ProjectRole) *model.ProjectRole {
}
}
func (p *Project) appendAddRoleEvent(event *es_models.Event) error {
role := new(ProjectRole)
err := role.setData(event)
if err != nil {
return err
}
role.ObjectRoot.CreationDate = event.CreationDate
p.Roles = append(p.Roles, role)
return nil
}
func (p *Project) appendChangeRoleEvent(event *es_models.Event) error {
role := new(ProjectRole)
err := role.setData(event)
if err != nil {
return err
}
if i, r := GetProjectRole(p.Roles, role.Key); r != nil {
p.Roles[i] = role
}
return nil
}
func (p *Project) appendRemoveRoleEvent(event *es_models.Event) error {
role := new(ProjectRole)
err := role.setData(event)
if err != nil {
return err
}
if i, r := GetProjectRole(p.Roles, role.Key); r != nil {
p.Roles[i] = p.Roles[len(p.Roles)-1]
p.Roles[len(p.Roles)-1] = nil
p.Roles = p.Roles[:len(p.Roles)-1]
}
return nil
}
func (r *ProjectRole) setData(event *es_models.Event) error {
r.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, r); err != nil {

View File

@@ -1,150 +0,0 @@
package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
"github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
)
func ProjectAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, project *model.Project) (*es_models.Aggregate, error) {
if project == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-doe93", "Errors.Internal")
}
return aggCreator.NewAggregate(ctx, project.AggregateID, model.ProjectAggregate, model.ProjectVersion, project.Sequence)
}
func ApplicationAddedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, app *model.Application) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if app == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-09du7", "Errors.Internal")
}
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
agg.AppendEvent(model.ApplicationAdded, app)
if app.OIDCConfig != nil {
agg.AppendEvent(model.OIDCConfigAdded, app.OIDCConfig)
}
if app.APIConfig != nil {
agg.AppendEvent(model.APIConfigAdded, app.APIConfig)
}
return agg, nil
}
}
func APIConfigChangedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, config *model.APIConfig) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if config == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-slf32", "Errors.Internal")
}
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
var changes map[string]interface{}
for _, a := range existingProject.Applications {
if a.AppID == config.AppID {
if a.APIConfig != nil {
changes = a.APIConfig.Changes(config)
}
}
}
agg.AppendEvent(model.APIConfigChanged, changes)
return agg, nil
}
}
func OIDCConfigSecretChangedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string, secret *crypto.CryptoValue) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
changes := make(map[string]interface{}, 2)
changes["appId"] = appID
changes["clientSecret"] = secret
agg.AppendEvent(model.OIDCConfigSecretChanged, changes)
return agg, nil
}
}
func APIConfigSecretChangedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string, secret *crypto.CryptoValue) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
changes := make(map[string]interface{}, 2)
changes["appId"] = appID
changes["clientSecret"] = secret
agg.AppendEvent(model.APIConfigSecretChanged, changes)
return agg, nil
}
}
func OIDCClientSecretCheckSucceededAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string) es_sdk.AggregateFunc {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
changes := make(map[string]interface{}, 1)
changes["appId"] = appID
agg.AppendEvent(model.OIDCClientSecretCheckSucceeded, changes)
return agg, nil
}
}
func OIDCClientSecretCheckFailedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, appID string) es_sdk.AggregateFunc {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
changes := make(map[string]interface{}, 1)
changes["appId"] = appID
agg.AppendEvent(model.OIDCClientSecretCheckFailed, changes)
return agg, nil
}
}
func OIDCApplicationKeyAddedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, key *model.ClientKey) es_sdk.AggregateFunc {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
agg.AppendEvent(model.ClientKeyAdded, key)
return agg, nil
}
}
func OIDCApplicationKeyRemovedAggregate(aggCreator *es_models.AggregateCreator, existingProject *model.Project, keyID string) es_sdk.AggregateFunc {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := ProjectAggregate(ctx, aggCreator, existingProject)
if err != nil {
return nil, err
}
changes := make(map[string]interface{}, 1)
changes["keyId"] = keyID
agg.AppendEvent(model.ClientKeyRemoved, changes)
return agg, nil
}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/lib/pq"
http_util "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
@@ -23,15 +24,17 @@ const (
)
type ApplicationView struct {
ID string `json:"appId" gorm:"column:id;primary_key"`
ProjectID string `json:"-" gorm:"column:project_id"`
Name string `json:"name" gorm:"column:app_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
State int32 `json:"-" gorm:"column:app_state"`
ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"`
ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"`
HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"`
ID string `json:"appId" gorm:"column:id;primary_key"`
ProjectID string `json:"-" gorm:"column:project_id"`
Name string `json:"name" gorm:"column:app_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
State int32 `json:"-" gorm:"column:app_state"`
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"`
ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"`
HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"`
PrivateLabelingSetting domain.PrivateLabelingSetting `json:"privateLabelingSetting" gorm:"column:private_labeling_setting"`
IsOIDC bool `json:"-" gorm:"column:is_oidc"`
OIDCVersion int32 `json:"oidcVersion" gorm:"column:oidc_version"`
@@ -58,15 +61,18 @@ type ApplicationView struct {
func ApplicationViewToModel(app *ApplicationView) *model.ApplicationView {
return &model.ApplicationView{
ID: app.ID,
ProjectID: app.ProjectID,
Name: app.Name,
State: model.AppState(app.State),
Sequence: app.Sequence,
CreationDate: app.CreationDate,
ChangeDate: app.ChangeDate,
ProjectRoleAssertion: app.ProjectRoleAssertion,
ProjectRoleCheck: app.ProjectRoleCheck,
ID: app.ID,
ProjectID: app.ProjectID,
Name: app.Name,
State: model.AppState(app.State),
Sequence: app.Sequence,
CreationDate: app.CreationDate,
ChangeDate: app.ChangeDate,
ResourceOwner: app.ResourceOwner,
ProjectRoleAssertion: app.ProjectRoleAssertion,
ProjectRoleCheck: app.ProjectRoleCheck,
HasProjectCheck: app.HasProjectCheck,
PrivateLabelingSetting: app.PrivateLabelingSetting,
IsOIDC: app.IsOIDC,
OIDCVersion: model.OIDCVersion(app.OIDCVersion),
@@ -158,6 +164,7 @@ func (a *ApplicationView) AppendEvent(event *models.Event) (err error) {
case es_model.ApplicationAdded:
a.setRootData(event)
a.CreationDate = event.CreationDate
a.ResourceOwner = event.ResourceOwner
err = a.SetData(event)
case es_model.OIDCConfigAdded:
a.IsOIDC = true
@@ -233,9 +240,10 @@ func (a *ApplicationView) setCompliance() {
func (a *ApplicationView) setProjectChanges(event *models.Event) error {
changes := struct {
ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"`
ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"`
HasProjectCheck *bool `json:"hasProjectCheck,omitempty"`
ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"`
ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"`
HasProjectCheck *bool `json:"hasProjectCheck,omitempty"`
PrivateLabelingSetting *domain.PrivateLabelingSetting `json:"privateLabelingSetting,omitempty"`
}{}
if err := json.Unmarshal(event.Data, &changes); err != nil {
logging.Log("EVEN-DFbfg").WithError(err).Error("could not unmarshal event data")
@@ -250,5 +258,8 @@ func (a *ApplicationView) setProjectChanges(event *models.Event) error {
if changes.HasProjectCheck != nil {
a.HasProjectCheck = *changes.HasProjectCheck
}
if changes.PrivateLabelingSetting != nil {
a.PrivateLabelingSetting = *changes.PrivateLabelingSetting
}
return nil
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model"
@@ -19,30 +20,32 @@ const (
)
type ProjectView struct {
ProjectID string `json:"-" gorm:"column:project_id;primary_key"`
Name string `json:"name" gorm:"column:project_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
State int32 `json:"-" gorm:"column:project_state"`
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"`
ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"`
HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"`
Sequence uint64 `json:"-" gorm:"column:sequence"`
ProjectID string `json:"-" gorm:"column:project_id;primary_key"`
Name string `json:"name" gorm:"column:project_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
State int32 `json:"-" gorm:"column:project_state"`
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
ProjectRoleAssertion bool `json:"projectRoleAssertion" gorm:"column:project_role_assertion"`
ProjectRoleCheck bool `json:"projectRoleCheck" gorm:"column:project_role_check"`
HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"`
PrivateLabelingSetting domain.PrivateLabelingSetting `json:"privateLabelingSetting" gorm:"column:private_labeling_setting"`
Sequence uint64 `json:"-" gorm:"column:sequence"`
}
func ProjectToModel(project *ProjectView) *model.ProjectView {
return &model.ProjectView{
ProjectID: project.ProjectID,
Name: project.Name,
ChangeDate: project.ChangeDate,
CreationDate: project.CreationDate,
State: model.ProjectState(project.State),
ResourceOwner: project.ResourceOwner,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
HasProjectCheck: project.HasProjectCheck,
Sequence: project.Sequence,
ProjectID: project.ProjectID,
Name: project.Name,
ChangeDate: project.ChangeDate,
CreationDate: project.CreationDate,
State: model.ProjectState(project.State),
ResourceOwner: project.ResourceOwner,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
HasProjectCheck: project.HasProjectCheck,
PrivateLabelingSetting: project.PrivateLabelingSetting,
Sequence: project.Sequence,
}
}