mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 19:37:24 +00:00
feat: application commands (#50)
* feat: eventstore repository * fix: remove gorm * version * feat: pkg * feat: add some files for project * feat: eventstore without eventstore-lib * rename files * gnueg * fix: key json * fix: add object * fix: change imports * fix: internal models * fix: some imports * fix: global model * feat: add global view functions * fix: add some functions on repo * feat(eventstore): sdk * fix(eventstore): search query * fix(eventstore): rename app to eventstore * delete empty test * remove unused func * merge master * fix(eventstore): tests * fix(models): delete unused struct * fix: some funcitons * feat(eventstore): implemented push events * fix: move project eventstore to project package * fix: change project eventstore funcs * feat(eventstore): overwrite context data * fix: change project eventstore * fix: add project repo to mgmt server * feat(types): SQL-config * fix: commented code * feat(eventstore): options to overwrite editor * feat: auth interceptor and cockroach migrations * fix: migrations * fix: fix filter * fix: not found on getbyid * fix: use global sql config * fix: add sequence * fix: add some tests * fix(eventstore): nullable sequence * fix: add some tests * merge * fix: add some tests * fix(migrations): correct statements for sequence * fix: add some tests * fix: add some tests * fix: changes from mr * fix: changes from mr * fix: add some tests * Update internal/eventstore/models/field.go Co-Authored-By: livio-a <livio.a@gmail.com> * fix(eventstore): code quality * fix: add types to aggregate/Event-types * fix: try tests * fix(eventstore): rename modifier* to editor* * fix(eventstore): delete editor_org * fix(migrations): remove editor_org field, rename modifier_* to editor_* * fix: query tests * fix: use prepare funcs * fix: go mod * fix: generate files * fix(eventstore): tests * fix(eventstore): rename modifier to editor * fix(migrations): add cluster migration, fix(migrations): fix typo of host in clean clsuter * fix(eventstore): move health * fix(eventstore): AggregateTypeFilter aggregateType as param * code quality * fix: go tests * feat: add member funcs * feat: add member model * feat: add member events * feat: add member repo model * fix: better error func testing * fix: project member funcs * fix: add tests * fix: add tests * feat: implement member requests * fix: merge master * fix: merge master * fix: read existing in project repo * fix: fix tests * feat: add internal cache * feat: add cache mock * fix: return values of cache mock * feat: add project role * fix: add cache config * fix: add role to eventstore * fix: use eventstore sdk * fix: use eventstore sdk * fix: add project role grpc requests * fix: fix getby id * fix: changes for mr * fix: change value to interface * feat: add app event creations * fix: searchmethods * Update internal/project/model/project_member.go Co-Authored-By: Silvan <silvan.reusser@gmail.com> * fix: use get project func * fix: append events * fix: check if value is string on equal ignore case * fix: add changes test * fix: add go mod * fix: add some tests * fix: return err not nil * fix: return err not nil * fix: add aggregate funcs and tests * fix: add oidc aggregate funcs and tests * fix: add oidc * fix: add some tests * fix: tests * fix: oidc validation * fix: generate client secret * fix: generate client id * fix: test change app * fix: deactivate/reactivate application * fix: change oidc config * fix: change oidc config secret * fix: implement grpc app funcs * fix: add application requests * fix: converter * fix: converter * fix: converter and generate clientid * fix: tests * fix: some fixes * feat: mr changes * fix: remove state converted * fix: add default oidc config * fix: use crypto pw generator * fix: rename responsetype * create GeneratorConfig and refactor some crypto.Generator code (#70) * Update internal/project/model/project_role.go Co-Authored-By: Silvan <silvan.reusser@gmail.com> * fix: change objectroot id * fix: caos err id Co-authored-by: adlerhurst <silvan.reusser@gmail.com> Co-authored-by: livio-a <livio.a@gmail.com>
This commit is contained in:
parent
802bb56ea1
commit
04b4cd80b8
@ -31,6 +31,14 @@ Mgmt:
|
||||
Type: 'fastcache'
|
||||
Config:
|
||||
MaxCacheSizeInByte: 10485760 #10mb
|
||||
PasswordSaltCost: 14
|
||||
ClientSecretGenerator:
|
||||
Length: 64
|
||||
IncludeLowerLetters: true
|
||||
IncludeUpperLetters: true
|
||||
IncludeDigits: true
|
||||
IncludeSymbols: true
|
||||
|
||||
|
||||
Auth:
|
||||
API:
|
||||
|
1
go.mod
1
go.mod
@ -34,6 +34,7 @@ require (
|
||||
github.com/mitchellh/reflectwalk v1.0.1 // indirect
|
||||
github.com/nicksnyder/go-i18n/v2 v2.0.3
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/sethvargo/go-password v0.1.3
|
||||
github.com/sirupsen/logrus v1.5.0 // indirect
|
||||
github.com/sony/sonyflake v1.0.0
|
||||
github.com/stretchr/testify v1.5.1
|
||||
|
2
go.sum
2
go.sum
@ -254,6 +254,8 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sethvargo/go-password v0.1.3 h1:18KkbGDkw8SuzeohAbWqBLNSfRQblVwEHOLbPa0PvWM=
|
||||
github.com/sethvargo/go-password v0.1.3/go.mod h1:2tyaaoHK/AlXwh5WWQDYjqQbHcq4cjPj5qb/ciYvu/Q=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
|
@ -4,16 +4,26 @@ import (
|
||||
"crypto/rand"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/types"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
LowerLetters = []rune("abcdefghijklmnopqrstuvwxyz")
|
||||
UpperLetters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
Digits = []rune("0123456789")
|
||||
Symbols = []rune("~!@#$^&*()_+`-={}|[]:<>?,./")
|
||||
lowerLetters = []rune("abcdefghijklmnopqrstuvwxyz")
|
||||
upperLetters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
digits = []rune("0123456789")
|
||||
symbols = []rune("~!@#$^&*()_+`-={}|[]:<>?,./")
|
||||
)
|
||||
|
||||
type GeneratorConfig struct {
|
||||
Length uint
|
||||
Expiry types.Duration
|
||||
IncludeLowerLetters bool
|
||||
IncludeUpperLetters bool
|
||||
IncludeDigits bool
|
||||
IncludeSymbols bool
|
||||
}
|
||||
|
||||
type Generator interface {
|
||||
Length() uint
|
||||
Expiry() time.Duration
|
||||
@ -21,66 +31,73 @@ type Generator interface {
|
||||
Runes() []rune
|
||||
}
|
||||
|
||||
type EncryptionGenerator struct {
|
||||
type generator struct {
|
||||
length uint
|
||||
expiry time.Duration
|
||||
alg EncryptionAlgorithm
|
||||
runes []rune
|
||||
}
|
||||
|
||||
func (g *EncryptionGenerator) Length() uint {
|
||||
func (g *generator) Length() uint {
|
||||
return g.length
|
||||
}
|
||||
|
||||
func (g *EncryptionGenerator) Expiry() time.Duration {
|
||||
func (g *generator) Expiry() time.Duration {
|
||||
return g.expiry
|
||||
}
|
||||
|
||||
func (g *EncryptionGenerator) Alg() Crypto {
|
||||
return g.alg
|
||||
}
|
||||
|
||||
func (g *EncryptionGenerator) Runes() []rune {
|
||||
func (g *generator) Runes() []rune {
|
||||
return g.runes
|
||||
}
|
||||
|
||||
func NewEncryptionGenerator(length uint, expiry time.Duration, alg EncryptionAlgorithm, runes []rune) *EncryptionGenerator {
|
||||
return &EncryptionGenerator{
|
||||
length: length,
|
||||
expiry: expiry,
|
||||
alg: alg,
|
||||
runes: runes,
|
||||
type encryptionGenerator struct {
|
||||
generator
|
||||
alg EncryptionAlgorithm
|
||||
}
|
||||
|
||||
func (g *encryptionGenerator) Alg() Crypto {
|
||||
return g.alg
|
||||
}
|
||||
|
||||
func NewEncryptionGenerator(config GeneratorConfig, algorithm EncryptionAlgorithm) Generator {
|
||||
return &encryptionGenerator{
|
||||
newGenerator(config),
|
||||
algorithm,
|
||||
}
|
||||
}
|
||||
|
||||
type HashGenerator struct {
|
||||
length uint
|
||||
expiry time.Duration
|
||||
alg HashAlgorithm
|
||||
runes []rune
|
||||
type hashGenerator struct {
|
||||
generator
|
||||
alg HashAlgorithm
|
||||
}
|
||||
|
||||
func (g *HashGenerator) Length() uint {
|
||||
return g.length
|
||||
}
|
||||
|
||||
func (g *HashGenerator) Expiry() time.Duration {
|
||||
return g.expiry
|
||||
}
|
||||
|
||||
func (g *HashGenerator) Alg() Crypto {
|
||||
func (g *hashGenerator) Alg() Crypto {
|
||||
return g.alg
|
||||
}
|
||||
|
||||
func (g *HashGenerator) Runes() []rune {
|
||||
return g.runes
|
||||
func NewHashGenerator(config GeneratorConfig, algorithm HashAlgorithm) Generator {
|
||||
return &hashGenerator{
|
||||
newGenerator(config),
|
||||
algorithm,
|
||||
}
|
||||
}
|
||||
|
||||
func NewHashGenerator(length uint, expiry time.Duration, alg HashAlgorithm, runes []rune) *HashGenerator {
|
||||
return &HashGenerator{
|
||||
length: length,
|
||||
expiry: expiry,
|
||||
alg: alg,
|
||||
func newGenerator(config GeneratorConfig) generator {
|
||||
var runes []rune
|
||||
if config.IncludeLowerLetters {
|
||||
runes = append(runes, lowerLetters...)
|
||||
}
|
||||
if config.IncludeUpperLetters {
|
||||
runes = append(runes, upperLetters...)
|
||||
}
|
||||
if config.IncludeDigits {
|
||||
runes = append(runes, digits...)
|
||||
}
|
||||
if config.IncludeSymbols {
|
||||
runes = append(runes, symbols...)
|
||||
}
|
||||
return generator{
|
||||
length: config.Length,
|
||||
expiry: config.Expiry.Duration,
|
||||
runes: runes,
|
||||
}
|
||||
}
|
||||
@ -98,6 +115,9 @@ func NewCode(g Generator) (*CryptoValue, string, error) {
|
||||
}
|
||||
|
||||
func IsCodeExpired(creationDate time.Time, expiry time.Duration) bool {
|
||||
if expiry == 0 {
|
||||
return false
|
||||
}
|
||||
return creationDate.Add(expiry).Before(time.Now().UTC())
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,14 @@ func TestIsCodeExpired(t *testing.T) {
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"never expires",
|
||||
args{
|
||||
creationDate: time.Now().Add(-5 * time.Minute),
|
||||
expiry: 0,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"expired",
|
||||
args{
|
||||
|
@ -5,15 +5,15 @@ import (
|
||||
)
|
||||
|
||||
type ObjectRoot struct {
|
||||
ID string `json:"-"`
|
||||
AggregateID string `json:"-"`
|
||||
Sequence uint64 `json:"-"`
|
||||
CreationDate time.Time `json:"-"`
|
||||
ChangeDate time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func (o *ObjectRoot) AppendEvent(event *Event) {
|
||||
if o.ID == "" {
|
||||
o.ID = event.AggregateID
|
||||
if o.AggregateID == "" {
|
||||
o.AggregateID = event.AggregateID
|
||||
}
|
||||
|
||||
o.ChangeDate = event.CreationDate
|
||||
|
@ -55,7 +55,7 @@ func TestObjectRoot_AppendEvent(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := &ObjectRoot{
|
||||
ID: tt.fields.ID,
|
||||
AggregateID: tt.fields.ID,
|
||||
Sequence: tt.fields.Sequence,
|
||||
CreationDate: tt.fields.CreationDate,
|
||||
ChangeDate: tt.fields.ChangeDate,
|
||||
|
@ -50,3 +50,49 @@ func (repo *ProjectRepo) RemoveProjectMember(ctx context.Context, projectID, use
|
||||
member := proj_model.NewProjectMember(projectID, userID)
|
||||
return repo.ProjectEvents.RemoveProjectMember(ctx, member)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) AddProjectRole(ctx context.Context, member *proj_model.ProjectRole) (*proj_model.ProjectRole, error) {
|
||||
return repo.ProjectEvents.AddProjectRole(ctx, member)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ChangeProjectRole(ctx context.Context, member *proj_model.ProjectRole) (*proj_model.ProjectRole, error) {
|
||||
return repo.ProjectEvents.ChangeProjectRole(ctx, member)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) RemoveProjectRole(ctx context.Context, projectID, key string) error {
|
||||
member := proj_model.NewProjectRole(projectID, key)
|
||||
return repo.ProjectEvents.RemoveProjectRole(ctx, member)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ApplicationByID(ctx context.Context, projectID, appID string) (app *proj_model.Application, err error) {
|
||||
return repo.ProjectEvents.ApplicationByIDs(ctx, projectID, appID)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) AddApplication(ctx context.Context, app *proj_model.Application) (*proj_model.Application, error) {
|
||||
return repo.ProjectEvents.AddApplication(ctx, app)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ChangeApplication(ctx context.Context, app *proj_model.Application) (*proj_model.Application, error) {
|
||||
return repo.ProjectEvents.ChangeApplication(ctx, app)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) DeactivateApplication(ctx context.Context, projectID, appID string) (*proj_model.Application, error) {
|
||||
return repo.ProjectEvents.DeactivateApplication(ctx, projectID, appID)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ReactivateApplication(ctx context.Context, projectID, appID string) (*proj_model.Application, error) {
|
||||
return repo.ProjectEvents.ReactivateApplication(ctx, projectID, appID)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) RemoveApplication(ctx context.Context, projectID, appID string) error {
|
||||
app := proj_model.NewApplication(projectID, appID)
|
||||
return repo.ProjectEvents.RemoveApplication(ctx, app)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ChangeOIDCConfig(ctx context.Context, config *proj_model.OIDCConfig) (*proj_model.OIDCConfig, error) {
|
||||
return repo.ProjectEvents.ChangeOIDCConfig(ctx, config)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ChangeOIDConfigSecret(ctx context.Context, projectID, appID string) (*proj_model.OIDCConfig, error) {
|
||||
return repo.ProjectEvents.ChangeOIDCConfigSecret(ctx, projectID, appID)
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||
)
|
||||
@ -10,6 +12,8 @@ type Config struct {
|
||||
Eventstore es_int.Config
|
||||
//View view.ViewConfig
|
||||
//Spooler spooler.SpoolerConfig
|
||||
PasswordSaltCost int
|
||||
ClientSecretGenerator crypto.GeneratorConfig
|
||||
}
|
||||
|
||||
type EsRepository struct {
|
||||
@ -33,7 +37,12 @@ func Start(conf Config) (*EsRepository, error) {
|
||||
//conf.Spooler.SQL = sql
|
||||
//spool := spooler.StartSpooler(conf.Spooler)
|
||||
|
||||
project, err := es_proj.StartProject(es_proj.ProjectConfig{Eventstore: es, Cache: conf.Eventstore.Cache})
|
||||
project, err := es_proj.StartProject(es_proj.ProjectConfig{
|
||||
Eventstore: es,
|
||||
Cache: conf.Eventstore.Cache,
|
||||
PasswordSaltCost: conf.PasswordSaltCost,
|
||||
ClientSecretGenerator: conf.ClientSecretGenerator,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -16,4 +16,17 @@ type ProjectRepository interface {
|
||||
AddProjectMember(ctx context.Context, member *model.ProjectMember) (*model.ProjectMember, error)
|
||||
ChangeProjectMember(ctx context.Context, member *model.ProjectMember) (*model.ProjectMember, error)
|
||||
RemoveProjectMember(ctx context.Context, projectID, userID string) error
|
||||
|
||||
AddProjectRole(ctx context.Context, role *model.ProjectRole) (*model.ProjectRole, error)
|
||||
ChangeProjectRole(ctx context.Context, role *model.ProjectRole) (*model.ProjectRole, error)
|
||||
RemoveProjectRole(ctx context.Context, projectID, key string) error
|
||||
|
||||
ApplicationByID(ctx context.Context, projectID, appID string) (*model.Application, error)
|
||||
AddApplication(ctx context.Context, app *model.Application) (*model.Application, error)
|
||||
ChangeApplication(ctx context.Context, app *model.Application) (*model.Application, error)
|
||||
DeactivateApplication(ctx context.Context, projectID, appID string) (*model.Application, error)
|
||||
ReactivateApplication(ctx context.Context, projectID, appID string) (*model.Application, error)
|
||||
RemoveApplication(ctx context.Context, projectID, appID string) error
|
||||
ChangeOIDCConfig(ctx context.Context, config *model.OIDCConfig) (*model.OIDCConfig, error)
|
||||
ChangeOIDConfigSecret(ctx context.Context, projectID, appID string) (*model.OIDCConfig, error)
|
||||
}
|
||||
|
47
internal/project/model/application.go
Normal file
47
internal/project/model/application.go
Normal file
@ -0,0 +1,47 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
AppID string
|
||||
State AppState
|
||||
Name string
|
||||
Type AppType
|
||||
OIDCConfig *OIDCConfig
|
||||
}
|
||||
|
||||
type AppState int32
|
||||
|
||||
const (
|
||||
APPSTATE_ACTIVE AppState = iota
|
||||
APPSTATE_INACTIVE
|
||||
)
|
||||
|
||||
type AppType int32
|
||||
|
||||
const (
|
||||
APPTYPE_UNDEFINED AppType = iota
|
||||
APPTYPE_OIDC
|
||||
APPTYPE_SAML
|
||||
)
|
||||
|
||||
func NewApplication(projectID, appID string) *Application {
|
||||
return &Application{ObjectRoot: es_models.ObjectRoot{AggregateID: projectID}, AppID: appID, State: APPSTATE_ACTIVE}
|
||||
}
|
||||
|
||||
func (a *Application) IsValid(includeConfig bool) bool {
|
||||
if a.Name == "" || a.AggregateID == "" {
|
||||
return false
|
||||
}
|
||||
if !includeConfig {
|
||||
return true
|
||||
}
|
||||
if a.Type == APPTYPE_OIDC && !a.OIDCConfig.IsValid() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
170
internal/project/model/application_test.go
Normal file
170
internal/project/model/application_test.go
Normal file
@ -0,0 +1,170 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestApplicationValid(t *testing.T) {
|
||||
type args struct {
|
||||
app *Application
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
name: "valid oidc application: responsetype code",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_CODE},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_AUTHORIZATION_CODE},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "invalid oidc application: responsetype code",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_CODE},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_IMPLICIT},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_ID_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_IMPLICIT},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "invalid oidc application: responsetype id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_ID_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_AUTHORIZATION_CODE},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_IMPLICIT},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "invalid oidc application: responsetype token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_AUTHORIZATION_CODE},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype code & id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_CODE, OIDCRESPONSETYPE_ID_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_AUTHORIZATION_CODE, OIDCGRANTTYPE_IMPLICIT},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype code & token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_CODE, OIDCRESPONSETYPE_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_AUTHORIZATION_CODE, OIDCGRANTTYPE_IMPLICIT},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype code & id_token & token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: APPTYPE_OIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCRESPONSETYPE_CODE, OIDCRESPONSETYPE_ID_TOKEN, OIDCRESPONSETYPE_TOKEN},
|
||||
GrantTypes: []OIDCGrantType{OIDCGRANTTYPE_AUTHORIZATION_CODE, OIDCGRANTTYPE_IMPLICIT},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.args.app.IsValid(true)
|
||||
if result != tt.result {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
88
internal/project/model/oidc_config.go
Normal file
88
internal/project/model/oidc_config.go
Normal file
@ -0,0 +1,88 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type OIDCConfig struct {
|
||||
es_models.ObjectRoot
|
||||
AppID string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
ClientSecretString string
|
||||
RedirectUris []string
|
||||
ResponseTypes []OIDCResponseType
|
||||
GrantTypes []OIDCGrantType
|
||||
ApplicationType OIDCApplicationType
|
||||
AuthMethodType OIDCAuthMethodType
|
||||
PostLogoutRedirectUris []string
|
||||
}
|
||||
|
||||
type OIDCResponseType int32
|
||||
|
||||
const (
|
||||
OIDCRESPONSETYPE_CODE OIDCResponseType = iota
|
||||
OIDCRESPONSETYPE_ID_TOKEN
|
||||
OIDCRESPONSETYPE_TOKEN
|
||||
)
|
||||
|
||||
type OIDCGrantType int32
|
||||
|
||||
const (
|
||||
OIDCGRANTTYPE_AUTHORIZATION_CODE OIDCGrantType = iota
|
||||
OIDCGRANTTYPE_IMPLICIT
|
||||
OIDCGRANTTYPE_REFRESH_TOKEN
|
||||
)
|
||||
|
||||
type OIDCApplicationType int32
|
||||
|
||||
const (
|
||||
OIDCAPPLICATIONTYPE_WEB OIDCApplicationType = iota
|
||||
OIDCAPPLICATIONTYPE_USER_AGENT
|
||||
OIDCAPPLICATIONTYPE_NATIVE
|
||||
)
|
||||
|
||||
type OIDCAuthMethodType int32
|
||||
|
||||
const (
|
||||
OIDCAUTHMETHODTYPE_BASIC OIDCAuthMethodType = iota
|
||||
OIDCAUTHMETHODTYPE_POST
|
||||
OIDCAUTHMETHODTYPE_NONE
|
||||
)
|
||||
|
||||
func (c *OIDCConfig) IsValid() bool {
|
||||
grantTypes := c.getRequiredGrantTypes()
|
||||
for _, grantType := range grantTypes {
|
||||
ok := c.containsGrantType(grantType)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) getRequiredGrantTypes() []OIDCGrantType {
|
||||
grantTypes := make([]OIDCGrantType, 0)
|
||||
implicit := false
|
||||
for _, r := range c.ResponseTypes {
|
||||
switch r {
|
||||
case OIDCRESPONSETYPE_CODE:
|
||||
grantTypes = append(grantTypes, OIDCGRANTTYPE_AUTHORIZATION_CODE)
|
||||
case OIDCRESPONSETYPE_ID_TOKEN, OIDCRESPONSETYPE_TOKEN:
|
||||
if !implicit {
|
||||
grantTypes = append(grantTypes, OIDCGRANTTYPE_IMPLICIT)
|
||||
}
|
||||
}
|
||||
}
|
||||
return grantTypes
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) containsGrantType(grantType OIDCGrantType) bool {
|
||||
for _, t := range c.GrantTypes {
|
||||
if t == grantType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@ -2,37 +2,35 @@ package model
|
||||
|
||||
import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
in_model "github.com/caos/zitadel/internal/model"
|
||||
)
|
||||
|
||||
type Project struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
State ProjectState
|
||||
Name string
|
||||
Members []*ProjectMember
|
||||
State ProjectState
|
||||
Name string
|
||||
Members []*ProjectMember
|
||||
Roles []*ProjectRole
|
||||
Applications []*Application
|
||||
}
|
||||
|
||||
type ProjectState in_model.Enum
|
||||
type ProjectState int32
|
||||
|
||||
var states = []string{"Active", "Inactive"}
|
||||
const (
|
||||
PROJECTSTATE_ACTIVE ProjectState = iota
|
||||
PROJECTSTATE_INACTIVE
|
||||
)
|
||||
|
||||
func NewProject(id string) *Project {
|
||||
return &Project{ObjectRoot: es_models.ObjectRoot{ID: id}, State: Active}
|
||||
return &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: id}, State: PROJECTSTATE_ACTIVE}
|
||||
}
|
||||
|
||||
func (p *Project) IsActive() bool {
|
||||
if p.State == Active {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return p.State == PROJECTSTATE_ACTIVE
|
||||
}
|
||||
|
||||
func (p *Project) IsValid() bool {
|
||||
if p.Name == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return p.Name != ""
|
||||
}
|
||||
|
||||
func (p *Project) ContainsMember(member *ProjectMember) bool {
|
||||
@ -43,3 +41,21 @@ func (p *Project) ContainsMember(member *ProjectMember) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Project) ContainsRole(role *ProjectRole) bool {
|
||||
for _, r := range p.Roles {
|
||||
if r.Key == role.Key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Project) ContainsApp(app *Application) (*Application, bool) {
|
||||
for _, a := range p.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
return a, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ type ProjectMember struct {
|
||||
}
|
||||
|
||||
func NewProjectMember(projectID, userID string) *ProjectMember {
|
||||
return &ProjectMember{ObjectRoot: es_models.ObjectRoot{ID: projectID}, UserID: userID}
|
||||
return &ProjectMember{ObjectRoot: es_models.ObjectRoot{AggregateID: projectID}, UserID: userID}
|
||||
}
|
||||
|
||||
func (p *ProjectMember) IsValid() bool {
|
||||
return p.ID != "" && p.UserID != "" && len(p.Roles) != 0
|
||||
return p.AggregateID != "" && p.UserID != "" && len(p.Roles) != 0
|
||||
}
|
||||
|
19
internal/project/model/project_role.go
Normal file
19
internal/project/model/project_role.go
Normal file
@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
type ProjectRole struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Key string
|
||||
DisplayName string
|
||||
Group string
|
||||
}
|
||||
|
||||
func NewProjectRole(projectID, key string) *ProjectRole {
|
||||
return &ProjectRole{ObjectRoot: es_models.ObjectRoot{AggregateID: projectID}, Key: key}
|
||||
}
|
||||
|
||||
func (p *ProjectRole) IsValid() bool {
|
||||
return p.AggregateID != "" && p.Key != ""
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package model
|
||||
|
||||
type state int32
|
||||
|
||||
func (s state) String() string {
|
||||
return states[s]
|
||||
}
|
||||
|
||||
const (
|
||||
Active state = iota
|
||||
Inactive
|
||||
)
|
||||
|
||||
func ProjectStateToInt(s ProjectState) int32 {
|
||||
if s == nil {
|
||||
return 0
|
||||
}
|
||||
return int32(s.(state))
|
||||
}
|
||||
|
||||
func ProjectStateFromInt(index int32) ProjectState {
|
||||
return state(index)
|
||||
}
|
@ -15,6 +15,7 @@ const (
|
||||
ProjectMemberRemoved models.EventType = "project.member.removed"
|
||||
|
||||
ProjectRoleAdded models.EventType = "project.role.added"
|
||||
ProjectRoleChanged models.EventType = "project.role.changed"
|
||||
ProjectRoleRemoved models.EventType = "project.role.removed"
|
||||
|
||||
ProjectGrantAdded models.EventType = "project.grant.added"
|
||||
@ -28,6 +29,7 @@ const (
|
||||
|
||||
ApplicationAdded models.EventType = "project.application.added"
|
||||
ApplicationChanged models.EventType = "project.application.changed"
|
||||
ApplicationRemoved models.EventType = "project.application.removed"
|
||||
ApplicationDeactivated models.EventType = "project.application.deactivated"
|
||||
ApplicationReactivated models.EventType = "project.application.reactivated"
|
||||
|
||||
|
@ -19,7 +19,7 @@ func StartCache(conf *config.CacheConfig) (*ProjectCache, error) {
|
||||
}
|
||||
|
||||
func (c *ProjectCache) getProject(ID string) (project *Project) {
|
||||
project = &Project{ObjectRoot: models.ObjectRoot{ID: ID}}
|
||||
project = &Project{ObjectRoot: models.ObjectRoot{AggregateID: ID}}
|
||||
if err := c.projectCache.Get(ID, project); err != nil {
|
||||
logging.Log("EVENT-4eTZh").WithError(err).Debug("error in getting cache")
|
||||
}
|
||||
@ -27,7 +27,7 @@ func (c *ProjectCache) getProject(ID string) (project *Project) {
|
||||
}
|
||||
|
||||
func (c *ProjectCache) cacheProject(project *Project) {
|
||||
err := c.projectCache.Set(project.ID, project)
|
||||
err := c.projectCache.Set(project.AggregateID, project)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-ThnBb").WithError(err).Debug("error in setting project cache")
|
||||
}
|
||||
|
@ -2,7 +2,12 @@ package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/sony/sonyflake"
|
||||
|
||||
"github.com/caos/zitadel/internal/cache/config"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
||||
@ -12,11 +17,15 @@ import (
|
||||
type ProjectEventstore struct {
|
||||
es_int.Eventstore
|
||||
projectCache *ProjectCache
|
||||
pwGenerator crypto.Generator
|
||||
idGenerator *sonyflake.Sonyflake
|
||||
}
|
||||
|
||||
type ProjectConfig struct {
|
||||
es_int.Eventstore
|
||||
Cache *config.CacheConfig
|
||||
Cache *config.CacheConfig
|
||||
PasswordSaltCost int
|
||||
ClientSecretGenerator crypto.GeneratorConfig
|
||||
}
|
||||
|
||||
func StartProject(conf ProjectConfig) (*ProjectEventstore, error) {
|
||||
@ -24,21 +33,26 @@ func StartProject(conf ProjectConfig) (*ProjectEventstore, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
passwordAlg := crypto.NewBCrypt(conf.PasswordSaltCost)
|
||||
pwGenerator := crypto.NewHashGenerator(conf.ClientSecretGenerator, passwordAlg)
|
||||
idGenerator := sonyflake.NewSonyflake(sonyflake.Settings{})
|
||||
return &ProjectEventstore{
|
||||
Eventstore: conf.Eventstore,
|
||||
projectCache: projectCache,
|
||||
pwGenerator: pwGenerator,
|
||||
idGenerator: idGenerator,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ProjectByID(ctx context.Context, id string) (*proj_model.Project, error) {
|
||||
project := es.projectCache.getProject(id)
|
||||
|
||||
query, err := ProjectByIDQuery(project.ID, project.Sequence)
|
||||
query, err := ProjectByIDQuery(project.AggregateID, project.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es_sdk.Filter(ctx, es.FilterEvents, project.AppendEvents, query)
|
||||
if err != nil {
|
||||
if err != nil && !(caos_errs.IsNotFound(err) && project.Sequence != 0) {
|
||||
return nil, err
|
||||
}
|
||||
es.projectCache.cacheProject(project)
|
||||
@ -49,11 +63,16 @@ func (es *ProjectEventstore) CreateProject(ctx context.Context, project *proj_mo
|
||||
if !project.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Name is required")
|
||||
}
|
||||
project.State = proj_model.Active
|
||||
id, err := es.idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
project.AggregateID = strconv.FormatUint(id, 10)
|
||||
project.State = proj_model.PROJECTSTATE_ACTIVE
|
||||
repoProject := ProjectFromModel(project)
|
||||
|
||||
createAggregate := ProjectCreateAggregate(es.AggregateCreator(), repoProject)
|
||||
err := es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, createAggregate)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, createAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -66,7 +85,7 @@ func (es *ProjectEventstore) UpdateProject(ctx context.Context, project *proj_mo
|
||||
if !project.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Name is required")
|
||||
}
|
||||
existingProject, err := es.ProjectByID(ctx, project.ID)
|
||||
existingProject, err := es.ProjectByID(ctx, project.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -121,7 +140,7 @@ func (es *ProjectEventstore) ProjectMemberByIDs(ctx context.Context, member *pro
|
||||
if member.UserID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-ld93d", "userID missing")
|
||||
}
|
||||
project, err := es.ProjectByID(ctx, member.ID)
|
||||
project, err := es.ProjectByID(ctx, member.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -137,7 +156,7 @@ func (es *ProjectEventstore) AddProjectMember(ctx context.Context, member *proj_
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "UserID and Roles are required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, member.ID)
|
||||
existing, err := es.ProjectByID(ctx, member.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -165,7 +184,7 @@ func (es *ProjectEventstore) ChangeProjectMember(ctx context.Context, member *pr
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "UserID and Roles are required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, member.ID)
|
||||
existing, err := es.ProjectByID(ctx, member.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -190,7 +209,7 @@ func (es *ProjectEventstore) RemoveProjectMember(ctx context.Context, member *pr
|
||||
if member.UserID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-d43fs", "UserID and Roles are required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, member.ID)
|
||||
existing, err := es.ProjectByID(ctx, member.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -205,3 +224,307 @@ func (es *ProjectEventstore) RemoveProjectMember(ctx context.Context, member *pr
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
return err
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) AddProjectRole(ctx context.Context, role *proj_model.ProjectRole) (*proj_model.ProjectRole, error) {
|
||||
if !role.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-idue3", "Key is required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, role.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existing.ContainsRole(role) {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "EVENT-sk35t", "Project contains role with same key")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoRole := ProjectRoleFromModel(role)
|
||||
projectAggregate := ProjectRoleAddedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoRole)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, r := range repoProject.Roles {
|
||||
if r.Key == role.Key {
|
||||
return ProjectRoleToModel(r), nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-sie83", "Could not find role in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ChangeProjectRole(ctx context.Context, role *proj_model.ProjectRole) (*proj_model.ProjectRole, error) {
|
||||
if !role.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9die3", "Key is required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, role.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existing.ContainsRole(role) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-die34", "Role doesn't exist on this project")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoRole := ProjectRoleFromModel(role)
|
||||
projectAggregate := ProjectRoleChangedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoRole)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, r := range repoProject.Roles {
|
||||
if r.Key == role.Key {
|
||||
return ProjectRoleToModel(r), nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-sl1or", "Could not find role in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) RemoveProjectRole(ctx context.Context, role *proj_model.ProjectRole) error {
|
||||
if role.Key == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-id823", "Key is required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, role.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !existing.ContainsRole(role) {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-oe823", "Role doesn't exist on project")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoRole := ProjectRoleFromModel(role)
|
||||
projectAggregate := ProjectRoleRemovedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoRole)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ApplicationByIDs(ctx context.Context, projectID, appID string) (*proj_model.Application, error) {
|
||||
if projectID == "" || appID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-ld93d", "project oder app AggregateID missing")
|
||||
}
|
||||
project, err := es.ProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, a := range project.Applications {
|
||||
if a.AppID == appID {
|
||||
return a, nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowNotFound(nil, "EVENT-8ei2s", "Could not find app")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) AddApplication(ctx context.Context, app *proj_model.Application) (*proj_model.Application, error) {
|
||||
if app == nil || !app.IsValid(true) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9eidw", "Some required fields are missing")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, app.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, err := es.idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.AppID = strconv.FormatUint(id, 10)
|
||||
|
||||
var stringPw string
|
||||
var cryptoPw *crypto.CryptoValue
|
||||
if app.OIDCConfig != nil {
|
||||
app.OIDCConfig.AppID = strconv.FormatUint(id, 10)
|
||||
stringPw, cryptoPw, err = generateNewClientSecret(es.pwGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.OIDCConfig.ClientSecret = cryptoPw
|
||||
clientID, err := generateNewClientID(es.idGenerator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.OIDCConfig.ClientID = clientID
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoApp := AppFromModel(app)
|
||||
|
||||
addAggregate := ApplicationAddedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoApp)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, addAggregate)
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, a := range repoProject.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
converted := AppToModel(a)
|
||||
converted.OIDCConfig.ClientSecretString = stringPw
|
||||
return converted, nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-3udjs", "Could not find member in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ChangeApplication(ctx context.Context, app *proj_model.Application) (*proj_model.Application, error) {
|
||||
if app == nil || !app.IsValid(false) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-dieuw", "some required fields missing")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, app.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := existing.ContainsApp(app); !ok {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-die83", "App is not in this project")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoApp := AppFromModel(app)
|
||||
|
||||
projectAggregate := ApplicationChangedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoApp)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, a := range repoProject.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
return AppToModel(a), nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-dksi8", "Could not find app in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) RemoveApplication(ctx context.Context, app *proj_model.Application) error {
|
||||
if app.AppID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-id832", "AppID is required")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, app.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := existing.ContainsApp(app); !ok {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-di83s", "Application doesn't exist on project")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
appRepo := AppFromModel(app)
|
||||
projectAggregate := ApplicationRemovedAggregate(es.Eventstore.AggregateCreator(), repoProject, appRepo)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) DeactivateApplication(ctx context.Context, projectID, appID string) (*proj_model.Application, error) {
|
||||
if appID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-dlp9e", "appID missing")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app := &proj_model.Application{AppID: appID}
|
||||
if _, ok := existing.ContainsApp(app); !ok {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-slpe9", "App is not in this project")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoApp := AppFromModel(app)
|
||||
|
||||
projectAggregate := ApplicationDeactivatedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoApp)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, a := range repoProject.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
return AppToModel(a), nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-sie83", "Could not find app in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ReactivateApplication(ctx context.Context, projectID, appID string) (*proj_model.Application, error) {
|
||||
if appID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-0odi2", "appID missing")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app := &proj_model.Application{AppID: appID}
|
||||
if _, ok := existing.ContainsApp(app); !ok {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-ld92d", "App is not in this project")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoApp := AppFromModel(app)
|
||||
|
||||
projectAggregate := ApplicationReactivatedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoApp)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, a := range repoProject.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
return AppToModel(a), nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-sld93", "Could not find app in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ChangeOIDCConfig(ctx context.Context, config *proj_model.OIDCConfig) (*proj_model.OIDCConfig, error) {
|
||||
if config == nil || !config.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-du834", "invalid oidc config")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, config.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ok bool
|
||||
var app *proj_model.Application
|
||||
if app, ok = existing.ContainsApp(&proj_model.Application{AppID: config.AppID}); !ok {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-dkso8", "App is not in this project")
|
||||
}
|
||||
if app.Type != proj_model.APPTYPE_OIDC {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-98uje", "App is not an oidc application")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
repoConfig := OIDCConfigFromModel(config)
|
||||
|
||||
projectAggregate := OIDCConfigChangedAggregate(es.Eventstore.AggregateCreator(), repoProject, repoConfig)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, a := range repoProject.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
return OIDCConfigToModel(a.OIDCConfig), nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-dk87s", "Could not find app in list")
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ChangeOIDCConfigSecret(ctx context.Context, projectID, appID string) (*proj_model.OIDCConfig, error) {
|
||||
if appID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-7ue34", "some required fields missing")
|
||||
}
|
||||
existing, err := es.ProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ok bool
|
||||
var app *proj_model.Application
|
||||
if app, ok = existing.ContainsApp(&proj_model.Application{AppID: appID}); !ok {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9odi4", "App is not in this project")
|
||||
}
|
||||
if app.Type != proj_model.APPTYPE_OIDC {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-dile4", "App is not an oidc application")
|
||||
}
|
||||
repoProject := ProjectFromModel(existing)
|
||||
|
||||
stringPw, crypto, err := generateNewClientSecret(es.pwGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectAggregate := OIDCConfigSecretChangedAggregate(es.Eventstore.AggregateCreator(), repoProject, appID, crypto)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoProject.AppendEvents, projectAggregate)
|
||||
es.projectCache.cacheProject(repoProject)
|
||||
for _, a := range repoProject.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
config := OIDCConfigToModel(a.OIDCConfig)
|
||||
config.ClientSecretString = stringPw
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-dk87s", "Could not find app in list")
|
||||
}
|
||||
|
@ -3,12 +3,30 @@ package eventsourcing
|
||||
import (
|
||||
"encoding/json"
|
||||
mock_cache "github.com/caos/zitadel/internal/cache/mock"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/mock"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/sony/sonyflake"
|
||||
)
|
||||
|
||||
func GetMockedEventstore(ctrl *gomock.Controller, mockEs *mock.MockEventstore) *ProjectEventstore {
|
||||
return &ProjectEventstore{
|
||||
Eventstore: mockEs,
|
||||
projectCache: GetMockCache(ctrl),
|
||||
idGenerator: GetSonyFlacke(),
|
||||
}
|
||||
}
|
||||
|
||||
func GetMockedEventstoreWithPw(ctrl *gomock.Controller, mockEs *mock.MockEventstore) *ProjectEventstore {
|
||||
return &ProjectEventstore{
|
||||
Eventstore: mockEs,
|
||||
projectCache: GetMockCache(ctrl),
|
||||
idGenerator: GetSonyFlacke(),
|
||||
pwGenerator: GetMockPwGenerator(ctrl),
|
||||
}
|
||||
}
|
||||
func GetMockCache(ctrl *gomock.Controller) *ProjectCache {
|
||||
mockCache := mock_cache.NewMockCache(ctrl)
|
||||
mockCache.EXPECT().Get(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
@ -16,60 +34,133 @@ func GetMockCache(ctrl *gomock.Controller) *ProjectCache {
|
||||
return &ProjectCache{projectCache: mockCache}
|
||||
}
|
||||
|
||||
func GetSonyFlacke() *sonyflake.Sonyflake {
|
||||
return sonyflake.NewSonyflake(sonyflake.Settings{})
|
||||
}
|
||||
|
||||
func GetMockPwGenerator(ctrl *gomock.Controller) crypto.Generator {
|
||||
generator := crypto.NewMockGenerator(ctrl)
|
||||
generator.EXPECT().Length().Return(uint(10))
|
||||
generator.EXPECT().Runes().Return([]rune("abcdefghijklmnopqrstuvwxyz"))
|
||||
generator.EXPECT().Alg().Return(crypto.NewBCrypt(10))
|
||||
return generator
|
||||
}
|
||||
|
||||
func GetMockProjectByIDOK(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockProjectByIDNoEvents(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProject(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProjectWithPw(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreWithPw(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateInactiveProject(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 2, Type: model.ProjectDeactivated, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 2, Type: model.ProjectDeactivated, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProjectWithMember(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
memberData, _ := json.Marshal(ProjectMember{UserID: "UserID", Roles: []string{"Role"}})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectMemberAdded, Data: memberData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectMemberAdded, Data: memberData},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProjectWithRole(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
roleData, _ := json.Marshal(ProjectRole{Key: "Key", DisplayName: "DisplayName", Group: "Group"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectRoleAdded, Data: roleData},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProjectWithOIDCApp(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
appData, _ := json.Marshal(Application{AppID: "AppID", Name: "Name"})
|
||||
oidcData, _ := json.Marshal(OIDCConfig{
|
||||
AppID: "AppID",
|
||||
ResponseTypes: []int32{int32(model.OIDCRESPONSETYPE_CODE)},
|
||||
GrantTypes: []int32{int32(model.OIDCGRANTTYPE_AUTHORIZATION_CODE)},
|
||||
})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ApplicationAdded, Data: appData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.OIDCConfigAdded, Data: oidcData},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreWithPw(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProjectWithSAMLApp(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
appData, _ := json.Marshal(Application{AppID: "AppID", Name: "Name"})
|
||||
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ApplicationAdded, Data: appData},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateProjectNoEvents(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
@ -78,17 +169,32 @@ func GetMockManipulateProjectNoEvents(ctrl *gomock.Controller) *ProjectEventstor
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockProjectMemberByIDsOK(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
projectData, _ := json.Marshal(Project{Name: "Name"})
|
||||
memberData, _ := json.Marshal(ProjectMember{UserID: "UserID", Roles: []string{"Role"}})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: projectData},
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectMemberAdded, Data: memberData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: projectData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectMemberAdded, Data: memberData},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs, projectCache: GetMockCache(ctrl)}
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockProjectAppsByIDsOK(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
projectData, _ := json.Marshal(Project{Name: "Name"})
|
||||
appData, _ := json.Marshal(Application{AppID: "AppID", Name: "Name"})
|
||||
oidcData, _ := json.Marshal(OIDCConfig{ClientID: "ClientID"})
|
||||
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded, Data: projectData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ApplicationAdded, Data: appData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.OIDCConfigAdded, Data: oidcData},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,11 +2,11 @@ package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -15,9 +15,11 @@ const (
|
||||
|
||||
type Project struct {
|
||||
es_models.ObjectRoot
|
||||
Name string `json:"name,omitempty"`
|
||||
State int32 `json:"-"`
|
||||
Members []*ProjectMember `json:"-"`
|
||||
Name string `json:"name,omitempty"`
|
||||
State int32 `json:"-"`
|
||||
Members []*ProjectMember `json:"-"`
|
||||
Roles []*ProjectRole `json:"-"`
|
||||
Applications []*Application `json:"-"`
|
||||
}
|
||||
|
||||
type ProjectMember struct {
|
||||
@ -26,6 +28,40 @@ type ProjectMember struct {
|
||||
Roles []string `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
type ProjectRole struct {
|
||||
es_models.ObjectRoot
|
||||
Key string `json:"key,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
}
|
||||
|
||||
type Application struct {
|
||||
es_models.ObjectRoot
|
||||
AppID string `json:"appId"`
|
||||
State int32 `json:"-"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Type int32 `json:"appType,omitempty"`
|
||||
OIDCConfig *OIDCConfig `json:"-"`
|
||||
}
|
||||
|
||||
type ApplicationID struct {
|
||||
es_models.ObjectRoot
|
||||
AppID string `json:"appId"`
|
||||
}
|
||||
|
||||
type OIDCConfig struct {
|
||||
es_models.ObjectRoot
|
||||
AppID string `json:"appId"`
|
||||
ClientID string `json:"clientId,omitempty"`
|
||||
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
|
||||
RedirectUris []string `json:"redirectUris,omitempty"`
|
||||
ResponseTypes []int32 `json:"responseTypes,omitempty"`
|
||||
GrantTypes []int32 `json:"grantTypes,omitempty"`
|
||||
ApplicationType int32 `json:"applicationType,omitempty"`
|
||||
AuthMethodType int32 `json:"authMethodType,omitempty"`
|
||||
PostLogoutRedirectUris []string `json:"postLogoutRedirectUris,omitempty"`
|
||||
}
|
||||
|
||||
func (p *Project) Changes(changed *Project) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
if changed.Name != "" && p.Name != changed.Name {
|
||||
@ -34,33 +70,74 @@ func (p *Project) Changes(changed *Project) map[string]interface{} {
|
||||
return changes
|
||||
}
|
||||
|
||||
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 (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 !reflect.DeepEqual(c.PostLogoutRedirectUris, changed.PostLogoutRedirectUris) {
|
||||
changes["postLogoutRedirectUris"] = changed.PostLogoutRedirectUris
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func ProjectFromModel(project *model.Project) *Project {
|
||||
members := ProjectMembersFromModel(project.Members)
|
||||
roles := ProjectRolesFromModel(project.Roles)
|
||||
apps := AppsFromModel(project.Applications)
|
||||
return &Project{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
ID: project.ObjectRoot.ID,
|
||||
AggregateID: project.ObjectRoot.AggregateID,
|
||||
Sequence: project.Sequence,
|
||||
ChangeDate: project.ChangeDate,
|
||||
CreationDate: project.CreationDate,
|
||||
},
|
||||
Name: project.Name,
|
||||
State: model.ProjectStateToInt(project.State),
|
||||
Members: members,
|
||||
Name: project.Name,
|
||||
State: int32(project.State),
|
||||
Members: members,
|
||||
Roles: roles,
|
||||
Applications: apps,
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectToModel(project *Project) *model.Project {
|
||||
members := ProjectMembersToModel(project.Members)
|
||||
roles := ProjectRolesToModel(project.Roles)
|
||||
apps := AppsToModel(project.Applications)
|
||||
return &model.Project{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
ID: project.ID,
|
||||
AggregateID: project.AggregateID,
|
||||
ChangeDate: project.ChangeDate,
|
||||
CreationDate: project.CreationDate,
|
||||
Sequence: project.Sequence,
|
||||
},
|
||||
Name: project.Name,
|
||||
State: model.ProjectStateFromInt(project.State),
|
||||
Members: members,
|
||||
Name: project.Name,
|
||||
State: model.ProjectState(project.State),
|
||||
Members: members,
|
||||
Roles: roles,
|
||||
Applications: apps,
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +160,7 @@ func ProjectMembersFromModel(members []*model.ProjectMember) []*ProjectMember {
|
||||
func ProjectMemberFromModel(member *model.ProjectMember) *ProjectMember {
|
||||
return &ProjectMember{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
ID: member.ObjectRoot.ID,
|
||||
AggregateID: member.ObjectRoot.AggregateID,
|
||||
Sequence: member.Sequence,
|
||||
ChangeDate: member.ChangeDate,
|
||||
CreationDate: member.CreationDate,
|
||||
@ -96,7 +173,7 @@ func ProjectMemberFromModel(member *model.ProjectMember) *ProjectMember {
|
||||
func ProjectMemberToModel(member *ProjectMember) *model.ProjectMember {
|
||||
return &model.ProjectMember{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
ID: member.ID,
|
||||
AggregateID: member.AggregateID,
|
||||
ChangeDate: member.ChangeDate,
|
||||
CreationDate: member.CreationDate,
|
||||
Sequence: member.Sequence,
|
||||
@ -106,6 +183,160 @@ func ProjectMemberToModel(member *ProjectMember) *model.ProjectMember {
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectRolesToModel(roles []*ProjectRole) []*model.ProjectRole {
|
||||
convertedRoles := make([]*model.ProjectRole, len(roles))
|
||||
for i, r := range roles {
|
||||
convertedRoles[i] = ProjectRoleToModel(r)
|
||||
}
|
||||
return convertedRoles
|
||||
}
|
||||
|
||||
func ProjectRolesFromModel(roles []*model.ProjectRole) []*ProjectRole {
|
||||
convertedRoles := make([]*ProjectRole, len(roles))
|
||||
for i, r := range roles {
|
||||
convertedRoles[i] = ProjectRoleFromModel(r)
|
||||
}
|
||||
return convertedRoles
|
||||
}
|
||||
|
||||
func ProjectRoleFromModel(role *model.ProjectRole) *ProjectRole {
|
||||
return &ProjectRole{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: role.ObjectRoot.AggregateID,
|
||||
Sequence: role.Sequence,
|
||||
ChangeDate: role.ChangeDate,
|
||||
CreationDate: role.CreationDate,
|
||||
},
|
||||
Key: role.Key,
|
||||
DisplayName: role.DisplayName,
|
||||
Group: role.Group,
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectRoleToModel(role *ProjectRole) *model.ProjectRole {
|
||||
return &model.ProjectRole{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: role.AggregateID,
|
||||
ChangeDate: role.ChangeDate,
|
||||
CreationDate: role.CreationDate,
|
||||
Sequence: role.Sequence,
|
||||
},
|
||||
Key: role.Key,
|
||||
DisplayName: role.DisplayName,
|
||||
Group: role.Group,
|
||||
}
|
||||
}
|
||||
|
||||
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: es_models.ObjectRoot{
|
||||
AggregateID: app.ObjectRoot.AggregateID,
|
||||
Sequence: app.Sequence,
|
||||
ChangeDate: app.ChangeDate,
|
||||
CreationDate: app.CreationDate,
|
||||
},
|
||||
AppID: app.AppID,
|
||||
Name: app.Name,
|
||||
State: int32(app.State),
|
||||
Type: int32(app.Type),
|
||||
}
|
||||
if app.OIDCConfig != nil {
|
||||
converted.OIDCConfig = OIDCConfigFromModel(app.OIDCConfig)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
func AppToModel(app *Application) *model.Application {
|
||||
converted := &model.Application{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: app.AggregateID,
|
||||
ChangeDate: app.ChangeDate,
|
||||
CreationDate: app.CreationDate,
|
||||
Sequence: app.Sequence,
|
||||
},
|
||||
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)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
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: es_models.ObjectRoot{
|
||||
AggregateID: config.ObjectRoot.AggregateID,
|
||||
Sequence: config.Sequence,
|
||||
ChangeDate: config.ChangeDate,
|
||||
CreationDate: config.CreationDate,
|
||||
},
|
||||
AppID: config.AppID,
|
||||
ClientID: config.ClientID,
|
||||
ClientSecret: config.ClientSecret,
|
||||
RedirectUris: config.RedirectUris,
|
||||
ResponseTypes: responseTypes,
|
||||
GrantTypes: grantTypes,
|
||||
ApplicationType: int32(config.ApplicationType),
|
||||
AuthMethodType: int32(config.AuthMethodType),
|
||||
PostLogoutRedirectUris: config.PostLogoutRedirectUris,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
return &model.OIDCConfig{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: config.ObjectRoot.AggregateID,
|
||||
Sequence: config.Sequence,
|
||||
ChangeDate: config.ChangeDate,
|
||||
CreationDate: config.CreationDate,
|
||||
},
|
||||
AppID: config.AppID,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectFromEvents(project *Project, events ...*es_models.Event) (*Project, error) {
|
||||
if project == nil {
|
||||
project = &Project{}
|
||||
@ -132,7 +363,7 @@ func (p *Project) AppendEvent(event *es_models.Event) error {
|
||||
logging.Log("EVEN-idl93").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
p.State = model.ProjectStateToInt(model.Active)
|
||||
p.State = int32(model.PROJECTSTATE_ACTIVE)
|
||||
return nil
|
||||
case model.ProjectDeactivated:
|
||||
return p.appendDeactivatedEvent()
|
||||
@ -144,22 +375,43 @@ func (p *Project) AppendEvent(event *es_models.Event) error {
|
||||
return p.appendChangeMemberEvent(event)
|
||||
case model.ProjectMemberRemoved:
|
||||
return p.appendRemoveMemberEvent(event)
|
||||
case model.ProjectRoleAdded:
|
||||
return p.appendAddRoleEvent(event)
|
||||
case model.ProjectRoleChanged:
|
||||
return p.appendChangeRoleEvent(event)
|
||||
case model.ProjectRoleRemoved:
|
||||
return p.appendRemoveRoleEvent(event)
|
||||
case model.ApplicationAdded:
|
||||
return p.appendAddAppEvent(event)
|
||||
case model.ApplicationChanged:
|
||||
return p.appendChangeAppEvent(event)
|
||||
case model.ApplicationRemoved:
|
||||
return p.appendRemoveAppEvent(event)
|
||||
case model.ApplicationDeactivated:
|
||||
return p.appendAppStateEvent(event, model.APPSTATE_INACTIVE)
|
||||
case model.ApplicationReactivated:
|
||||
return p.appendAppStateEvent(event, model.APPSTATE_ACTIVE)
|
||||
case model.OIDCConfigAdded:
|
||||
return p.appendAddOIDCConfigEvent(event)
|
||||
case model.OIDCConfigChanged, model.OIDCConfigSecretChanged:
|
||||
return p.appendChangeOIDCConfigEvent(event)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) appendDeactivatedEvent() error {
|
||||
p.State = model.ProjectStateToInt(model.Inactive)
|
||||
p.State = int32(model.PROJECTSTATE_INACTIVE)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) appendReactivatedEvent() error {
|
||||
p.State = model.ProjectStateToInt(model.Active)
|
||||
p.State = int32(model.PROJECTSTATE_ACTIVE)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) appendAddMemberEvent(event *es_models.Event) error {
|
||||
member, err := getMemberData(event)
|
||||
member := &ProjectMember{}
|
||||
err := member.setData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -169,7 +421,8 @@ func (p *Project) appendAddMemberEvent(event *es_models.Event) error {
|
||||
}
|
||||
|
||||
func (p *Project) appendChangeMemberEvent(event *es_models.Event) error {
|
||||
member, err := getMemberData(event)
|
||||
member := &ProjectMember{}
|
||||
err := member.setData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -182,7 +435,8 @@ func (p *Project) appendChangeMemberEvent(event *es_models.Event) error {
|
||||
}
|
||||
|
||||
func (p *Project) appendRemoveMemberEvent(event *es_models.Event) error {
|
||||
member, err := getMemberData(event)
|
||||
member := &ProjectMember{}
|
||||
err := member.setData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -196,12 +450,165 @@ func (p *Project) appendRemoveMemberEvent(event *es_models.Event) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMemberData(event *es_models.Event) (*ProjectMember, error) {
|
||||
member := &ProjectMember{}
|
||||
member.ObjectRoot.AppendEvent(event)
|
||||
if err := json.Unmarshal(event.Data, member); err != nil {
|
||||
func (m *ProjectMember) setData(event *es_models.Event) error {
|
||||
m.ObjectRoot.AppendEvent(event)
|
||||
if err := json.Unmarshal(event.Data, m); err != nil {
|
||||
logging.Log("EVEN-e4dkp").WithError(err).Error("could not unmarshal event data")
|
||||
return nil, errors.ThrowInternal(err, "EVENT-83js6", "could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return member, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
for i, r := range p.Roles {
|
||||
if r.Key == role.Key {
|
||||
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
|
||||
}
|
||||
for i, r := range p.Roles {
|
||||
if r.Key == role.Key {
|
||||
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 {
|
||||
logging.Log("EVEN-d9euw").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
for i, a := range p.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
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
|
||||
}
|
||||
for i, a := range p.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
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
|
||||
}
|
||||
for i, a := range p.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
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 {
|
||||
logging.Log("EVEN-8die3").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
for i, a := range p.Applications {
|
||||
if a.AppID == config.AppID {
|
||||
p.Applications[i].Type = int32(model.APPTYPE_OIDC)
|
||||
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
|
||||
}
|
||||
for i, a := range p.Applications {
|
||||
if a.AppID == config.AppID {
|
||||
p.Applications[i].OIDCConfig.setData(event)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OIDCConfig) setData(event *es_models.Event) error {
|
||||
o.ObjectRoot.AppendEvent(event)
|
||||
if err := json.Unmarshal(event.Data, o); err != nil {
|
||||
logging.Log("EVEN-d8e3s").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -8,168 +8,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
)
|
||||
|
||||
func TestProjectFromEvents(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "project from events, ok",
|
||||
args: args{
|
||||
event: []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded},
|
||||
},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "project from events, nil project",
|
||||
args: args{
|
||||
event: []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded},
|
||||
},
|
||||
project: nil,
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.project != nil {
|
||||
data, _ := json.Marshal(tt.args.project)
|
||||
tt.args.event[0].Data = data
|
||||
}
|
||||
result, _ := ProjectFromEvents(tt.args.project, tt.args.event...)
|
||||
if result.Name != tt.result.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.result.Name, result.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendEvent(t *testing.T) {
|
||||
type args struct {
|
||||
event *es_models.Event
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append added event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "append change event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectChanged},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "append deactivate event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectDeactivated},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Inactive)},
|
||||
},
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectReactivated},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.project != nil {
|
||||
data, _ := json.Marshal(tt.args.project)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
result := &Project{}
|
||||
result.AppendEvent(tt.args.event)
|
||||
if result.State != tt.result.State {
|
||||
t.Errorf("got wrong result state: expected: %v, actual: %v ", tt.result.State, result.State)
|
||||
}
|
||||
if result.Name != tt.result.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.result.Name, result.Name)
|
||||
}
|
||||
if result.ObjectRoot.ID != tt.result.ObjectRoot.ID {
|
||||
t.Errorf("got wrong result id: expected: %v, actual: %v ", tt.result.ObjectRoot.ID, result.ObjectRoot.ID)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendDeactivatedEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
},
|
||||
result: &Project{State: int32(model.Inactive)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.args.project.appendDeactivatedEvent()
|
||||
if tt.args.project.State != tt.result.State {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, tt.args.project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendReactivatedEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
},
|
||||
result: &Project{State: int32(model.Active)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.args.project.appendReactivatedEvent()
|
||||
if tt.args.project.State != tt.result.State {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, tt.args.project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChanges(t *testing.T) {
|
||||
func TestProjectChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existing *Project
|
||||
new *Project
|
||||
@ -213,6 +52,302 @@ func TestChanges(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplicationChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existing *Application
|
||||
new *Application
|
||||
}
|
||||
type res struct {
|
||||
changesLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "application name changes",
|
||||
args: args{
|
||||
existing: &Application{AppID: "AppID", Name: "Name"},
|
||||
new: &Application{AppID: "AppID", Name: "NameChanged"},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
args: args{
|
||||
existing: &Application{AppID: "AppID", Name: "Name"},
|
||||
new: &Application{AppID: "AppID", Name: "Name"},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
changes := tt.args.existing.Changes(tt.args.new)
|
||||
if len(changes) != tt.res.changesLen {
|
||||
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOIDCConfigChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existing *OIDCConfig
|
||||
new *OIDCConfig
|
||||
}
|
||||
type res struct {
|
||||
changesLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "all possible values change",
|
||||
args: args{
|
||||
existing: &OIDCConfig{
|
||||
AppID: "AppID",
|
||||
RedirectUris: []string{"RedirectUris"},
|
||||
ResponseTypes: []int32{1},
|
||||
GrantTypes: []int32{1},
|
||||
ApplicationType: 1,
|
||||
AuthMethodType: 1,
|
||||
PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"},
|
||||
},
|
||||
new: &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{
|
||||
existing: &OIDCConfig{
|
||||
AppID: "AppID",
|
||||
RedirectUris: []string{"RedirectUris"},
|
||||
ResponseTypes: []int32{1},
|
||||
GrantTypes: []int32{1},
|
||||
ApplicationType: 1,
|
||||
AuthMethodType: 1,
|
||||
PostLogoutRedirectUris: []string{"PostLogoutRedirectUris"},
|
||||
},
|
||||
new: &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{
|
||||
existing: &OIDCConfig{
|
||||
AppID: "AppID",
|
||||
ClientID: "ClientID",
|
||||
},
|
||||
new: &OIDCConfig{
|
||||
AppID: "AppIDChange",
|
||||
ClientID: "ClientIDChange",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
changes := tt.args.existing.Changes(tt.args.new)
|
||||
if len(changes) != tt.res.changesLen {
|
||||
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectFromEvents(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "project from events, ok",
|
||||
args: args{
|
||||
event: []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded},
|
||||
},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, State: int32(model.PROJECTSTATE_ACTIVE), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "project from events, nil project",
|
||||
args: args{
|
||||
event: []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded},
|
||||
},
|
||||
project: nil,
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, State: int32(model.PROJECTSTATE_ACTIVE)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.project != nil {
|
||||
data, _ := json.Marshal(tt.args.project)
|
||||
tt.args.event[0].Data = data
|
||||
}
|
||||
result, _ := ProjectFromEvents(tt.args.project, tt.args.event...)
|
||||
if result.Name != tt.result.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.result.Name, result.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendEvent(t *testing.T) {
|
||||
type args struct {
|
||||
event *es_models.Event
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append added event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectAdded},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, State: int32(model.PROJECTSTATE_ACTIVE), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "append change event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectChanged},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, State: int32(model.PROJECTSTATE_ACTIVE), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "append deactivate event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectDeactivated},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, State: int32(model.PROJECTSTATE_INACTIVE)},
|
||||
},
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.ProjectReactivated},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, State: int32(model.PROJECTSTATE_ACTIVE)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.project != nil {
|
||||
data, _ := json.Marshal(tt.args.project)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
result := new(Project)
|
||||
result.AppendEvent(tt.args.event)
|
||||
if result.State != tt.result.State {
|
||||
t.Errorf("got wrong result state: expected: %v, actual: %v ", tt.result.State, result.State)
|
||||
}
|
||||
if result.Name != tt.result.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.result.Name, result.Name)
|
||||
}
|
||||
if result.ObjectRoot.AggregateID != tt.result.ObjectRoot.AggregateID {
|
||||
t.Errorf("got wrong result id: expected: %v, actual: %v ", tt.result.ObjectRoot.AggregateID, result.ObjectRoot.AggregateID)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendDeactivatedEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
},
|
||||
result: &Project{State: int32(model.PROJECTSTATE_INACTIVE)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.args.project.appendDeactivatedEvent()
|
||||
if tt.args.project.State != tt.result.State {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, tt.args.project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendReactivatedEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
},
|
||||
result: &Project{State: int32(model.PROJECTSTATE_ACTIVE)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.args.project.appendReactivatedEvent()
|
||||
if tt.args.project.State != tt.result.State {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, tt.args.project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendAddMemberEvent(t *testing.T) {
|
||||
type args struct {
|
||||
@ -319,7 +454,361 @@ func TestAppendRemoveMemberEvent(t *testing.T) {
|
||||
}
|
||||
tt.args.project.appendRemoveMemberEvent(tt.args.event)
|
||||
if len(tt.args.project.Members) != 0 {
|
||||
t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.project.Members))
|
||||
t.Errorf("got wrong result should have no member actual: %v ", len(tt.args.project.Members))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendAddRoleEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
role *ProjectRole
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append add role event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
role: &ProjectRole{Key: "Key", DisplayName: "DisplayName", Group: "Group"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Project{Roles: []*ProjectRole{&ProjectRole{Key: "Key", DisplayName: "DisplayName", Group: "Group"}}},
|
||||
},
|
||||
}
|
||||
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.appendAddRoleEvent(tt.args.event)
|
||||
if len(tt.args.project.Roles) != 1 {
|
||||
t.Errorf("got wrong result should have one role actual: %v ", len(tt.args.project.Roles))
|
||||
}
|
||||
if tt.args.project.Roles[0] == tt.result.Roles[0] {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Roles[0], tt.args.project.Roles[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendChangeRoleEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
role *ProjectRole
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append change role event",
|
||||
args: args{
|
||||
project: &Project{Roles: []*ProjectRole{&ProjectRole{Key: "Key", DisplayName: "DisplayName", Group: "Group"}}},
|
||||
role: &ProjectRole{Key: "Key", DisplayName: "DisplayNameChanged", Group: "Group"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Project{Roles: []*ProjectRole{&ProjectRole{Key: "Key", DisplayName: "DisplayNameChanged", Group: "Group"}}},
|
||||
},
|
||||
}
|
||||
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.appendChangeRoleEvent(tt.args.event)
|
||||
if len(tt.args.project.Roles) != 1 {
|
||||
t.Errorf("got wrong result should have one role actual: %v ", len(tt.args.project.Roles))
|
||||
}
|
||||
if tt.args.project.Roles[0] == tt.result.Roles[0] {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Roles[0], tt.args.project.Roles[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendRemoveRoleEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
role *ProjectRole
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append remove role event",
|
||||
args: args{
|
||||
project: &Project{Roles: []*ProjectRole{&ProjectRole{Key: "Key", DisplayName: "DisplayName", Group: "Group"}}},
|
||||
role: &ProjectRole{Key: "Key"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Project{Roles: []*ProjectRole{}},
|
||||
},
|
||||
}
|
||||
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.appendRemoveRoleEvent(tt.args.event)
|
||||
if len(tt.args.project.Roles) != 0 {
|
||||
t.Errorf("got wrong result should have no role actual: %v ", len(tt.args.project.Roles))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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{&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{&Application{Name: "Application"}}},
|
||||
app: &Application{Name: "Application Change"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Project{Applications: []*Application{&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{&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{&Application{AppID: "AppID", Name: "Application", State: int32(model.APPSTATE_ACTIVE)}}},
|
||||
app: &ApplicationID{AppID: "AppID"},
|
||||
event: &es_models.Event{},
|
||||
state: model.APPSTATE_INACTIVE,
|
||||
},
|
||||
result: &Project{Applications: []*Application{&Application{AppID: "AppID", Name: "Application", State: int32(model.APPSTATE_INACTIVE)}}},
|
||||
},
|
||||
{
|
||||
name: "append reactivate application event",
|
||||
args: args{
|
||||
project: &Project{Applications: []*Application{&Application{AppID: "AppID", Name: "Application", State: int32(model.APPSTATE_INACTIVE)}}},
|
||||
app: &ApplicationID{AppID: "AppID"},
|
||||
event: &es_models.Event{},
|
||||
state: model.APPSTATE_ACTIVE,
|
||||
},
|
||||
result: &Project{Applications: []*Application{&Application{AppID: "AppID", Name: "Application", State: int32(model.APPSTATE_ACTIVE)}}},
|
||||
},
|
||||
}
|
||||
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])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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{&Application{AppID: "AppID"}}},
|
||||
config: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Project{Applications: []*Application{&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{&Application{AppID: "AppID", OIDCConfig: &OIDCConfig{AppID: "AppID", ClientID: "ClientID"}}}},
|
||||
config: &OIDCConfig{AppID: "AppID", ClientID: "ClientID Changed"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Project{Applications: []*Application{&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])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
30
internal/project/repository/eventsourcing/oidc.go
Normal file
30
internal/project/repository/eventsourcing/oidc.go
Normal file
@ -0,0 +1,30 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/sony/sonyflake"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//ClientID random_number@projectname (eg. 495894098234@zitadel)
|
||||
func generateNewClientID(idGenerator *sonyflake.Sonyflake, project *model.Project) (string, error) {
|
||||
rndID, err := idGenerator.NextID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v@%v", rndID, strings.ReplaceAll(strings.ToLower(project.Name), " ", "_")), nil
|
||||
}
|
||||
|
||||
func generateNewClientSecret(pwGenerator crypto.Generator) (string, *crypto.CryptoValue, error) {
|
||||
cryptoValue, stringSecret, err := crypto.NewCode(pwGenerator)
|
||||
if err != nil {
|
||||
logging.Log("APP-UpnTI").OnError(err).Error("unable to create client secret")
|
||||
return "", nil, errors.ThrowInternal(err, "APP-gH2Wl", "unable to create password")
|
||||
}
|
||||
return stringSecret, cryptoValue, nil
|
||||
}
|
@ -2,17 +2,13 @@ package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/sony/sonyflake"
|
||||
)
|
||||
|
||||
var idGenerator = sonyflake.NewSonyflake(sonyflake.Settings{})
|
||||
|
||||
func ProjectByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, error) {
|
||||
if id == "" {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dke74", "id should be filled")
|
||||
@ -27,8 +23,11 @@ func ProjectQuery(latestSequence uint64) *es_models.SearchQuery {
|
||||
LatestSequenceFilter(latestSequence)
|
||||
}
|
||||
|
||||
func ProjectAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, id string, sequence uint64) (*es_models.Aggregate, error) {
|
||||
return aggCreator.NewAggregate(ctx, id, model.ProjectAggregate, projectVersion, sequence)
|
||||
func ProjectAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, project *Project) (*es_models.Aggregate, error) {
|
||||
if project == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-doe93", "existing project should not be nil")
|
||||
}
|
||||
return aggCreator.NewAggregate(ctx, project.AggregateID, model.ProjectAggregate, projectVersion, project.Sequence)
|
||||
}
|
||||
|
||||
func ProjectCreateAggregate(aggCreator *es_models.AggregateCreator, project *Project) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
@ -36,14 +35,8 @@ func ProjectCreateAggregate(aggCreator *es_models.AggregateCreator, project *Pro
|
||||
if project == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-kdie6", "project should not be nil")
|
||||
}
|
||||
var err error
|
||||
id, err := idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
project.ID = strconv.FormatUint(id, 10)
|
||||
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, project.ID, project.Sequence)
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -54,13 +47,10 @@ func ProjectCreateAggregate(aggCreator *es_models.AggregateCreator, project *Pro
|
||||
|
||||
func ProjectUpdateAggregate(aggCreator *es_models.AggregateCreator, existing *Project, new *Project) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dk93d", "existing project should not be nil")
|
||||
}
|
||||
if new == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dhr74", "new project should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -79,10 +69,7 @@ func ProjectReactivateAggregate(aggCreator *es_models.AggregateCreator, project
|
||||
|
||||
func projectStateAggregate(aggCreator *es_models.AggregateCreator, project *Project, state models.EventType) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if project == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-37dur", "existing project should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, project.ID, project.Sequence)
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -92,10 +79,10 @@ func projectStateAggregate(aggCreator *es_models.AggregateCreator, project *Proj
|
||||
|
||||
func ProjectMemberAddedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, member *ProjectMember) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-di38f", "existing project should not be nil")
|
||||
if member == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-ie34f", "member should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -105,11 +92,11 @@ func ProjectMemberAddedAggregate(aggCreator *es_models.AggregateCreator, existin
|
||||
|
||||
func ProjectMemberChangedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, member *ProjectMember) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-sle3d", "existing project should not be nil")
|
||||
if member == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-d34fs", "member should not be nil")
|
||||
}
|
||||
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -119,13 +106,174 @@ func ProjectMemberChangedAggregate(aggCreator *es_models.AggregateCreator, exist
|
||||
|
||||
func ProjectMemberRemovedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, member *ProjectMember) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-slo9e", "existing project should not be nil")
|
||||
if member == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dieu7", "member should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.ProjectMemberRemoved, member)
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectRoleAddedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, role *ProjectRole) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if role == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-sleo9", "role should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.ProjectRoleAdded, role)
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectRoleChangedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, role *ProjectRole) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if role == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-oe8sf", "member should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.ProjectRoleChanged, role)
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectRoleRemovedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, role *ProjectRole) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if role == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-d8eis", "member should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.ProjectRoleRemoved, role)
|
||||
}
|
||||
}
|
||||
|
||||
func ApplicationAddedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, app *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", "app should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agg.AppendEvent(model.ApplicationAdded, app)
|
||||
if app.OIDCConfig != nil {
|
||||
agg.AppendEvent(model.OIDCConfigAdded, app.OIDCConfig)
|
||||
}
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ApplicationChangedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, app *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-sleo9", "app should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var changes map[string]interface{}
|
||||
for _, a := range existing.Applications {
|
||||
if a.AppID == app.AppID {
|
||||
changes = a.Changes(app)
|
||||
}
|
||||
}
|
||||
agg.AppendEvent(model.ApplicationChanged, changes)
|
||||
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ApplicationRemovedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, app *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-se23g", "app should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agg.AppendEvent(model.ApplicationRemoved, &ApplicationID{AppID: app.AppID})
|
||||
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ApplicationDeactivatedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, app *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-slfi3", "app should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agg.AppendEvent(model.ApplicationDeactivated, &ApplicationID{AppID: app.AppID})
|
||||
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ApplicationReactivatedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, app *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-slf32", "app should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agg.AppendEvent(model.ApplicationReactivated, &ApplicationID{AppID: app.AppID})
|
||||
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
||||
func OIDCConfigChangedAggregate(aggCreator *es_models.AggregateCreator, existing *Project, config *OIDCConfig) 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", "config should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var changes map[string]interface{}
|
||||
for _, a := range existing.Applications {
|
||||
if a.AppID == config.AppID {
|
||||
if a.OIDCConfig != nil {
|
||||
changes = a.OIDCConfig.Changes(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
agg.AppendEvent(model.OIDCConfigChanged, changes)
|
||||
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
||||
func OIDCConfigSecretChangedAggregate(aggCreator *es_models.AggregateCreator, existing *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, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := make(map[string]interface{}, 1)
|
||||
changes["appId"] = appID
|
||||
changes["clientSecret"] = secret
|
||||
|
||||
agg.AppendEvent(model.OIDCConfigSecretChanged, changes)
|
||||
|
||||
return agg, nil
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,8 @@ import (
|
||||
|
||||
func Test_ToPBStruct(t *testing.T) {
|
||||
type obj struct {
|
||||
ID string
|
||||
Seq uint64
|
||||
AggregateID string
|
||||
Seq uint64
|
||||
}
|
||||
type args struct {
|
||||
obj obj
|
||||
@ -24,11 +24,11 @@ func Test_ToPBStruct(t *testing.T) {
|
||||
{
|
||||
name: "to pb stuct",
|
||||
args: args{
|
||||
obj: obj{ID: "ID", Seq: 12345},
|
||||
obj: obj{AggregateID: "AggregateID", Seq: 12345},
|
||||
},
|
||||
wantErr: false,
|
||||
length: 2,
|
||||
result: obj{ID: "ID", Seq: 12345},
|
||||
result: obj{AggregateID: "AggregateID", Seq: 12345},
|
||||
},
|
||||
{
|
||||
name: "empty struct",
|
||||
@ -37,7 +37,7 @@ func Test_ToPBStruct(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
length: 2,
|
||||
result: obj{ID: "", Seq: 0},
|
||||
result: obj{AggregateID: "", Seq: 0},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@ -49,8 +49,8 @@ func Test_ToPBStruct(t *testing.T) {
|
||||
if !tt.wantErr && len(fields.Fields) != tt.length {
|
||||
t.Errorf("got wrong result length, expecting: %v, actual: %v ", tt.length, len(fields.Fields))
|
||||
}
|
||||
if !tt.wantErr && tt.result.ID != fields.Fields["ID"].GetStringValue() {
|
||||
t.Errorf("got wrong result, ID should be same: expecting: %v, actual: %v ", tt.result.ID, fields.Fields["ID"].GetStringValue())
|
||||
if !tt.wantErr && tt.result.AggregateID != fields.Fields["AggregateID"].GetStringValue() {
|
||||
t.Errorf("got wrong result, AggregateID should be same: expecting: %v, actual: %v ", tt.result.AggregateID, fields.Fields["AggregateID"].GetStringValue())
|
||||
}
|
||||
if !tt.wantErr && int(tt.result.Seq) != int(fields.Fields["Seq"].GetNumberValue()) {
|
||||
t.Errorf("got wrong result, Seq should be same: expecting: %v, actual: %v ", tt.result.Seq, fields.Fields["Seq"].GetStringValue())
|
||||
@ -61,8 +61,8 @@ func Test_ToPBStruct(t *testing.T) {
|
||||
|
||||
func Test_FromPBStruct(t *testing.T) {
|
||||
type obj struct {
|
||||
ID string
|
||||
Seq uint64
|
||||
AggregateID string
|
||||
Seq uint64
|
||||
}
|
||||
type args struct {
|
||||
obj *obj
|
||||
@ -79,23 +79,22 @@ func Test_FromPBStruct(t *testing.T) {
|
||||
args: args{
|
||||
obj: &obj{},
|
||||
fields: &pb_struct.Struct{Fields: map[string]*pb_struct.Value{
|
||||
"ID": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: "ID"}},
|
||||
"Seq": &pb_struct.Value{Kind: &pb_struct.Value_NumberValue{NumberValue: 12345}},
|
||||
"AggregateID": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: "AggregateID"}},
|
||||
"Seq": &pb_struct.Value{Kind: &pb_struct.Value_NumberValue{NumberValue: 12345}},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
result: obj{ID: "ID", Seq: 12345},
|
||||
result: obj{AggregateID: "AggregateID", Seq: 12345},
|
||||
},
|
||||
{
|
||||
name: "no fields",
|
||||
args: args{
|
||||
obj: &obj{},
|
||||
fields: &pb_struct.Struct{Fields: map[string]*pb_struct.Value{},
|
||||
},
|
||||
obj: &obj{},
|
||||
fields: &pb_struct.Struct{Fields: map[string]*pb_struct.Value{}},
|
||||
},
|
||||
wantErr: false,
|
||||
result: obj{ID: "", Seq: 0},
|
||||
result: obj{AggregateID: "", Seq: 0},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@ -104,8 +103,8 @@ func Test_FromPBStruct(t *testing.T) {
|
||||
if tt.wantErr && err == nil {
|
||||
t.Errorf("got wrong result, should get err: actual: %v ", err)
|
||||
}
|
||||
if !tt.wantErr && tt.result.ID != tt.args.obj.ID {
|
||||
t.Errorf("got wrong result, ID should be same: expecting: %v, actual: %v ", tt.result.ID, tt.args.obj.ID)
|
||||
if !tt.wantErr && tt.result.AggregateID != tt.args.obj.AggregateID {
|
||||
t.Errorf("got wrong result, AggregateID should be same: expecting: %v, actual: %v ", tt.result.AggregateID, tt.args.obj.AggregateID)
|
||||
}
|
||||
if !tt.wantErr && int(tt.result.Seq) != int(tt.args.obj.Seq) {
|
||||
t.Errorf("got wrong result, Seq should be same: expecting: %v, actual: %v ", tt.result.Seq, tt.args.obj.Seq)
|
||||
|
@ -91,10 +91,10 @@ func TestPrepareSearchQuery(t *testing.T) {
|
||||
{
|
||||
"search with search query",
|
||||
mockDB(t).
|
||||
expectGetSearchRequestWithSearchQuery("TESTTABLE", TestSearchKey_ID.ToColumnName(), "=", "ID", 2, 2),
|
||||
expectGetSearchRequestWithSearchQuery("TESTTABLE", TestSearchKey_ID.ToColumnName(), "=", "AggregateID", 2, 2),
|
||||
args{
|
||||
table: "TESTTABLE",
|
||||
searchRequest: TestSearchRequest{queries: []SearchQuery{TestSearchQuery{key: TestSearchKey_ID, method: model.SEARCHMETHOD_EQUALS_IGNORE_CASE, value: "ID"}}},
|
||||
searchRequest: TestSearchRequest{queries: []SearchQuery{TestSearchQuery{key: TestSearchKey_ID, method: model.SEARCHMETHOD_EQUALS_IGNORE_CASE, value: "AggregateID"}}},
|
||||
},
|
||||
res{
|
||||
count: 2,
|
||||
@ -104,10 +104,10 @@ func TestPrepareSearchQuery(t *testing.T) {
|
||||
{
|
||||
"search with all params",
|
||||
mockDB(t).
|
||||
expectGetSearchRequestWithAllParams("TESTTABLE", TestSearchKey_ID.ToColumnName(), "=", "ID", "ASC", TestSearchKey_ID, 2, 2, 2, 5),
|
||||
expectGetSearchRequestWithAllParams("TESTTABLE", TestSearchKey_ID.ToColumnName(), "=", "AggregateID", "ASC", TestSearchKey_ID, 2, 2, 2, 5),
|
||||
args{
|
||||
table: "TESTTABLE",
|
||||
searchRequest: TestSearchRequest{limit: 2, offset: 2, sortingColumn: TestSearchKey_ID, asc: true, queries: []SearchQuery{TestSearchQuery{key: TestSearchKey_ID, method: model.SEARCHMETHOD_EQUALS_IGNORE_CASE, value: "ID"}}},
|
||||
searchRequest: TestSearchRequest{limit: 2, offset: 2, sortingColumn: TestSearchKey_ID, asc: true, queries: []SearchQuery{TestSearchQuery{key: TestSearchKey_ID, method: model.SEARCHMETHOD_EQUALS_IGNORE_CASE, value: "AggregateID"}}},
|
||||
},
|
||||
res{
|
||||
count: 5,
|
||||
|
@ -20,7 +20,7 @@ func PrepareGetByKey(table string, key ColumnKey, id string) func(db *gorm.DB, r
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return caos_errs.ThrowNotFound(err, "VIEW-XRI9c", "object not found")
|
||||
}
|
||||
logging.LogWithFields("VIEW-xVShS", "ID", id).WithError(err).Warn("get from view error")
|
||||
logging.LogWithFields("VIEW-xVShS", "AggregateID", id).WithError(err).Warn("get from view error")
|
||||
return caos_errs.ThrowInternal(err, "VIEW-J92Td", "view error")
|
||||
}
|
||||
}
|
||||
|
@ -270,11 +270,11 @@ func TestPreparePut(t *testing.T) {
|
||||
"ok",
|
||||
mockDB(t).
|
||||
expectBegin(nil).
|
||||
expectSave("TESTTABLE", Test{ID: "ID", Test: "VALUE"}).
|
||||
expectSave("TESTTABLE", Test{ID: "AggregateID", Test: "VALUE"}).
|
||||
expectCommit(nil),
|
||||
args{
|
||||
table: "TESTTABLE",
|
||||
object: &Test{ID: "ID", Test: "VALUE"},
|
||||
object: &Test{ID: "AggregateID", Test: "VALUE"},
|
||||
},
|
||||
res{
|
||||
result: Test{ID: "VALUE"},
|
||||
@ -285,11 +285,11 @@ func TestPreparePut(t *testing.T) {
|
||||
"db error",
|
||||
mockDB(t).
|
||||
expectBegin(nil).
|
||||
expectSaveErr("TESTTABLE", Test{ID: "ID", Test: "VALUE"}, gorm.ErrUnaddressable).
|
||||
expectSaveErr("TESTTABLE", Test{ID: "AggregateID", Test: "VALUE"}, gorm.ErrUnaddressable).
|
||||
expectCommit(nil),
|
||||
args{
|
||||
table: "TESTTABLE",
|
||||
object: &Test{ID: "ID", Test: "VALUE"},
|
||||
object: &Test{ID: "AggregateID", Test: "VALUE"},
|
||||
},
|
||||
res{
|
||||
result: Test{ID: "VALUE"},
|
||||
|
@ -3,33 +3,69 @@ package grpc
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) SearchApplications(ctx context.Context, request *ApplicationSearchRequest) (*ApplicationSearchResponse, error) {
|
||||
func (s *Server) SearchApplications(ctx context.Context, in *ApplicationSearchRequest) (*ApplicationSearchResponse, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-yW23f", "Not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) ApplicationByID(ctx context.Context, request *ApplicationID) (*Application, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-bmr6X", "Not implemented")
|
||||
func (s *Server) ApplicationByID(ctx context.Context, in *ApplicationID) (*Application, error) {
|
||||
app, err := s.project.ApplicationByID(ctx, in.ProjectId, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appFromModel(app), nil
|
||||
}
|
||||
|
||||
func (s *Server) CreateOIDCApplication(ctx context.Context, in *OIDCApplicationCreate) (*Application, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-poe4d", "Not implemented")
|
||||
app, err := s.project.AddApplication(ctx, oidcAppCreateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appFromModel(app), nil
|
||||
}
|
||||
func (s *Server) UpdateApplication(ctx context.Context, in *ApplicationUpdate) (*Application, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-bmt6J", "Not implemented")
|
||||
app, err := s.project.ChangeApplication(ctx, appUpdateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appFromModel(app), nil
|
||||
}
|
||||
func (s *Server) DeactivateApplication(ctx context.Context, in *ApplicationID) (*Application, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-cD34f", "Not implemented")
|
||||
app, err := s.project.DeactivateApplication(ctx, in.ProjectId, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appFromModel(app), nil
|
||||
}
|
||||
func (s *Server) ReactivateApplication(ctx context.Context, in *ApplicationID) (*Application, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-mo98S", "Not implemented")
|
||||
app, err := s.project.ReactivateApplication(ctx, in.ProjectId, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appFromModel(app), nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveApplication(ctx context.Context, in *ApplicationID) (*empty.Empty, error) {
|
||||
err := s.project.RemoveApplication(ctx, in.ProjectId, in.Id)
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfigUpdate) (*OIDCConfig, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-xm56g", "Not implemented")
|
||||
config, err := s.project.ChangeOIDCConfig(ctx, oidcConfigUpdateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oidcConfigFromModel(config), nil
|
||||
}
|
||||
|
||||
func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *ApplicationID) (*ClientSecret, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-dlwp3", "Not implemented")
|
||||
config, err := s.project.ChangeOIDConfigSecret(ctx, in.ProjectId, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientSecret{ClientSecret: config.ClientSecretString}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ApplicationChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
||||
|
225
pkg/management/api/grpc/application_converter.go
Normal file
225
pkg/management/api/grpc/application_converter.go
Normal file
@ -0,0 +1,225 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
func appFromModel(app *proj_model.Application) *Application {
|
||||
creationDate, err := ptypes.TimestampProto(app.CreationDate)
|
||||
logging.Log("GRPC-iejs3").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(app.ChangeDate)
|
||||
logging.Log("GRPC-di7rw").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &Application{
|
||||
Id: app.AppID,
|
||||
State: appStateFromModel(app.State),
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Name: app.Name,
|
||||
Sequence: app.Sequence,
|
||||
AppConfig: appConfigFromModel(app),
|
||||
}
|
||||
}
|
||||
|
||||
func appConfigFromModel(app *proj_model.Application) isApplication_AppConfig {
|
||||
if app.Type == proj_model.APPTYPE_OIDC {
|
||||
return &Application_OidcConfig{
|
||||
OidcConfig: oidcConfigFromModel(app.OIDCConfig),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func oidcConfigFromModel(config *proj_model.OIDCConfig) *OIDCConfig {
|
||||
return &OIDCConfig{
|
||||
RedirectUris: config.RedirectUris,
|
||||
ResponseTypes: oidcResponseTypesFromModel(config.ResponseTypes),
|
||||
GrantTypes: oidcGrantTypesFromModel(config.GrantTypes),
|
||||
ApplicationType: oidcApplicationTypeFromModel(config.ApplicationType),
|
||||
ClientId: config.ClientID,
|
||||
ClientSecret: config.ClientSecretString,
|
||||
AuthMethodType: oidcAuthMethodTypeFromModel(config.AuthMethodType),
|
||||
PostLogoutRedirectUris: config.PostLogoutRedirectUris,
|
||||
}
|
||||
}
|
||||
|
||||
func oidcAppCreateToModel(app *OIDCApplicationCreate) *proj_model.Application {
|
||||
return &proj_model.Application{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: app.ProjectId,
|
||||
},
|
||||
Name: app.Name,
|
||||
Type: proj_model.APPTYPE_OIDC,
|
||||
OIDCConfig: &proj_model.OIDCConfig{
|
||||
RedirectUris: app.RedirectUris,
|
||||
ResponseTypes: oidcResponseTypesToModel(app.ResponseTypes),
|
||||
GrantTypes: oidcGrantTypesToModel(app.GrantTypes),
|
||||
ApplicationType: oidcApplicationTypeToModel(app.ApplicationType),
|
||||
AuthMethodType: oidcAuthMethodTypeToModel(app.AuthMethodType),
|
||||
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func appUpdateToModel(app *ApplicationUpdate) *proj_model.Application {
|
||||
return &proj_model.Application{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: app.ProjectId,
|
||||
},
|
||||
AppID: app.Id,
|
||||
Name: app.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func oidcConfigUpdateToModel(app *OIDCConfigUpdate) *proj_model.OIDCConfig {
|
||||
return &proj_model.OIDCConfig{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: app.ProjectId,
|
||||
},
|
||||
AppID: app.ApplicationId,
|
||||
RedirectUris: app.RedirectUris,
|
||||
ResponseTypes: oidcResponseTypesToModel(app.ResponseTypes),
|
||||
GrantTypes: oidcGrantTypesToModel(app.GrantTypes),
|
||||
ApplicationType: oidcApplicationTypeToModel(app.ApplicationType),
|
||||
AuthMethodType: oidcAuthMethodTypeToModel(app.AuthMethodType),
|
||||
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
|
||||
}
|
||||
}
|
||||
|
||||
func appStateFromModel(state proj_model.AppState) AppState {
|
||||
switch state {
|
||||
case proj_model.APPSTATE_ACTIVE:
|
||||
return AppState_APPSTATE_ACTIVE
|
||||
case proj_model.APPSTATE_INACTIVE:
|
||||
return AppState_APPSTATE_INACTIVE
|
||||
default:
|
||||
return AppState_APPSTATE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func oidcResponseTypesToModel(responseTypes []OIDCResponseType) []proj_model.OIDCResponseType {
|
||||
if responseTypes == nil || len(responseTypes) == 0 {
|
||||
return []proj_model.OIDCResponseType{proj_model.OIDCRESPONSETYPE_CODE}
|
||||
}
|
||||
oidcResponseTypes := make([]proj_model.OIDCResponseType, len(responseTypes))
|
||||
|
||||
for i, responseType := range responseTypes {
|
||||
switch responseType {
|
||||
case OIDCResponseType_OIDCRESPONSETYPE_CODE:
|
||||
oidcResponseTypes[i] = proj_model.OIDCRESPONSETYPE_CODE
|
||||
case OIDCResponseType_OIDCRESPONSETYPE_ID_TOKEN:
|
||||
oidcResponseTypes[i] = proj_model.OIDCRESPONSETYPE_ID_TOKEN
|
||||
case OIDCResponseType_OIDCRESPONSETYPE_TOKEN:
|
||||
oidcResponseTypes[i] = proj_model.OIDCRESPONSETYPE_TOKEN
|
||||
}
|
||||
}
|
||||
|
||||
return oidcResponseTypes
|
||||
}
|
||||
|
||||
func oidcResponseTypesFromModel(responseTypes []proj_model.OIDCResponseType) []OIDCResponseType {
|
||||
oidcResponseTypes := make([]OIDCResponseType, len(responseTypes))
|
||||
|
||||
for i, responseType := range responseTypes {
|
||||
switch responseType {
|
||||
case proj_model.OIDCRESPONSETYPE_CODE:
|
||||
oidcResponseTypes[i] = OIDCResponseType_OIDCRESPONSETYPE_CODE
|
||||
case proj_model.OIDCRESPONSETYPE_ID_TOKEN:
|
||||
oidcResponseTypes[i] = OIDCResponseType_OIDCRESPONSETYPE_ID_TOKEN
|
||||
case proj_model.OIDCRESPONSETYPE_TOKEN:
|
||||
oidcResponseTypes[i] = OIDCResponseType_OIDCRESPONSETYPE_TOKEN
|
||||
}
|
||||
}
|
||||
|
||||
return oidcResponseTypes
|
||||
}
|
||||
|
||||
func oidcGrantTypesToModel(grantTypes []OIDCGrantType) []proj_model.OIDCGrantType {
|
||||
if grantTypes == nil || len(grantTypes) == 0 {
|
||||
return []proj_model.OIDCGrantType{proj_model.OIDCGRANTTYPE_AUTHORIZATION_CODE}
|
||||
}
|
||||
oidcGrantTypes := make([]proj_model.OIDCGrantType, len(grantTypes))
|
||||
|
||||
for i, grantType := range grantTypes {
|
||||
switch grantType {
|
||||
case OIDCGrantType_OIDCGRANTTYPE_AUTHORIZATION_CODE:
|
||||
oidcGrantTypes[i] = proj_model.OIDCGRANTTYPE_AUTHORIZATION_CODE
|
||||
case OIDCGrantType_OIDCGRANTTYPE_IMPLICIT:
|
||||
oidcGrantTypes[i] = proj_model.OIDCGRANTTYPE_IMPLICIT
|
||||
case OIDCGrantType_OIDCGRANTTYPE_REFRESH_TOKEN:
|
||||
oidcGrantTypes[i] = proj_model.OIDCGRANTTYPE_REFRESH_TOKEN
|
||||
}
|
||||
}
|
||||
return oidcGrantTypes
|
||||
}
|
||||
|
||||
func oidcGrantTypesFromModel(grantTypes []proj_model.OIDCGrantType) []OIDCGrantType {
|
||||
oidcGrantTypes := make([]OIDCGrantType, len(grantTypes))
|
||||
|
||||
for i, grantType := range grantTypes {
|
||||
switch grantType {
|
||||
case proj_model.OIDCGRANTTYPE_AUTHORIZATION_CODE:
|
||||
oidcGrantTypes[i] = OIDCGrantType_OIDCGRANTTYPE_AUTHORIZATION_CODE
|
||||
case proj_model.OIDCGRANTTYPE_IMPLICIT:
|
||||
oidcGrantTypes[i] = OIDCGrantType_OIDCGRANTTYPE_IMPLICIT
|
||||
case proj_model.OIDCGRANTTYPE_REFRESH_TOKEN:
|
||||
oidcGrantTypes[i] = OIDCGrantType_OIDCGRANTTYPE_REFRESH_TOKEN
|
||||
}
|
||||
}
|
||||
return oidcGrantTypes
|
||||
}
|
||||
|
||||
func oidcApplicationTypeToModel(appType OIDCApplicationType) proj_model.OIDCApplicationType {
|
||||
switch appType {
|
||||
case OIDCApplicationType_OIDCAPPLICATIONTYPE_WEB:
|
||||
return proj_model.OIDCAPPLICATIONTYPE_WEB
|
||||
case OIDCApplicationType_OIDCAPPLICATIONTYPE_USER_AGENT:
|
||||
return proj_model.OIDCAPPLICATIONTYPE_USER_AGENT
|
||||
case OIDCApplicationType_OIDCAPPLICATIONTYPE_NATIVE:
|
||||
return proj_model.OIDCAPPLICATIONTYPE_NATIVE
|
||||
}
|
||||
return proj_model.OIDCAPPLICATIONTYPE_WEB
|
||||
}
|
||||
|
||||
func oidcApplicationTypeFromModel(appType proj_model.OIDCApplicationType) OIDCApplicationType {
|
||||
switch appType {
|
||||
case proj_model.OIDCAPPLICATIONTYPE_WEB:
|
||||
return OIDCApplicationType_OIDCAPPLICATIONTYPE_WEB
|
||||
case proj_model.OIDCAPPLICATIONTYPE_USER_AGENT:
|
||||
return OIDCApplicationType_OIDCAPPLICATIONTYPE_USER_AGENT
|
||||
case proj_model.OIDCAPPLICATIONTYPE_NATIVE:
|
||||
return OIDCApplicationType_OIDCAPPLICATIONTYPE_NATIVE
|
||||
default:
|
||||
return OIDCApplicationType_OIDCAPPLICATIONTYPE_WEB
|
||||
}
|
||||
}
|
||||
|
||||
func oidcAuthMethodTypeToModel(authType OIDCAuthMethodType) proj_model.OIDCAuthMethodType {
|
||||
switch authType {
|
||||
case OIDCAuthMethodType_OIDCAUTHMETHODTYPE_BASIC:
|
||||
return proj_model.OIDCAUTHMETHODTYPE_BASIC
|
||||
case OIDCAuthMethodType_OIDCAUTHMETHODTYPE_POST:
|
||||
return proj_model.OIDCAUTHMETHODTYPE_POST
|
||||
case OIDCAuthMethodType_OIDCAUTHMETHODTYPE_NONE:
|
||||
return proj_model.OIDCAUTHMETHODTYPE_NONE
|
||||
default:
|
||||
return proj_model.OIDCAUTHMETHODTYPE_BASIC
|
||||
}
|
||||
}
|
||||
|
||||
func oidcAuthMethodTypeFromModel(authType proj_model.OIDCAuthMethodType) OIDCAuthMethodType {
|
||||
switch authType {
|
||||
case proj_model.OIDCAUTHMETHODTYPE_BASIC:
|
||||
return OIDCAuthMethodType_OIDCAUTHMETHODTYPE_BASIC
|
||||
case proj_model.OIDCAUTHMETHODTYPE_POST:
|
||||
return OIDCAuthMethodType_OIDCAUTHMETHODTYPE_POST
|
||||
case proj_model.OIDCAUTHMETHODTYPE_NONE:
|
||||
return OIDCAuthMethodType_OIDCAUTHMETHODTYPE_NONE
|
||||
default:
|
||||
return OIDCAuthMethodType_OIDCAUTHMETHODTYPE_BASIC
|
||||
}
|
||||
}
|
@ -325,6 +325,11 @@ var ManagementService_AuthMethods = utils_auth.MethodMapping{
|
||||
CheckParam: "Id",
|
||||
},
|
||||
|
||||
"/caos.zitadel.management.api.v1.ManagementService/ChangeProjectRole": utils_auth.Option{
|
||||
Permission: "project.role.write",
|
||||
CheckParam: "Id",
|
||||
},
|
||||
|
||||
"/caos.zitadel.management.api.v1.ManagementService/RemoveProjectRole": utils_auth.Option{
|
||||
Permission: "project.role.delete",
|
||||
CheckParam: "Id",
|
||||
@ -360,6 +365,11 @@ var ManagementService_AuthMethods = utils_auth.MethodMapping{
|
||||
CheckParam: "ProjectId",
|
||||
},
|
||||
|
||||
"/caos.zitadel.management.api.v1.ManagementService/RemoveApplication": utils_auth.Option{
|
||||
Permission: "project.app.delete",
|
||||
CheckParam: "ProjectId",
|
||||
},
|
||||
|
||||
"/caos.zitadel.management.api.v1.ManagementService/UpdateApplicationOIDCConfig": utils_auth.Option{
|
||||
Permission: "project.app.write",
|
||||
CheckParam: "ProjectId",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1860,6 +1860,52 @@ func request_ManagementService_AddProjectRole_0(ctx context.Context, marshaler r
|
||||
|
||||
}
|
||||
|
||||
func request_ManagementService_ChangeProjectRole_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ProjectRoleChange
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
val, ok = pathParams["key"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "key")
|
||||
}
|
||||
|
||||
protoReq.Key, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "key", err)
|
||||
}
|
||||
|
||||
msg, err := client.ChangeProjectRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_ManagementService_RemoveProjectRole_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ProjectRoleRemove
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -1882,15 +1928,15 @@ func request_ManagementService_RemoveProjectRole_0(ctx context.Context, marshale
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
val, ok = pathParams["name"]
|
||||
val, ok = pathParams["key"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "key")
|
||||
}
|
||||
|
||||
protoReq.Name, err = runtime.String(val)
|
||||
protoReq.Key, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "key", err)
|
||||
}
|
||||
|
||||
msg, err := client.RemoveProjectRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
@ -2144,6 +2190,44 @@ func request_ManagementService_ReactivateApplication_0(ctx context.Context, mars
|
||||
|
||||
}
|
||||
|
||||
func request_ManagementService_RemoveApplication_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ApplicationID
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["project_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id")
|
||||
}
|
||||
|
||||
protoReq.ProjectId, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
|
||||
}
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := client.RemoveApplication(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_ManagementService_UpdateApplicationOIDCConfig_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OIDCConfigUpdate
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -4874,6 +4958,26 @@ func RegisterManagementServiceHandlerClient(ctx context.Context, mux *runtime.Se
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("PUT", pattern_ManagementService_ChangeProjectRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_ManagementService_ChangeProjectRole_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ManagementService_ChangeProjectRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_ManagementService_RemoveProjectRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@ -5014,6 +5118,26 @@ func RegisterManagementServiceHandlerClient(ctx context.Context, mux *runtime.Se
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_ManagementService_RemoveApplication_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_ManagementService_RemoveApplication_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ManagementService_RemoveApplication_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("PUT", pattern_ManagementService_UpdateApplicationOIDCConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@ -5788,7 +5912,9 @@ var (
|
||||
|
||||
pattern_ManagementService_AddProjectRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"projects", "id", "roles"}, ""))
|
||||
|
||||
pattern_ManagementService_RemoveProjectRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"projects", "id", "roles", "name"}, ""))
|
||||
pattern_ManagementService_ChangeProjectRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"projects", "id", "roles", "key"}, ""))
|
||||
|
||||
pattern_ManagementService_RemoveProjectRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"projects", "id", "roles", "key"}, ""))
|
||||
|
||||
pattern_ManagementService_SearchApplications_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 2, 3}, []string{"projects", "project_id", "applications", "_search"}, ""))
|
||||
|
||||
@ -5802,6 +5928,8 @@ var (
|
||||
|
||||
pattern_ManagementService_ReactivateApplication_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"projects", "project_id", "applications", "id", "_reactivate"}, ""))
|
||||
|
||||
pattern_ManagementService_RemoveApplication_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"projects", "project_id", "applications", "id"}, ""))
|
||||
|
||||
pattern_ManagementService_UpdateApplicationOIDCConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"projects", "project_id", "applications", "application_id", "oidcconfig"}, ""))
|
||||
|
||||
pattern_ManagementService_RegenerateOIDCClientSecret_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"projects", "project_id", "applications", "id", "oidcconfig", "_changeclientsecret"}, ""))
|
||||
@ -5998,6 +6126,8 @@ var (
|
||||
|
||||
forward_ManagementService_AddProjectRole_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_ChangeProjectRole_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_RemoveProjectRole_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_SearchApplications_0 = runtime.ForwardResponseMessage
|
||||
@ -6012,6 +6142,8 @@ var (
|
||||
|
||||
forward_ManagementService_ReactivateApplication_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_RemoveApplication_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_UpdateApplicationOIDCConfig_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_RegenerateOIDCClientSecret_0 = runtime.ForwardResponseMessage
|
||||
|
@ -1318,7 +1318,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"properties": {}
|
||||
"$ref": "#/definitions/v1ProjectRole"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1343,7 +1343,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/projects/{id}/roles/{name}": {
|
||||
"/projects/{id}/roles/{key}": {
|
||||
"delete": {
|
||||
"operationId": "RemoveProjectRole",
|
||||
"responses": {
|
||||
@ -1362,7 +1362,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"name": "key",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
@ -1371,6 +1371,42 @@
|
||||
"tags": [
|
||||
"ManagementService"
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"operationId": "ChangeProjectRole",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1ProjectRole"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "key",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1ProjectRoleChange"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"ManagementService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/projects/{project_id}/applications/_search": {
|
||||
@ -1473,6 +1509,34 @@
|
||||
"ManagementService"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"operationId": "RemoveApplication",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"ManagementService"
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"operationId": "UpdateApplication",
|
||||
"responses": {
|
||||
@ -3868,7 +3932,7 @@
|
||||
"enum": [
|
||||
"OIDCRESPONSETYPE_CODE",
|
||||
"OIDCRESPONSETYPE_ID_TOKEN",
|
||||
"OIDCRESPONSETYPE_TOKEN_ID_TOKEN"
|
||||
"OIDCRESPONSETYPE_TOKEN"
|
||||
],
|
||||
"default": "OIDCRESPONSETYPE_CODE"
|
||||
},
|
||||
@ -4898,7 +4962,7 @@
|
||||
"project_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
@ -4908,6 +4972,10 @@
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -4923,7 +4991,24 @@
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1ProjectRoleChange": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
@ -4938,7 +5023,7 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"PROJECTROLESEARCHKEY_UNSPECIFIED",
|
||||
"PROJECTROLESEARCHKEY_NAME",
|
||||
"PROJECTROLESEARCHKEY_KEY",
|
||||
"PROJECTROLESEARCHKEY_DISPLAY_NAME"
|
||||
],
|
||||
"default": "PROJECTROLESEARCHKEY_UNSPECIFIED"
|
||||
|
@ -98,14 +98,14 @@ func (mr *MockManagementServiceClientMockRecorder) AddProjectMember(arg0, arg1 i
|
||||
}
|
||||
|
||||
// AddProjectRole mocks base method
|
||||
func (m *MockManagementServiceClient) AddProjectRole(arg0 context.Context, arg1 *grpc.ProjectRoleAdd, arg2 ...grpc0.CallOption) (*emptypb.Empty, error) {
|
||||
func (m *MockManagementServiceClient) AddProjectRole(arg0 context.Context, arg1 *grpc.ProjectRoleAdd, arg2 ...grpc0.CallOption) (*grpc.ProjectRole, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "AddProjectRole", varargs...)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
ret0, _ := ret[0].(*grpc.ProjectRole)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@ -217,6 +217,26 @@ func (mr *MockManagementServiceClientMockRecorder) ChangeProjectMember(arg0, arg
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProjectMember", reflect.TypeOf((*MockManagementServiceClient)(nil).ChangeProjectMember), varargs...)
|
||||
}
|
||||
|
||||
// ChangeProjectRole mocks base method
|
||||
func (m *MockManagementServiceClient) ChangeProjectRole(arg0 context.Context, arg1 *grpc.ProjectRoleChange, arg2 ...grpc0.CallOption) (*grpc.ProjectRole, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "ChangeProjectRole", varargs...)
|
||||
ret0, _ := ret[0].(*grpc.ProjectRole)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ChangeProjectRole indicates an expected call of ChangeProjectRole
|
||||
func (mr *MockManagementServiceClientMockRecorder) ChangeProjectRole(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProjectRole", reflect.TypeOf((*MockManagementServiceClient)(nil).ChangeProjectRole), varargs...)
|
||||
}
|
||||
|
||||
// ChangeUserEmail mocks base method
|
||||
func (m *MockManagementServiceClient) ChangeUserEmail(arg0 context.Context, arg1 *grpc.UpdateUserEmailRequest, arg2 ...grpc0.CallOption) (*grpc.UserEmail, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -51,11 +51,24 @@ func (s *Server) GetGrantedProjectGrantByID(ctx context.Context, request *Grante
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-974vd", "Not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*empty.Empty, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-0ow2C", "Not implemented")
|
||||
func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*ProjectRole, error) {
|
||||
role, err := s.project.AddProjectRole(ctx, projectRoleAddToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectRoleFromModel(role), nil
|
||||
}
|
||||
func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) (*ProjectRole, error) {
|
||||
role, err := s.project.ChangeProjectRole(ctx, projectRoleChangeToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectRoleFromModel(role), nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveProjectRole(ctx context.Context, in *ProjectRoleRemove) (*empty.Empty, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-bm6iB", "Not implemented")
|
||||
err := s.project.RemoveProjectRole(ctx, in.Id, in.Key)
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) SearchProjectRoles(ctx context.Context, in *ProjectRoleSearchRequest) (*ProjectRoleSearchResponse, error) {
|
||||
|
@ -15,7 +15,7 @@ func projectFromModel(project *proj_model.Project) *Project {
|
||||
logging.Log("GRPC-di7rw").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &Project{
|
||||
Id: project.ID,
|
||||
Id: project.AggregateID,
|
||||
State: projectStateFromModel(project.State),
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
@ -26,9 +26,9 @@ func projectFromModel(project *proj_model.Project) *Project {
|
||||
|
||||
func projectStateFromModel(state proj_model.ProjectState) ProjectState {
|
||||
switch state {
|
||||
case proj_model.Active:
|
||||
case proj_model.PROJECTSTATE_ACTIVE:
|
||||
return ProjectState_PROJECTSTATE_ACTIVE
|
||||
case proj_model.Inactive:
|
||||
case proj_model.PROJECTSTATE_INACTIVE:
|
||||
return ProjectState_PROJECTSTATE_INACTIVE
|
||||
default:
|
||||
return ProjectState_PROJECTSTATE_UNSPECIFIED
|
||||
@ -38,8 +38,47 @@ func projectStateFromModel(state proj_model.ProjectState) ProjectState {
|
||||
func projectUpdateToModel(project *ProjectUpdateRequest) *proj_model.Project {
|
||||
return &proj_model.Project{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
ID: project.Id,
|
||||
AggregateID: project.Id,
|
||||
},
|
||||
Name: project.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func projectRoleFromModel(role *proj_model.ProjectRole) *ProjectRole {
|
||||
creationDate, err := ptypes.TimestampProto(role.CreationDate)
|
||||
logging.Log("GRPC-due83").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(role.ChangeDate)
|
||||
logging.Log("GRPC-id93s").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &ProjectRole{
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: role.Sequence,
|
||||
Key: role.Key,
|
||||
DisplayName: role.DisplayName,
|
||||
Group: role.Group,
|
||||
}
|
||||
}
|
||||
|
||||
func projectRoleAddToModel(role *ProjectRoleAdd) *proj_model.ProjectRole {
|
||||
return &proj_model.ProjectRole{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: role.Id,
|
||||
},
|
||||
Key: role.Key,
|
||||
DisplayName: role.DisplayName,
|
||||
Group: role.Group,
|
||||
}
|
||||
}
|
||||
|
||||
func projectRoleChangeToModel(role *ProjectRoleChange) *proj_model.ProjectRole {
|
||||
return &proj_model.ProjectRole{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: role.Id,
|
||||
},
|
||||
Key: role.Key,
|
||||
DisplayName: role.DisplayName,
|
||||
Group: role.Group,
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ func projectMemberFromModel(member *proj_model.ProjectMember) *ProjectMember {
|
||||
func projectMemberAddToModel(member *ProjectMemberAdd) *proj_model.ProjectMember {
|
||||
return &proj_model.ProjectMember{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
ID: member.Id,
|
||||
AggregateID: member.Id,
|
||||
},
|
||||
UserID: member.UserId,
|
||||
Roles: member.Roles,
|
||||
@ -36,7 +36,7 @@ func projectMemberAddToModel(member *ProjectMemberAdd) *proj_model.ProjectMember
|
||||
func projectMemberChangeToModel(member *ProjectMemberChange) *proj_model.ProjectMember {
|
||||
return &proj_model.ProjectMember{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
ID: member.Id,
|
||||
AggregateID: member.Id,
|
||||
},
|
||||
UserID: member.UserId,
|
||||
Roles: member.Roles,
|
||||
|
@ -722,7 +722,7 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc AddProjectRole(ProjectRoleAdd) returns (google.protobuf.Empty) {
|
||||
rpc AddProjectRole(ProjectRoleAdd) returns (ProjectRole) {
|
||||
option (google.api.http) = {
|
||||
post: "/projects/{id}/roles"
|
||||
body: "*"
|
||||
@ -734,9 +734,21 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc ChangeProjectRole(ProjectRoleChange) returns (ProjectRole) {
|
||||
option (google.api.http) = {
|
||||
put: "/projects/{id}/roles/{key}"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "project.role.write"
|
||||
check_field_name: "Id"
|
||||
};
|
||||
}
|
||||
|
||||
rpc RemoveProjectRole(ProjectRoleRemove) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
delete: "/projects/{id}/roles/{name}"
|
||||
delete: "/projects/{id}/roles/{key}"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
@ -817,6 +829,17 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc RemoveApplication(ApplicationID) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
delete: "/projects/{project_id}/applications/{id}"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "project.app.delete"
|
||||
check_field_name: "ProjectId"
|
||||
};
|
||||
}
|
||||
|
||||
rpc UpdateApplicationOIDCConfig(OIDCConfigUpdate) returns (OIDCConfig) {
|
||||
option (google.api.http) = {
|
||||
put: "/projects/{project_id}/applications/{application_id}/oidcconfig"
|
||||
@ -1724,24 +1747,32 @@ message ProjectMemberRemove {
|
||||
}
|
||||
|
||||
message ProjectRoleAdd {
|
||||
string id = 1;
|
||||
string key = 2;
|
||||
string display_name = 3;
|
||||
string group = 4;
|
||||
}
|
||||
|
||||
message ProjectRoleChange {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string key = 2;
|
||||
string display_name = 3;
|
||||
string group = 4;
|
||||
}
|
||||
|
||||
message ProjectRole {
|
||||
string project_id = 1;
|
||||
string name = 2;
|
||||
string key = 2;
|
||||
string display_name = 3;
|
||||
google.protobuf.Timestamp creation_date = 4;
|
||||
string group = 5;
|
||||
uint64 sequence = 6;
|
||||
google.protobuf.Timestamp change_date = 5;
|
||||
string group = 6;
|
||||
uint64 sequence = 7;
|
||||
}
|
||||
|
||||
message ProjectRoleRemove {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string key = 2;
|
||||
}
|
||||
|
||||
message ProjectRoleSearchResponse {
|
||||
@ -1766,7 +1797,7 @@ message ProjectRoleSearchQuery {
|
||||
|
||||
enum ProjectRoleSearchKey {
|
||||
PROJECTROLESEARCHKEY_UNSPECIFIED = 0;
|
||||
PROJECTROLESEARCHKEY_NAME = 1;
|
||||
PROJECTROLESEARCHKEY_KEY = 1;
|
||||
PROJECTROLESEARCHKEY_DISPLAY_NAME = 2;
|
||||
}
|
||||
|
||||
@ -1859,7 +1890,7 @@ message OIDCConfigUpdate {
|
||||
enum OIDCResponseType {
|
||||
OIDCRESPONSETYPE_CODE = 0;
|
||||
OIDCRESPONSETYPE_ID_TOKEN = 1;
|
||||
OIDCRESPONSETYPE_TOKEN_ID_TOKEN = 2;
|
||||
OIDCRESPONSETYPE_TOKEN = 2;
|
||||
}
|
||||
|
||||
enum OIDCGrantType {
|
||||
|
Loading…
x
Reference in New Issue
Block a user