Tim Möhlmann 26d1563643
feat(api): feature flags (#7356)
* feat(api): feature API proto definitions

* update proto based on discussion with @livio-a

* cleanup old feature flag stuff

* authz instance queries

* align defaults

* projection definitions

* define commands and event reducers

* implement system and instance setter APIs

* api getter implementation

* unit test repository package

* command unit tests

* unit test Get queries

* grpc converter unit tests

* migrate the V1 features

* migrate oidc to dynamic features

* projection unit test

* fix instance by host

* fix instance by id data type in sql

* fix linting errors

* add system projection test

* fix behavior inversion

* resolve proto file comments

* rename SystemDefaultLoginInstanceEventType to SystemLoginDefaultOrgEventType so it's consistent with the instance level event

* use write models and conditional set events

* system features integration tests

* instance features integration tests

* error on empty request

* documentation entry

* typo in feature.proto

* fix start unit tests

* solve linting error on key case switch

* remove system defaults after discussion with @eliobischof

* fix system feature projection

* resolve comments in defaults.yaml

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-02-28 10:55:54 +02:00

131 lines
3.9 KiB
Go

package eventsourcing
import (
"context"
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/eventstore"
auth_handler "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/handler"
auth_view "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/zitadel/zitadel/internal/auth_request/repository/cache"
"github.com/zitadel/zitadel/internal/command"
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/database"
eventstore2 "github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/id"
"github.com/zitadel/zitadel/internal/query"
)
type Config struct {
SearchLimit uint64
Spooler auth_handler.Config
}
type EsRepository struct {
eventstore.UserRepo
eventstore.AuthRequestRepo
eventstore.TokenRepo
eventstore.RefreshTokenRepo
eventstore.UserSessionRepo
eventstore.OrgRepository
}
func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *database.DB, esV2 *eventstore2.Eventstore, oidcEncryption crypto.EncryptionAlgorithm, userEncryption crypto.EncryptionAlgorithm) (*EsRepository, error) {
view, err := auth_view.StartView(dbClient, oidcEncryption, queries, esV2)
if err != nil {
return nil, err
}
auth_handler.Register(ctx, conf.Spooler, view, queries)
auth_handler.Start(ctx)
authReq := cache.Start(dbClient)
userRepo := eventstore.UserRepo{
SearchLimit: conf.SearchLimit,
Eventstore: esV2,
View: view,
Query: queries,
SystemDefaults: systemDefaults,
}
//TODO: remove as soon as possible
queryView := queryViewWrapper{
queries,
view,
}
return &EsRepository{
userRepo,
eventstore.AuthRequestRepo{
PrivacyPolicyProvider: queries,
LabelPolicyProvider: queries,
Command: command,
Query: queries,
OrgViewProvider: queries,
AuthRequests: authReq,
View: view,
UserCodeAlg: userEncryption,
UserSessionViewProvider: view,
UserViewProvider: view,
UserCommandProvider: command,
UserEventProvider: &userRepo,
IDPProviderViewProvider: queries,
IDPUserLinksProvider: queries,
LockoutPolicyViewProvider: queries,
LoginPolicyViewProvider: queries,
UserGrantProvider: queryView,
ProjectProvider: queryView,
ApplicationProvider: queries,
CustomTextProvider: queries,
IdGenerator: id.SonyFlakeGenerator(),
},
eventstore.TokenRepo{
View: view,
Eventstore: esV2,
},
eventstore.RefreshTokenRepo{
View: view,
Eventstore: esV2,
SearchLimit: conf.SearchLimit,
KeyAlgorithm: oidcEncryption,
},
eventstore.UserSessionRepo{
View: view,
},
eventstore.OrgRepository{
SearchLimit: conf.SearchLimit,
View: view,
SystemDefaults: systemDefaults,
Eventstore: esV2,
Query: queries,
},
}, nil
}
type queryViewWrapper struct {
*query.Queries
*auth_view.View
}
func (q queryViewWrapper) UserGrantsByProjectAndUserID(ctx context.Context, 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(ctx, queries, true)
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
}
return repo.AuthRequestRepo.Health(ctx)
}