diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index 7176ad16b2..5e422f11c8 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -23,14 +23,13 @@ import ( "github.com/caos/zitadel/internal/api/oidc" auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing" "github.com/caos/zitadel/internal/authz" - authz_repo "github.com/caos/zitadel/internal/authz/repository/eventsourcing" + authz_repo "github.com/caos/zitadel/internal/authz/repository" "github.com/caos/zitadel/internal/command" "github.com/caos/zitadel/internal/config" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/id" - mgmt_es "github.com/caos/zitadel/internal/management/repository/eventsourcing" "github.com/caos/zitadel/internal/notification" "github.com/caos/zitadel/internal/query" "github.com/caos/zitadel/internal/query/projection" @@ -64,7 +63,6 @@ type Config struct { AuthZ authz.Config Auth auth_es.Config Admin admin_es.Config - Mgmt mgmt_es.Config API api.Config UI ui.Config @@ -158,10 +156,10 @@ func startZitadel(configPaths []string) { } keyChan := make(chan interface{}) - queries, err := query.StartQueries(ctx, esQueries, conf.Projections, conf.SystemDefaults, keyChan) + queries, err := query.StartQueries(ctx, esQueries, conf.Projections, conf.SystemDefaults, keyChan, conf.InternalAuthZ.RolePermissionMappings) logging.Log("MAIN-WpeJY").OnError(err).Fatal("cannot start queries") - authZRepo, err := authz.Start(ctx, conf.AuthZ, conf.InternalAuthZ, conf.SystemDefaults, queries) + authZRepo, err := authz.Start(conf.AuthZ, conf.SystemDefaults, queries) logging.Log("MAIN-s9KOw").OnError(err).Fatal("error starting authz repo") esCommands, err := eventstore.StartWithUser(conf.EventstoreBase, conf.Commands.Eventstore) @@ -177,15 +175,15 @@ func startZitadel(configPaths []string) { var authRepo *auth_es.EsRepository if *authEnabled || *oidcEnabled || *loginEnabled { - authRepo, err = auth_es.Start(conf.Auth, conf.InternalAuthZ, conf.SystemDefaults, commands, queries, authZRepo, esQueries) + authRepo, err = auth_es.Start(conf.Auth, conf.SystemDefaults, commands, queries) logging.Log("MAIN-9oRw6").OnError(err).Fatal("error starting auth repo") } repo := struct { - authz_repo.EsRepository + authz_repo.Repository query.Queries }{ - *authZRepo, + authZRepo, *queries, } @@ -215,33 +213,27 @@ func startUI(ctx context.Context, conf *Config, authRepo *auth_es.EsRepository, uis.Start(ctx) } -func startAPI(ctx context.Context, conf *Config, verifier *internal_authz.TokenVerifier, authZRepo *authz_repo.EsRepository, authRepo *auth_es.EsRepository, command *command.Commands, query *query.Queries, static static.Storage, es *eventstore.Eventstore, projections types.SQL, keyChan <-chan interface{}) { - roles := make([]string, len(conf.InternalAuthZ.RolePermissionMappings)) - for i, role := range conf.InternalAuthZ.RolePermissionMappings { - roles[i] = role.Role - } - repo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, command, static, roles, *localDevMode) +func startAPI(ctx context.Context, conf *Config, verifier *internal_authz.TokenVerifier, authZRepo authz_repo.Repository, authRepo *auth_es.EsRepository, command *command.Commands, query *query.Queries, static static.Storage, es *eventstore.Eventstore, projections types.SQL, keyChan <-chan interface{}) { + repo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, command, static, *localDevMode) logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo") apis := api.Create(conf.API, conf.InternalAuthZ, query, authZRepo, authRepo, repo, conf.SystemDefaults) if *adminEnabled { - apis.RegisterServer(ctx, admin.CreateServer(command, query, repo, conf.SystemDefaults.Domain, conf.Admin.APIDomain+"/assets/v1/")) + apis.RegisterServer(ctx, admin.CreateServer(command, query, repo, conf.SystemDefaults.Domain, conf.API.Domain+"/assets/v1/")) } - managementRepo, err := mgmt_es.Start(conf.Mgmt, conf.SystemDefaults, roles, query, static) - logging.Log("API-Gd2qq").OnError(err).Fatal("error starting management repo") if *managementEnabled { - apis.RegisterServer(ctx, management.CreateServer(command, query, managementRepo, conf.SystemDefaults, conf.Mgmt.APIDomain+"/assets/v1/")) + apis.RegisterServer(ctx, management.CreateServer(command, query, conf.SystemDefaults, conf.API.Domain+"/assets/v1/")) } if *authEnabled { - apis.RegisterServer(ctx, auth.CreateServer(command, query, authRepo, conf.SystemDefaults, conf.Auth.APIDomain+"/assets/v1/")) + apis.RegisterServer(ctx, auth.CreateServer(command, query, authRepo, conf.SystemDefaults, conf.API.Domain+"/assets/v1/")) } if *oidcEnabled { - op := oidc.NewProvider(ctx, conf.API.OIDC, command, query, authRepo, conf.SystemDefaults.KeyConfig, *localDevMode, es, projections, keyChan, conf.Mgmt.APIDomain+"/assets/v1/") + op := oidc.NewProvider(ctx, conf.API.OIDC, command, query, authRepo, conf.SystemDefaults.KeyConfig, *localDevMode, es, projections, keyChan, conf.API.Domain+"/assets/v1/") apis.RegisterHandler("/oauth/v2", op.HttpHandler()) } if *assetsEnabled { - assetsHandler := assets.NewHandler(command, verifier, conf.InternalAuthZ, id.SonyFlakeGenerator, static, managementRepo, query) + assetsHandler := assets.NewHandler(command, verifier, conf.InternalAuthZ, id.SonyFlakeGenerator, static, query) apis.RegisterHandler("/assets/v1", assetsHandler) } diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml index d30d424b9b..53e5709eac 100644 --- a/cmd/zitadel/startup.yaml +++ b/cmd/zitadel/startup.yaml @@ -246,53 +246,8 @@ Admin: BulkLimit: 10000 FailureCountUntilSkip: 5 -Mgmt: - SearchLimit: 1000 - Domain: $ZITADEL_DEFAULT_DOMAIN - APIDomain: $ZITADEL_API_DOMAIN - Eventstore: - ServiceName: 'ManagementAPI' - Repository: - SQL: - Host: $ZITADEL_EVENTSTORE_HOST - Port: $ZITADEL_EVENTSTORE_PORT - User: 'management' - Database: 'eventstore' - Password: $CR_MANAGEMENT_PASSWORD - MaxOpenConns: 3 - MaxConnLifetime: 30m - MaxConnIdleTime: 30m - Options: $CR_OPTIONS - SSL: - Mode: $CR_SSL_MODE - RootCert: $CR_ROOT_CERT - Cert: $CR_MANAGEMENT_CERT - Key: $CR_MANAGEMENT_KEY - Cache: - Type: 'fastcache' - Config: - MaxCacheSizeInByte: 10485760 #10mb - View: - Host: $ZITADEL_EVENTSTORE_HOST - Port: $ZITADEL_EVENTSTORE_PORT - User: 'management' - Options: $CR_OPTIONS - Database: 'management' - Password: $CR_MANAGEMENT_PASSWORD - MaxOpenConns: 3 - MaxConnLifetime: 30m - MaxConnIdleTime: 30m - SSL: - Mode: $CR_SSL_MODE - RootCert: $CR_ROOT_CERT - Cert: $CR_MANAGEMENT_CERT - Key: $CR_MANAGEMENT_KEY - Spooler: - ConcurrentWorkers: 1 - BulkLimit: 10000 - FailureCountUntilSkip: 5 - API: + Domain: $ZITADEL_API_DOMAIN GRPC: ServerPort: 50001 GatewayPort: 50002 diff --git a/docs/docs/apis/proto/auth.md b/docs/docs/apis/proto/auth.md index 2127690cec..5d576d0a90 100644 --- a/docs/docs/apis/proto/auth.md +++ b/docs/docs/apis/proto/auth.md @@ -1042,8 +1042,7 @@ This is an empty request | Field | Type | Description | Validation | | ----- | ---- | ----------- | ----------- | -| details | zitadel.v1.ListDetails | - | | -| result | repeated zitadel.change.v1.Change | - | | +| result | repeated zitadel.change.v1.Change | zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) | | diff --git a/docs/docs/apis/proto/management.md b/docs/docs/apis/proto/management.md index a916e49a2d..ed4b19e6fa 100644 --- a/docs/docs/apis/proto/management.md +++ b/docs/docs/apis/proto/management.md @@ -5179,8 +5179,7 @@ This is an empty response | Field | Type | Description | Validation | | ----- | ---- | ----------- | ----------- | -| details | zitadel.v1.ListDetails | - | | -| result | repeated zitadel.change.v1.Change | - | | +| result | repeated zitadel.change.v1.Change | zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) | | @@ -5453,8 +5452,7 @@ This is an empty response | Field | Type | Description | Validation | | ----- | ---- | ----------- | ----------- | -| details | zitadel.v1.ListDetails | - | | -| result | repeated zitadel.change.v1.Change | - | | +| result | repeated zitadel.change.v1.Change | zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) | | @@ -5568,8 +5566,7 @@ This is an empty request | Field | Type | Description | Validation | | ----- | ---- | ----------- | ----------- | -| details | zitadel.v1.ListDetails | - | | -| result | repeated zitadel.change.v1.Change | - | | +| result | repeated zitadel.change.v1.Change | zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) | | @@ -5759,8 +5756,7 @@ This is an empty request | Field | Type | Description | Validation | | ----- | ---- | ----------- | ----------- | -| details | zitadel.v1.ListDetails | - | | -| result | repeated zitadel.change.v1.Change | - | | +| result | repeated zitadel.change.v1.Change | zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) | | diff --git a/internal/admin/repository/eventsourcing/eventstore/iam.go b/internal/admin/repository/eventsourcing/eventstore/iam.go deleted file mode 100644 index d54fb22e4b..0000000000 --- a/internal/admin/repository/eventsourcing/eventstore/iam.go +++ /dev/null @@ -1,55 +0,0 @@ -package eventstore - -import ( - "context" - "net/http" - "strings" - "sync" - - "github.com/caos/logging" - "golang.org/x/text/language" - - admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view" - "github.com/caos/zitadel/internal/config/systemdefaults" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - "github.com/caos/zitadel/internal/i18n" - "github.com/caos/zitadel/internal/query" -) - -type IAMRepository struct { - Query *query.Queries - Eventstore v1.Eventstore - SearchLimit uint64 - View *admin_view.View - SystemDefaults systemdefaults.SystemDefaults - Roles []string - PrefixAvatarURL string - LoginDir http.FileSystem - NotificationDir http.FileSystem - LoginTranslationFileContents map[string][]byte - NotificationTranslationFileContents map[string][]byte - mutex sync.Mutex - supportedLangs []language.Tag -} - -func (repo *IAMRepository) Languages(ctx context.Context) ([]language.Tag, error) { - if len(repo.supportedLangs) == 0 { - langs, err := i18n.SupportedLanguages(repo.LoginDir) - if err != nil { - logging.Log("ADMIN-tiMWs").WithError(err).Debug("unable to parse language") - return nil, err - } - repo.supportedLangs = langs - } - return repo.supportedLangs, nil -} - -func (repo *IAMRepository) GetIAMMemberRoles() []string { - roles := make([]string, 0) - for _, roleMap := range repo.Roles { - if strings.HasPrefix(roleMap, "IAM") { - roles = append(roles, roleMap) - } - } - return roles -} diff --git a/internal/admin/repository/eventsourcing/repository.go b/internal/admin/repository/eventsourcing/repository.go index 053b09f7ef..0828d9cc08 100644 --- a/internal/admin/repository/eventsourcing/repository.go +++ b/internal/admin/repository/eventsourcing/repository.go @@ -3,9 +3,6 @@ package eventsourcing import ( "context" - "github.com/caos/logging" - "github.com/rakyll/statik/fs" - "github.com/caos/zitadel/internal/admin/repository/eventsourcing/eventstore" "github.com/caos/zitadel/internal/admin/repository/eventsourcing/spooler" admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view" @@ -28,11 +25,10 @@ type Config struct { type EsRepository struct { spooler *es_spol.Spooler - eventstore.IAMRepository eventstore.AdministratorRepo } -func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, static static.Storage, roles []string, localDevMode bool) (*EsRepository, error) { +func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, static static.Storage, localDevMode bool) (*EsRepository, error) { es, err := v1.Start(conf.Eventstore) if err != nil { return nil, err @@ -47,28 +43,9 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, c } spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults, command, static, localDevMode) - assetsAPI := conf.APIDomain + "/assets/v1/" - - statikLoginFS, err := fs.NewWithNamespace("login") - logging.Log("CONFI-7usEW").OnError(err).Panic("unable to start login statik dir") - - statikNotificationFS, err := fs.NewWithNamespace("notification") - logging.Log("CONFI-7usEW").OnError(err).Panic("unable to start notification statik dir") return &EsRepository{ spooler: spool, - IAMRepository: eventstore.IAMRepository{ - Eventstore: es, - View: view, - SystemDefaults: systemDefaults, - SearchLimit: conf.SearchLimit, - Roles: roles, - PrefixAvatarURL: assetsAPI, - LoginDir: statikLoginFS, - NotificationDir: statikNotificationFS, - LoginTranslationFileContents: make(map[string][]byte), - NotificationTranslationFileContents: make(map[string][]byte), - }, AdministratorRepo: eventstore.AdministratorRepo{ View: view, }, diff --git a/internal/admin/repository/iam.go b/internal/admin/repository/iam.go deleted file mode 100644 index 8a78f49fc4..0000000000 --- a/internal/admin/repository/iam.go +++ /dev/null @@ -1,13 +0,0 @@ -package repository - -import ( - "context" - - "golang.org/x/text/language" -) - -type IAMRepository interface { - Languages(ctx context.Context) ([]language.Tag, error) - - GetIAMMemberRoles() []string -} diff --git a/internal/admin/repository/repository.go b/internal/admin/repository/repository.go index 36142985be..cefaf02a36 100644 --- a/internal/admin/repository/repository.go +++ b/internal/admin/repository/repository.go @@ -4,6 +4,5 @@ import "context" type Repository interface { Health(ctx context.Context) error - IAMRepository AdministratorRepository } diff --git a/internal/api/api.go b/internal/api/api.go index 561b1a7f71..3d5de426d8 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -17,7 +17,7 @@ import ( http_util "github.com/caos/zitadel/internal/api/http" "github.com/caos/zitadel/internal/api/oidc" auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing" - authz_es "github.com/caos/zitadel/internal/authz/repository/eventsourcing" + authz_repo "github.com/caos/zitadel/internal/authz/repository" "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/errors" @@ -29,8 +29,9 @@ import ( ) type Config struct { - GRPC grpc_util.Config - OIDC oidc.OPHandlerConfig + GRPC grpc_util.Config + OIDC oidc.OPHandlerConfig + Domain string } type API struct { @@ -58,16 +59,16 @@ type admin interface { GetSpoolerDiv(database, viewName string) int64 } -func Create(config Config, authZ authz.Config, q *query.Queries, authZRepo *authz_es.EsRepository, authRepo *auth_es.EsRepository, adminRepo *admin_es.EsRepository, sd systemdefaults.SystemDefaults) *API { +func Create(config Config, authZ authz.Config, q *query.Queries, authZRepo authz_repo.Repository, authRepo *auth_es.EsRepository, adminRepo *admin_es.EsRepository, sd systemdefaults.SystemDefaults) *API { api := &API{ serverPort: config.GRPC.ServerPort, } repo := struct { - authz_es.EsRepository + authz_repo.Repository query.Queries }{ - *authZRepo, + authZRepo, *q, } diff --git a/internal/api/assets/asset.go b/internal/api/assets/asset.go index 442ddb0ad6..4aabc81d2d 100644 --- a/internal/api/assets/asset.go +++ b/internal/api/assets/asset.go @@ -17,7 +17,6 @@ import ( "github.com/caos/zitadel/internal/command" "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/id" - "github.com/caos/zitadel/internal/management/repository" "github.com/caos/zitadel/internal/query" "github.com/caos/zitadel/internal/static" ) @@ -28,7 +27,6 @@ type Handler struct { commands *command.Commands authInterceptor *http_mw.AuthInterceptor idGenerator id.Generator - orgRepo repository.OrgRepository query *query.Queries } @@ -74,7 +72,6 @@ func NewHandler( authConfig authz.Config, idGenerator id.Generator, storage static.Storage, - orgRepo repository.OrgRepository, queries *query.Queries, ) http.Handler { h := &Handler{ @@ -83,7 +80,6 @@ func NewHandler( authInterceptor: http_mw.AuthorizationInterceptor(verifier, authConfig), idGenerator: idGenerator, storage: storage, - orgRepo: orgRepo, query: queries, } diff --git a/internal/api/grpc/admin/iam_member.go b/internal/api/grpc/admin/iam_member.go index 2275da13b0..4fd1b6ea1b 100644 --- a/internal/api/grpc/admin/iam_member.go +++ b/internal/api/grpc/admin/iam_member.go @@ -10,7 +10,7 @@ import ( ) func (s *Server) ListIAMMemberRoles(ctx context.Context, req *admin_pb.ListIAMMemberRolesRequest) (*admin_pb.ListIAMMemberRolesResponse, error) { - roles := s.iam.GetIAMMemberRoles() + roles := s.query.GetIAMMemberRoles() return &admin_pb.ListIAMMemberRolesResponse{ Roles: roles, Details: object.ToListDetails(uint64(len(roles)), 0, time.Now()), diff --git a/internal/api/grpc/admin/language.go b/internal/api/grpc/admin/language.go index 9257bed7ef..67fa950d79 100644 --- a/internal/api/grpc/admin/language.go +++ b/internal/api/grpc/admin/language.go @@ -8,7 +8,7 @@ import ( ) func (s *Server) GetSupportedLanguages(ctx context.Context, req *admin_pb.GetSupportedLanguagesRequest) (*admin_pb.GetSupportedLanguagesResponse, error) { - langs, err := s.iam.Languages(ctx) + langs, err := s.query.Languages(ctx) if err != nil { return nil, err } diff --git a/internal/api/grpc/admin/server.go b/internal/api/grpc/admin/server.go index cc24ae1aeb..18818f1401 100644 --- a/internal/api/grpc/admin/server.go +++ b/internal/api/grpc/admin/server.go @@ -22,7 +22,6 @@ type Server struct { admin.UnimplementedAdminServiceServer command *command.Commands query *query.Queries - iam repository.IAMRepository administrator repository.AdministratorRepository iamDomain string assetsAPIDomain string @@ -36,7 +35,6 @@ func CreateServer(command *command.Commands, query *query.Queries, repo reposito return &Server{ command: command, query: query, - iam: repo, administrator: repo, iamDomain: iamDomain, assetsAPIDomain: assetsAPIDomain, diff --git a/internal/api/grpc/auth/permission.go b/internal/api/grpc/auth/permission.go index fe6fe47313..ea9ea464b2 100644 --- a/internal/api/grpc/auth/permission.go +++ b/internal/api/grpc/auth/permission.go @@ -3,28 +3,43 @@ package auth import ( "context" + "github.com/caos/zitadel/internal/api/authz" obj_grpc "github.com/caos/zitadel/internal/api/grpc/object" user_grpc "github.com/caos/zitadel/internal/api/grpc/user" + "github.com/caos/zitadel/internal/query" auth_pb "github.com/caos/zitadel/pkg/grpc/auth" ) func (s *Server) ListMyZitadelPermissions(ctx context.Context, _ *auth_pb.ListMyZitadelPermissionsRequest) (*auth_pb.ListMyZitadelPermissionsResponse, error) { - perms, err := s.repo.SearchMyZitadelPermissions(ctx) + perms, err := s.query.MyZitadelPermissions(ctx, authz.GetCtxData(ctx).UserID) if err != nil { return nil, err } return &auth_pb.ListMyZitadelPermissionsResponse{ - Result: perms, + Result: perms.Permissions, }, nil } func (s *Server) ListMyProjectPermissions(ctx context.Context, _ *auth_pb.ListMyProjectPermissionsRequest) (*auth_pb.ListMyProjectPermissionsResponse, error) { - perms, err := s.repo.SearchMyProjectPermissions(ctx) + ctxData := authz.GetCtxData(ctx) + userGrantOrgID, err := query.NewUserGrantResourceOwnerSearchQuery(ctxData.OrgID) + if err != nil { + return nil, err + } + userGrantProjectID, err := query.NewUserGrantProjectIDSearchQuery(ctxData.ProjectID) + if err != nil { + return nil, err + } + userGrantUserID, err := query.NewUserGrantUserIDSearchQuery(ctxData.UserID) + if err != nil { + return nil, err + } + userGrant, err := s.query.UserGrant(ctx, userGrantOrgID, userGrantProjectID, userGrantUserID) if err != nil { return nil, err } return &auth_pb.ListMyProjectPermissionsResponse{ - Result: perms, + Result: userGrant.Roles, }, nil } diff --git a/internal/api/grpc/auth/user.go b/internal/api/grpc/auth/user.go index 24a7e6ea0f..16ad3df195 100644 --- a/internal/api/grpc/auth/user.go +++ b/internal/api/grpc/auth/user.go @@ -12,7 +12,6 @@ import ( "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/query" - grant_model "github.com/caos/zitadel/internal/usergrant/model" auth_pb "github.com/caos/zitadel/pkg/grpc/auth" ) @@ -26,7 +25,12 @@ func (s *Server) GetMyUser(ctx context.Context, _ *auth_pb.GetMyUserRequest) (*a func (s *Server) RemoveMyUser(ctx context.Context, _ *auth_pb.RemoveMyUserRequest) (*auth_pb.RemoveMyUserResponse, error) { ctxData := authz.GetCtxData(ctx) - grants, err := s.repo.SearchMyUserGrants(ctx, &grant_model.UserGrantSearchRequest{Queries: []*grant_model.UserGrantSearchQuery{}}) + userGrantUserID, err := query.NewUserGrantUserIDSearchQuery(ctxData.UserID) + if err != nil { + return nil, err + } + queries := &query.UserGrantsQueries{Queries: []query.SearchQuery{userGrantUserID}} + grants, err := s.query.UserGrants(ctx, queries) if err != nil { return nil, err } @@ -41,7 +45,7 @@ func (s *Server) RemoveMyUser(ctx context.Context, _ *auth_pb.RemoveMyUserReques if err != nil { return nil, err } - details, err := s.command.RemoveUser(ctx, ctxData.UserID, ctxData.ResourceOwner, memberships.Memberships, userGrantsToIDs(grants.Result)...) + details, err := s.command.RemoveUser(ctx, ctxData.UserID, ctxData.ResourceOwner, memberships.Memberships, userGrantsToIDs(grants.UserGrants)...) if err != nil { return nil, err } @@ -51,17 +55,17 @@ func (s *Server) RemoveMyUser(ctx context.Context, _ *auth_pb.RemoveMyUserReques } func (s *Server) ListMyUserChanges(ctx context.Context, req *auth_pb.ListMyUserChangesRequest) (*auth_pb.ListMyUserChangesResponse, error) { - sequence, limit, asc := change.ChangeQueryToModel(req.Query) + sequence, limit, asc := change.ChangeQueryToQuery(req.Query) features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).ResourceOwner) if err != nil { return nil, err } - changes, err := s.repo.MyUserChanges(ctx, sequence, limit, asc, features.AuditLogRetention) + changes, err := s.query.UserChanges(ctx, authz.GetCtxData(ctx).UserID, sequence, limit, asc, features.AuditLogRetention) if err != nil { return nil, err } return &auth_pb.ListMyUserChangesResponse{ - Result: change.UserChangesToPb(changes.Changes), + Result: change.ChangesToPb(changes.Changes, s.assetsAPIDomain), }, nil } @@ -124,14 +128,18 @@ func ctxToObjectRoot(ctx context.Context) models.ObjectRoot { } func (s *Server) ListMyUserGrants(ctx context.Context, req *auth_pb.ListMyUserGrantsRequest) (*auth_pb.ListMyUserGrantsResponse, error) { - res, err := s.repo.SearchMyUserGrants(ctx, ListMyUserGrantsRequestToModel(req)) + queries, err := ListMyUserGrantsRequestToQuery(ctx, req) + if err != nil { + return nil, err + } + res, err := s.query.UserGrants(ctx, queries) if err != nil { return nil, err } return &auth_pb.ListMyUserGrantsResponse{ - Result: UserGrantsToPb(res.Result), + Result: UserGrantsToPb(res.UserGrants), Details: obj_grpc.ToListDetails( - res.TotalResult, + res.Count, res.Sequence, res.Timestamp, ), @@ -152,13 +160,21 @@ func (s *Server) ListMyProjectOrgs(ctx context.Context, req *auth_pb.ListMyProje //client of user is not in project of ZITADEL if ctxData.ProjectID != iam.IAMProjectID { - grants, err := s.repo.UserGrantsByProjectAndUserID(ctxData.ProjectID, ctxData.UserID) + userGrantProjectID, err := query.NewUserGrantProjectIDSearchQuery(ctxData.ProjectID) + if err != nil { + return nil, err + } + userGrantUserID, err := query.NewUserGrantUserIDSearchQuery(ctxData.UserID) + if err != nil { + return nil, err + } + grants, err := s.query.UserGrants(ctx, &query.UserGrantsQueries{Queries: []query.SearchQuery{userGrantProjectID, userGrantUserID}}) if err != nil { return nil, err } - ids := make([]string, 0, len(grants)) - for _, grant := range grants { + ids := make([]string, 0, len(grants.UserGrants)) + for _, grant := range grants.UserGrants { ids = appendIfNotExists(ids, grant.ResourceOwner) } @@ -276,7 +292,7 @@ func MemberTypeToDomain(m *query.Membership) (_ domain.MemberType, displayName, return domain.MemberTypeUnspecified, "", "", "" } -func userGrantsToIDs(userGrants []*grant_model.UserGrantView) []string { +func userGrantsToIDs(userGrants []*query.UserGrant) []string { converted := make([]string, len(userGrants)) for i, grant := range userGrants { converted[i] = grant.ID diff --git a/internal/api/grpc/auth/user_grant.go b/internal/api/grpc/auth/user_grant.go index abbf40833a..58fce75781 100644 --- a/internal/api/grpc/auth/user_grant.go +++ b/internal/api/grpc/auth/user_grant.go @@ -1,21 +1,33 @@ package auth import ( + "context" + + "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/api/grpc/object" - "github.com/caos/zitadel/internal/usergrant/model" + "github.com/caos/zitadel/internal/query" auth_pb "github.com/caos/zitadel/pkg/grpc/auth" ) -func ListMyUserGrantsRequestToModel(req *auth_pb.ListMyUserGrantsRequest) *model.UserGrantSearchRequest { +func ListMyUserGrantsRequestToQuery(ctx context.Context, req *auth_pb.ListMyUserGrantsRequest) (*query.UserGrantsQueries, error) { offset, limit, asc := object.ListQueryToModel(req.Query) - return &model.UserGrantSearchRequest{ - Offset: offset, - Limit: limit, - Asc: asc, + userGrantUserID, err := query.NewUserGrantUserIDSearchQuery(authz.GetCtxData(ctx).UserID) + if err != nil { + return nil, err } + return &query.UserGrantsQueries{ + SearchRequest: query.SearchRequest{ + Offset: offset, + Limit: limit, + Asc: asc, + }, + Queries: []query.SearchQuery{ + userGrantUserID, + }, + }, nil } -func UserGrantsToPb(grants []*model.UserGrantView) []*auth_pb.UserGrant { +func UserGrantsToPb(grants []*query.UserGrant) []*auth_pb.UserGrant { userGrants := make([]*auth_pb.UserGrant, len(grants)) for i, grant := range grants { userGrants[i] = UserGrantToPb(grant) @@ -23,13 +35,13 @@ func UserGrantsToPb(grants []*model.UserGrantView) []*auth_pb.UserGrant { return userGrants } -func UserGrantToPb(grant *model.UserGrantView) *auth_pb.UserGrant { +func UserGrantToPb(grant *query.UserGrant) *auth_pb.UserGrant { return &auth_pb.UserGrant{ GrantId: grant.ID, OrgId: grant.ResourceOwner, OrgName: grant.OrgName, ProjectId: grant.ProjectID, UserId: grant.UserID, - Roles: grant.RoleKeys, + Roles: grant.Roles, } } diff --git a/internal/api/grpc/change/changes.go b/internal/api/grpc/change/changes.go index 3b380c8538..82dd061bc1 100644 --- a/internal/api/grpc/change/changes.go +++ b/internal/api/grpc/change/changes.go @@ -1,100 +1,39 @@ package change import ( - org_model "github.com/caos/zitadel/internal/org/model" - proj_model "github.com/caos/zitadel/internal/project/model" - user_model "github.com/caos/zitadel/internal/user/model" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/caos/zitadel/internal/domain" + + "github.com/caos/zitadel/internal/query" change_pb "github.com/caos/zitadel/pkg/grpc/change" "github.com/caos/zitadel/pkg/grpc/message" ) -func ChangeQueryToModel(query *change_pb.ChangeQuery) (sequence uint64, limit uint64, asc bool) { +func ChangeQueryToQuery(query *change_pb.ChangeQuery) (sequence uint64, limit uint64, asc bool) { if query == nil { return 0, 0, false } return query.Sequence, uint64(query.Limit), query.Asc } -func UserChangesToPb(changes []*user_model.UserChange) []*change_pb.Change { +func ChangesToPb(changes []*query.Change, assetAPIPrefix string) []*change_pb.Change { c := make([]*change_pb.Change, len(changes)) for i, change := range changes { - c[i] = UserChangeToPb(change) + c[i] = ChangeToPb(change, assetAPIPrefix) } return c } -func UserChangeToPb(change *user_model.UserChange) *change_pb.Change { +func ChangeToPb(change *query.Change, assetAPIPrefix string) *change_pb.Change { return &change_pb.Change{ - ChangeDate: change.ChangeDate, - EventType: message.NewLocalizedEventType(change.EventType), - Sequence: change.Sequence, - EditorId: change.ModifierID, - EditorDisplayName: change.ModifierName, - EditorPreferredLoginName: change.ModifierLoginName, - EditorAvatarUrl: change.ModifierAvatarURL, - // ResourceOwnerId: change.,TODO: resource owner not returned - } -} - -func OrgChangesToPb(changes []*org_model.OrgChange) []*change_pb.Change { - c := make([]*change_pb.Change, len(changes)) - for i, change := range changes { - c[i] = OrgChangeToPb(change) - } - return c -} - -func OrgChangeToPb(change *org_model.OrgChange) *change_pb.Change { - return &change_pb.Change{ - ChangeDate: change.ChangeDate, + ChangeDate: timestamppb.New(change.ChangeDate), EventType: message.NewLocalizedEventType(change.EventType), Sequence: change.Sequence, EditorId: change.ModifierId, EditorDisplayName: change.ModifierName, EditorPreferredLoginName: change.ModifierLoginName, - EditorAvatarUrl: change.ModifierAvatarURL, - // ResourceOwnerId: change.,TODO: resource owner not returned - } -} - -func ProjectChangesToPb(changes []*proj_model.ProjectChange) []*change_pb.Change { - c := make([]*change_pb.Change, len(changes)) - for i, change := range changes { - c[i] = ProjectChangeToPb(change) - } - return c -} - -func ProjectChangeToPb(change *proj_model.ProjectChange) *change_pb.Change { - return &change_pb.Change{ - ChangeDate: change.ChangeDate, - EventType: message.NewLocalizedEventType(change.EventType), - Sequence: change.Sequence, - EditorId: change.ModifierId, - EditorDisplayName: change.ModifierName, - EditorPreferredLoginName: change.ModifierLoginName, - EditorAvatarUrl: change.ModifierAvatarURL, - // ResourceOwnerId: change.,TODO: resource owner not returned - } -} - -func AppChangesToPb(changes []*proj_model.ApplicationChange) []*change_pb.Change { - c := make([]*change_pb.Change, len(changes)) - for i, change := range changes { - c[i] = AppChangeToPb(change) - } - return c -} - -func AppChangeToPb(change *proj_model.ApplicationChange) *change_pb.Change { - return &change_pb.Change{ - ChangeDate: change.ChangeDate, - EventType: message.NewLocalizedEventType(change.EventType), - Sequence: change.Sequence, - EditorId: change.ModifierId, - EditorDisplayName: change.ModifierName, - EditorPreferredLoginName: change.ModifierLoginName, - EditorAvatarUrl: change.ModifierAvatarURL, - // ResourceOwnerId: change.,TODO: resource owner not returned + EditorAvatarUrl: domain.AvatarURL(assetAPIPrefix, change.ModifierResourceOwner, change.ModifierAvatarKey), + ResourceOwnerId: change.ResourceOwner, } } diff --git a/internal/api/grpc/management/org.go b/internal/api/grpc/management/org.go index e4312a6164..d540f95b1f 100644 --- a/internal/api/grpc/management/org.go +++ b/internal/api/grpc/management/org.go @@ -33,17 +33,17 @@ func (s *Server) GetOrgByDomainGlobal(ctx context.Context, req *mgmt_pb.GetOrgBy } func (s *Server) ListOrgChanges(ctx context.Context, req *mgmt_pb.ListOrgChangesRequest) (*mgmt_pb.ListOrgChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToModel(req.Query) + sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - response, err := s.org.OrgChanges(ctx, authz.GetCtxData(ctx).OrgID, sequence, limit, asc, features.AuditLogRetention) + response, err := s.query.OrgChanges(ctx, authz.GetCtxData(ctx).OrgID, sequence, limit, asc, features.AuditLogRetention) if err != nil { return nil, err } return &mgmt_pb.ListOrgChangesResponse{ - Result: change_grpc.OrgChangesToPb(response.Changes), + Result: change_grpc.ChangesToPb(response.Changes, s.assetAPIPrefix), }, nil } @@ -211,7 +211,7 @@ func (s *Server) ListOrgMemberRoles(ctx context.Context, req *mgmt_pb.ListOrgMem if err != nil { return nil, err } - roles := s.org.GetOrgMemberRoles(authz.GetCtxData(ctx).OrgID == iam.GlobalOrgID) + roles := s.query.GetOrgMemberRoles(authz.GetCtxData(ctx).OrgID == iam.GlobalOrgID) return &mgmt_pb.ListOrgMemberRolesResponse{ Result: roles, }, nil diff --git a/internal/api/grpc/management/project.go b/internal/api/grpc/management/project.go index 7e363d43a8..755d81c126 100644 --- a/internal/api/grpc/management/project.go +++ b/internal/api/grpc/management/project.go @@ -110,17 +110,17 @@ func (s *Server) ListGrantedProjectRoles(ctx context.Context, req *mgmt_pb.ListG } func (s *Server) ListProjectChanges(ctx context.Context, req *mgmt_pb.ListProjectChangesRequest) (*mgmt_pb.ListProjectChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToModel(req.Query) + sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - res, err := s.project.ProjectChanges(ctx, req.ProjectId, sequence, limit, asc, features.AuditLogRetention) + res, err := s.query.ProjectChanges(ctx, req.ProjectId, sequence, limit, asc, features.AuditLogRetention) if err != nil { return nil, err } return &mgmt_pb.ListProjectChangesResponse{ - Result: change_grpc.ProjectChangesToPb(res.Changes), + Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix), }, nil } @@ -289,7 +289,7 @@ func (s *Server) RemoveProjectRole(ctx context.Context, req *mgmt_pb.RemoveProje } func (s *Server) ListProjectMemberRoles(ctx context.Context, _ *mgmt_pb.ListProjectMemberRolesRequest) (*mgmt_pb.ListProjectMemberRolesResponse, error) { - roles, err := s.project.GetProjectMemberRoles(ctx) + roles, err := s.query.GetProjectMemberRoles(ctx) if err != nil { return nil, err } diff --git a/internal/api/grpc/management/project_application.go b/internal/api/grpc/management/project_application.go index 3bee22e57f..f4cbd6e87d 100644 --- a/internal/api/grpc/management/project_application.go +++ b/internal/api/grpc/management/project_application.go @@ -42,17 +42,17 @@ func (s *Server) ListApps(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*m } func (s *Server) ListAppChanges(ctx context.Context, req *mgmt_pb.ListAppChangesRequest) (*mgmt_pb.ListAppChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToModel(req.Query) + sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - res, err := s.project.ApplicationChanges(ctx, req.ProjectId, req.AppId, sequence, limit, asc, features.AuditLogRetention) + res, err := s.query.ApplicationChanges(ctx, req.ProjectId, req.AppId, sequence, limit, asc, features.AuditLogRetention) if err != nil { return nil, err } return &mgmt_pb.ListAppChangesResponse{ - Result: change_grpc.AppChangesToPb(res.Changes), + Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix), }, nil } diff --git a/internal/api/grpc/management/project_grant.go b/internal/api/grpc/management/project_grant.go index d63c666ecb..3f83577bd3 100644 --- a/internal/api/grpc/management/project_grant.go +++ b/internal/api/grpc/management/project_grant.go @@ -160,7 +160,7 @@ func (s *Server) RemoveProjectGrant(ctx context.Context, req *mgmt_pb.RemoveProj } func (s *Server) ListProjectGrantMemberRoles(ctx context.Context, req *mgmt_pb.ListProjectGrantMemberRolesRequest) (*mgmt_pb.ListProjectGrantMemberRolesResponse, error) { - roles := s.project.GetProjectGrantMemberRoles() + roles := s.query.GetProjectGrantMemberRoles() return &mgmt_pb.ListProjectGrantMemberRolesResponse{ Result: roles, Details: object_grpc.ToListDetails(uint64(len(roles)), 0, time.Now()), diff --git a/internal/api/grpc/management/server.go b/internal/api/grpc/management/server.go index e9c79e39fc..67baa1e510 100644 --- a/internal/api/grpc/management/server.go +++ b/internal/api/grpc/management/server.go @@ -7,8 +7,6 @@ import ( "github.com/caos/zitadel/internal/api/grpc/server" "github.com/caos/zitadel/internal/command" "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/management/repository" - "github.com/caos/zitadel/internal/management/repository/eventsourcing" "github.com/caos/zitadel/internal/query" "github.com/caos/zitadel/pkg/grpc/management" ) @@ -23,24 +21,14 @@ type Server struct { management.UnimplementedManagementServiceServer command *command.Commands query *query.Queries - project repository.ProjectRepository - org repository.OrgRepository - user repository.UserRepository systemDefaults systemdefaults.SystemDefaults assetAPIPrefix string } -type Config struct { - Repository eventsourcing.Config -} - -func CreateServer(command *command.Commands, query *query.Queries, repo repository.Repository, sd systemdefaults.SystemDefaults, assetAPIPrefix string) *Server { +func CreateServer(command *command.Commands, query *query.Queries, sd systemdefaults.SystemDefaults, assetAPIPrefix string) *Server { return &Server{ command: command, query: query, - project: repo, - org: repo, - user: repo, systemDefaults: sd, assetAPIPrefix: assetAPIPrefix, } diff --git a/internal/api/grpc/management/user.go b/internal/api/grpc/management/user.go index a0ffc3715c..34d56c5ed6 100644 --- a/internal/api/grpc/management/user.go +++ b/internal/api/grpc/management/user.go @@ -70,17 +70,17 @@ func (s *Server) ListUsers(ctx context.Context, req *mgmt_pb.ListUsersRequest) ( } func (s *Server) ListUserChanges(ctx context.Context, req *mgmt_pb.ListUserChangesRequest) (*mgmt_pb.ListUserChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToModel(req.Query) + sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - res, err := s.user.UserChanges(ctx, req.UserId, sequence, limit, asc, features.AuditLogRetention) + res, err := s.query.UserChanges(ctx, req.UserId, sequence, limit, asc, features.AuditLogRetention) if err != nil { return nil, err } return &mgmt_pb.ListUserChangesResponse{ - Result: change_grpc.UserChangesToPb(res.Changes), + Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix), }, nil } diff --git a/internal/api/grpc/management/user_grant.go b/internal/api/grpc/management/user_grant.go index 9d5357ea06..ceab3d772a 100644 --- a/internal/api/grpc/management/user_grant.go +++ b/internal/api/grpc/management/user_grant.go @@ -11,11 +11,15 @@ import ( ) func (s *Server) GetUserGrantByID(ctx context.Context, req *mgmt_pb.GetUserGrantByIDRequest) (*mgmt_pb.GetUserGrantByIDResponse, error) { + idQuery, err := query.NewUserGrantGrantIDSearchQuery(req.GrantId) + if err != nil { + return nil, err + } ownerQuery, err := query.NewUserGrantResourceOwnerSearchQuery(authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - grant, err := s.query.UserGrantByID(ctx, req.GrantId, ownerQuery) + grant, err := s.query.UserGrant(ctx, idQuery, ownerQuery) if err != nil { return nil, err } diff --git a/internal/api/oidc/client.go b/internal/api/oidc/client.go index c3ac9c6905..c76a1a4594 100644 --- a/internal/api/oidc/client.go +++ b/internal/api/oidc/client.go @@ -17,7 +17,6 @@ import ( "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/query" "github.com/caos/zitadel/internal/telemetry/tracing" - grant_model "github.com/caos/zitadel/internal/usergrant/model" ) const ( @@ -108,7 +107,14 @@ func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secr UserID: oidcCtx, OrgID: oidcCtx, }) - return o.repo.AuthorizeClientIDSecret(ctx, id, secret) + app, err := o.query.AppByClientID(ctx, id) + if err != nil { + return err + } + if app.OIDCConfig != nil { + return o.command.VerifyOIDCClientSecret(ctx, app.ProjectID, app.ID, secret) + } + return o.command.VerifyAPIClientSecret(ctx, app.ProjectID, app.ID, secret) } func (o *OPStorage) SetUserinfoFromToken(ctx context.Context, userInfo oidc.UserInfoSetter, tokenID, subject, origin string) (err error) { @@ -293,13 +299,23 @@ func (o *OPStorage) assertRoles(ctx context.Context, userID, applicationID strin if err != nil { return nil, err } - grants, err := o.repo.UserGrantsByProjectAndUserID(projectID, userID) + projectQuery, err := query.NewUserGrantProjectIDSearchQuery(projectID) + if err != nil { + return nil, err + } + userIDQuery, err := query.NewUserGrantUserIDSearchQuery(userID) + if err != nil { + return nil, err + } + grants, err := o.query.UserGrants(ctx, &query.UserGrantsQueries{ + Queries: []query.SearchQuery{projectQuery, userIDQuery}, + }) if err != nil { return nil, err } projectRoles := make(map[string]map[string]string) for _, requestedRole := range requestedRoles { - for _, grant := range grants { + for _, grant := range grants.UserGrants { checkGrantedRoles(projectRoles, grant, requestedRole) } } @@ -335,8 +351,8 @@ func (o *OPStorage) assertUserResourceOwner(ctx context.Context, userID string) }, nil } -func checkGrantedRoles(roles map[string]map[string]string, grant *grant_model.UserGrantView, requestedRole string) { - for _, grantedRole := range grant.RoleKeys { +func checkGrantedRoles(roles map[string]map[string]string, grant *query.UserGrant, requestedRole string) { + for _, grantedRole := range grant.Roles { if requestedRole == grantedRole { appendRole(roles, grantedRole, grant.ResourceOwner, grant.OrgPrimaryDomain) } diff --git a/internal/auth/repository/application.go b/internal/auth/repository/application.go deleted file mode 100644 index 0e9b1076f3..0000000000 --- a/internal/auth/repository/application.go +++ /dev/null @@ -1,9 +0,0 @@ -package repository - -import ( - "context" -) - -type ApplicationRepository interface { - AuthorizeClientIDSecret(ctx context.Context, clientID, secret string) error -} diff --git a/internal/auth/repository/eventsourcing/eventstore/application.go b/internal/auth/repository/eventsourcing/eventstore/application.go deleted file mode 100644 index ad1050aecd..0000000000 --- a/internal/auth/repository/eventsourcing/eventstore/application.go +++ /dev/null @@ -1,28 +0,0 @@ -package eventstore - -import ( - "context" - - "github.com/caos/zitadel/internal/command" - "github.com/caos/zitadel/internal/query" - "github.com/caos/zitadel/internal/telemetry/tracing" -) - -type ApplicationRepo struct { - Commands *command.Commands - Query *query.Queries -} - -func (a *ApplicationRepo) AuthorizeClientIDSecret(ctx context.Context, clientID, secret string) (err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - app, err := a.Query.AppByClientID(ctx, clientID) - if err != nil { - return err - } - if app.OIDCConfig != nil { - return a.Commands.VerifyOIDCClientSecret(ctx, app.ProjectID, app.ID, secret) - } - return a.Commands.VerifyAPIClientSecret(ctx, app.ProjectID, app.ID, secret) -} diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go index f4fea523ce..92b2a5c1dd 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go @@ -24,7 +24,6 @@ import ( user_model "github.com/caos/zitadel/internal/user/model" es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" user_view_model "github.com/caos/zitadel/internal/user/repository/view/model" - grant_view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" ) type AuthRequestRepo struct { @@ -104,7 +103,7 @@ type orgViewProvider interface { type userGrantProvider interface { ProjectByOIDCClientID(context.Context, string) (*query.Project, error) - UserGrantsByProjectAndUserID(string, string) ([]*grant_view_model.UserGrantView, error) + UserGrantsByProjectAndUserID(string, string) ([]*query.UserGrant, error) } type projectProvider interface { diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go b/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go index 52b1b2a90c..2659f77bcd 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go @@ -20,7 +20,6 @@ import ( user_model "github.com/caos/zitadel/internal/user/model" user_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" user_view_model "github.com/caos/zitadel/internal/user/repository/view/model" - grant_view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" ) type mockViewNoUserSession struct{} @@ -216,10 +215,10 @@ func (m *mockUserGrants) ProjectByOIDCClientID(ctx context.Context, s string) (* return &query.Project{ProjectRoleCheck: m.roleCheck}, nil } -func (m *mockUserGrants) UserGrantsByProjectAndUserID(s string, s2 string) ([]*grant_view_model.UserGrantView, error) { - var grants []*grant_view_model.UserGrantView +func (m *mockUserGrants) UserGrantsByProjectAndUserID(s string, s2 string) ([]*query.UserGrant, error) { + var grants []*query.UserGrant if m.userGrants > 0 { - grants = make([]*grant_view_model.UserGrantView, m.userGrants) + grants = make([]*query.UserGrant, m.userGrants) } return grants, nil } diff --git a/internal/auth/repository/eventsourcing/eventstore/user_grant.go b/internal/auth/repository/eventsourcing/eventstore/user_grant.go deleted file mode 100644 index b31a960c8a..0000000000 --- a/internal/auth/repository/eventsourcing/eventstore/user_grant.go +++ /dev/null @@ -1,322 +0,0 @@ -package eventstore - -import ( - "context" - - "github.com/caos/logging" - - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/query" - - "github.com/caos/zitadel/internal/api/authz" - "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" - authz_repo "github.com/caos/zitadel/internal/authz/repository/eventsourcing" - caos_errs "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/telemetry/tracing" - user_view_model "github.com/caos/zitadel/internal/user/repository/view/model" - grant_model "github.com/caos/zitadel/internal/usergrant/model" - "github.com/caos/zitadel/internal/usergrant/repository/view/model" -) - -type UserGrantRepo struct { - SearchLimit uint64 - View *view.View - IamID string - Auth authz.Config - AuthZRepo *authz_repo.EsRepository - PrefixAvatarURL string - - Query *query.Queries -} - -func (repo *UserGrantRepo) SearchMyUserGrants(ctx context.Context, request *grant_model.UserGrantSearchRequest) (*grant_model.UserGrantSearchResponse, error) { - err := request.EnsureLimit(repo.SearchLimit) - if err != nil { - return nil, err - } - sequence, err := repo.View.GetLatestUserGrantSequence() - logging.Log("EVENT-Hd7s3").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest user grant sequence") - request.Queries = append(request.Queries, &grant_model.UserGrantSearchQuery{Key: grant_model.UserGrantSearchKeyUserID, Method: domain.SearchMethodEquals, Value: authz.GetCtxData(ctx).UserID}) - grants, count, err := repo.View.SearchUserGrants(request) - if err != nil { - return nil, err - } - result := &grant_model.UserGrantSearchResponse{ - Offset: request.Offset, - Limit: request.Limit, - TotalResult: count, - Result: model.UserGrantsToModel(grants, repo.PrefixAvatarURL), - } - if err == nil { - result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.LastSuccessfulSpoolerRun - } - return result, nil -} - -func (repo *UserGrantRepo) SearchMyProjectOrgs(ctx context.Context, request *grant_model.UserGrantSearchRequest) (*grant_model.ProjectOrgSearchResponse, error) { - err := request.EnsureLimit(repo.SearchLimit) - if err != nil { - return nil, err - } - ctxData := authz.GetCtxData(ctx) - if ctxData.ProjectID == "" { - return nil, caos_errs.ThrowPreconditionFailed(nil, "APP-7lqva", "Could not get ProjectID") - } - - err = repo.AuthZRepo.FillIamProjectID(ctx) - if err != nil { - return nil, err - } - if ctxData.ProjectID == repo.AuthZRepo.UserGrantRepo.IamProjectID { - isAdmin, err := repo.IsIamAdmin(ctx) - if err != nil { - return nil, err - } - if isAdmin { - return repo.SearchAdminOrgs(request) - } - return repo.searchZitadelOrgs(ctxData, request) - } - request.Queries = append(request.Queries, &grant_model.UserGrantSearchQuery{Key: grant_model.UserGrantSearchKeyProjectID, Method: domain.SearchMethodEquals, Value: ctxData.ProjectID}) - - grants, err := repo.SearchMyUserGrants(ctx, request) - if err != nil { - return nil, err - } - if len(grants.Result) > 0 { - return grantRespToOrgResp(grants), nil - } - return repo.userOrg(ctxData) -} - -func (repo *UserGrantRepo) membershipsToOrgResp(memberships *query.Memberships) *grant_model.ProjectOrgSearchResponse { - orgs := make([]*grant_model.Org, 0, len(memberships.Memberships)) - for _, m := range memberships.Memberships { - if !containsOrg(orgs, m.ResourceOwner) { - org, err := repo.Query.OrgByID(context.TODO(), m.ResourceOwner) - if err != nil { - logging.LogWithFields("EVENT-k8Ikl", "owner", m.ResourceOwner).WithError(err).Warn("org not found") - orgs = append(orgs, &grant_model.Org{OrgID: m.ResourceOwner}) - continue - } - orgs = append(orgs, &grant_model.Org{OrgID: m.ResourceOwner, OrgName: org.Name}) - } - } - return &grant_model.ProjectOrgSearchResponse{ - TotalResult: memberships.Count, - Result: orgs, - } -} - -func (repo *UserGrantRepo) SearchMyZitadelPermissions(ctx context.Context) ([]string, error) { - memberships, err := repo.searchUserMemberships(ctx) - if err != nil { - return nil, err - } - permissions := &grant_model.Permissions{Permissions: []string{}} - for _, membership := range memberships { - for _, role := range membership.Roles { - permissions = repo.mapRoleToPermission(permissions, membership, role) - } - } - return permissions.Permissions, nil -} - -func (repo *UserGrantRepo) searchUserMemberships(ctx context.Context) ([]*query.Membership, error) { - ctxData := authz.GetCtxData(ctx) - userQuery, err := query.NewMembershipUserIDQuery(ctxData.UserID) - if err != nil { - return nil, err - } - ownerQuery, err := query.NewMembershipResourceOwnerQuery(ctxData.OrgID) - if err != nil { - return nil, err - } - - orgMemberships, err := repo.Query.Memberships(ctx, &query.MembershipSearchQuery{ - Queries: []query.SearchQuery{userQuery, ownerQuery}, - }) - if err != nil { - return nil, err - } - iamQuery, err := query.NewMembershipIsIAMQuery() - if err != nil { - return nil, err - } - iamMemberships, err := repo.Query.Memberships(ctx, &query.MembershipSearchQuery{ - Queries: []query.SearchQuery{userQuery, iamQuery}, - }) - if err != nil { - return nil, err - } - if orgMemberships.Count == 0 && iamMemberships.Count == 0 { - return []*query.Membership{}, nil - } - return append(orgMemberships.Memberships, iamMemberships.Memberships...), nil -} - -func (repo *UserGrantRepo) SearchMyProjectPermissions(ctx context.Context) ([]string, error) { - ctxData := authz.GetCtxData(ctx) - //TODO: blocked until user grants moved to query-pkg - usergrant, err := repo.View.UserGrantByIDs(ctxData.OrgID, ctxData.ProjectID, ctxData.UserID) - if err != nil { - return nil, err - } - permissions := make([]string, len(usergrant.RoleKeys)) - for i, role := range usergrant.RoleKeys { - permissions[i] = role - } - return permissions, nil -} - -func (repo *UserGrantRepo) SearchAdminOrgs(request *grant_model.UserGrantSearchRequest) (*grant_model.ProjectOrgSearchResponse, error) { - searchRequest := query.OrgSearchQueries{ - SearchRequest: query.SearchRequest{ - SortingColumn: query.OrgColumnName, - Asc: true, - }, - } - if len(request.Queries) > 0 { - for _, q := range request.Queries { - if q.Key == grant_model.UserGrantSearchKeyOrgName { - nameQuery, err := query.NewOrgNameSearchQuery(query.TextComparisonFromMethod(q.Method), q.Value.(string)) - if err != nil { - return nil, err - } - searchRequest.Queries = append(searchRequest.Queries, nameQuery) - } - } - } - orgs, err := repo.Query.SearchOrgs(context.TODO(), &searchRequest) - if err != nil { - return nil, err - } - return orgRespToOrgResp(orgs), nil -} - -func (repo *UserGrantRepo) IsIamAdmin(ctx context.Context) (bool, error) { - //TODO: blocked until user grants moved to query - grantSearch := &grant_model.UserGrantSearchRequest{ - Queries: []*grant_model.UserGrantSearchQuery{ - {Key: grant_model.UserGrantSearchKeyResourceOwner, Method: domain.SearchMethodEquals, Value: repo.IamID}, - }} - result, err := repo.SearchMyUserGrants(ctx, grantSearch) - if err != nil { - return false, err - } - if result.TotalResult == 0 { - return false, nil - } - return true, nil -} - -func (repo *UserGrantRepo) UserGrantsByProjectAndUserID(projectID, userID string) ([]*grant_model.UserGrantView, error) { - grants, err := repo.View.UserGrantsByProjectAndUserID(projectID, userID) - if err != nil { - return nil, err - } - return model.UserGrantsToModel(grants, repo.PrefixAvatarURL), nil -} - -func (repo *UserGrantRepo) userOrg(ctxData authz.CtxData) (*grant_model.ProjectOrgSearchResponse, error) { - //TODO: blocked until user moved to query pkg - user, err := repo.View.UserByID(ctxData.UserID) - if err != nil { - return nil, err - } - org, err := repo.Query.OrgByID(context.TODO(), user.ResourceOwner) - if err != nil { - return nil, err - } - return &grant_model.ProjectOrgSearchResponse{Result: []*grant_model.Org{{ - OrgID: org.ID, - OrgName: org.Name, - }}}, nil -} - -func (repo *UserGrantRepo) searchZitadelOrgs(ctxData authz.CtxData, request *grant_model.UserGrantSearchRequest) (*grant_model.ProjectOrgSearchResponse, error) { - userQuery, err := query.NewMembershipUserIDQuery(ctxData.UserID) - if err != nil { - return nil, err - } - memberships, err := repo.Query.Memberships(context.TODO(), &query.MembershipSearchQuery{ - SearchRequest: query.SearchRequest{ - Offset: request.Offset, - Limit: request.Limit, - Asc: request.Asc, - //TODO: sorting column - }, - Queries: []query.SearchQuery{userQuery}, - }) - if err != nil { - return nil, err - } - if len(memberships.Memberships) > 0 { - return repo.membershipsToOrgResp(memberships), nil - } - return repo.userOrg(ctxData) -} - -func (repo *UserGrantRepo) mapRoleToPermission(permissions *grant_model.Permissions, membership *query.Membership, role string) *grant_model.Permissions { - for _, mapping := range repo.Auth.RolePermissionMappings { - if mapping.Role == role { - ctxID := "" - if membership.Project != nil { - ctxID = membership.Project.ProjectID - } else if membership.ProjectGrant != nil { - ctxID = membership.ProjectGrant.GrantID - } - permissions.AppendPermissions(ctxID, mapping.Permissions...) - } - } - return permissions -} - -func grantRespToOrgResp(grants *grant_model.UserGrantSearchResponse) *grant_model.ProjectOrgSearchResponse { - resp := &grant_model.ProjectOrgSearchResponse{ - TotalResult: grants.TotalResult, - } - resp.Result = make([]*grant_model.Org, len(grants.Result)) - for i, g := range grants.Result { - resp.Result[i] = &grant_model.Org{OrgID: g.ResourceOwner, OrgName: g.OrgName} - } - return resp -} - -func orgRespToOrgResp(orgs *query.Orgs) *grant_model.ProjectOrgSearchResponse { - resp := &grant_model.ProjectOrgSearchResponse{ - TotalResult: orgs.Count, - } - resp.Result = make([]*grant_model.Org, len(orgs.Orgs)) - for i, o := range orgs.Orgs { - resp.Result[i] = &grant_model.Org{OrgID: o.ID, OrgName: o.Name} - } - return resp -} - -func containsOrg(orgs []*grant_model.Org, resourceOwner string) bool { - for _, org := range orgs { - if org.OrgID == resourceOwner { - return true - } - } - return false -} - -func userMembershipToMembership(membership *user_view_model.UserMembershipView) *authz.Membership { - return &authz.Membership{ - MemberType: authz.MemberType(membership.MemberType), - AggregateID: membership.AggregateID, - ObjectID: membership.ObjectID, - Roles: membership.Roles, - } -} - -func userMembershipsToMemberships(memberships []*user_view_model.UserMembershipView) []*authz.Membership { - result := make([]*authz.Membership, len(memberships)) - for i, m := range memberships { - result[i] = userMembershipToMembership(m) - } - return result -} diff --git a/internal/auth/repository/eventsourcing/handler/handler.go b/internal/auth/repository/eventsourcing/handler/handler.go index 0c446226b7..4faa8bc369 100644 --- a/internal/auth/repository/eventsourcing/handler/handler.go +++ b/internal/auth/repository/eventsourcing/handler/handler.go @@ -39,9 +39,6 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount, es}), newToken( handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount, es}), - newUserGrant( - handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es}, - systemDefaults.IamID), newIDPConfig( handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}), newIDPProvider( diff --git a/internal/auth/repository/eventsourcing/handler/user_grant.go b/internal/auth/repository/eventsourcing/handler/user_grant.go deleted file mode 100644 index 4fc7bf86f2..0000000000 --- a/internal/auth/repository/eventsourcing/handler/user_grant.go +++ /dev/null @@ -1,541 +0,0 @@ -package handler - -import ( - "context" - "strings" - - "github.com/caos/logging" - - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/errors" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - es_models "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/eventstore/v1/query" - es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" - "github.com/caos/zitadel/internal/eventstore/v1/spooler" - iam_model "github.com/caos/zitadel/internal/iam/model" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - iam_view "github.com/caos/zitadel/internal/iam/repository/view" - org_model "github.com/caos/zitadel/internal/org/model" - org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" - org_view "github.com/caos/zitadel/internal/org/repository/view" - proj_model "github.com/caos/zitadel/internal/project/model" - proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" - proj_view "github.com/caos/zitadel/internal/project/repository/view" - usr_model "github.com/caos/zitadel/internal/user/model" - usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" - "github.com/caos/zitadel/internal/user/repository/view" - "github.com/caos/zitadel/internal/user/repository/view/model" - grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model" - view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" -) - -const ( - userGrantTable = "auth.user_grants" -) - -type UserGrant struct { - handler - iamID string - iamProjectID string - subscription *v1.Subscription -} - -func newUserGrant( - handler handler, - iamID string, -) *UserGrant { - h := &UserGrant{ - handler: handler, - iamID: iamID, - } - - h.subscribe() - - return h -} - -func (k *UserGrant) subscribe() { - k.subscription = k.es.Subscribe(k.AggregateTypes()...) - go func() { - for event := range k.subscription.Events { - query.ReduceEvent(k, event) - } - }() -} - -func (u *UserGrant) ViewModel() string { - return userGrantTable -} - -func (u *UserGrant) Subscription() *v1.Subscription { - return u.subscription -} - -func (_ *UserGrant) AggregateTypes() []es_models.AggregateType { - return []es_models.AggregateType{grant_es_model.UserGrantAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate, usr_es_model.UserAggregate, proj_es_model.ProjectAggregate} -} - -func (u *UserGrant) CurrentSequence() (uint64, error) { - sequence, err := u.view.GetLatestUserGrantSequence() - if err != nil { - return 0, err - } - return sequence.CurrentSequence, nil -} - -func (u *UserGrant) EventQuery() (*es_models.SearchQuery, error) { - if u.iamProjectID == "" { - err := u.setIamProjectID() - if err != nil { - return nil, err - } - } - sequence, err := u.view.GetLatestUserGrantSequence() - if err != nil { - return nil, err - } - return es_models.NewSearchQuery(). - AggregateTypeFilter(u.AggregateTypes()...). - LatestSequenceFilter(sequence.CurrentSequence), nil -} - -func (u *UserGrant) Reduce(event *es_models.Event) (err error) { - switch event.AggregateType { - case grant_es_model.UserGrantAggregate: - err = u.processUserGrant(event) - case usr_es_model.UserAggregate: - err = u.processUser(event) - case proj_es_model.ProjectAggregate: - err = u.processProject(event) - case iam_es_model.IAMAggregate: - err = u.processIAMMember(event, "IAM", false) - case org_es_model.OrgAggregate: - return u.processOrg(event) - } - return err -} - -func (u *UserGrant) processUserGrant(event *es_models.Event) (err error) { - grant := new(view_model.UserGrantView) - switch event.Type { - case grant_es_model.UserGrantAdded: - err = grant.AppendEvent(event) - if err != nil { - return err - } - err = u.fillData(grant, event.ResourceOwner) - case grant_es_model.UserGrantChanged, - grant_es_model.UserGrantCascadeChanged, - grant_es_model.UserGrantDeactivated, - grant_es_model.UserGrantReactivated: - grant, err = u.view.UserGrantByID(event.AggregateID) - if err != nil { - return err - } - err = grant.AppendEvent(event) - case grant_es_model.UserGrantRemoved, grant_es_model.UserGrantCascadeRemoved: - return u.view.DeleteUserGrant(event.AggregateID, event) - default: - return u.view.ProcessedUserGrantSequence(event) - } - if err != nil { - return err - } - return u.view.PutUserGrant(grant, event) -} - -func (u *UserGrant) processUser(event *es_models.Event) (err error) { - switch event.Type { - case usr_es_model.UserProfileChanged, - usr_es_model.UserEmailChanged, - usr_es_model.HumanProfileChanged, - usr_es_model.HumanEmailChanged, - usr_es_model.MachineChanged, - usr_es_model.HumanAvatarAdded, - usr_es_model.HumanAvatarRemoved: - grants, err := u.view.UserGrantsByUserID(event.AggregateID) - if err != nil { - return err - } - if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event) - } - user, err := u.getUserByID(event.AggregateID) - if err != nil { - return err - } - for _, grant := range grants { - u.fillUserData(grant, user) - } - return u.view.PutUserGrants(grants, event) - default: - return u.view.ProcessedUserGrantSequence(event) - } -} - -func (u *UserGrant) processProject(event *es_models.Event) (err error) { - switch event.Type { - case proj_es_model.ProjectChanged: - proj := new(proj_es_model.Project) - err := proj.SetData(event) - if err != nil { - return err - } - if proj.Name == "" { - return u.view.ProcessedUserGrantSequence(event) - } - grants, err := u.view.UserGrantsByProjectID(event.AggregateID) - if err != nil { - return err - } - for _, grant := range grants { - grant.ProjectName = proj.Name - } - return u.view.PutUserGrants(grants, event) - case proj_es_model.ProjectMemberAdded, proj_es_model.ProjectMemberChanged, - proj_es_model.ProjectMemberRemoved, proj_es_model.ProjectMemberCascadeRemoved: - member := new(proj_es_model.ProjectMember) - err := member.SetData(event) - if err != nil { - return err - } - return u.processMember(event, "PROJECT", event.AggregateID, member.UserID, member.Roles) - case proj_es_model.ProjectGrantMemberAdded, proj_es_model.ProjectGrantMemberChanged, - proj_es_model.ProjectGrantMemberRemoved, proj_es_model.ProjectGrantMemberCascadeRemoved: - member := new(proj_es_model.ProjectGrantMember) - err := member.SetData(event) - if err != nil { - return err - } - return u.processMember(event, "PROJECT_GRANT", member.GrantID, member.UserID, member.Roles) - default: - return u.view.ProcessedUserGrantSequence(event) - } -} - -func (u *UserGrant) processOrg(event *es_models.Event) (err error) { - switch event.Type { - case org_es_model.OrgMemberAdded, org_es_model.OrgMemberChanged, - org_es_model.OrgMemberRemoved, org_es_model.OrgMemberCascadeRemoved: - member := new(org_es_model.OrgMember) - member.SetData(event) - return u.processMember(event, "ORG", "", member.UserID, member.Roles) - case org_es_model.OrgChanged: - grants, err := u.view.UserGrantsByProjectID(event.AggregateID) - if err != nil { - return err - } - if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event) - } - org, err := u.getOrgByID(context.Background(), event.AggregateID) - if err != nil { - return err - } - for _, grant := range grants { - u.fillOrgData(grant, org) - } - return u.view.PutUserGrants(grants, event) - default: - return u.view.ProcessedUserGrantSequence(event) - } -} - -func (u *UserGrant) processIAMMember(event *es_models.Event, rolePrefix string, suffix bool) error { - member := new(iam_es_model.IAMMember) - - switch event.Type { - case iam_es_model.IAMMemberAdded, iam_es_model.IAMMemberChanged: - member.SetData(event) - - grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID) - if err != nil && !errors.IsNotFound(err) { - return err - } - if errors.IsNotFound(err) { - grant = &view_model.UserGrantView{ - ID: u.iamProjectID + member.UserID, - ResourceOwner: u.iamID, - OrgName: u.iamID, - ProjectID: u.iamProjectID, - UserID: member.UserID, - RoleKeys: member.Roles, - CreationDate: event.CreationDate, - } - if suffix { - grant.RoleKeys = suffixRoles(event.AggregateID, grant.RoleKeys) - } - } else { - newRoles := member.Roles - if grant.RoleKeys != nil { - grant.RoleKeys = mergeExistingRoles(rolePrefix, "", grant.RoleKeys, newRoles) - } else { - grant.RoleKeys = newRoles - } - } - grant.Sequence = event.Sequence - grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, event) - case iam_es_model.IAMMemberRemoved, - iam_es_model.IAMMemberCascadeRemoved: - member.SetData(event) - grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID) - if err != nil { - return err - } - return u.view.DeleteUserGrant(grant.ID, event) - default: - return u.view.ProcessedUserGrantSequence(event) - } -} - -func (u *UserGrant) processMember(event *es_models.Event, rolePrefix, roleSuffix string, userID string, roleKeys []string) error { - switch event.Type { - case org_es_model.OrgMemberAdded, proj_es_model.ProjectMemberAdded, proj_es_model.ProjectGrantMemberAdded, - org_es_model.OrgMemberChanged, proj_es_model.ProjectMemberChanged, proj_es_model.ProjectGrantMemberChanged: - - grant, err := u.view.UserGrantByIDs(event.ResourceOwner, u.iamProjectID, userID) - if err != nil && !errors.IsNotFound(err) { - return err - } - if roleSuffix != "" { - roleKeys = suffixRoles(roleSuffix, roleKeys) - } - if errors.IsNotFound(err) { - grant = &view_model.UserGrantView{ - ID: u.iamProjectID + event.ResourceOwner + userID, - ResourceOwner: event.ResourceOwner, - ProjectID: u.iamProjectID, - UserID: userID, - RoleKeys: roleKeys, - CreationDate: event.CreationDate, - } - u.fillData(grant, event.ResourceOwner) - } else { - newRoles := roleKeys - if grant.RoleKeys != nil { - grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, newRoles) - } else { - grant.RoleKeys = newRoles - } - } - grant.Sequence = event.Sequence - grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, event) - case org_es_model.OrgMemberRemoved, - org_es_model.OrgMemberCascadeRemoved, - proj_es_model.ProjectMemberRemoved, - proj_es_model.ProjectMemberCascadeRemoved, - proj_es_model.ProjectGrantMemberRemoved, - proj_es_model.ProjectGrantMemberCascadeRemoved: - - grant, err := u.view.UserGrantByIDs(event.ResourceOwner, u.iamProjectID, userID) - if err != nil && !errors.IsNotFound(err) { - return err - } - if errors.IsNotFound(err) { - return u.view.ProcessedUserGrantSequence(event) - } - if roleSuffix != "" { - roleKeys = suffixRoles(roleSuffix, roleKeys) - } - if grant.RoleKeys == nil { - return u.view.ProcessedUserGrantSequence(event) - } - grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil) - return u.view.PutUserGrant(grant, event) - default: - return u.view.ProcessedUserGrantSequence(event) - } -} - -func suffixRoles(suffix string, roles []string) []string { - suffixedRoles := make([]string, len(roles)) - for i := 0; i < len(roles); i++ { - suffixedRoles[i] = roles[i] + ":" + suffix - } - return suffixedRoles -} - -func mergeExistingRoles(rolePrefix, suffix string, existingRoles, newRoles []string) []string { - mergedRoles := make([]string, 0) - for _, existingRole := range existingRoles { - if !strings.HasPrefix(existingRole, rolePrefix) { - mergedRoles = append(mergedRoles, existingRole) - continue - } - if suffix != "" && !strings.HasSuffix(existingRole, suffix) { - mergedRoles = append(mergedRoles, existingRole) - } - } - return append(mergedRoles, newRoles...) -} - -func (u *UserGrant) setIamProjectID() error { - if u.iamProjectID != "" { - return nil - } - iam, err := u.getIAMByID(context.Background()) - if err != nil { - return err - } - - if iam.SetUpDone < domain.StepCount-1 { - return errors.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done") - } - u.iamProjectID = iam.IAMProjectID - return nil -} - -func (u *UserGrant) fillData(grant *view_model.UserGrantView, resourceOwner string) (err error) { - user, err := u.getUserByID(grant.UserID) - if err != nil { - return err - } - u.fillUserData(grant, user) - project, err := u.getProjectByID(context.Background(), grant.ProjectID) - if err != nil { - return err - } - u.fillProjectData(grant, project) - - org, err := u.getOrgByID(context.TODO(), resourceOwner) - if err != nil { - return err - } - u.fillOrgData(grant, org) - return nil -} - -func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *model.UserView) { - grant.UserName = user.UserName - grant.UserResourceOwner = user.ResourceOwner - if user.HumanView != nil { - grant.FirstName = user.FirstName - grant.LastName = user.LastName - grant.DisplayName = user.FirstName + " " + user.LastName - grant.Email = user.Email - grant.AvatarKey = user.AvatarKey - } - if user.MachineView != nil { - grant.DisplayName = user.MachineView.Name - } -} - -func (u *UserGrant) fillProjectData(grant *view_model.UserGrantView, project *proj_model.Project) { - grant.ProjectName = project.Name - grant.ProjectOwner = project.ResourceOwner -} - -func (u *UserGrant) fillOrgData(grant *view_model.UserGrantView, org *org_model.Org) { - grant.OrgName = org.Name - for _, domain := range org.Domains { - if domain.Primary { - grant.OrgPrimaryDomain = domain.Domain - break - } - } -} - -func (u *UserGrant) OnError(event *es_models.Event, err error) error { - logging.LogWithFields("SPOOL-UZmc7", "id", event.AggregateID).WithError(err).Warn("something went wrong in user grant handler") - return spooler.HandleError(event, err, u.view.GetLatestUserGrantFailedEvent, u.view.ProcessedUserGrantFailedEvent, u.view.ProcessedUserGrantSequence, u.errorCountUntilSkip) -} - -func (u *UserGrant) OnSuccess() error { - return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp) -} - -func (u *UserGrant) getUserByID(userID string) (*model.UserView, error) { - user, usrErr := u.view.UserByID(userID) - if usrErr != nil && !errors.IsNotFound(usrErr) { - return nil, usrErr - } - if user == nil { - user = &model.UserView{} - } - events, err := u.getUserEvents(userID, user.Sequence) - if err != nil { - return user, usrErr - } - userCopy := *user - for _, event := range events { - if err := userCopy.AppendEvent(event); err != nil { - return user, nil - } - } - if userCopy.State == int32(usr_model.UserStateDeleted) { - return nil, errors.ThrowNotFound(nil, "HANDLER-m9dos", "Errors.User.NotFound") - } - return &userCopy, nil -} - -func (u *UserGrant) getUserEvents(userID string, sequence uint64) ([]*es_models.Event, error) { - query, err := view.UserByIDQuery(userID, sequence) - if err != nil { - return nil, err - } - - return u.es.FilterEvents(context.Background(), query) -} - -func (u *UserGrant) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) { - query, err := org_view.OrgByIDQuery(orgID, 0) - if err != nil { - return nil, err - } - - esOrg := &org_es_model.Org{ - ObjectRoot: es_models.ObjectRoot{ - AggregateID: orgID, - }, - } - err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query) - if err != nil && !errors.IsNotFound(err) { - return nil, err - } - if esOrg.Sequence == 0 { - return nil, errors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound") - } - - return org_es_model.OrgToModel(esOrg), nil -} - -func (u *UserGrant) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) { - query, err := proj_view.ProjectByIDQuery(projID, 0) - if err != nil { - return nil, err - } - esProject := &proj_es_model.Project{ - ObjectRoot: es_models.ObjectRoot{ - AggregateID: projID, - }, - } - err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query) - if err != nil && !errors.IsNotFound(err) { - return nil, err - } - if esProject.Sequence == 0 { - return nil, errors.ThrowNotFound(nil, "EVENT-DAfng", "Errors.Project.NotFound") - } - - return proj_es_model.ProjectToModel(esProject), nil -} - -func (u *UserGrant) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { - query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) - if err != nil { - return nil, err - } - iam := &iam_es_model.IAM{ - ObjectRoot: es_models.ObjectRoot{ - AggregateID: domain.IAMID, - }, - } - err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query) - if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 { - return nil, err - } - return iam_es_model.IAMToModel(iam), nil -} diff --git a/internal/auth/repository/eventsourcing/repository.go b/internal/auth/repository/eventsourcing/repository.go index eb00722b30..bcccbcb2a2 100644 --- a/internal/auth/repository/eventsourcing/repository.go +++ b/internal/auth/repository/eventsourcing/repository.go @@ -3,17 +3,14 @@ package eventsourcing import ( "context" - "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/auth/repository/eventsourcing/eventstore" "github.com/caos/zitadel/internal/auth/repository/eventsourcing/spooler" auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" "github.com/caos/zitadel/internal/auth_request/repository/cache" - authz_repo "github.com/caos/zitadel/internal/authz/repository/eventsourcing" "github.com/caos/zitadel/internal/command" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/crypto" - es2 "github.com/caos/zitadel/internal/eventstore" v1 "github.com/caos/zitadel/internal/eventstore/v1" es_spol "github.com/caos/zitadel/internal/eventstore/v1/spooler" "github.com/caos/zitadel/internal/id" @@ -37,13 +34,11 @@ type EsRepository struct { eventstore.AuthRequestRepo eventstore.TokenRepo eventstore.RefreshTokenRepo - eventstore.ApplicationRepo eventstore.UserSessionRepo - eventstore.UserGrantRepo eventstore.OrgRepository } -func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, authZRepo *authz_repo.EsRepository, esV2 *es2.Eventstore) (*EsRepository, error) { +func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries) (*EsRepository, error) { es, err := v1.Start(conf.Eventstore) if err != nil { return nil, err @@ -83,10 +78,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co PrefixAvatarURL: assetsAPI, } //TODO: remove as soon as possible - queryView := struct { - *query.Queries - *auth_view.View - }{ + queryView := queryViewWrapper{ queries, view, } @@ -131,22 +123,9 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co SearchLimit: conf.SearchLimit, KeyAlgorithm: keyAlgorithm, }, - eventstore.ApplicationRepo{ - Commands: command, - Query: queries, - }, - eventstore.UserSessionRepo{ View: view, }, - eventstore.UserGrantRepo{ - SearchLimit: conf.SearchLimit, - View: view, - IamID: systemDefaults.IamID, - Auth: authZ, - AuthZRepo: authZRepo, - Query: queries, - }, eventstore.OrgRepository{ SearchLimit: conf.SearchLimit, View: view, @@ -157,6 +136,27 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co }, nil } +type queryViewWrapper struct { + *query.Queries + *auth_view.View +} + +func (q queryViewWrapper) UserGrantsByProjectAndUserID(projectID, userID string) ([]*query.UserGrant, error) { + userGrantProjectID, err := query.NewUserGrantProjectIDSearchQuery(projectID) + if err != nil { + return nil, err + } + userGrantUserID, err := query.NewUserGrantUserIDSearchQuery(userID) + if err != nil { + return nil, err + } + queries := &query.UserGrantsQueries{Queries: []query.SearchQuery{userGrantUserID, userGrantProjectID}} + grants, err := q.Queries.UserGrants(context.TODO(), queries) + if err != nil { + return nil, err + } + return grants.UserGrants, nil +} func (repo *EsRepository) Health(ctx context.Context) error { if err := repo.UserRepo.Health(ctx); err != nil { return err diff --git a/internal/auth/repository/eventsourcing/view/key.go b/internal/auth/repository/eventsourcing/view/key.go deleted file mode 100644 index 111db368fd..0000000000 --- a/internal/auth/repository/eventsourcing/view/key.go +++ /dev/null @@ -1,89 +0,0 @@ -package view - -import ( - "time" - - "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/eventstore/v1/models" - key_model "github.com/caos/zitadel/internal/key/model" - "github.com/caos/zitadel/internal/key/repository/view" - "github.com/caos/zitadel/internal/key/repository/view/model" - "github.com/caos/zitadel/internal/view/repository" -) - -const ( - keyTable = "auth.keys" -) - -func (v *View) KeyByIDAndType(keyID string, private bool) (*model.KeyView, error) { - return view.KeyByIDAndType(v.Db, keyTable, keyID, private) -} - -func (v *View) GetActivePrivateKeyForSigning(expiry time.Time) (*key_model.KeyView, error) { - key, err := view.GetSigningKey(v.Db, keyTable, expiry) - if err != nil { - return nil, err - } - return model.KeyViewToModel(key), nil -} - -func (v *View) GetSigningKey(expiry time.Time) (*key_model.SigningKey, time.Time, error) { - key, err := view.GetSigningKey(v.Db, keyTable, expiry) - if err != nil { - return nil, time.Time{}, err - } - signingKey, err := key_model.SigningKeyFromKeyView(model.KeyViewToModel(key), v.keyAlgorithm) - return signingKey, key.Expiry, err -} - -func (v *View) GetActiveKeySet() ([]*key_model.PublicKey, error) { - keys, err := view.GetActivePublicKeys(v.Db, keyTable) - if err != nil { - return nil, err - } - return key_model.PublicKeysFromKeyView(model.KeyViewsToModel(keys), v.keyAlgorithm) -} - -func (v *View) PutKeys(privateKey, publicKey *model.KeyView, event *models.Event) error { - err := view.PutKeys(v.Db, keyTable, privateKey, publicKey) - if err != nil { - return err - } - return v.ProcessedKeySequence(event) -} - -func (v *View) DeleteKey(keyID string, private bool, event *models.Event) error { - err := view.DeleteKey(v.Db, keyTable, keyID, private) - if err != nil && !errors.IsNotFound(err) { - return err - } - return v.ProcessedKeySequence(event) -} - -func (v *View) DeleteKeyPair(keyID string, event *models.Event) error { - err := view.DeleteKeyPair(v.Db, keyTable, keyID) - if err != nil && !errors.IsNotFound(err) { - return err - } - return v.ProcessedKeySequence(event) -} - -func (v *View) GetLatestKeySequence() (*repository.CurrentSequence, error) { - return v.latestSequence(keyTable) -} - -func (v *View) ProcessedKeySequence(event *models.Event) error { - return v.saveCurrentSequence(keyTable, event) -} - -func (v *View) UpdateKeySpoolerRunTimestamp() error { - return v.updateSpoolerRunSequence(keyTable) -} - -func (v *View) GetLatestKeyFailedEvent(sequence uint64) (*repository.FailedEvent, error) { - return v.latestFailedEvent(keyTable, sequence) -} - -func (v *View) ProcessedKeyFailedEvent(failedEvent *repository.FailedEvent) error { - return v.saveFailedEvent(failedEvent) -} diff --git a/internal/auth/repository/eventsourcing/view/user_grant.go b/internal/auth/repository/eventsourcing/view/user_grant.go deleted file mode 100644 index 75221b40ef..0000000000 --- a/internal/auth/repository/eventsourcing/view/user_grant.go +++ /dev/null @@ -1,86 +0,0 @@ -package view - -import ( - "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/eventstore/v1/models" - grant_model "github.com/caos/zitadel/internal/usergrant/model" - "github.com/caos/zitadel/internal/usergrant/repository/view" - "github.com/caos/zitadel/internal/usergrant/repository/view/model" - "github.com/caos/zitadel/internal/view/repository" -) - -const ( - userGrantTable = "auth.user_grants" -) - -func (v *View) UserGrantByID(grantID string) (*model.UserGrantView, error) { - return view.UserGrantByID(v.Db, userGrantTable, grantID) -} - -func (v *View) UserGrantByIDs(resourceOwnerID, projectID, userID string) (*model.UserGrantView, error) { - return view.UserGrantByIDs(v.Db, userGrantTable, resourceOwnerID, projectID, userID) -} - -func (v *View) UserGrantsByUserID(userID string) ([]*model.UserGrantView, error) { - return view.UserGrantsByUserID(v.Db, userGrantTable, userID) -} - -func (v *View) UserGrantsByProjectID(projectID string) ([]*model.UserGrantView, error) { - return view.UserGrantsByProjectID(v.Db, userGrantTable, projectID) -} - -func (v *View) UserGrantsByOrgID(projectID string) ([]*model.UserGrantView, error) { - return view.UserGrantsByOrgID(v.Db, userGrantTable, projectID) -} - -func (v *View) UserGrantsByProjectAndUserID(projectID, userID string) ([]*model.UserGrantView, error) { - return view.UserGrantsByProjectAndUserID(v.Db, userGrantTable, projectID, userID) -} - -func (v *View) SearchUserGrants(request *grant_model.UserGrantSearchRequest) ([]*model.UserGrantView, uint64, error) { - return view.SearchUserGrants(v.Db, userGrantTable, request) -} - -func (v *View) PutUserGrant(grant *model.UserGrantView, event *models.Event) error { - err := view.PutUserGrant(v.Db, userGrantTable, grant) - if err != nil { - return err - } - return v.ProcessedUserGrantSequence(event) -} - -func (v *View) PutUserGrants(grants []*model.UserGrantView, event *models.Event) error { - err := view.PutUserGrants(v.Db, userGrantTable, grants...) - if err != nil { - return err - } - return v.ProcessedUserGrantSequence(event) -} - -func (v *View) DeleteUserGrant(grantID string, event *models.Event) error { - err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) - if err != nil && !errors.IsNotFound(err) { - return err - } - return v.ProcessedUserGrantSequence(event) -} - -func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userGrantTable) -} - -func (v *View) ProcessedUserGrantSequence(event *models.Event) error { - return v.saveCurrentSequence(userGrantTable, event) -} - -func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { - return v.updateSpoolerRunSequence(userGrantTable) -} - -func (v *View) GetLatestUserGrantFailedEvent(sequence uint64) (*repository.FailedEvent, error) { - return v.latestFailedEvent(userGrantTable, sequence) -} - -func (v *View) ProcessedUserGrantFailedEvent(failedEvent *repository.FailedEvent) error { - return v.saveFailedEvent(failedEvent) -} diff --git a/internal/auth/repository/repository.go b/internal/auth/repository/repository.go index 0e35656a9a..a235b20bd3 100644 --- a/internal/auth/repository/repository.go +++ b/internal/auth/repository/repository.go @@ -9,9 +9,7 @@ type Repository interface { UserRepository AuthRequestRepository TokenRepository - ApplicationRepository UserSessionRepository - UserGrantRepository OrgRepository RefreshTokenRepository } diff --git a/internal/auth/repository/user_grant.go b/internal/auth/repository/user_grant.go deleted file mode 100644 index e7a9409cb9..0000000000 --- a/internal/auth/repository/user_grant.go +++ /dev/null @@ -1,14 +0,0 @@ -package repository - -import ( - "context" - "github.com/caos/zitadel/internal/usergrant/model" -) - -type UserGrantRepository interface { - SearchMyUserGrants(ctx context.Context, request *model.UserGrantSearchRequest) (*model.UserGrantSearchResponse, error) - SearchMyProjectOrgs(ctx context.Context, request *model.UserGrantSearchRequest) (*model.ProjectOrgSearchResponse, error) - SearchMyZitadelPermissions(ctx context.Context) ([]string, error) - SearchMyProjectPermissions(ctx context.Context) ([]string, error) - UserGrantsByProjectAndUserID(projectID, userID string) ([]*model.UserGrantView, error) -} diff --git a/internal/authz/authz.go b/internal/authz/authz.go index 40538635d4..867c6fc67d 100644 --- a/internal/authz/authz.go +++ b/internal/authz/authz.go @@ -1,9 +1,7 @@ package authz import ( - "context" - - "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/authz/repository" "github.com/caos/zitadel/internal/authz/repository/eventsourcing" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/query" @@ -13,6 +11,6 @@ type Config struct { Repository eventsourcing.Config } -func Start(ctx context.Context, config Config, authZ authz.Config, systemDefaults sd.SystemDefaults, queries *query.Queries) (*eventsourcing.EsRepository, error) { - return eventsourcing.Start(config.Repository, authZ, systemDefaults, queries) +func Start(config Config, systemDefaults sd.SystemDefaults, queries *query.Queries) (repository.Repository, error) { + return eventsourcing.Start(config.Repository, systemDefaults, queries) } diff --git a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go index 2d50dd0265..a1c967e368 100644 --- a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go +++ b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go @@ -14,9 +14,6 @@ import ( caos_errs "github.com/caos/zitadel/internal/errors" v1 "github.com/caos/zitadel/internal/eventstore/v1" "github.com/caos/zitadel/internal/eventstore/v1/models" - es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" - iam_model "github.com/caos/zitadel/internal/iam/model" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_view "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/query" "github.com/caos/zitadel/internal/telemetry/tracing" @@ -33,7 +30,7 @@ type TokenVerifierRepo struct { Query *query.Queries } -func (repo *TokenVerifierRepo) TokenByID(ctx context.Context, tokenID, userID string) (*usr_model.TokenView, error) { +func (repo *TokenVerifierRepo) tokenByID(ctx context.Context, tokenID, userID string) (*usr_model.TokenView, error) { token, viewErr := repo.View.TokenByID(tokenID) if viewErr != nil && !caos_errs.IsNotFound(viewErr) { return nil, viewErr @@ -82,7 +79,7 @@ func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenStrin if len(splittedToken) != 2 { return "", "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "APP-GDg3a", "invalid token") } - token, err := repo.TokenByID(ctx, splittedToken[0], splittedToken[1]) + token, err := repo.tokenByID(ctx, splittedToken[0], splittedToken[1]) if err != nil { return "", "", "", "", "", caos_errs.ThrowUnauthenticated(err, "APP-BxUSiL", "invalid token") } @@ -237,7 +234,7 @@ func (repo *TokenVerifierRepo) VerifierClientID(ctx context.Context, appName str ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - iam, err := repo.getIAMByID(ctx) + iam, err := repo.Query.IAMByID(ctx, domain.IAMID) if err != nil { return "", "", err } @@ -261,23 +258,6 @@ func (r *TokenVerifierRepo) getUserEvents(ctx context.Context, userID string, se return r.Eventstore.FilterEvents(ctx, query) } -func (u *TokenVerifierRepo) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { - query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) - if err != nil { - return nil, err - } - iam := &iam_es_model.IAM{ - ObjectRoot: models.ObjectRoot{ - AggregateID: domain.IAMID, - }, - } - err = es_sdk.Filter(ctx, u.Eventstore.FilterEvents, iam.AppendEvents, query) - if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 { - return nil, err - } - return iam_es_model.IAMToModel(iam), nil -} - func (repo *TokenVerifierRepo) checkDefaultFeatures(ctx context.Context, requiredFeatures ...string) error { features, err := repo.Query.DefaultFeatures(ctx) if err != nil { diff --git a/internal/authz/repository/eventsourcing/eventstore/user_grant.go b/internal/authz/repository/eventsourcing/eventstore/user_grant.go deleted file mode 100644 index c58fbbb431..0000000000 --- a/internal/authz/repository/eventsourcing/eventstore/user_grant.go +++ /dev/null @@ -1,158 +0,0 @@ -package eventstore - -import ( - "context" - - v1 "github.com/caos/zitadel/internal/eventstore/v1" - "github.com/caos/zitadel/internal/eventstore/v1/models" - es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" - iam_model "github.com/caos/zitadel/internal/iam/model" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - iam_view "github.com/caos/zitadel/internal/iam/repository/view" - - "github.com/caos/zitadel/internal/api/authz" - "github.com/caos/zitadel/internal/authz/repository/eventsourcing/view" - "github.com/caos/zitadel/internal/domain" - caos_errs "github.com/caos/zitadel/internal/errors" - user_model "github.com/caos/zitadel/internal/user/model" - user_view_model "github.com/caos/zitadel/internal/user/repository/view/model" - grant_model "github.com/caos/zitadel/internal/usergrant/model" -) - -type UserGrantRepo struct { - View *view.View - IamID string - IamProjectID string - Auth authz.Config - Eventstore v1.Eventstore -} - -func (repo *UserGrantRepo) Health() error { - return repo.View.Health() -} - -func (repo *UserGrantRepo) SearchMyMemberships(ctx context.Context) ([]*authz.Membership, error) { - memberships, err := repo.searchUserMemberships(ctx) - if err != nil { - return nil, err - } - return userMembershipsToMemberships(memberships), nil -} - -func (repo *UserGrantRepo) SearchMyZitadelPermissions(ctx context.Context) ([]string, error) { - memberships, err := repo.searchUserMemberships(ctx) - if err != nil { - return nil, err - } - permissions := &grant_model.Permissions{Permissions: []string{}} - for _, membership := range memberships { - for _, role := range membership.Roles { - permissions = repo.mapRoleToPermission(permissions, membership, role) - } - } - return permissions.Permissions, nil -} - -func (repo *UserGrantRepo) searchUserMemberships(ctx context.Context) ([]*user_view_model.UserMembershipView, error) { - ctxData := authz.GetCtxData(ctx) - orgMemberships, orgCount, err := repo.View.SearchUserMemberships(&user_model.UserMembershipSearchRequest{ - Queries: []*user_model.UserMembershipSearchQuery{ - { - Key: user_model.UserMembershipSearchKeyUserID, - Method: domain.SearchMethodEquals, - Value: ctxData.UserID, - }, - { - Key: user_model.UserMembershipSearchKeyResourceOwner, - Method: domain.SearchMethodEquals, - Value: ctxData.OrgID, - }, - }, - }) - if err != nil { - return nil, err - } - iamMemberships, iamCount, err := repo.View.SearchUserMemberships(&user_model.UserMembershipSearchRequest{ - Queries: []*user_model.UserMembershipSearchQuery{ - { - Key: user_model.UserMembershipSearchKeyUserID, - Method: domain.SearchMethodEquals, - Value: ctxData.UserID, - }, - { - Key: user_model.UserMembershipSearchKeyAggregateID, - Method: domain.SearchMethodEquals, - Value: repo.IamID, - }, - }, - }) - if err != nil { - return nil, err - } - if orgCount == 0 && iamCount == 0 { - return []*user_view_model.UserMembershipView{}, nil - } - return append(orgMemberships, iamMemberships...), nil -} - -func (repo *UserGrantRepo) FillIamProjectID(ctx context.Context) error { - if repo.IamProjectID != "" { - return nil - } - iam, err := repo.getIAMByID(ctx) - if err != nil { - return err - } - if iam.SetUpDone < domain.StepCount-1 { - return caos_errs.ThrowPreconditionFailed(nil, "EVENT-skiwS", "Setup not done") - } - repo.IamProjectID = iam.IAMProjectID - return nil -} - -func (repo *UserGrantRepo) mapRoleToPermission(permissions *grant_model.Permissions, membership *user_view_model.UserMembershipView, role string) *grant_model.Permissions { - for _, mapping := range repo.Auth.RolePermissionMappings { - if mapping.Role == role { - ctxID := "" - if membership.MemberType == int32(user_model.MemberTypeProject) || membership.MemberType == int32(user_model.MemberTypeProjectGrant) { - ctxID = membership.ObjectID - } - permissions.AppendPermissions(ctxID, mapping.Permissions...) - } - } - return permissions -} - -func (u *UserGrantRepo) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { - query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) - if err != nil { - return nil, err - } - iam := &iam_es_model.IAM{ - ObjectRoot: models.ObjectRoot{ - AggregateID: domain.IAMID, - }, - } - err = es_sdk.Filter(ctx, u.Eventstore.FilterEvents, iam.AppendEvents, query) - if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 { - return nil, err - } - return iam_es_model.IAMToModel(iam), nil -} - -func userMembershipToMembership(membership *user_view_model.UserMembershipView) *authz.Membership { - return &authz.Membership{ - MemberType: authz.MemberType(membership.MemberType), - AggregateID: membership.AggregateID, - ObjectID: membership.ObjectID, - Roles: membership.Roles, - } -} - -func userMembershipsToMemberships(memberships []*user_view_model.UserMembershipView) []*authz.Membership { - result := make([]*authz.Membership, len(memberships)) - for i, m := range memberships { - result[i] = userMembershipToMembership(m) - } - return result -} diff --git a/internal/authz/repository/eventsourcing/eventstore/user_membership.go b/internal/authz/repository/eventsourcing/eventstore/user_membership.go new file mode 100644 index 0000000000..2da622af61 --- /dev/null +++ b/internal/authz/repository/eventsourcing/eventstore/user_membership.go @@ -0,0 +1,86 @@ +package eventstore + +import ( + "context" + + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/authz/repository/eventsourcing/view" + "github.com/caos/zitadel/internal/domain" + user_model "github.com/caos/zitadel/internal/user/model" + user_view_model "github.com/caos/zitadel/internal/user/repository/view/model" +) + +type UserMembershipRepo struct { + View *view.View +} + +func (repo *UserMembershipRepo) Health() error { + return repo.View.Health() +} + +func (repo *UserMembershipRepo) SearchMyMemberships(ctx context.Context) ([]*authz.Membership, error) { + memberships, err := repo.searchUserMemberships(ctx) + if err != nil { + return nil, err + } + return userMembershipsToMemberships(memberships), nil +} + +func (repo *UserMembershipRepo) searchUserMemberships(ctx context.Context) ([]*user_view_model.UserMembershipView, error) { + ctxData := authz.GetCtxData(ctx) + orgMemberships, orgCount, err := repo.View.SearchUserMemberships(&user_model.UserMembershipSearchRequest{ + Queries: []*user_model.UserMembershipSearchQuery{ + { + Key: user_model.UserMembershipSearchKeyUserID, + Method: domain.SearchMethodEquals, + Value: ctxData.UserID, + }, + { + Key: user_model.UserMembershipSearchKeyResourceOwner, + Method: domain.SearchMethodEquals, + Value: ctxData.OrgID, + }, + }, + }) + if err != nil { + return nil, err + } + iamMemberships, iamCount, err := repo.View.SearchUserMemberships(&user_model.UserMembershipSearchRequest{ + Queries: []*user_model.UserMembershipSearchQuery{ + { + Key: user_model.UserMembershipSearchKeyUserID, + Method: domain.SearchMethodEquals, + Value: ctxData.UserID, + }, + { + Key: user_model.UserMembershipSearchKeyAggregateID, + Method: domain.SearchMethodEquals, + Value: domain.IAMID, + }, + }, + }) + if err != nil { + return nil, err + } + if orgCount == 0 && iamCount == 0 { + return []*user_view_model.UserMembershipView{}, nil + } + return append(orgMemberships, iamMemberships...), nil +} + +func userMembershipToMembership(membership *user_view_model.UserMembershipView) *authz.Membership { + return &authz.Membership{ + MemberType: authz.MemberType(membership.MemberType), + AggregateID: membership.AggregateID, + ObjectID: membership.ObjectID, + Roles: membership.Roles, + } +} + +func userMembershipsToMemberships(memberships []*user_view_model.UserMembershipView) []*authz.Membership { + result := make([]*authz.Membership, len(memberships)) + for i, m := range memberships { + result[i] = userMembershipToMembership(m) + } + return result +} diff --git a/internal/authz/repository/eventsourcing/repository.go b/internal/authz/repository/eventsourcing/repository.go index 472669fdd2..005e54761a 100644 --- a/internal/authz/repository/eventsourcing/repository.go +++ b/internal/authz/repository/eventsourcing/repository.go @@ -3,19 +3,17 @@ package eventsourcing import ( "context" - "github.com/caos/zitadel/internal/crypto" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - - "github.com/caos/zitadel/internal/query" - - "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/authz/repository" "github.com/caos/zitadel/internal/authz/repository/eventsourcing/eventstore" "github.com/caos/zitadel/internal/authz/repository/eventsourcing/spooler" authz_view "github.com/caos/zitadel/internal/authz/repository/eventsourcing/view" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" + "github.com/caos/zitadel/internal/crypto" + v1 "github.com/caos/zitadel/internal/eventstore/v1" es_spol "github.com/caos/zitadel/internal/eventstore/v1/spooler" "github.com/caos/zitadel/internal/id" + "github.com/caos/zitadel/internal/query" ) type Config struct { @@ -26,11 +24,11 @@ type Config struct { type EsRepository struct { spooler *es_spol.Spooler - eventstore.UserGrantRepo + eventstore.UserMembershipRepo eventstore.TokenVerifierRepo } -func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, queries *query.Queries) (*EsRepository, error) { +func Start(conf Config, systemDefaults sd.SystemDefaults, queries *query.Queries) (repository.Repository, error) { es, err := v1.Start(conf.Eventstore) if err != nil { return nil, err @@ -56,16 +54,12 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, qu return &EsRepository{ spool, - eventstore.UserGrantRepo{ - View: view, - IamID: systemDefaults.IamID, - Auth: authZ, - Eventstore: es, + eventstore.UserMembershipRepo{ + View: view, }, eventstore.TokenVerifierRepo{ TokenVerificationKey: keyAlgorithm, Eventstore: es, - IAMID: systemDefaults.IamID, View: view, Query: queries, }, @@ -73,7 +67,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, qu } func (repo *EsRepository) Health(ctx context.Context) error { - if err := repo.UserGrantRepo.Health(); err != nil { + if err := repo.UserMembershipRepo.Health(); err != nil { return err } return nil diff --git a/internal/authz/repository/repository.go b/internal/authz/repository/repository.go index 5cfe5fd0fb..bb13c95008 100644 --- a/internal/authz/repository/repository.go +++ b/internal/authz/repository/repository.go @@ -1,10 +1,9 @@ package repository -import ( - "context" -) +import "context" type Repository interface { Health(context.Context) error - UserGrantRepository + UserMembershipRepository + TokenVerifierRepository } diff --git a/internal/authz/repository/token_verifier.go b/internal/authz/repository/token_verifier.go index 137f7b3c1b..c9bcf30a1e 100644 --- a/internal/authz/repository/token_verifier.go +++ b/internal/authz/repository/token_verifier.go @@ -5,7 +5,8 @@ import ( ) type TokenVerifierRepository interface { - VerifyAccessToken(ctx context.Context, appName string) (string, string, string, error) - ProjectIDByClientID(ctx context.Context, clientID string) (string, error) - ExistsOrg(ctx context.Context, orgID string) error + VerifyAccessToken(ctx context.Context, tokenString, verifierClientID, projectID string) (userID string, agentID string, clientID, prefLang, resourceOwner string, err error) + ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error) + CheckOrgFeatures(ctx context.Context, orgID string, requiredFeatures ...string) error + VerifierClientID(ctx context.Context, appName string) (clientID, projectID string, err error) } diff --git a/internal/authz/repository/user_grant.go b/internal/authz/repository/user_grant.go deleted file mode 100644 index 64c2ee3304..0000000000 --- a/internal/authz/repository/user_grant.go +++ /dev/null @@ -1,12 +0,0 @@ -package repository - -import ( - "context" - - "github.com/caos/zitadel/internal/api/authz" -) - -type UserGrantRepository interface { - ResolveGrants(ctx context.Context) (*authz.Grant, error) - SearchMyZitadelPermissions(ctx context.Context) ([]string, error) -} diff --git a/internal/authz/repository/user_membership.go b/internal/authz/repository/user_membership.go new file mode 100644 index 0000000000..05addfd897 --- /dev/null +++ b/internal/authz/repository/user_membership.go @@ -0,0 +1,11 @@ +package repository + +import ( + "context" + + "github.com/caos/zitadel/internal/api/authz" +) + +type UserMembershipRepository interface { + SearchMyMemberships(ctx context.Context) ([]*authz.Membership, error) +} diff --git a/internal/command/command.go b/internal/command/command.go index 8743e330af..f1f02cd4d3 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -5,16 +5,15 @@ import ( "time" "github.com/caos/zitadel/internal/api/authz" - authz_repo "github.com/caos/zitadel/internal/authz/repository/eventsourcing" + "github.com/caos/zitadel/internal/api/http" + authz_repo "github.com/caos/zitadel/internal/authz/repository" + sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" + "github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/action" - - "github.com/caos/zitadel/internal/api/http" - sd "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/id" + "github.com/caos/zitadel/internal/repository/action" iam_repo "github.com/caos/zitadel/internal/repository/iam" "github.com/caos/zitadel/internal/repository/keypair" "github.com/caos/zitadel/internal/repository/org" @@ -71,7 +70,7 @@ func StartCommands( defaults sd.SystemDefaults, authZConfig authz.Config, staticStore static.Storage, - authZRepo *authz_repo.EsRepository, + authZRepo authz_repo.Repository, ) (repo *Commands, err error) { repo = &Commands{ eventstore: es, diff --git a/internal/domain/permission.go b/internal/domain/permission.go new file mode 100644 index 0000000000..a9a1df5f42 --- /dev/null +++ b/internal/domain/permission.go @@ -0,0 +1,23 @@ +package domain + +type Permissions struct { + Permissions []string +} + +func (p *Permissions) AppendPermissions(ctxID string, permissions ...string) { + for _, permission := range permissions { + p.appendPermission(ctxID, permission) + } +} + +func (p *Permissions) appendPermission(ctxID, permission string) { + if ctxID != "" { + permission = permission + ":" + ctxID + } + for _, existingPermission := range p.Permissions { + if existingPermission == permission { + return + } + } + p.Permissions = append(p.Permissions, permission) +} diff --git a/internal/management/repository/eventsourcing/eventstore/org.go b/internal/management/repository/eventsourcing/eventstore/org.go deleted file mode 100644 index d081eb7acf..0000000000 --- a/internal/management/repository/eventsourcing/eventstore/org.go +++ /dev/null @@ -1,117 +0,0 @@ -package eventstore - -import ( - "context" - "encoding/json" - "net/http" - "strings" - "sync" - "time" - - "github.com/caos/logging" - "github.com/golang/protobuf/ptypes" - "golang.org/x/text/language" - - "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/errors" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - org_model "github.com/caos/zitadel/internal/org/model" - org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" - org_view "github.com/caos/zitadel/internal/org/repository/view" - "github.com/caos/zitadel/internal/query" -) - -type OrgRepository struct { - Query *query.Queries - SearchLimit uint64 - Eventstore v1.Eventstore - Roles []string - SystemDefaults systemdefaults.SystemDefaults - PrefixAvatarURL string - LoginDir http.FileSystem - NotificationDir http.FileSystem - LoginTranslationFileContents map[string][]byte - NotificationTranslationFileContents map[string][]byte - mutex sync.Mutex - supportedLangs []language.Tag -} - -func (repo *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error) { - changes, err := repo.getOrgChanges(ctx, id, lastSequence, limit, sortAscending, auditLogRetention) - if err != nil { - return nil, err - } - for _, change := range changes.Changes { - change.ModifierName = change.ModifierId - change.ModifierLoginName = change.ModifierId - user, _ := repo.Query.GetUserByID(ctx, change.ModifierId) - if user != nil { - change.ModifierLoginName = user.PreferredLoginName - if user.Human != nil { - change.ModifierName = user.Human.DisplayName - change.ModifierAvatarURL = domain.AvatarURL(repo.PrefixAvatarURL, user.ResourceOwner, user.Human.AvatarKey) - } - if user.Machine != nil { - change.ModifierName = user.Machine.Name - } - } - } - return changes, nil -} - -func (repo *OrgRepository) GetOrgMemberRoles(isGlobal bool) []string { - roles := make([]string, 0) - for _, roleMap := range repo.Roles { - if strings.HasPrefix(roleMap, "ORG") { - roles = append(roles, roleMap) - } - } - if isGlobal { - roles = append(roles, domain.RoleSelfManagementGlobal) - } - return roles -} - -func (repo *OrgRepository) getOrgChanges(ctx context.Context, orgID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error) { - query := org_view.ChangesQuery(orgID, lastSequence, limit, sortAscending, auditLogRetention) - - events, err := repo.Eventstore.FilterEvents(context.Background(), query) - if err != nil { - logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable") - return nil, errors.ThrowInternal(err, "EVENT-328b1", "Errors.Org.NotFound") - } - if len(events) == 0 { - return nil, errors.ThrowNotFound(nil, "EVENT-FpQqK", "Errors.Changes.NotFound") - } - - changes := make([]*org_model.OrgChange, len(events)) - - for i, event := range events { - creationDate, err := ptypes.TimestampProto(event.CreationDate) - logging.Log("EVENT-qxIR7").OnError(err).Debug("unable to parse timestamp") - change := &org_model.OrgChange{ - ChangeDate: creationDate, - EventType: event.Type.String(), - ModifierId: event.EditorUser, - Sequence: event.Sequence, - } - - if event.Data != nil { - org := new(org_es_model.Org) - err := json.Unmarshal(event.Data, org) - logging.Log("EVENT-XCLEm").OnError(err).Debug("unable to unmarshal data") - change.Data = org - } - - changes[i] = change - if lastSequence < event.Sequence { - lastSequence = event.Sequence - } - } - - return &org_model.OrgChanges{ - Changes: changes, - LastSequence: lastSequence, - }, nil -} diff --git a/internal/management/repository/eventsourcing/eventstore/project.go b/internal/management/repository/eventsourcing/eventstore/project.go deleted file mode 100644 index 9c79333680..0000000000 --- a/internal/management/repository/eventsourcing/eventstore/project.go +++ /dev/null @@ -1,204 +0,0 @@ -package eventstore - -import ( - "context" - "encoding/json" - "strings" - "time" - - "github.com/caos/logging" - "github.com/golang/protobuf/ptypes" - - "github.com/caos/zitadel/internal/api/authz" - "github.com/caos/zitadel/internal/domain" - caos_errs "github.com/caos/zitadel/internal/errors" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - "github.com/caos/zitadel/internal/eventstore/v1/models" - proj_model "github.com/caos/zitadel/internal/project/model" - proj_view "github.com/caos/zitadel/internal/project/repository/view" - "github.com/caos/zitadel/internal/query" -) - -type ProjectRepo struct { - v1.Eventstore - Roles []string - IAMID string - PrefixAvatarURL string - Query *query.Queries -} - -func (repo *ProjectRepo) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*proj_model.ProjectChanges, error) { - changes, err := repo.getProjectChanges(ctx, id, lastSequence, limit, sortAscending, retention) - if err != nil { - return nil, err - } - for _, change := range changes.Changes { - change.ModifierName = change.ModifierId - change.ModifierLoginName = change.ModifierId - user, _ := repo.Query.GetUserByID(ctx, change.ModifierId) - if user != nil { - change.ModifierLoginName = user.PreferredLoginName - if user.Human != nil { - change.ModifierName = user.Human.DisplayName - change.ModifierAvatarURL = domain.AvatarURL(repo.PrefixAvatarURL, user.ResourceOwner, user.Human.AvatarKey) - } - if user.Machine != nil { - change.ModifierName = user.Machine.Name - } - } - } - return changes, nil -} - -func (repo *ProjectRepo) ApplicationChanges(ctx context.Context, projectID string, appID string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*proj_model.ApplicationChanges, error) { - changes, err := repo.getApplicationChanges(ctx, projectID, appID, lastSequence, limit, sortAscending, retention) - if err != nil { - return nil, err - } - for _, change := range changes.Changes { - change.ModifierName = change.ModifierId - change.ModifierLoginName = change.ModifierId - user, _ := repo.Query.GetUserByID(ctx, change.ModifierId) - if user != nil { - change.ModifierLoginName = user.PreferredLoginName - if user.Human != nil { - change.ModifierName = user.Human.DisplayName - change.ModifierAvatarURL = domain.AvatarURL(repo.PrefixAvatarURL, user.ResourceOwner, user.Human.AvatarKey) - } - if user.Machine != nil { - change.ModifierName = user.Machine.Name - } - } - } - return changes, nil -} - -func (repo *ProjectRepo) GetProjectMemberRoles(ctx context.Context) ([]string, error) { - iam, err := repo.Query.IAMByID(ctx, repo.IAMID) - if err != nil { - return nil, err - } - roles := make([]string, 0) - global := authz.GetCtxData(ctx).OrgID == iam.GlobalOrgID - for _, roleMap := range repo.Roles { - if strings.HasPrefix(roleMap, "PROJECT") && !strings.HasPrefix(roleMap, "PROJECT_GRANT") { - if global && !strings.HasSuffix(roleMap, "GLOBAL") { - continue - } - roles = append(roles, roleMap) - } - } - return roles, nil -} - -func (repo *ProjectRepo) GetProjectGrantMemberRoles() []string { - roles := make([]string, 0) - for _, roleMap := range repo.Roles { - if strings.HasPrefix(roleMap, "PROJECT_GRANT") { - roles = append(roles, roleMap) - } - } - return roles -} - -func (repo *ProjectRepo) getProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*proj_model.ProjectChanges, error) { - query := proj_view.ChangesQuery(id, lastSequence, limit, sortAscending, retention) - - events, err := repo.Eventstore.FilterEvents(context.Background(), query) - if err != nil { - logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable") - return nil, caos_errs.ThrowInternal(err, "EVENT-328b1", "Errors.Internal") - } - if len(events) == 0 { - return nil, caos_errs.ThrowNotFound(nil, "EVENT-FpQqK", "Errors.Changes.NotFound") - } - - changes := make([]*proj_model.ProjectChange, len(events)) - - for i, event := range events { - creationDate, err := ptypes.TimestampProto(event.CreationDate) - logging.Log("EVENT-qxIR7").OnError(err).Debug("unable to parse timestamp") - change := &proj_model.ProjectChange{ - ChangeDate: creationDate, - EventType: event.Type.String(), - ModifierId: event.EditorUser, - Sequence: event.Sequence, - } - - if event.Data != nil { - var data interface{} - if strings.Contains(change.EventType, "application") { - data = new(proj_model.Application) - } else { - data = new(proj_model.Project) - } - err = json.Unmarshal(event.Data, data) - logging.Log("EVENT-NCkpN").OnError(err).Debug("unable to unmarshal data") - change.Data = data - } - - changes[i] = change - if lastSequence < event.Sequence { - lastSequence = event.Sequence - } - } - - return &proj_model.ProjectChanges{ - Changes: changes, - LastSequence: lastSequence, - }, nil -} - -func (repo *ProjectRepo) getProjectEvents(ctx context.Context, id string, sequence uint64) ([]*models.Event, error) { - query, err := proj_view.ProjectByIDQuery(id, sequence) - if err != nil { - return nil, err - } - return repo.Eventstore.FilterEvents(ctx, query) -} - -func (repo *ProjectRepo) getApplicationChanges(ctx context.Context, projectID string, appID string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*proj_model.ApplicationChanges, error) { - query := proj_view.ChangesQuery(projectID, lastSequence, limit, sortAscending, retention) - - events, err := repo.Eventstore.FilterEvents(ctx, query) - if err != nil { - logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable") - return nil, caos_errs.ThrowInternal(err, "EVENT-sw6Ku", "Errors.Internal") - } - if len(events) == 0 { - return nil, caos_errs.ThrowNotFound(nil, "EVENT-9IHLP", "Errors.Changes.NotFound") - } - - result := make([]*proj_model.ApplicationChange, 0) - for _, event := range events { - if !strings.Contains(event.Type.String(), "application") || event.Data == nil { - continue - } - - app := new(proj_model.Application) - err := json.Unmarshal(event.Data, app) - logging.Log("EVENT-GIiKD").OnError(err).Debug("unable to unmarshal data") - if app.AppID != appID { - continue - } - - creationDate, err := ptypes.TimestampProto(event.CreationDate) - logging.Log("EVENT-MJzeN").OnError(err).Debug("unable to parse timestamp") - - result = append(result, &proj_model.ApplicationChange{ - ChangeDate: creationDate, - EventType: event.Type.String(), - ModifierId: event.EditorUser, - Sequence: event.Sequence, - Data: app, - }) - if lastSequence < event.Sequence { - lastSequence = event.Sequence - } - } - - return &proj_model.ApplicationChanges{ - Changes: result, - LastSequence: lastSequence, - }, nil -} diff --git a/internal/management/repository/eventsourcing/eventstore/user.go b/internal/management/repository/eventsourcing/eventstore/user.go deleted file mode 100644 index 946ead3630..0000000000 --- a/internal/management/repository/eventsourcing/eventstore/user.go +++ /dev/null @@ -1,101 +0,0 @@ -package eventstore - -import ( - "context" - "time" - - "github.com/caos/logging" - "github.com/golang/protobuf/ptypes" - - "github.com/caos/zitadel/internal/query" - - "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/errors" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - "github.com/caos/zitadel/internal/eventstore/v1/models" - usr_model "github.com/caos/zitadel/internal/user/model" - usr_view "github.com/caos/zitadel/internal/user/repository/view" -) - -type UserRepo struct { - v1.Eventstore - Query *query.Queries - SystemDefaults systemdefaults.SystemDefaults - PrefixAvatarURL string -} - -func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*usr_model.UserChanges, error) { - changes, err := repo.getUserChanges(ctx, id, lastSequence, limit, sortAscending, retention) - if err != nil { - return nil, err - } - for _, change := range changes.Changes { - change.ModifierName = change.ModifierID - change.ModifierLoginName = change.ModifierID - user, _ := repo.Query.GetUserByID(ctx, change.ModifierID) - if user != nil { - change.ModifierLoginName = user.PreferredLoginName - if user.Human != nil { - change.ModifierName = user.Human.DisplayName - change.ModifierAvatarURL = domain.AvatarURL(repo.PrefixAvatarURL, user.ResourceOwner, user.Human.AvatarKey) - } - if user.Machine != nil { - change.ModifierName = user.Machine.Name - } - } - } - return changes, nil -} - -func (r *UserRepo) getUserChanges(ctx context.Context, userID string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*usr_model.UserChanges, error) { - query := usr_view.ChangesQuery(userID, lastSequence, limit, sortAscending, retention) - - events, err := r.Eventstore.FilterEvents(ctx, query) - if err != nil { - logging.Log("EVENT-g9HCv").WithError(err).Warn("eventstore unavailable") - return nil, errors.ThrowInternal(err, "EVENT-htuG9", "Errors.Internal") - } - if len(events) == 0 { - return nil, errors.ThrowNotFound(nil, "EVENT-6cAxe", "Errors.User.NoChanges") - } - - result := make([]*usr_model.UserChange, len(events)) - - for i, event := range events { - creationDate, err := ptypes.TimestampProto(event.CreationDate) - logging.Log("EVENT-8GTGS").OnError(err).Debug("unable to parse timestamp") - change := &usr_model.UserChange{ - ChangeDate: creationDate, - EventType: event.Type.String(), - ModifierID: event.EditorUser, - Sequence: event.Sequence, - } - - //TODO: now all types should be unmarshalled, e.g. password - // if len(event.Data) != 0 { - // user := new(model.User) - // err := json.Unmarshal(event.Data, user) - // logging.Log("EVENT-Rkg7X").OnError(err).Debug("unable to unmarshal data") - // change.Data = user - // } - - result[i] = change - if lastSequence < event.Sequence { - lastSequence = event.Sequence - } - } - - return &usr_model.UserChanges{ - Changes: result, - LastSequence: lastSequence, - }, nil -} - -func (r *UserRepo) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) { - query, err := usr_view.UserByIDQuery(userID, sequence) - if err != nil { - return nil, err - } - return r.Eventstore.FilterEvents(ctx, query) -} diff --git a/internal/management/repository/eventsourcing/repository.go b/internal/management/repository/eventsourcing/repository.go deleted file mode 100644 index bd3223b20c..0000000000 --- a/internal/management/repository/eventsourcing/repository.go +++ /dev/null @@ -1,60 +0,0 @@ -package eventsourcing - -import ( - "github.com/caos/logging" - "github.com/rakyll/statik/fs" - - sd "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/config/types" - v1 "github.com/caos/zitadel/internal/eventstore/v1" - "github.com/caos/zitadel/internal/management/repository/eventsourcing/eventstore" - "github.com/caos/zitadel/internal/query" - "github.com/caos/zitadel/internal/static" -) - -type Config struct { - SearchLimit uint64 - Domain string - APIDomain string - Eventstore v1.Config - View types.SQL -} - -type EsRepository struct { - eventstore.OrgRepository - eventstore.ProjectRepo - eventstore.UserRepo -} - -func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string, queries *query.Queries, staticStorage static.Storage) (*EsRepository, error) { - - es, err := v1.Start(conf.Eventstore) - if err != nil { - return nil, err - } - - assetsAPI := conf.APIDomain + "/assets/v1/" - - statikLoginFS, err := fs.NewWithNamespace("login") - logging.Log("CONFI-7usEW").OnError(err).Panic("unable to start login statik dir") - - statikNotificationFS, err := fs.NewWithNamespace("notification") - logging.Log("CONFI-7usEW").OnError(err).Panic("unable to start notification statik dir") - - return &EsRepository{ - OrgRepository: eventstore.OrgRepository{ - SearchLimit: conf.SearchLimit, - Eventstore: es, - Roles: roles, - SystemDefaults: systemDefaults, - PrefixAvatarURL: assetsAPI, - LoginDir: statikLoginFS, - NotificationDir: statikNotificationFS, - LoginTranslationFileContents: make(map[string][]byte), - NotificationTranslationFileContents: make(map[string][]byte), - Query: queries, - }, - ProjectRepo: eventstore.ProjectRepo{es, roles, systemDefaults.IamID, assetsAPI, queries}, - UserRepo: eventstore.UserRepo{es, queries, systemDefaults, assetsAPI}, - }, nil -} diff --git a/internal/management/repository/org.go b/internal/management/repository/org.go deleted file mode 100644 index 3182d864bb..0000000000 --- a/internal/management/repository/org.go +++ /dev/null @@ -1,14 +0,0 @@ -package repository - -import ( - "context" - "time" - - org_model "github.com/caos/zitadel/internal/org/model" -) - -type OrgRepository interface { - OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error) - - GetOrgMemberRoles(isGlobal bool) []string -} diff --git a/internal/management/repository/project.go b/internal/management/repository/project.go deleted file mode 100644 index 61e41c9b41..0000000000 --- a/internal/management/repository/project.go +++ /dev/null @@ -1,18 +0,0 @@ -package repository - -import ( - "context" - "time" - - "github.com/caos/zitadel/internal/project/model" -) - -type ProjectRepository interface { - GetProjectMemberRoles(ctx context.Context) ([]string, error) - - ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*model.ProjectChanges, error) - - ApplicationChanges(ctx context.Context, projectID string, appID string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*model.ApplicationChanges, error) - - GetProjectGrantMemberRoles() []string -} diff --git a/internal/management/repository/repository.go b/internal/management/repository/repository.go deleted file mode 100644 index 2b8511d81f..0000000000 --- a/internal/management/repository/repository.go +++ /dev/null @@ -1,7 +0,0 @@ -package repository - -type Repository interface { - ProjectRepository - OrgRepository - UserRepository -} diff --git a/internal/management/repository/user.go b/internal/management/repository/user.go deleted file mode 100644 index bc55066afc..0000000000 --- a/internal/management/repository/user.go +++ /dev/null @@ -1,12 +0,0 @@ -package repository - -import ( - "context" - "time" - - "github.com/caos/zitadel/internal/user/model" -) - -type UserRepository interface { - UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*model.UserChanges, error) -} diff --git a/internal/query/changes.go b/internal/query/changes.go new file mode 100644 index 0000000000..0b80f739e8 --- /dev/null +++ b/internal/query/changes.go @@ -0,0 +1,122 @@ +package query + +import ( + "context" + "time" + + "github.com/caos/logging" + + "github.com/caos/zitadel/internal/repository/user" + + "github.com/caos/zitadel/internal/repository/project" + + "github.com/caos/zitadel/internal/repository/org" + + "github.com/caos/zitadel/internal/eventstore" + + "github.com/caos/zitadel/internal/errors" +) + +type Changes struct { + Changes []*Change +} + +type Change struct { + ChangeDate time.Time + EventType string + Sequence uint64 + ResourceOwner string + ModifierId string + ModifierName string + ModifierLoginName string + ModifierResourceOwner string + ModifierAvatarKey string +} + +func (q *Queries) OrgChanges(ctx context.Context, orgID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) { + query := func(query *eventstore.SearchQuery) { + query.AggregateTypes(org.AggregateType). + AggregateIDs(orgID) + } + return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) + +} + +func (q *Queries) ProjectChanges(ctx context.Context, projectID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) { + query := func(query *eventstore.SearchQuery) { + query.AggregateTypes(project.AggregateType). + AggregateIDs(projectID) + } + return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) +} + +func (q *Queries) ApplicationChanges(ctx context.Context, projectID, appID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) { + query := func(query *eventstore.SearchQuery) { + query.AggregateTypes(project.AggregateType). + AggregateIDs(projectID). + EventData(map[string]interface{}{ + "appId": appID, + }) + } + return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) +} + +func (q *Queries) UserChanges(ctx context.Context, userID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) { + query := func(query *eventstore.SearchQuery) { + query.AggregateTypes(user.AggregateType). + AggregateIDs(userID) + } + return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) +} + +func (q *Queries) changes(ctx context.Context, query func(query *eventstore.SearchQuery), lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) { + builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit) + if !sortAscending { + builder.OrderDesc() + } + search := builder.AddQuery().SequenceGreater(lastSequence) //always use greater (less is done automatically by sorting desc) + query(search) + + events, err := q.eventstore.Filter(ctx, builder) + if err != nil { + logging.Log("QUERY-ZRffs").WithError(err).Warn("eventstore unavailable") + return nil, errors.ThrowInternal(err, "QUERY-328b1", "Errors.Internal") + } + if len(events) == 0 { + return nil, errors.ThrowNotFound(nil, "QUERY-FpQqK", "Errors.Changes.NotFound") + } + changes := make([]*Change, 0, len(events)) + for _, event := range events { + if event.CreationDate().Before(time.Now().Add(-auditLogRetention)) { + continue + } + change := &Change{ + ChangeDate: event.CreationDate(), + EventType: string(event.Type()), + Sequence: event.Sequence(), + ResourceOwner: event.Aggregate().ResourceOwner, + ModifierId: event.EditorUser(), + ModifierName: event.EditorUser(), + ModifierLoginName: event.EditorUser(), + } + editor, _ := q.GetUserByID(ctx, change.ModifierId) + if editor != nil { + change.ModifierLoginName = editor.PreferredLoginName + change.ModifierResourceOwner = editor.ResourceOwner + if editor.Human != nil { + change.ModifierName = editor.Human.DisplayName + change.ModifierAvatarKey = editor.Human.AvatarKey + } + if editor.Machine != nil { + change.ModifierName = editor.Machine.Name + } + } + changes = append(changes, change) + } + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "QUERY-DEGS2", "Errors.Changes.AuditRetention") + } + return &Changes{ + Changes: changes, + }, nil +} diff --git a/internal/query/converter.go b/internal/query/converter.go deleted file mode 100644 index dee686c808..0000000000 --- a/internal/query/converter.go +++ /dev/null @@ -1,27 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/eventstore/v1/models" - "github.com/caos/zitadel/internal/iam/model" -) - -func readModelToIAM(readModel *ReadModel) *model.IAM { - return &model.IAM{ - ObjectRoot: readModelToObjectRoot(readModel.ReadModel), - GlobalOrgID: readModel.GlobalOrgID, - IAMProjectID: readModel.ProjectID, - SetUpDone: readModel.SetUpDone, - SetUpStarted: readModel.SetUpStarted, - } -} - -func readModelToObjectRoot(readModel eventstore.ReadModel) models.ObjectRoot { - return models.ObjectRoot{ - AggregateID: readModel.AggregateID, - ChangeDate: readModel.ChangeDate, - CreationDate: readModel.CreationDate, - ResourceOwner: readModel.ResourceOwner, - Sequence: readModel.ProcessedSequence, - } -} diff --git a/internal/query/iam_idp_config_model.go b/internal/query/iam_idp_config_model.go deleted file mode 100644 index 9e5d96a86f..0000000000 --- a/internal/query/iam_idp_config_model.go +++ /dev/null @@ -1,55 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" -) - -type IAMIDPConfigReadModel struct { - IDPConfigReadModel - - iamID string - configID string -} - -func NewIAMIDPConfigReadModel(iamID, configID string) *IAMIDPConfigReadModel { - return &IAMIDPConfigReadModel{ - iamID: iamID, - configID: configID, - } -} - -func (rm *IAMIDPConfigReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.IDPConfigAddedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.IDPConfigAddedEvent) - case *iam.IDPConfigChangedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.IDPConfigChangedEvent) - case *iam.IDPConfigDeactivatedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.IDPConfigDeactivatedEvent) - case *iam.IDPConfigReactivatedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.IDPConfigReactivatedEvent) - case *iam.IDPConfigRemovedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.IDPConfigRemovedEvent) - case *iam.IDPOIDCConfigAddedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.OIDCConfigAddedEvent) - case *iam.IDPOIDCConfigChangedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.OIDCConfigChangedEvent) - case *iam.IDPJWTConfigAddedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.JWTConfigAddedEvent) - case *iam.IDPJWTConfigChangedEvent: - rm.IDPConfigReadModel.AppendEvents(&e.JWTConfigChangedEvent) - } - } -} - -func (rm *IAMIDPConfigReadModel) Query() *eventstore.SearchQueryBuilder { - return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). - AddQuery(). - AggregateTypes(iam.AggregateType). - AggregateIDs(rm.iamID). - EventData(map[string]interface{}{ - "idpConfigId": rm.configID, - }).Builder() -} diff --git a/internal/query/iam_idp_configs_model.go b/internal/query/iam_idp_configs_model.go deleted file mode 100644 index c24d77c4c0..0000000000 --- a/internal/query/iam_idp_configs_model.go +++ /dev/null @@ -1,31 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" -) - -type IAMIDPConfigsReadModel struct { - IDPConfigsReadModel -} - -func (rm *IAMIDPConfigsReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.IDPConfigAddedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.IDPConfigAddedEvent) - case *iam.IDPConfigChangedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.IDPConfigChangedEvent) - case *iam.IDPConfigDeactivatedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.IDPConfigDeactivatedEvent) - case *iam.IDPConfigReactivatedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.IDPConfigReactivatedEvent) - case *iam.IDPConfigRemovedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.IDPConfigRemovedEvent) - case *iam.IDPOIDCConfigAddedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.OIDCConfigAddedEvent) - case *iam.IDPOIDCConfigChangedEvent: - rm.IDPConfigsReadModel.AppendEvents(&e.OIDCConfigChangedEvent) - } - } -} diff --git a/internal/query/iam_member_model.go b/internal/query/iam_member_model.go deleted file mode 100644 index f5503a267c..0000000000 --- a/internal/query/iam_member_model.go +++ /dev/null @@ -1,45 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/member" -) - -type IAMMemberReadModel struct { - MemberReadModel - - userID string - iamID string -} - -func NewIAMMemberReadModel(iamID, userID string) *IAMMemberReadModel { - return &IAMMemberReadModel{ - iamID: iamID, - userID: userID, - } -} - -func (rm *IAMMemberReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.MemberAddedEvent: - rm.MemberReadModel.AppendEvents(&e.MemberAddedEvent) - case *iam.MemberChangedEvent: - rm.MemberReadModel.AppendEvents(&e.MemberChangedEvent) - case *member.MemberAddedEvent, *member.MemberChangedEvent, - *iam.MemberRemovedEvent, *iam.MemberCascadeRemovedEvent: - rm.MemberReadModel.AppendEvents(e) - } - } -} - -func (rm *IAMMemberReadModel) Query() *eventstore.SearchQueryBuilder { - return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). - AddQuery(). - AggregateTypes(iam.AggregateType). - AggregateIDs(rm.iamID). - EventData(map[string]interface{}{ - "userId": rm.userID, - }).Builder() -} diff --git a/internal/query/iam_members_model.go b/internal/query/iam_members_model.go deleted file mode 100644 index cd770a54c3..0000000000 --- a/internal/query/iam_members_model.go +++ /dev/null @@ -1,25 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" -) - -type IAMMembersReadModel struct { - MembersReadModel -} - -func (rm *IAMMembersReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.MemberAddedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberAddedEvent) - case *iam.MemberChangedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberChangedEvent) - case *iam.MemberRemovedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberRemovedEvent) - case *iam.MemberCascadeRemovedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberCascadeRemovedEvent) - } - } -} diff --git a/internal/query/iam_model.go b/internal/query/iam_model.go deleted file mode 100644 index e52db76e47..0000000000 --- a/internal/query/iam_model.go +++ /dev/null @@ -1,136 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/member" - "github.com/caos/zitadel/internal/repository/policy" -) - -type ReadModel struct { - eventstore.ReadModel - - SetUpStarted domain.Step - SetUpDone domain.Step - - Members IAMMembersReadModel - IDPs IAMIDPConfigsReadModel - - GlobalOrgID string - ProjectID string - - DefaultLoginPolicy IAMLoginPolicyReadModel - DefaultLabelPolicy IAMLabelPolicyReadModel - DefaultOrgIAMPolicy IAMOrgIAMPolicyReadModel - DefaultPasswordComplexityPolicy IAMPasswordComplexityPolicyReadModel - DefaultPasswordAgePolicy IAMPasswordAgePolicyReadModel - DefaultPasswordLockoutPolicy IAMLockoutPolicyReadModel -} - -func NewReadModel(id string) *ReadModel { - return &ReadModel{ - ReadModel: eventstore.ReadModel{ - AggregateID: id, - }, - } -} - -func (rm *ReadModel) IDPByID(idpID string) *IAMIDPConfigReadModel { - _, config := rm.IDPs.ConfigByID(idpID) - if config == nil { - return nil - } - return &IAMIDPConfigReadModel{IDPConfigReadModel: *config} -} - -func (rm *ReadModel) AppendEvents(events ...eventstore.Event) { - rm.ReadModel.AppendEvents(events...) - for _, event := range events { - switch event.(type) { - case *member.MemberAddedEvent, - *member.MemberChangedEvent, - *member.MemberRemovedEvent: - - rm.Members.AppendEvents(event) - case *iam.IDPConfigAddedEvent, - *iam.IDPConfigChangedEvent, - *iam.IDPConfigDeactivatedEvent, - *iam.IDPConfigReactivatedEvent, - *iam.IDPConfigRemovedEvent, - *iam.IDPOIDCConfigAddedEvent, - *iam.IDPOIDCConfigChangedEvent: - - rm.IDPs.AppendEvents(event) - case *policy.LabelPolicyAddedEvent, - *policy.LabelPolicyChangedEvent: - - rm.DefaultLabelPolicy.AppendEvents(event) - case *policy.LoginPolicyAddedEvent, - *policy.LoginPolicyChangedEvent: - - rm.DefaultLoginPolicy.AppendEvents(event) - case *policy.OrgIAMPolicyAddedEvent: - rm.DefaultOrgIAMPolicy.AppendEvents(event) - case *policy.PasswordComplexityPolicyAddedEvent, - *policy.PasswordComplexityPolicyChangedEvent: - - rm.DefaultPasswordComplexityPolicy.AppendEvents(event) - case *policy.PasswordAgePolicyAddedEvent, - *policy.PasswordAgePolicyChangedEvent: - - rm.DefaultPasswordAgePolicy.AppendEvents(event) - case *policy.LockoutPolicyAddedEvent, - *policy.LockoutPolicyChangedEvent: - - rm.DefaultPasswordLockoutPolicy.AppendEvents(event) - } - } -} - -func (rm *ReadModel) Reduce() (err error) { - for _, event := range rm.Events { - switch e := event.(type) { - case *iam.ProjectSetEvent: - rm.ProjectID = e.ProjectID - case *iam.GlobalOrgSetEvent: - rm.GlobalOrgID = e.OrgID - case *iam.SetupStepEvent: - if e.Done { - rm.SetUpDone = e.Step - } else { - rm.SetUpStarted = e.Step - } - } - } - for _, reduce := range []func() error{ - rm.Members.Reduce, - rm.IDPs.Reduce, - rm.DefaultLoginPolicy.Reduce, - rm.DefaultLabelPolicy.Reduce, - rm.DefaultOrgIAMPolicy.Reduce, - rm.DefaultPasswordComplexityPolicy.Reduce, - rm.DefaultPasswordAgePolicy.Reduce, - rm.DefaultPasswordLockoutPolicy.Reduce, - rm.ReadModel.Reduce, - } { - if err = reduce(); err != nil { - return err - } - } - - return nil -} - -func (rm *ReadModel) AppendAndReduce(events ...eventstore.Event) error { - rm.AppendEvents(events...) - return rm.Reduce() -} - -func (rm *ReadModel) Query() *eventstore.SearchQueryBuilder { - return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). - AddQuery(). - AggregateTypes(iam.AggregateType). - AggregateIDs(rm.AggregateID). - Builder() -} diff --git a/internal/query/iam_policy_label_model.go b/internal/query/iam_policy_label_model.go deleted file mode 100644 index 6496580aaf..0000000000 --- a/internal/query/iam_policy_label_model.go +++ /dev/null @@ -1,22 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/policy" -) - -type IAMLabelPolicyReadModel struct{ LabelPolicyReadModel } - -func (rm *IAMLabelPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.LabelPolicyAddedEvent: - rm.LabelPolicyReadModel.AppendEvents(&e.LabelPolicyAddedEvent) - case *iam.LabelPolicyChangedEvent: - rm.LabelPolicyReadModel.AppendEvents(&e.LabelPolicyChangedEvent) - case *policy.LabelPolicyAddedEvent, *policy.LabelPolicyChangedEvent: - rm.LabelPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/iam_policy_login_model.go b/internal/query/iam_policy_login_model.go deleted file mode 100644 index bdaff15895..0000000000 --- a/internal/query/iam_policy_login_model.go +++ /dev/null @@ -1,22 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/policy" -) - -type IAMLoginPolicyReadModel struct{ LoginPolicyReadModel } - -func (rm *IAMLoginPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.LoginPolicyAddedEvent: - rm.LoginPolicyReadModel.AppendEvents(&e.LoginPolicyAddedEvent) - case *iam.LoginPolicyChangedEvent: - rm.LoginPolicyReadModel.AppendEvents(&e.LoginPolicyChangedEvent) - case *policy.LoginPolicyAddedEvent, *policy.LoginPolicyChangedEvent: - rm.LoginPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/iam_policy_org_iam_model.go b/internal/query/iam_policy_org_iam_model.go deleted file mode 100644 index cd1fded951..0000000000 --- a/internal/query/iam_policy_org_iam_model.go +++ /dev/null @@ -1,20 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/policy" -) - -type IAMOrgIAMPolicyReadModel struct{ OrgIAMPolicyReadModel } - -func (rm *IAMOrgIAMPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.OrgIAMPolicyAddedEvent: - rm.OrgIAMPolicyReadModel.AppendEvents(&e.OrgIAMPolicyAddedEvent) - case *policy.OrgIAMPolicyAddedEvent: - rm.OrgIAMPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/iam_policy_password_age_model.go b/internal/query/iam_policy_password_age_model.go deleted file mode 100644 index c5b8a98c80..0000000000 --- a/internal/query/iam_policy_password_age_model.go +++ /dev/null @@ -1,26 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/policy" -) - -type IAMPasswordAgePolicyReadModel struct { - PasswordAgePolicyReadModel -} - -func (rm *IAMPasswordAgePolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.PasswordAgePolicyAddedEvent: - rm.PasswordAgePolicyReadModel.AppendEvents(&e.PasswordAgePolicyAddedEvent) - case *iam.PasswordAgePolicyChangedEvent: - rm.PasswordAgePolicyReadModel.AppendEvents(&e.PasswordAgePolicyChangedEvent) - case *policy.PasswordAgePolicyAddedEvent, - *policy.PasswordAgePolicyChangedEvent: - - rm.PasswordAgePolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/iam_policy_password_complexity_model.go b/internal/query/iam_policy_password_complexity_model.go deleted file mode 100644 index 0dc0380266..0000000000 --- a/internal/query/iam_policy_password_complexity_model.go +++ /dev/null @@ -1,26 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/policy" -) - -type IAMPasswordComplexityPolicyReadModel struct { - PasswordComplexityPolicyReadModel -} - -func (rm *IAMPasswordComplexityPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.PasswordComplexityPolicyAddedEvent: - rm.PasswordComplexityPolicyReadModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent) - case *iam.PasswordComplexityPolicyChangedEvent: - rm.PasswordComplexityPolicyReadModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent) - case *policy.PasswordComplexityPolicyAddedEvent, - *policy.PasswordComplexityPolicyChangedEvent: - - rm.PasswordComplexityPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/iam_policy_password_lockout_model.go b/internal/query/iam_policy_password_lockout_model.go deleted file mode 100644 index a08f54c741..0000000000 --- a/internal/query/iam_policy_password_lockout_model.go +++ /dev/null @@ -1,24 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/iam" - "github.com/caos/zitadel/internal/repository/policy" -) - -type IAMLockoutPolicyReadModel struct { - LockoutPolicyReadModel -} - -func (rm *IAMLockoutPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *iam.LockoutPolicyAddedEvent: - rm.LockoutPolicyReadModel.AppendEvents(&e.LockoutPolicyAddedEvent) - case *iam.LockoutPolicyChangedEvent: - rm.LockoutPolicyReadModel.AppendEvents(&e.LockoutPolicyChangedEvent) - case *policy.LockoutPolicyAddedEvent, *policy.LockoutPolicyChangedEvent: - rm.LockoutPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/idp_config_model.go b/internal/query/idp_config_model.go deleted file mode 100644 index 38cf631b41..0000000000 --- a/internal/query/idp_config_model.go +++ /dev/null @@ -1,111 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/idpconfig" -) - -type IDPConfigReadModel struct { - eventstore.ReadModel - - State domain.IDPConfigState - ConfigID string - Name string - AutoRegister bool - StylingType domain.IDPConfigStylingType - ProviderType domain.IdentityProviderType - - OIDCConfig *OIDCConfigReadModel - JWTConfig *JWTConfigReadModel -} - -func NewIDPConfigReadModel(configID string) *IDPConfigReadModel { - return &IDPConfigReadModel{ - ConfigID: configID, - } -} - -func (rm *IDPConfigReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *idpconfig.IDPConfigAddedEvent: - rm.ReadModel.AppendEvents(e) - case *idpconfig.IDPConfigChangedEvent: - rm.ReadModel.AppendEvents(e) - case *idpconfig.IDPConfigDeactivatedEvent: - rm.ReadModel.AppendEvents(e) - case *idpconfig.IDPConfigReactivatedEvent: - rm.ReadModel.AppendEvents(e) - case *idpconfig.IDPConfigRemovedEvent: - rm.ReadModel.AppendEvents(e) - case *idpconfig.OIDCConfigAddedEvent: - rm.OIDCConfig = &OIDCConfigReadModel{} - rm.ReadModel.AppendEvents(e) - rm.OIDCConfig.AppendEvents(event) - case *idpconfig.OIDCConfigChangedEvent: - rm.ReadModel.AppendEvents(e) - rm.OIDCConfig.AppendEvents(event) - case *idpconfig.JWTConfigAddedEvent: - rm.JWTConfig = &JWTConfigReadModel{} - rm.ReadModel.AppendEvents(e) - rm.JWTConfig.AppendEvents(event) - case *idpconfig.JWTConfigChangedEvent: - rm.ReadModel.AppendEvents(e) - rm.JWTConfig.AppendEvents(event) - } - } -} - -func (rm *IDPConfigReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *idpconfig.IDPConfigAddedEvent: - rm.reduceConfigAddedEvent(e) - case *idpconfig.IDPConfigChangedEvent: - rm.reduceConfigChangedEvent(e) - case *idpconfig.IDPConfigDeactivatedEvent: - rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateInactive) - case *idpconfig.IDPConfigReactivatedEvent: - rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateActive) - case *idpconfig.IDPConfigRemovedEvent: - rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateRemoved) - } - } - - if rm.OIDCConfig != nil { - if err := rm.OIDCConfig.Reduce(); err != nil { - return err - } - } - if rm.JWTConfig != nil { - if err := rm.JWTConfig.Reduce(); err != nil { - return err - } - } - return rm.ReadModel.Reduce() -} - -func (rm *IDPConfigReadModel) reduceConfigAddedEvent(e *idpconfig.IDPConfigAddedEvent) { - rm.ConfigID = e.ConfigID - rm.Name = e.Name - rm.StylingType = e.StylingType - rm.State = domain.IDPConfigStateActive - rm.AutoRegister = e.AutoRegister -} - -func (rm *IDPConfigReadModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigChangedEvent) { - if e.Name != nil { - rm.Name = *e.Name - } - if e.StylingType != nil && e.StylingType.Valid() { - rm.StylingType = *e.StylingType - } - if e.AutoRegister != nil { - rm.AutoRegister = *e.AutoRegister - } -} - -func (rm *IDPConfigReadModel) reduceConfigStateChanged(configID string, state domain.IDPConfigState) { - rm.State = state -} diff --git a/internal/query/idp_configs_model.go b/internal/query/idp_configs_model.go deleted file mode 100644 index e712352eaa..0000000000 --- a/internal/query/idp_configs_model.go +++ /dev/null @@ -1,64 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/idpconfig" -) - -type IDPConfigsReadModel struct { - eventstore.ReadModel - - Configs []*IDPConfigReadModel -} - -func (rm *IDPConfigsReadModel) ConfigByID(id string) (idx int, config *IDPConfigReadModel) { - for idx, config = range rm.Configs { - if config.ConfigID == id { - return idx, config - } - } - return -1, nil -} - -func (rm *IDPConfigsReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *idpconfig.IDPConfigAddedEvent: - config := NewIDPConfigReadModel(e.ConfigID) - rm.Configs = append(rm.Configs, config) - config.AppendEvents(event) - case *idpconfig.IDPConfigChangedEvent: - _, config := rm.ConfigByID(e.ConfigID) - config.AppendEvents(e) - case *idpconfig.IDPConfigDeactivatedEvent: - _, config := rm.ConfigByID(e.ConfigID) - config.AppendEvents(e) - case *idpconfig.IDPConfigReactivatedEvent: - _, config := rm.ConfigByID(e.ConfigID) - config.AppendEvents(e) - case *idpconfig.OIDCConfigAddedEvent: - _, config := rm.ConfigByID(e.IDPConfigID) - config.AppendEvents(e) - case *idpconfig.OIDCConfigChangedEvent: - _, config := rm.ConfigByID(e.IDPConfigID) - config.AppendEvents(e) - case *idpconfig.IDPConfigRemovedEvent: - idx, _ := rm.ConfigByID(e.ConfigID) - if idx < 0 { - continue - } - copy(rm.Configs[idx:], rm.Configs[idx+1:]) - rm.Configs[len(rm.Configs)-1] = nil - rm.Configs = rm.Configs[:len(rm.Configs)-1] - } - } -} - -func (rm *IDPConfigsReadModel) Reduce() error { - for _, config := range rm.Configs { - if err := config.Reduce(); err != nil { - return err - } - } - return nil -} diff --git a/internal/query/jwt_config_model.go b/internal/query/jwt_config_model.go deleted file mode 100644 index 799fe0d08b..0000000000 --- a/internal/query/jwt_config_model.go +++ /dev/null @@ -1,47 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/idpconfig" -) - -type JWTConfigReadModel struct { - eventstore.ReadModel - - IDPConfigID string - JWTEndpoint string - Issuer string - KeysEndpoint string -} - -func (rm *JWTConfigReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *idpconfig.JWTConfigAddedEvent: - rm.reduceConfigAddedEvent(e) - case *idpconfig.JWTConfigChangedEvent: - rm.reduceConfigChangedEvent(e) - } - } - - return rm.ReadModel.Reduce() -} - -func (rm *JWTConfigReadModel) reduceConfigAddedEvent(e *idpconfig.JWTConfigAddedEvent) { - rm.IDPConfigID = e.IDPConfigID - rm.JWTEndpoint = e.JWTEndpoint - rm.Issuer = e.Issuer - rm.KeysEndpoint = e.KeysEndpoint -} - -func (rm *JWTConfigReadModel) reduceConfigChangedEvent(e *idpconfig.JWTConfigChangedEvent) { - if e.JWTEndpoint != nil { - rm.JWTEndpoint = *e.JWTEndpoint - } - if e.Issuer != nil { - rm.Issuer = *e.Issuer - } - if e.KeysEndpoint != nil { - rm.KeysEndpoint = *e.KeysEndpoint - } -} diff --git a/internal/query/member.go b/internal/query/member.go index 5de18e57b0..3a255ab99c 100644 --- a/internal/query/member.go +++ b/internal/query/member.go @@ -1,11 +1,9 @@ package query import ( - "context" "time" "github.com/caos/zitadel/internal/query/projection" - "github.com/caos/zitadel/internal/telemetry/tracing" sq "github.com/Masterminds/squirrel" ) @@ -63,19 +61,6 @@ type Member struct { AvatarURL string } -func (r *Queries) IAMMemberByID(ctx context.Context, iamID, userID string) (member *IAMMemberReadModel, err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - member = NewIAMMemberReadModel(iamID, userID) - err = r.eventstore.FilterToQueryReducer(ctx, member) - if err != nil { - return nil, err - } - - return member, nil -} - var ( memberTableAlias = table{ name: "members", diff --git a/internal/query/member_model.go b/internal/query/member_model.go deleted file mode 100644 index 0cdf5d7f9e..0000000000 --- a/internal/query/member_model.go +++ /dev/null @@ -1,35 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/member" -) - -//MemberReadModel represenets the default member view. -// It's computed from events. -type MemberReadModel struct { - eventstore.ReadModel - - UserID string - Roles []string -} - -//NewMemberReadModel is the default constructor of MemberReadModel -func NewMemberReadModel(userID string) *MemberReadModel { - return &MemberReadModel{ - UserID: userID, - } -} - -//Reduce extends eventstore.MemberReadModel -func (rm *MemberReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *member.MemberAddedEvent: - rm.Roles = e.Roles - case *member.MemberChangedEvent: - rm.Roles = e.Roles - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/member_roles.go b/internal/query/member_roles.go new file mode 100644 index 0000000000..740cfb10cc --- /dev/null +++ b/internal/query/member_roles.go @@ -0,0 +1,60 @@ +package query + +import ( + "context" + "strings" + + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/domain" +) + +func (q *Queries) GetIAMMemberRoles() []string { + roles := make([]string, 0) + for _, roleMap := range q.zitadelRoles { + if strings.HasPrefix(roleMap.Role, "IAM") { + roles = append(roles, roleMap.Role) + } + } + return roles +} + +func (q *Queries) GetOrgMemberRoles(isGlobal bool) []string { + roles := make([]string, 0) + for _, roleMap := range q.zitadelRoles { + if strings.HasPrefix(roleMap.Role, "ORG") { + roles = append(roles, roleMap.Role) + } + } + if isGlobal { + roles = append(roles, domain.RoleSelfManagementGlobal) + } + return roles +} + +func (q *Queries) GetProjectMemberRoles(ctx context.Context) ([]string, error) { + iam, err := q.IAMByID(ctx, domain.IAMID) + if err != nil { + return nil, err + } + roles := make([]string, 0) + global := authz.GetCtxData(ctx).OrgID == iam.GlobalOrgID + for _, roleMap := range q.zitadelRoles { + if strings.HasPrefix(roleMap.Role, "PROJECT") && !strings.HasPrefix(roleMap.Role, "PROJECT_GRANT") { + if global && !strings.HasSuffix(roleMap.Role, "GLOBAL") { + continue + } + roles = append(roles, roleMap.Role) + } + } + return roles, nil +} + +func (q *Queries) GetProjectGrantMemberRoles() []string { + roles := make([]string, 0) + for _, roleMap := range q.zitadelRoles { + if strings.HasPrefix(roleMap.Role, "PROJECT_GRANT") { + roles = append(roles, roleMap.Role) + } + } + return roles +} diff --git a/internal/query/members_model.go b/internal/query/members_model.go deleted file mode 100644 index 592bb7a359..0000000000 --- a/internal/query/members_model.go +++ /dev/null @@ -1,53 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/member" -) - -type MembersReadModel struct { - eventstore.ReadModel - - Members []*MemberReadModel -} - -func (rm *MembersReadModel) MemberByUserID(id string) (idx int, member *MemberReadModel) { - for idx, member = range rm.Members { - if member.UserID == id { - return idx, member - } - } - return -1, nil -} - -func (rm *MembersReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *member.MemberAddedEvent: - m := NewMemberReadModel(e.UserID) - rm.Members = append(rm.Members, m) - m.AppendEvents(e) - case *member.MemberChangedEvent: - _, m := rm.MemberByUserID(e.UserID) - m.AppendEvents(e) - case *member.MemberRemovedEvent: - idx, _ := rm.MemberByUserID(e.UserID) - if idx < 0 { - continue - } - copy(rm.Members[idx:], rm.Members[idx+1:]) - rm.Members[len(rm.Members)-1] = nil - rm.Members = rm.Members[:len(rm.Members)-1] - } - } -} - -func (rm *MembersReadModel) Reduce() (err error) { - for _, m := range rm.Members { - err = m.Reduce() - if err != nil { - return err - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/oidc_config_model.go b/internal/query/oidc_config_model.go deleted file mode 100644 index 5353d0d176..0000000000 --- a/internal/query/oidc_config_model.go +++ /dev/null @@ -1,71 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/crypto" - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/idpconfig" -) - -type OIDCConfigReadModel struct { - eventstore.ReadModel - - IDPConfigID string - ClientID string - ClientSecret *crypto.CryptoValue - Issuer string - AuthorizationEndpoint string - TokenEndpoint string - Scopes []string - IDPDisplayNameMapping domain.OIDCMappingField - UserNameMapping domain.OIDCMappingField -} - -func (rm *OIDCConfigReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *idpconfig.OIDCConfigAddedEvent: - rm.reduceConfigAddedEvent(e) - case *idpconfig.OIDCConfigChangedEvent: - rm.reduceConfigChangedEvent(e) - } - } - - return rm.ReadModel.Reduce() -} - -func (rm *OIDCConfigReadModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAddedEvent) { - rm.IDPConfigID = e.IDPConfigID - rm.ClientID = e.ClientID - rm.ClientSecret = e.ClientSecret - rm.Issuer = e.Issuer - rm.AuthorizationEndpoint = e.AuthorizationEndpoint - rm.TokenEndpoint = e.TokenEndpoint - rm.Scopes = e.Scopes - rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping - rm.UserNameMapping = e.UserNameMapping -} - -func (rm *OIDCConfigReadModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigChangedEvent) { - if e.ClientID != nil { - rm.ClientID = *e.ClientID - } - if e.Issuer != nil { - rm.Issuer = *e.Issuer - } - if e.AuthorizationEndpoint != nil { - rm.AuthorizationEndpoint = *e.AuthorizationEndpoint - } - if e.TokenEndpoint != nil { - rm.TokenEndpoint = *e.TokenEndpoint - } - if len(e.Scopes) > 0 { - rm.Scopes = e.Scopes - } - if e.IDPDisplayNameMapping != nil && e.IDPDisplayNameMapping.Valid() { - rm.IDPDisplayNameMapping = *e.IDPDisplayNameMapping - } - if e.UserNameMapping != nil && e.UserNameMapping.Valid() { - rm.UserNameMapping = *e.UserNameMapping - } -} diff --git a/internal/query/org_member_model.go b/internal/query/org_member_model.go deleted file mode 100644 index e06bc1eec9..0000000000 --- a/internal/query/org_member_model.go +++ /dev/null @@ -1,38 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" -) - -type OrgMembersReadModel struct { - MembersReadModel -} - -func (rm *OrgMembersReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.MemberAddedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberAddedEvent) - case *org.MemberChangedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberChangedEvent) - case *org.MemberRemovedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberRemovedEvent) - case *org.MemberCascadeRemovedEvent: - rm.MembersReadModel.AppendEvents(&e.MemberCascadeRemovedEvent) - } - } -} - -type OrgMemberReadModel MemberReadModel - -func (rm *OrgMemberReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.MemberAddedEvent: - rm.ReadModel.AppendEvents(&e.MemberAddedEvent) - case *org.MemberChangedEvent: - rm.ReadModel.AppendEvents(&e.MemberChangedEvent) - } - } -} diff --git a/internal/query/org_policy_label_model.go b/internal/query/org_policy_label_model.go deleted file mode 100644 index 27b19be80c..0000000000 --- a/internal/query/org_policy_label_model.go +++ /dev/null @@ -1,22 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgLabelPolicyReadModel struct{ LabelPolicyReadModel } - -func (rm *OrgLabelPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.LabelPolicyAddedEvent: - rm.LabelPolicyReadModel.AppendEvents(&e.LabelPolicyAddedEvent) - case *org.LabelPolicyChangedEvent: - rm.LabelPolicyReadModel.AppendEvents(&e.LabelPolicyChangedEvent) - case *policy.LabelPolicyAddedEvent, *policy.LabelPolicyChangedEvent: - rm.LabelPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/org_policy_login_model.go b/internal/query/org_policy_login_model.go deleted file mode 100644 index 9fff9f4490..0000000000 --- a/internal/query/org_policy_login_model.go +++ /dev/null @@ -1,22 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgLoginPolicyReadModel struct{ LoginPolicyReadModel } - -func (rm *OrgLoginPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.LoginPolicyAddedEvent: - rm.LoginPolicyReadModel.AppendEvents(&e.LoginPolicyAddedEvent) - case *org.LoginPolicyChangedEvent: - rm.LoginPolicyReadModel.AppendEvents(&e.LoginPolicyChangedEvent) - case *policy.LoginPolicyAddedEvent, *policy.LoginPolicyChangedEvent: - rm.LoginPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/org_policy_org_iam_model.go b/internal/query/org_policy_org_iam_model.go deleted file mode 100644 index 5b00483d1b..0000000000 --- a/internal/query/org_policy_org_iam_model.go +++ /dev/null @@ -1,20 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgOrgIAMPolicyReadModel struct{ OrgIAMPolicyReadModel } - -func (rm *OrgOrgIAMPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.OrgIAMPolicyAddedEvent: - rm.OrgIAMPolicyReadModel.AppendEvents(&e.OrgIAMPolicyAddedEvent) - case *policy.OrgIAMPolicyAddedEvent: - rm.OrgIAMPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/org_policy_password_age_model.go b/internal/query/org_policy_password_age_model.go deleted file mode 100644 index def930b6f2..0000000000 --- a/internal/query/org_policy_password_age_model.go +++ /dev/null @@ -1,24 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgPasswordAgePolicyReadModel struct { - PasswordAgePolicyReadModel -} - -func (rm *OrgPasswordAgePolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.PasswordAgePolicyAddedEvent: - rm.PasswordAgePolicyReadModel.AppendEvents(&e.PasswordAgePolicyAddedEvent) - case *org.PasswordAgePolicyChangedEvent: - rm.PasswordAgePolicyReadModel.AppendEvents(&e.PasswordAgePolicyChangedEvent) - case *policy.PasswordAgePolicyAddedEvent, *policy.PasswordAgePolicyChangedEvent: - rm.PasswordAgePolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/org_policy_password_complexity_model.go b/internal/query/org_policy_password_complexity_model.go deleted file mode 100644 index ff6f5329a4..0000000000 --- a/internal/query/org_policy_password_complexity_model.go +++ /dev/null @@ -1,24 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgPasswordComplexityPolicyReadModel struct { - PasswordComplexityPolicyReadModel -} - -func (rm *OrgPasswordComplexityPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.PasswordComplexityPolicyAddedEvent: - rm.PasswordComplexityPolicyReadModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent) - case *org.PasswordComplexityPolicyChangedEvent: - rm.PasswordComplexityPolicyReadModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent) - case *policy.PasswordComplexityPolicyAddedEvent, *policy.PasswordComplexityPolicyChangedEvent: - rm.PasswordComplexityPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/org_policy_password_lockout_model.go b/internal/query/org_policy_password_lockout_model.go deleted file mode 100644 index 4e0d65ff4f..0000000000 --- a/internal/query/org_policy_password_lockout_model.go +++ /dev/null @@ -1,24 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/org" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgPasswordLockoutPolicyReadModel struct { - LockoutPolicyReadModel -} - -func (rm *OrgPasswordLockoutPolicyReadModel) AppendEvents(events ...eventstore.Event) { - for _, event := range events { - switch e := event.(type) { - case *org.LockoutPolicyAddedEvent: - rm.LockoutPolicyReadModel.AppendEvents(&e.LockoutPolicyAddedEvent) - case *org.LockoutPolicyChangedEvent: - rm.LockoutPolicyReadModel.AppendEvents(&e.LockoutPolicyChangedEvent) - case *policy.LockoutPolicyAddedEvent, *policy.LockoutPolicyChangedEvent: - rm.LockoutPolicyReadModel.AppendEvents(e) - } - } -} diff --git a/internal/query/policy_label_model.go b/internal/query/policy_label_model.go deleted file mode 100644 index b7df0fc669..0000000000 --- a/internal/query/policy_label_model.go +++ /dev/null @@ -1,65 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/policy" -) - -type LabelPolicyReadModel struct { - eventstore.ReadModel - - PrimaryColor string - BackgroundColor string - WarnColor string - FontColor string - PrimaryColorDark string - BackgroundColorDark string - WarnColorDark string - FontColorDark string - IsActive bool -} - -func (rm *LabelPolicyReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *policy.LabelPolicyAddedEvent: - rm.PrimaryColor = e.PrimaryColor - rm.BackgroundColor = e.BackgroundColor - rm.FontColor = e.FontColor - rm.WarnColor = e.WarnColor - rm.PrimaryColorDark = e.PrimaryColorDark - rm.BackgroundColorDark = e.BackgroundColorDark - rm.FontColorDark = e.FontColorDark - rm.WarnColorDark = e.WarnColorDark - rm.IsActive = true - case *policy.LabelPolicyChangedEvent: - if e.PrimaryColor != nil { - rm.PrimaryColor = *e.PrimaryColor - } - if e.BackgroundColor != nil { - rm.BackgroundColor = *e.BackgroundColor - } - if e.WarnColor != nil { - rm.WarnColor = *e.WarnColor - } - if e.FontColor != nil { - rm.FontColor = *e.FontColor - } - if e.PrimaryColorDark != nil { - rm.PrimaryColorDark = *e.PrimaryColorDark - } - if e.BackgroundColorDark != nil { - rm.BackgroundColorDark = *e.BackgroundColorDark - } - if e.WarnColorDark != nil { - rm.WarnColorDark = *e.WarnColorDark - } - if e.FontColorDark != nil { - rm.FontColorDark = *e.FontColorDark - } - case *policy.LabelPolicyRemovedEvent: - rm.IsActive = false - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/policy_login_model.go b/internal/query/policy_login_model.go deleted file mode 100644 index b940280cd8..0000000000 --- a/internal/query/policy_login_model.go +++ /dev/null @@ -1,51 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/domain" - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/policy" -) - -type LoginPolicyReadModel struct { - eventstore.ReadModel - - AllowUserNamePassword bool - AllowRegister bool - AllowExternalIDP bool - ForceMFA bool - PasswordlessType domain.PasswordlessType - IsActive bool -} - -func (rm *LoginPolicyReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *policy.LoginPolicyAddedEvent: - rm.AllowUserNamePassword = e.AllowUserNamePassword - rm.AllowExternalIDP = e.AllowExternalIDP - rm.AllowRegister = e.AllowRegister - rm.ForceMFA = e.ForceMFA - rm.PasswordlessType = e.PasswordlessType - rm.IsActive = true - case *policy.LoginPolicyChangedEvent: - if e.AllowUserNamePassword != nil { - rm.AllowUserNamePassword = *e.AllowUserNamePassword - } - if e.AllowExternalIDP != nil { - rm.AllowExternalIDP = *e.AllowExternalIDP - } - if e.AllowRegister != nil { - rm.AllowRegister = *e.AllowRegister - } - if e.ForceMFA != nil { - rm.ForceMFA = *e.ForceMFA - } - if e.PasswordlessType != nil { - rm.PasswordlessType = *e.PasswordlessType - } - case *policy.LoginPolicyRemovedEvent: - rm.IsActive = false - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/policy_org_iam_model.go b/internal/query/policy_org_iam_model.go deleted file mode 100644 index 04774c92b2..0000000000 --- a/internal/query/policy_org_iam_model.go +++ /dev/null @@ -1,26 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/policy" -) - -type OrgIAMPolicyReadModel struct { - eventstore.ReadModel - - UserLoginMustBeDomain bool -} - -func (rm *OrgIAMPolicyReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *policy.OrgIAMPolicyAddedEvent: - rm.UserLoginMustBeDomain = e.UserLoginMustBeDomain - case *policy.OrgIAMPolicyChangedEvent: - if e.UserLoginMustBeDomain != nil { - rm.UserLoginMustBeDomain = *e.UserLoginMustBeDomain - } - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/policy_password_age_model.go b/internal/query/policy_password_age_model.go deleted file mode 100644 index 52afd6546b..0000000000 --- a/internal/query/policy_password_age_model.go +++ /dev/null @@ -1,31 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/policy" -) - -type PasswordAgePolicyReadModel struct { - eventstore.ReadModel - - ExpireWarnDays uint64 - MaxAgeDays uint64 -} - -func (rm *PasswordAgePolicyReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *policy.PasswordAgePolicyAddedEvent: - rm.ExpireWarnDays = e.ExpireWarnDays - rm.MaxAgeDays = e.MaxAgeDays - case *policy.PasswordAgePolicyChangedEvent: - if e.ExpireWarnDays != nil { - rm.ExpireWarnDays = *e.ExpireWarnDays - } - if e.MaxAgeDays != nil { - rm.MaxAgeDays = *e.MaxAgeDays - } - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/policy_password_complexity_model.go b/internal/query/policy_password_complexity_model.go deleted file mode 100644 index db17f74412..0000000000 --- a/internal/query/policy_password_complexity_model.go +++ /dev/null @@ -1,46 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/policy" -) - -type PasswordComplexityPolicyReadModel struct { - eventstore.ReadModel - - MinLength uint64 - HasLowercase bool - HasUpperCase bool - HasNumber bool - HasSymbol bool -} - -func (rm *PasswordComplexityPolicyReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *policy.PasswordComplexityPolicyAddedEvent: - rm.MinLength = e.MinLength - rm.HasLowercase = e.HasLowercase - rm.HasUpperCase = e.HasUppercase - rm.HasNumber = e.HasNumber - rm.HasSymbol = e.HasSymbol - case *policy.PasswordComplexityPolicyChangedEvent: - if e.MinLength != nil { - rm.MinLength = *e.MinLength - } - if e.HasLowercase != nil { - rm.HasLowercase = *e.HasLowercase - } - if e.HasUppercase != nil { - rm.HasUpperCase = *e.HasUppercase - } - if e.HasNumber != nil { - rm.HasNumber = *e.HasNumber - } - if e.HasSymbol != nil { - rm.HasSymbol = *e.HasSymbol - } - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/policy_password_lockout_model.go b/internal/query/policy_password_lockout_model.go deleted file mode 100644 index 9f235ca05e..0000000000 --- a/internal/query/policy_password_lockout_model.go +++ /dev/null @@ -1,31 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/policy" -) - -type LockoutPolicyReadModel struct { - eventstore.ReadModel - - MaxAttempts uint64 - ShowLockOutFailures bool -} - -func (rm *LockoutPolicyReadModel) Reduce() error { - for _, event := range rm.Events { - switch e := event.(type) { - case *policy.LockoutPolicyAddedEvent: - rm.MaxAttempts = e.MaxPasswordAttempts - rm.ShowLockOutFailures = e.ShowLockOutFailures - case *policy.LockoutPolicyChangedEvent: - if e.MaxPasswordAttempts != nil { - rm.MaxAttempts = *e.MaxPasswordAttempts - } - if e.ShowLockOutFailures != nil { - rm.ShowLockOutFailures = *e.ShowLockOutFailures - } - } - } - return rm.ReadModel.Reduce() -} diff --git a/internal/query/query.go b/internal/query/query.go index 23fb6f2511..c8c1aa492d 100644 --- a/internal/query/query.go +++ b/internal/query/query.go @@ -7,6 +7,10 @@ import ( "sync" "github.com/caos/logging" + "github.com/rakyll/statik/fs" + "golang.org/x/text/language" + + "github.com/caos/zitadel/internal/api/authz" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/eventstore" @@ -18,8 +22,6 @@ import ( "github.com/caos/zitadel/internal/repository/project" usr_repo "github.com/caos/zitadel/internal/repository/user" "github.com/caos/zitadel/internal/repository/usergrant" - "github.com/rakyll/statik/fs" - "golang.org/x/text/language" ) type Queries struct { @@ -34,13 +36,14 @@ type Queries struct { LoginTranslationFileContents map[string][]byte NotificationTranslationFileContents map[string][]byte supportedLangs []language.Tag + zitadelRoles []authz.RoleMapping } type Config struct { Eventstore types.SQLUser } -func StartQueries(ctx context.Context, es *eventstore.Eventstore, projections projection.Config, defaults sd.SystemDefaults, keyChan chan<- interface{}) (repo *Queries, err error) { +func StartQueries(ctx context.Context, es *eventstore.Eventstore, projections projection.Config, defaults sd.SystemDefaults, keyChan chan<- interface{}, zitadelRoles []authz.RoleMapping) (repo *Queries, err error) { sqlClient, err := projections.CRDB.Start() if err != nil { return nil, err @@ -61,6 +64,7 @@ func StartQueries(ctx context.Context, es *eventstore.Eventstore, projections pr NotificationDir: statikNotificationFS, LoginTranslationFileContents: make(map[string][]byte), NotificationTranslationFileContents: make(map[string][]byte), + zitadelRoles: zitadelRoles, } iam_repo.RegisterEventMappers(repo.eventstore) usr_repo.RegisterEventMappers(repo.eventstore) diff --git a/internal/query/user.go b/internal/query/user.go index d2128cccc0..d47f8d4b4b 100644 --- a/internal/query/user.go +++ b/internal/query/user.go @@ -13,7 +13,6 @@ import ( "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/query/projection" ) @@ -354,11 +353,6 @@ func (q *Queries) IsUserUnique(ctx context.Context, username, email, resourceOwn return scan(row) } -func (q *Queries) UserEvents(ctx context.Context, orgID, userID string, sequence uint64) ([]eventstore.Event, error) { - query := NewUserEventSearchQuery(userID, orgID, sequence) - return q.eventstore.Filter(ctx, query) -} - func (q *UserSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder { query = q.SearchRequest.toQuery(query) for _, q := range q.Queries { diff --git a/internal/query/user_grant.go b/internal/query/user_grant.go index c288cf0535..fbf4feb75b 100644 --- a/internal/query/user_grant.go +++ b/internal/query/user_grant.go @@ -185,14 +185,12 @@ var ( } ) -func (q *Queries) UserGrantByID(ctx context.Context, id string, queries ...SearchQuery) (*UserGrant, error) { +func (q *Queries) UserGrant(ctx context.Context, queries ...SearchQuery) (*UserGrant, error) { query, scan := prepareUserGrantQuery() for _, q := range queries { query = q.toQuery(query) } - stmt, args, err := query.Where(sq.Eq{ - UserGrantID.identifier(): id, - }).ToSql() + stmt, args, err := query.ToSql() if err != nil { return nil, errors.ThrowInternal(err, "QUERY-Fa1KW", "Errors.Query.SQLStatement") } diff --git a/internal/query/user_model.go b/internal/query/user_model.go deleted file mode 100644 index d6baeb6870..0000000000 --- a/internal/query/user_model.go +++ /dev/null @@ -1,67 +0,0 @@ -package query - -import ( - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/repository/user" -) - -type UserReadModel struct { - eventstore.ReadModel -} - -func NewUserReadModel(id string) *UserReadModel { - return &UserReadModel{ - ReadModel: eventstore.ReadModel{ - AggregateID: id, - }, - } -} - -func (rm *UserReadModel) AppendEvents(events ...eventstore.Event) { - rm.ReadModel.AppendEvents(events...) - for _, event := range events { - switch event.(type) { - // TODO: implement append events - } - } -} - -func (rm *UserReadModel) Reduce() (err error) { - for _, event := range rm.Events { - switch event.(type) { - //TODO: implement reduce - } - } - for _, reduce := range []func() error{ - rm.ReadModel.Reduce, - } { - if err = reduce(); err != nil { - return err - } - } - - return nil -} - -func (rm *UserReadModel) AppendAndReduce(events ...eventstore.Event) error { - rm.AppendEvents(events...) - return rm.Reduce() -} - -func (rm *UserReadModel) Query() *eventstore.SearchQueryBuilder { - return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). - AddQuery(). - AggregateTypes(user.AggregateType). - AggregateIDs(rm.AggregateID). - Builder() -} - -func NewUserEventSearchQuery(userID, orgID string, sequence uint64) *eventstore.SearchQueryBuilder { - return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). - ResourceOwner(orgID). - AddQuery(). - AggregateTypes(user.AggregateType). - AggregateIDs(userID). - SequenceGreater(sequence). - Builder() -} diff --git a/internal/query/zitadel_permission.go b/internal/query/zitadel_permission.go new file mode 100644 index 0000000000..0b7672a18f --- /dev/null +++ b/internal/query/zitadel_permission.go @@ -0,0 +1,42 @@ +package query + +import ( + "context" + + "github.com/caos/zitadel/internal/domain" +) + +func (q *Queries) MyZitadelPermissions(ctx context.Context, userID string) (*domain.Permissions, error) { + userIDQuery, err := NewMembershipUserIDQuery(userID) + if err != nil { + return nil, err + } + memberships, err := q.Memberships(ctx, &MembershipSearchQuery{ + Queries: []SearchQuery{userIDQuery}, + }) + if err != nil { + return nil, err + } + permissions := &domain.Permissions{Permissions: []string{}} + for _, membership := range memberships.Memberships { + for _, role := range membership.Roles { + permissions = q.mapRoleToPermission(permissions, membership, role) + } + } + return permissions, nil +} + +func (q *Queries) mapRoleToPermission(permissions *domain.Permissions, membership *Membership, role string) *domain.Permissions { + for _, mapping := range q.zitadelRoles { + if mapping.Role == role { + ctxID := "" + if membership.Project != nil { + ctxID = membership.Project.ProjectID + } else if membership.ProjectGrant != nil { + ctxID = membership.ProjectGrant.GrantID + } + permissions.AppendPermissions(ctxID, mapping.Permissions...) + } + } + return permissions +} diff --git a/internal/static/i18n/de.yaml b/internal/static/i18n/de.yaml index da93cbfefd..cd72d44a63 100644 --- a/internal/static/i18n/de.yaml +++ b/internal/static/i18n/de.yaml @@ -341,6 +341,7 @@ Errors: NotExisting: Identitäts Provider Konfiguration existiert nicht Changes: NotFound: Es konnte kein Änderungsverlauf gefunden werden + AuditRetention: Änderungsverlauf ist ausserhalb der Audit Log Retention Token: NotFound: Token konnte nicht gefunden werden UserSession: diff --git a/internal/static/i18n/en.yaml b/internal/static/i18n/en.yaml index 0abf4e838b..78aa331df4 100644 --- a/internal/static/i18n/en.yaml +++ b/internal/static/i18n/en.yaml @@ -341,6 +341,7 @@ Errors: NotExisting: Identity Provider Configuration doesn't exist Changes: NotFound: No history found + AuditRetention: History is outside of the Audit Log Retention Token: NotFound: Token not found UserSession: diff --git a/internal/static/i18n/it.yaml b/internal/static/i18n/it.yaml index 5113bf3f04..40c3aaead2 100644 --- a/internal/static/i18n/it.yaml +++ b/internal/static/i18n/it.yaml @@ -339,6 +339,7 @@ Errors: NotExisting: La configurazione del IDP non esiste Changes: NotFound: Nessuna storia trovata + AuditRetention: La storia è al di fuori della Ritenzione Audit Log Token: NotFound: Token non trovato UserSession: diff --git a/proto/zitadel/auth.proto b/proto/zitadel/auth.proto index c06b22c862..03903d2986 100644 --- a/proto/zitadel/auth.proto +++ b/proto/zitadel/auth.proto @@ -638,7 +638,9 @@ message ListMyUserChangesRequest { } message ListMyUserChangesResponse { - zitadel.v1.ListDetails details = 1; + reserved 1; + reserved "details"; + // zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) repeated zitadel.change.v1.Change result = 2; } diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto index 840bfcd310..385f181de4 100644 --- a/proto/zitadel/management.proto +++ b/proto/zitadel/management.proto @@ -2933,7 +2933,9 @@ message ListUserChangesRequest { } message ListUserChangesResponse { - zitadel.v1.ListDetails details = 1; + reserved 1; + reserved "details"; + // zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) repeated zitadel.change.v1.Change result = 2; } @@ -3449,7 +3451,9 @@ message ListOrgChangesRequest { } message ListOrgChangesResponse { - zitadel.v1.ListDetails details = 1; + reserved 1; + reserved "details"; + // zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) repeated zitadel.change.v1.Change result = 2; } @@ -3636,7 +3640,9 @@ message ListProjectChangesRequest { } message ListProjectChangesResponse { - zitadel.v1.ListDetails details = 1; + reserved 1; + reserved "details"; + // zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) repeated zitadel.change.v1.Change result = 2; } @@ -3843,7 +3849,9 @@ message ListAppChangesRequest { } message ListAppChangesResponse { - zitadel.v1.ListDetails details = 1; + reserved 1; + reserved "details"; + // zitadel.v1.ListDetails details = 1; was always returned empty (as we cannot get the necessary infos) repeated zitadel.change.v1.Change result = 2; }