mirror of
https://github.com/zitadel/zitadel.git
synced 2025-04-15 20:41:30 +00:00
feat: iam query (#3085)
* fix: only show factors with state ready * fix: get iam by id and clean up code * fix: get iam by id and clean up code * fix: remove unused code
This commit is contained in:
parent
37d8e23186
commit
01501c5087
@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
"github.com/caos/zitadel/internal/telemetry/metrics"
|
"github.com/caos/zitadel/internal/telemetry/metrics"
|
||||||
"github.com/caos/zitadel/internal/telemetry/metrics/otel"
|
"github.com/caos/zitadel/internal/telemetry/metrics/otel"
|
||||||
@ -46,7 +45,7 @@ type API struct {
|
|||||||
|
|
||||||
type health interface {
|
type health interface {
|
||||||
Health(ctx context.Context) error
|
Health(ctx context.Context) error
|
||||||
IAMByID(ctx context.Context, id string) (*iam_model.IAM, error)
|
IAMByID(ctx context.Context, id string) (*query.IAM, error)
|
||||||
VerifierClientID(ctx context.Context, appName string) (string, string, error)
|
VerifierClientID(ctx context.Context, appName string) (string, string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,10 +111,10 @@ func (a *API) healthHandler() http.Handler {
|
|||||||
if err != nil && !errors.IsNotFound(err) {
|
if err != nil && !errors.IsNotFound(err) {
|
||||||
return errors.ThrowPreconditionFailed(err, "API-dsgT2", "IAM SETUP CHECK FAILED")
|
return errors.ThrowPreconditionFailed(err, "API-dsgT2", "IAM SETUP CHECK FAILED")
|
||||||
}
|
}
|
||||||
if iam == nil || iam.SetUpStarted < domain.StepCount-1 {
|
if iam == nil || iam.SetupStarted < domain.StepCount-1 {
|
||||||
return errors.ThrowPreconditionFailed(nil, "API-HBfs3", "IAM NOT SET UP")
|
return errors.ThrowPreconditionFailed(nil, "API-HBfs3", "IAM NOT SET UP")
|
||||||
}
|
}
|
||||||
if iam.SetUpDone < domain.StepCount-1 {
|
if iam.SetupDone < domain.StepCount-1 {
|
||||||
return errors.ThrowPreconditionFailed(nil, "API-DASs2", "IAM SETUP RUNNING")
|
return errors.ThrowPreconditionFailed(nil, "API-DASs2", "IAM SETUP RUNNING")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) GetSupportedLanguages(ctx context.Context, req *auth_pb.GetSupportedLanguagesRequest) (*auth_pb.GetSupportedLanguagesResponse, error) {
|
func (s *Server) GetSupportedLanguages(ctx context.Context, req *auth_pb.GetSupportedLanguagesRequest) (*auth_pb.GetSupportedLanguagesResponse, error) {
|
||||||
langs, err := s.repo.Languages(ctx)
|
langs, err := s.query.Languages(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) GetSupportedLanguages(ctx context.Context, req *mgmt_pb.GetSupportedLanguagesRequest) (*mgmt_pb.GetSupportedLanguagesResponse, error) {
|
func (s *Server) GetSupportedLanguages(ctx context.Context, req *mgmt_pb.GetSupportedLanguagesRequest) (*mgmt_pb.GetSupportedLanguagesResponse, error) {
|
||||||
langs, err := s.org.Languages(ctx)
|
langs, err := s.query.Languages(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ func (s *Server) SetPrimaryOrgDomain(ctx context.Context, req *mgmt_pb.SetPrimar
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ListOrgMemberRoles(ctx context.Context, req *mgmt_pb.ListOrgMemberRolesRequest) (*mgmt_pb.ListOrgMemberRolesResponse, error) {
|
func (s *Server) ListOrgMemberRoles(ctx context.Context, req *mgmt_pb.ListOrgMemberRolesRequest) (*mgmt_pb.ListOrgMemberRolesResponse, error) {
|
||||||
iam, err := s.iam.IAMByID(ctx, domain.IAMID)
|
iam, err := s.query.IAMByID(ctx, domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ type Server struct {
|
|||||||
project repository.ProjectRepository
|
project repository.ProjectRepository
|
||||||
org repository.OrgRepository
|
org repository.OrgRepository
|
||||||
user repository.UserRepository
|
user repository.UserRepository
|
||||||
iam repository.IamRepository
|
|
||||||
systemDefaults systemdefaults.SystemDefaults
|
systemDefaults systemdefaults.SystemDefaults
|
||||||
assetAPIPrefix string
|
assetAPIPrefix string
|
||||||
}
|
}
|
||||||
@ -42,7 +41,6 @@ func CreateServer(command *command.Commands, query *query.Queries, repo reposito
|
|||||||
project: repo,
|
project: repo,
|
||||||
org: repo,
|
org: repo,
|
||||||
user: repo,
|
user: repo,
|
||||||
iam: repo,
|
|
||||||
systemDefaults: sd,
|
systemDefaults: sd,
|
||||||
assetAPIPrefix: assetAPIPrefix,
|
assetAPIPrefix: assetAPIPrefix,
|
||||||
}
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package eventstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/caos/logging"
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
|
||||||
"github.com/caos/zitadel/internal/query"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/iam/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IAMRepository struct {
|
|
||||||
IAMID string
|
|
||||||
LoginDir http.FileSystem
|
|
||||||
|
|
||||||
IAMV2QuerySide *query.Queries
|
|
||||||
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) GetIAM(ctx context.Context) (*model.IAM, error) {
|
|
||||||
return repo.IAMV2QuerySide.IAMByID(ctx, repo.IAMID)
|
|
||||||
}
|
|
@ -3,9 +3,6 @@ package eventsourcing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
|
||||||
"github.com/rakyll/statik/fs"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/eventstore"
|
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/eventstore"
|
||||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/spooler"
|
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/spooler"
|
||||||
@ -44,7 +41,6 @@ type EsRepository struct {
|
|||||||
eventstore.UserSessionRepo
|
eventstore.UserSessionRepo
|
||||||
eventstore.UserGrantRepo
|
eventstore.UserGrantRepo
|
||||||
eventstore.OrgRepository
|
eventstore.OrgRepository
|
||||||
eventstore.IAMRepository
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, authZ authz.Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, authZRepo *authz_repo.EsRepository, esV2 *es2.Eventstore) (*EsRepository, error) {
|
||||||
@ -76,9 +72,6 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
statikLoginFS, err := fs.NewWithNamespace("login")
|
|
||||||
logging.Log("CONFI-20opp").OnError(err).Panic("unable to start login statik dir")
|
|
||||||
|
|
||||||
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults, queries)
|
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults, queries)
|
||||||
|
|
||||||
userRepo := eventstore.UserRepo{
|
userRepo := eventstore.UserRepo{
|
||||||
@ -161,11 +154,6 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
|||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
Query: queries,
|
Query: queries,
|
||||||
},
|
},
|
||||||
eventstore.IAMRepository{
|
|
||||||
IAMID: systemDefaults.IamID,
|
|
||||||
LoginDir: statikLoginFS,
|
|
||||||
IAMV2QuerySide: queries,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/iam/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IAMRepository interface {
|
|
||||||
Languages(ctx context.Context) ([]language.Tag, error)
|
|
||||||
GetIAM(ctx context.Context) (*model.IAM, error)
|
|
||||||
}
|
|
@ -13,6 +13,5 @@ type Repository interface {
|
|||||||
UserSessionRepository
|
UserSessionRepository
|
||||||
UserGrantRepository
|
UserGrantRepository
|
||||||
OrgRepository
|
OrgRepository
|
||||||
IAMRepository
|
|
||||||
RefreshTokenRepository
|
RefreshTokenRepository
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package eventsourcing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/logging"
|
|
||||||
"github.com/caos/zitadel/internal/cache"
|
|
||||||
"github.com/caos/zitadel/internal/cache/config"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IAMCache struct {
|
|
||||||
iamCache cache.Cache
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartCache(conf *config.CacheConfig) (*IAMCache, error) {
|
|
||||||
iamCache, err := conf.Config.NewCache()
|
|
||||||
logging.Log("EVENT-9siew").OnError(err).Panic("unable to create iam cache")
|
|
||||||
|
|
||||||
return &IAMCache{iamCache: iamCache}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *IAMCache) getIAM(ID string) *model.IAM {
|
|
||||||
user := &model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: ID}}
|
|
||||||
if err := c.iamCache.Get(ID, user); err != nil {
|
|
||||||
logging.Log("EVENT-slo9x").WithError(err).Debug("error in getting cache")
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *IAMCache) cacheIAM(iam *model.IAM) {
|
|
||||||
err := c.iamCache.Set(iam.AggregateID, iam)
|
|
||||||
if err != nil {
|
|
||||||
logging.Log("EVENT-os03w").WithError(err).Debug("error in setting iam cache")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package eventsourcing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/cache/config"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IAMConfig struct {
|
|
||||||
v1.Eventstore
|
|
||||||
Cache *config.CacheConfig
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package eventsourcing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/errors"
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IAMByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, error) {
|
|
||||||
if id == "" {
|
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-0soe4", "Errors.IAM.IDMissing")
|
|
||||||
}
|
|
||||||
return IAMQuery(latestSequence).
|
|
||||||
AggregateIDFilter(id), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func IAMQuery(latestSequence uint64) *es_models.SearchQuery {
|
|
||||||
return es_models.NewSearchQuery().
|
|
||||||
AggregateTypeFilter(model.IAMAggregate).
|
|
||||||
LatestSequenceFilter(latestSequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IAMAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, iam *model.IAM) (*es_models.Aggregate, error) {
|
|
||||||
if iam == nil {
|
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-lo04e", "Errors.Internal")
|
|
||||||
}
|
|
||||||
return aggCreator.NewAggregate(ctx, iam.AggregateID, model.IAMAggregate, model.IAMVersion, iam.Sequence)
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
"github.com/caos/zitadel/internal/view/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetCustomTexts(db *gorm.DB, table string, aggregateID, template, lang string) ([]*model.CustomTextView, error) {
|
|
||||||
texts := make([]*model.CustomTextView, 0)
|
|
||||||
queries := []*iam_model.CustomTextSearchQuery{
|
|
||||||
{
|
|
||||||
Key: iam_model.CustomTextSearchKeyAggregateID,
|
|
||||||
Value: aggregateID,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: iam_model.CustomTextSearchKeyTemplate,
|
|
||||||
Value: template,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: iam_model.CustomTextSearchKeyLanguage,
|
|
||||||
Value: lang,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
query := repository.PrepareSearchQuery(table, model.CustomTextSearchRequest{Queries: queries})
|
|
||||||
_, err := query(db, &texts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return texts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCustomTextsByAggregateIDAndTemplate(db *gorm.DB, table string, aggregateID, template string) ([]*model.CustomTextView, error) {
|
|
||||||
texts := make([]*model.CustomTextView, 0)
|
|
||||||
queries := []*iam_model.CustomTextSearchQuery{
|
|
||||||
{
|
|
||||||
Key: iam_model.CustomTextSearchKeyAggregateID,
|
|
||||||
Value: aggregateID,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: iam_model.CustomTextSearchKeyTemplate,
|
|
||||||
Value: template,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
query := repository.PrepareSearchQuery(table, model.CustomTextSearchRequest{Queries: queries})
|
|
||||||
_, err := query(db, &texts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return texts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CustomTextByIDs(db *gorm.DB, table, aggregateID, template, lang, key string) (*model.CustomTextView, error) {
|
|
||||||
customText := new(model.CustomTextView)
|
|
||||||
aggregateIDQuery := &model.CustomTextSearchQuery{Key: iam_model.CustomTextSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
|
||||||
textTypeQuery := &model.CustomTextSearchQuery{Key: iam_model.CustomTextSearchKeyTemplate, Value: template, Method: domain.SearchMethodEquals}
|
|
||||||
languageQuery := &model.CustomTextSearchQuery{Key: iam_model.CustomTextSearchKeyLanguage, Value: lang, Method: domain.SearchMethodEquals}
|
|
||||||
keyQuery := &model.CustomTextSearchQuery{Key: iam_model.CustomTextSearchKeyKey, Value: key, Method: domain.SearchMethodEquals}
|
|
||||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery, textTypeQuery, languageQuery, keyQuery)
|
|
||||||
err := query(db, customText)
|
|
||||||
if caos_errs.IsNotFound(err) {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-8nUU3", "Errors.CustomCustomText.NotExisting")
|
|
||||||
}
|
|
||||||
return customText, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutCustomText(db *gorm.DB, table string, customText *model.CustomTextView) error {
|
|
||||||
save := repository.PrepareSave(table)
|
|
||||||
return save(db, customText)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteCustomText(db *gorm.DB, table, aggregateID, template, lang, key string) error {
|
|
||||||
aggregateIDSearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyAggregateID), Value: aggregateID}
|
|
||||||
templateSearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyTemplate), Value: template}
|
|
||||||
languageSearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyLanguage), Value: lang}
|
|
||||||
keySearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyKey), Value: key}
|
|
||||||
delete := repository.PrepareDeleteByKeys(table, aggregateIDSearch, templateSearch, keySearch, languageSearch)
|
|
||||||
return delete(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteCustomTextTemplate(db *gorm.DB, table, aggregateID, template, lang string) error {
|
|
||||||
aggregateIDSearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyAggregateID), Value: aggregateID}
|
|
||||||
templateSearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyTemplate), Value: template}
|
|
||||||
languageSearch := repository.Key{Key: model.CustomTextSearchKey(iam_model.CustomTextSearchKeyLanguage), Value: lang}
|
|
||||||
delete := repository.PrepareDeleteByKeys(table, aggregateIDSearch, templateSearch, languageSearch)
|
|
||||||
return delete(db)
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
"github.com/caos/zitadel/internal/view/repository"
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IAMMemberByIDs(db *gorm.DB, table, orgID, userID string) (*model.IAMMemberView, error) {
|
|
||||||
member := new(model.IAMMemberView)
|
|
||||||
|
|
||||||
iamIDQuery := &model.IAMMemberSearchQuery{Key: iam_model.IAMMemberSearchKeyIamID, Value: orgID, Method: domain.SearchMethodEquals}
|
|
||||||
userIDQuery := &model.IAMMemberSearchQuery{Key: iam_model.IAMMemberSearchKeyUserID, Value: userID, Method: domain.SearchMethodEquals}
|
|
||||||
query := repository.PrepareGetByQuery(table, iamIDQuery, userIDQuery)
|
|
||||||
err := query(db, member)
|
|
||||||
if caos_errs.IsNotFound(err) {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Ahq2s", "Errors.IAM.MemberNotExisting")
|
|
||||||
}
|
|
||||||
return member, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SearchIAMMembers(db *gorm.DB, table string, req *iam_model.IAMMemberSearchRequest) ([]*model.IAMMemberView, uint64, error) {
|
|
||||||
members := make([]*model.IAMMemberView, 0)
|
|
||||||
query := repository.PrepareSearchQuery(table, model.IAMMemberSearchRequest{Limit: req.Limit, Offset: req.Offset, Queries: req.Queries})
|
|
||||||
count, err := query(db, &members)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
return members, count, nil
|
|
||||||
}
|
|
||||||
func IAMMembersByUserID(db *gorm.DB, table string, userID string) ([]*model.IAMMemberView, error) {
|
|
||||||
members := make([]*model.IAMMemberView, 0)
|
|
||||||
queries := []*iam_model.IAMMemberSearchQuery{
|
|
||||||
{
|
|
||||||
Key: iam_model.IAMMemberSearchKeyUserID,
|
|
||||||
Value: userID,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
query := repository.PrepareSearchQuery(table, model.IAMMemberSearchRequest{Queries: queries})
|
|
||||||
_, err := query(db, &members)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return members, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutIAMMember(db *gorm.DB, table string, role *model.IAMMemberView) error {
|
|
||||||
save := repository.PrepareSave(table)
|
|
||||||
return save(db, role)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutIAMMembers(db *gorm.DB, table string, members ...*model.IAMMemberView) error {
|
|
||||||
save := repository.PrepareBulkSave(table)
|
|
||||||
m := make([]interface{}, len(members))
|
|
||||||
for i, member := range members {
|
|
||||||
m[i] = member
|
|
||||||
}
|
|
||||||
return save(db, m...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteIAMMember(db *gorm.DB, table, orgID, userID string) error {
|
|
||||||
member, err := IAMMemberByIDs(db, table, orgID, userID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
delete := repository.PrepareDeleteByObject(table, member)
|
|
||||||
return delete(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteIAMMembersByUserID(db *gorm.DB, table, userID string) error {
|
|
||||||
delete := repository.PrepareDeleteByKey(table, model.IAMMemberSearchKey(iam_model.IAMMemberSearchKeyUserID), userID)
|
|
||||||
return delete(db)
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
"github.com/caos/zitadel/internal/view/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetMessageTexts(db *gorm.DB, table string, aggregateID string) ([]*model.MessageTextView, error) {
|
|
||||||
texts := make([]*model.MessageTextView, 0)
|
|
||||||
queries := []*iam_model.MessageTextSearchQuery{
|
|
||||||
{
|
|
||||||
Key: iam_model.MessageTextSearchKeyAggregateID,
|
|
||||||
Value: aggregateID,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
query := repository.PrepareSearchQuery(table, model.MessageTextSearchRequest{Queries: queries})
|
|
||||||
_, err := query(db, &texts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return texts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMessageTextByIDs(db *gorm.DB, table, aggregateID, textType, lang string) (*model.MessageTextView, error) {
|
|
||||||
mailText := new(model.MessageTextView)
|
|
||||||
aggregateIDQuery := &model.MessageTextSearchQuery{Key: iam_model.MessageTextSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
|
||||||
textTypeQuery := &model.MessageTextSearchQuery{Key: iam_model.MessageTextSearchKeyMessageTextType, Value: textType, Method: domain.SearchMethodEquals}
|
|
||||||
languageQuery := &model.MessageTextSearchQuery{Key: iam_model.MessageTextSearchKeyLanguage, Value: lang, Method: domain.SearchMethodEquals}
|
|
||||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery, textTypeQuery, languageQuery)
|
|
||||||
err := query(db, mailText)
|
|
||||||
if caos_errs.IsNotFound(err) {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-IiJjm", "Errors.IAM.CustomMessageText.NotExisting")
|
|
||||||
}
|
|
||||||
return mailText, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutMessageText(db *gorm.DB, table string, mailText *model.MessageTextView) error {
|
|
||||||
save := repository.PrepareSave(table)
|
|
||||||
return save(db, mailText)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteMessageText(db *gorm.DB, table, aggregateID, textType, lang string) error {
|
|
||||||
aggregateIDSearch := repository.Key{Key: model.MessageTextSearchKey(iam_model.MessageTextSearchKeyAggregateID), Value: aggregateID}
|
|
||||||
textTypeSearch := repository.Key{Key: model.MessageTextSearchKey(iam_model.MessageTextSearchKeyMessageTextType), Value: textType}
|
|
||||||
languageSearch := repository.Key{Key: model.MessageTextSearchKey(iam_model.MessageTextSearchKeyLanguage), Value: lang}
|
|
||||||
delete := repository.PrepareDeleteByKeys(table, aggregateIDSearch, textTypeSearch, languageSearch)
|
|
||||||
return delete(db)
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
"github.com/caos/zitadel/internal/view/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetMetadataList(db *gorm.DB, table string, aggregateID string) ([]*model.MetadataView, error) {
|
|
||||||
metadatas := make([]*model.MetadataView, 0)
|
|
||||||
queries := []*domain.MetadataSearchQuery{
|
|
||||||
{
|
|
||||||
Key: domain.MetadataSearchKeyAggregateID,
|
|
||||||
Value: aggregateID,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
query := repository.PrepareSearchQuery(table, model.MetadataSearchRequest{Queries: queries})
|
|
||||||
_, err := query(db, &metadatas)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return metadatas, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func MetadataByKey(db *gorm.DB, table, aggregateID, key string) (*model.MetadataView, error) {
|
|
||||||
metadata := new(model.MetadataView)
|
|
||||||
aggregateIDQuery := &model.MetadataSearchQuery{Key: domain.MetadataSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
|
||||||
keyQuery := &model.MetadataSearchQuery{Key: domain.MetadataSearchKeyKey, Value: key, Method: domain.SearchMethodEquals}
|
|
||||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery, keyQuery)
|
|
||||||
err := query(db, metadata)
|
|
||||||
if caos_errs.IsNotFound(err) {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-m0pes", "Errors.Metadata.NotExisting")
|
|
||||||
}
|
|
||||||
return metadata, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func MetadataByKeyAndResourceOwner(db *gorm.DB, table, aggregateID, resourceOwner, key string) (*model.MetadataView, error) {
|
|
||||||
metadata := new(model.MetadataView)
|
|
||||||
aggregateIDQuery := &model.MetadataSearchQuery{Key: domain.MetadataSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
|
||||||
resourceOwnerQuery := &model.MetadataSearchQuery{Key: domain.MetadataSearchKeyResourceOwner, Value: resourceOwner, Method: domain.SearchMethodEquals}
|
|
||||||
keyQuery := &model.MetadataSearchQuery{Key: domain.MetadataSearchKeyKey, Value: key, Method: domain.SearchMethodEquals}
|
|
||||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery, resourceOwnerQuery, keyQuery)
|
|
||||||
err := query(db, metadata)
|
|
||||||
if caos_errs.IsNotFound(err) {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-29kkd", "Errors.Metadata.NotExisting")
|
|
||||||
}
|
|
||||||
return metadata, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SearchMetadata(db *gorm.DB, table string, req *domain.MetadataSearchRequest) ([]*model.MetadataView, uint64, error) {
|
|
||||||
metadata := make([]*model.MetadataView, 0)
|
|
||||||
query := repository.PrepareSearchQuery(table, model.MetadataSearchRequest{Limit: req.Limit, Offset: req.Offset, Queries: req.Queries})
|
|
||||||
count, err := query(db, &metadata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
return metadata, count, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutMetadata(db *gorm.DB, table string, customText *model.MetadataView) error {
|
|
||||||
save := repository.PrepareSave(table)
|
|
||||||
return save(db, customText)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteMetadata(db *gorm.DB, table, aggregateID, key string) error {
|
|
||||||
aggregateIDQuery := repository.Key{Key: model.MetadataSearchKey(domain.MetadataSearchKeyAggregateID), Value: aggregateID}
|
|
||||||
keyQuery := repository.Key{Key: model.MetadataSearchKey(domain.MetadataSearchKeyKey), Value: key}
|
|
||||||
deleteMD := repository.PrepareDeleteByKeys(table, aggregateIDQuery, keyQuery)
|
|
||||||
return deleteMD(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteMetadataByAggregateID(db *gorm.DB, table, aggregateID string) error {
|
|
||||||
aggregateIDQuery := repository.Key{Key: model.MetadataSearchKey(domain.MetadataSearchKeyAggregateID), Value: aggregateID}
|
|
||||||
deleteMD := repository.PrepareDeleteByKeys(table, aggregateIDQuery)
|
|
||||||
return deleteMD(db)
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package eventstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/query"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IAMRepository struct {
|
|
||||||
IAMV2Query *query.Queries
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *IAMRepository) IAMByID(ctx context.Context, id string) (*iam_model.IAM, error) {
|
|
||||||
return repo.IAMV2Query.IAMByID(ctx, id)
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
|
||||||
org_model "github.com/caos/zitadel/internal/org/model"
|
org_model "github.com/caos/zitadel/internal/org/model"
|
||||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||||
org_view "github.com/caos/zitadel/internal/org/repository/view"
|
org_view "github.com/caos/zitadel/internal/org/repository/view"
|
||||||
@ -38,18 +37,6 @@ type OrgRepository struct {
|
|||||||
supportedLangs []language.Tag
|
supportedLangs []language.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *OrgRepository) 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 *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error) {
|
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)
|
changes, err := repo.getOrgChanges(ctx, id, lastSequence, limit, sortAscending, auditLogRetention)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,7 +24,6 @@ type EsRepository struct {
|
|||||||
eventstore.OrgRepository
|
eventstore.OrgRepository
|
||||||
eventstore.ProjectRepo
|
eventstore.ProjectRepo
|
||||||
eventstore.UserRepo
|
eventstore.UserRepo
|
||||||
eventstore.IAMRepository
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string, queries *query.Queries, staticStorage static.Storage) (*EsRepository, error) {
|
func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string, queries *query.Queries, staticStorage static.Storage) (*EsRepository, error) {
|
||||||
@ -55,8 +54,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string, querie
|
|||||||
NotificationTranslationFileContents: make(map[string][]byte),
|
NotificationTranslationFileContents: make(map[string][]byte),
|
||||||
Query: queries,
|
Query: queries,
|
||||||
},
|
},
|
||||||
ProjectRepo: eventstore.ProjectRepo{es, roles, systemDefaults.IamID, assetsAPI, queries},
|
ProjectRepo: eventstore.ProjectRepo{es, roles, systemDefaults.IamID, assetsAPI, queries},
|
||||||
UserRepo: eventstore.UserRepo{es, queries, systemDefaults, assetsAPI},
|
UserRepo: eventstore.UserRepo{es, queries, systemDefaults, assetsAPI},
|
||||||
IAMRepository: eventstore.IAMRepository{IAMV2Query: queries},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IamRepository interface {
|
|
||||||
IAMByID(ctx context.Context, id string) (*iam_model.IAM, error)
|
|
||||||
}
|
|
@ -4,13 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
|
|
||||||
org_model "github.com/caos/zitadel/internal/org/model"
|
org_model "github.com/caos/zitadel/internal/org/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrgRepository interface {
|
type OrgRepository interface {
|
||||||
Languages(ctx context.Context) ([]language.Tag, error)
|
|
||||||
OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error)
|
OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error)
|
||||||
|
|
||||||
GetOrgMemberRoles(isGlobal bool) []string
|
GetOrgMemberRoles(isGlobal bool) []string
|
||||||
|
@ -4,5 +4,4 @@ type Repository interface {
|
|||||||
ProjectRepository
|
ProjectRepository
|
||||||
OrgRepository
|
OrgRepository
|
||||||
UserRepository
|
UserRepository
|
||||||
IamRepository
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (v *View) MessageTextByIDs(aggregateID, textType, lang, messageTextTableVar string) (*model.MessageTextView, error) {
|
|
||||||
return view.GetMessageTextByIDs(v.Db, messageTextTableVar, aggregateID, textType, lang)
|
|
||||||
}
|
|
116
internal/query/iam.go
Normal file
116
internal/query/iam.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
errs "errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/query/projection"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
iamTable = table{
|
||||||
|
name: projection.IAMProjectionTable,
|
||||||
|
}
|
||||||
|
IAMColumnID = Column{
|
||||||
|
name: projection.IAMColumnID,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
IAMColumnChangeDate = Column{
|
||||||
|
name: projection.IAMColumnChangeDate,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
IAMColumnSequence = Column{
|
||||||
|
name: projection.IAMColumnSequence,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
IAMColumnGlobalOrgID = Column{
|
||||||
|
name: projection.IAMColumnGlobalOrgID,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
IAMColumnProjectID = Column{
|
||||||
|
name: projection.IAMColumnProjectID,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
IAMColumnSetupStarted = Column{
|
||||||
|
name: projection.IAMColumnSetUpStarted,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
IAMColumnSetupDone = Column{
|
||||||
|
name: projection.IAMColumnSetUpDone,
|
||||||
|
table: iamTable,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type IAM struct {
|
||||||
|
ID string
|
||||||
|
ChangeDate time.Time
|
||||||
|
Sequence uint64
|
||||||
|
|
||||||
|
GlobalOrgID string
|
||||||
|
IAMProjectID string
|
||||||
|
SetupStarted domain.Step
|
||||||
|
SetupDone domain.Step
|
||||||
|
}
|
||||||
|
|
||||||
|
type IAMSearchQueries struct {
|
||||||
|
SearchRequest
|
||||||
|
Queries []SearchQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *IAMSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||||
|
query = q.SearchRequest.toQuery(query)
|
||||||
|
for _, q := range q.Queries {
|
||||||
|
query = q.toQuery(query)
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) IAMByID(ctx context.Context, id string) (*IAM, error) {
|
||||||
|
stmt, scan := prepareIAMQuery()
|
||||||
|
query, args, err := stmt.Where(sq.Eq{
|
||||||
|
IAMColumnID.identifier(): id,
|
||||||
|
}).ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "QUERY-d9ngs", "Errors.Query.SQLStatement")
|
||||||
|
}
|
||||||
|
|
||||||
|
row := q.client.QueryRowContext(ctx, query, args...)
|
||||||
|
return scan(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareIAMQuery() (sq.SelectBuilder, func(*sql.Row) (*IAM, error)) {
|
||||||
|
return sq.Select(
|
||||||
|
IAMColumnID.identifier(),
|
||||||
|
IAMColumnChangeDate.identifier(),
|
||||||
|
IAMColumnSequence.identifier(),
|
||||||
|
IAMColumnGlobalOrgID.identifier(),
|
||||||
|
IAMColumnProjectID.identifier(),
|
||||||
|
IAMColumnSetupStarted.identifier(),
|
||||||
|
IAMColumnSetupDone.identifier(),
|
||||||
|
).
|
||||||
|
From(iamTable.identifier()).PlaceholderFormat(sq.Dollar),
|
||||||
|
func(row *sql.Row) (*IAM, error) {
|
||||||
|
o := new(IAM)
|
||||||
|
err := row.Scan(
|
||||||
|
&o.ID,
|
||||||
|
&o.ChangeDate,
|
||||||
|
&o.Sequence,
|
||||||
|
&o.GlobalOrgID,
|
||||||
|
&o.IAMProjectID,
|
||||||
|
&o.SetupStarted,
|
||||||
|
&o.SetupDone,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
if errs.Is(err, sql.ErrNoRows) {
|
||||||
|
return nil, errors.ThrowNotFound(err, "QUERY-n0wng", "Errors.IAM.NotFound")
|
||||||
|
}
|
||||||
|
return nil, errors.ThrowInternal(err, "QUERY-d9nw", "Errors.Internal")
|
||||||
|
}
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
}
|
124
internal/query/iam_test.go
Normal file
124
internal/query/iam_test.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_IAMPrepares(t *testing.T) {
|
||||||
|
type want struct {
|
||||||
|
sqlExpectations sqlExpectation
|
||||||
|
err checkErr
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
prepare interface{}
|
||||||
|
want want
|
||||||
|
object interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "prepareIAMQuery no result",
|
||||||
|
prepare: prepareIAMQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQueries(
|
||||||
|
regexp.QuoteMeta(`SELECT zitadel.projections.iam.id,`+
|
||||||
|
` zitadel.projections.iam.change_date,`+
|
||||||
|
` zitadel.projections.iam.sequence,`+
|
||||||
|
` zitadel.projections.iam.global_org_id,`+
|
||||||
|
` zitadel.projections.iam.iam_project_id,`+
|
||||||
|
` zitadel.projections.iam.setup_started,`+
|
||||||
|
` zitadel.projections.iam.setup_done`+
|
||||||
|
` FROM zitadel.projections.iam`),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
err: func(err error) (error, bool) {
|
||||||
|
if !errs.IsNotFound(err) {
|
||||||
|
return fmt.Errorf("err should be zitadel.NotFoundError got: %w", err), false
|
||||||
|
}
|
||||||
|
return nil, true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
object: (*IAM)(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prepareIAMQuery found",
|
||||||
|
prepare: prepareIAMQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQuery(
|
||||||
|
regexp.QuoteMeta(`SELECT zitadel.projections.iam.id,`+
|
||||||
|
` zitadel.projections.iam.change_date,`+
|
||||||
|
` zitadel.projections.iam.sequence,`+
|
||||||
|
` zitadel.projections.iam.global_org_id,`+
|
||||||
|
` zitadel.projections.iam.iam_project_id,`+
|
||||||
|
` zitadel.projections.iam.setup_started,`+
|
||||||
|
` zitadel.projections.iam.setup_done`+
|
||||||
|
` FROM zitadel.projections.iam`),
|
||||||
|
[]string{
|
||||||
|
"id",
|
||||||
|
"change_date",
|
||||||
|
"sequence",
|
||||||
|
"global_org_id",
|
||||||
|
"iam_project_id",
|
||||||
|
"setup_started",
|
||||||
|
"setup_done",
|
||||||
|
},
|
||||||
|
[]driver.Value{
|
||||||
|
"id",
|
||||||
|
testNow,
|
||||||
|
uint64(20211108),
|
||||||
|
"global-org-id",
|
||||||
|
"project-id",
|
||||||
|
domain.Step2,
|
||||||
|
domain.Step1,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
object: &IAM{
|
||||||
|
ID: "id",
|
||||||
|
ChangeDate: testNow,
|
||||||
|
Sequence: 20211108,
|
||||||
|
GlobalOrgID: "global-org-id",
|
||||||
|
IAMProjectID: "project-id",
|
||||||
|
SetupStarted: domain.Step2,
|
||||||
|
SetupDone: domain.Step1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prepareIAMQuery sql err",
|
||||||
|
prepare: prepareIAMQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQueryErr(
|
||||||
|
regexp.QuoteMeta(`SELECT zitadel.projections.iam.id,`+
|
||||||
|
` zitadel.projections.iam.change_date,`+
|
||||||
|
` zitadel.projections.iam.sequence,`+
|
||||||
|
` zitadel.projections.iam.global_org_id,`+
|
||||||
|
` zitadel.projections.iam.iam_project_id,`+
|
||||||
|
` zitadel.projections.iam.setup_started,`+
|
||||||
|
` zitadel.projections.iam.setup_done`+
|
||||||
|
` FROM zitadel.projections.iam`),
|
||||||
|
sql.ErrConnDone,
|
||||||
|
),
|
||||||
|
err: func(err error) (error, bool) {
|
||||||
|
if !errors.Is(err, sql.ErrConnDone) {
|
||||||
|
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
|
||||||
|
}
|
||||||
|
return nil, true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
object: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
21
internal/query/languages.go
Normal file
21
internal/query/languages.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (q *Queries) Languages(ctx context.Context) ([]language.Tag, error) {
|
||||||
|
if len(q.supportedLangs) == 0 {
|
||||||
|
langs, err := i18n.SupportedLanguages(q.LoginDir)
|
||||||
|
if err != nil {
|
||||||
|
logging.Log("ADMIN-tiMWs").WithError(err).Debug("unable to parse language")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
q.supportedLangs = langs
|
||||||
|
}
|
||||||
|
return q.supportedLangs, nil
|
||||||
|
}
|
@ -10,7 +10,6 @@ import (
|
|||||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/config/types"
|
"github.com/caos/zitadel/internal/config/types"
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/query/projection"
|
"github.com/caos/zitadel/internal/query/projection"
|
||||||
"github.com/caos/zitadel/internal/repository/action"
|
"github.com/caos/zitadel/internal/repository/action"
|
||||||
iam_repo "github.com/caos/zitadel/internal/repository/iam"
|
iam_repo "github.com/caos/zitadel/internal/repository/iam"
|
||||||
@ -19,7 +18,6 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/repository/project"
|
"github.com/caos/zitadel/internal/repository/project"
|
||||||
usr_repo "github.com/caos/zitadel/internal/repository/user"
|
usr_repo "github.com/caos/zitadel/internal/repository/user"
|
||||||
"github.com/caos/zitadel/internal/repository/usergrant"
|
"github.com/caos/zitadel/internal/repository/usergrant"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
|
||||||
"github.com/rakyll/statik/fs"
|
"github.com/rakyll/statik/fs"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
@ -35,6 +33,7 @@ type Queries struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
LoginTranslationFileContents map[string][]byte
|
LoginTranslationFileContents map[string][]byte
|
||||||
NotificationTranslationFileContents map[string][]byte
|
NotificationTranslationFileContents map[string][]byte
|
||||||
|
supportedLangs []language.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -78,25 +77,3 @@ func StartQueries(ctx context.Context, es *eventstore.Eventstore, projections pr
|
|||||||
|
|
||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Queries) IAMByID(ctx context.Context, id string) (_ *iam_model.IAM, err error) {
|
|
||||||
readModel, err := r.iamByID(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return readModelToIAM(readModel), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Queries) iamByID(ctx context.Context, id string) (_ *ReadModel, err error) {
|
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
|
||||||
defer func() { span.EndWithError(err) }()
|
|
||||||
|
|
||||||
readModel := NewReadModel(id)
|
|
||||||
err = r.eventstore.FilterToQueryReducer(ctx, readModel)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return readModel, nil
|
|
||||||
}
|
|
||||||
|
@ -16,7 +16,7 @@ func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.Exte
|
|||||||
resourceOwner = config.AggregateID
|
resourceOwner = config.AggregateID
|
||||||
}
|
}
|
||||||
if resourceOwner == domain.IAMID {
|
if resourceOwner == domain.IAMID {
|
||||||
iam, err := l.authRepo.GetIAM(ctx)
|
iam, err := l.query.IAMByID(ctx, domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.R
|
|||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
iam, err := l.authRepo.GetIAM(r.Context())
|
iam, err := l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
|
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
|
||||||
return
|
return
|
||||||
@ -248,13 +248,13 @@ func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.R
|
|||||||
l.renderNextStep(w, r, authReq)
|
l.renderNextStep(w, r, authReq)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) renderExternalNotFoundOption(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, iam *iam_model.IAM, orgIAMPolicy *query.OrgIAMPolicy, human *domain.Human, externalIDP *domain.UserIDPLink, err error) {
|
func (l *Login) renderExternalNotFoundOption(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, iam *query.IAM, orgIAMPolicy *query.OrgIAMPolicy, human *domain.Human, externalIDP *domain.UserIDPLink, err error) {
|
||||||
var errID, errMessage string
|
var errID, errMessage string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errID, errMessage = l.getErrorMessage(r, err)
|
errID, errMessage = l.getErrorMessage(r, err)
|
||||||
}
|
}
|
||||||
if orgIAMPolicy == nil {
|
if orgIAMPolicy == nil {
|
||||||
iam, err = l.authRepo.GetIAM(r.Context())
|
iam, err = l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@ -335,7 +335,7 @@ func (l *Login) handleExternalNotFoundOptionCheck(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) {
|
func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) {
|
||||||
iam, err := l.authRepo.GetIAM(r.Context())
|
iam, err := l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
|
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
|
||||||
return
|
return
|
||||||
|
@ -111,7 +111,7 @@ func (l *Login) handleExternalRegisterCallback(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) handleExternalUserRegister(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView, userAgentID string, tokens *oidc.Tokens) {
|
func (l *Login) handleExternalUserRegister(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView, userAgentID string, tokens *oidc.Tokens) {
|
||||||
iam, err := l.authRepo.GetIAM(r.Context())
|
iam, err := l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@ -137,7 +137,7 @@ func (l *Login) handleExternalUserRegister(w http.ResponseWriter, r *http.Reques
|
|||||||
l.registerExternalUser(w, r, authReq, iam, user, externalIDP)
|
l.registerExternalUser(w, r, authReq, iam, user, externalIDP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, iam *iam_model.IAM, user *domain.Human, externalIDP *domain.UserIDPLink) {
|
func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, iam *query.IAM, user *domain.Human, externalIDP *domain.UserIDPLink) {
|
||||||
resourceOwner := iam.GlobalOrgID
|
resourceOwner := iam.GlobalOrgID
|
||||||
memberRoles := []string{domain.RoleSelfManagementGlobal}
|
memberRoles := []string{domain.RoleSelfManagementGlobal}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ func (l *Login) handleExternalRegisterCheck(w http.ResponseWriter, r *http.Reque
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
iam, err := l.authRepo.GetIAM(r.Context())
|
iam, err := l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
|
@ -61,7 +61,7 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
l.renderRegister(w, r, authRequest, data, err)
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iam, err := l.authRepo.GetIAM(r.Context())
|
iam, err := l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegister(w, r, authRequest, data, err)
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
@ -115,7 +115,7 @@ func (l *Login) renderRegister(w http.ResponseWriter, r *http.Request, authReque
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resourceOwner == "" {
|
if resourceOwner == "" {
|
||||||
iam, err := l.authRepo.GetIAM(r.Context())
|
iam, err := l.query.IAMByID(r.Context(), domain.IAMID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegister(w, r, authRequest, formData, err)
|
l.renderRegister(w, r, authRequest, formData, err)
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user