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

@@ -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,
}
}