mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-12 00:55:12 +00:00
feat(rt): authorizations (#11066)
# Which Problems Are Solved This PR implements relational table and repository interface for the authorizations feature as described in https://github.com/zitadel/zitadel/issues/10767 # How the Problems Are Solved By * adding new `zitadel.authorizations` and `zitadel.authorization_roles` tables * implementing the `AuthorizationRepository` interface to create, update, query, and delete user authorizations and roles * implementing `authorization_relational.go` projection to update `zitadel.authorizations` and `zitadel.authorization_roles` tables based on events # Additional Changes N/A # Additional Context - Closes #10767 --------- Co-authored-by: Livio Spring <[email protected]>
This commit is contained in:
co-authored by
Livio Spring
parent
11cf2c252a
commit
8472c7683d
@@ -0,0 +1,188 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
|
||||
repoDomain "github.com/zitadel/zitadel/backend/v3/domain"
|
||||
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
"github.com/zitadel/zitadel/internal/repository/usergrant"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
AuthorizationRelationalProjectionTable = "zitadel.authorizations"
|
||||
)
|
||||
|
||||
type authorizationRelationalProjection struct{}
|
||||
|
||||
func (*authorizationRelationalProjection) Name() string {
|
||||
return AuthorizationRelationalProjectionTable
|
||||
}
|
||||
|
||||
func newAuthorizationRelationalProjection(ctx context.Context, config handler.Config) *handler.Handler {
|
||||
return handler.NewHandler(ctx, &config, new(authorizationRelationalProjection))
|
||||
}
|
||||
|
||||
func (a *authorizationRelationalProjection) Reducers() []handler.AggregateReducer {
|
||||
return []handler.AggregateReducer{
|
||||
{
|
||||
Aggregate: usergrant.AggregateType,
|
||||
EventReducers: []handler.EventReducer{
|
||||
{
|
||||
Event: usergrant.UserGrantAddedType,
|
||||
Reduce: a.reduceUserGrantAdded,
|
||||
},
|
||||
{
|
||||
Event: usergrant.UserGrantChangedType,
|
||||
Reduce: a.reduceUserGrantChanged,
|
||||
},
|
||||
{
|
||||
Event: usergrant.UserGrantCascadeChangedType,
|
||||
Reduce: a.reduceUserGrantChanged,
|
||||
},
|
||||
{
|
||||
Event: usergrant.UserGrantCascadeRemovedType,
|
||||
Reduce: a.reduceUserGrantRemoved,
|
||||
},
|
||||
{
|
||||
Event: usergrant.UserGrantRemovedType,
|
||||
Reduce: a.reduceUserGrantRemoved,
|
||||
},
|
||||
{
|
||||
Event: usergrant.UserGrantDeactivatedType,
|
||||
Reduce: a.reduceUserGrantDeactivated,
|
||||
},
|
||||
{
|
||||
Event: usergrant.UserGrantReactivatedType,
|
||||
Reduce: a.reduceUserGrantReactivated,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *authorizationRelationalProjection) reduceUserGrantAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*usergrant.UserGrantAddedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInternalf(nil, "HANDL-an0k9a", "reduce.wrong.event.type %s", usergrant.UserGrantAddedType)
|
||||
}
|
||||
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, _ string) error {
|
||||
tx, ok := ex.(*sql.Tx)
|
||||
if !ok {
|
||||
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-FrDVPk", "reduce.wrong.db.pool %T", ex)
|
||||
}
|
||||
|
||||
repo := repository.AuthorizationRepository()
|
||||
var grantID *string
|
||||
if e.ProjectGrantID != "" {
|
||||
grantID = gu.Ptr(e.ProjectGrantID)
|
||||
}
|
||||
return repo.Create(ctx, v3_sql.SQLTx(tx), &repoDomain.Authorization{
|
||||
InstanceID: e.Aggregate().InstanceID,
|
||||
ID: e.Aggregate().ID,
|
||||
UserID: e.UserID,
|
||||
ProjectID: e.ProjectID,
|
||||
GrantID: grantID,
|
||||
Roles: e.RoleKeys,
|
||||
CreatedAt: e.CreationDate(),
|
||||
UpdatedAt: e.CreationDate(),
|
||||
State: repoDomain.AuthorizationStateActive,
|
||||
})
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (a *authorizationRelationalProjection) reduceUserGrantChanged(event eventstore.Event) (*handler.Statement, error) {
|
||||
var roles []string
|
||||
switch e := event.(type) {
|
||||
case *usergrant.UserGrantChangedEvent:
|
||||
roles = e.RoleKeys
|
||||
case *usergrant.UserGrantCascadeChangedEvent:
|
||||
roles = e.RoleKeys
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-kg1ryL", "reduce.wrong.event.type %v", []eventstore.EventType{usergrant.UserGrantChangedType, usergrant.UserGrantCascadeChangedType})
|
||||
}
|
||||
|
||||
return handler.NewStatement(event, func(ctx context.Context, ex handler.Executer, _ string) error {
|
||||
tx, ok := ex.(*sql.Tx)
|
||||
if !ok {
|
||||
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-sBwGEW", "reduce.wrong.db.pool %T", ex)
|
||||
}
|
||||
|
||||
repo := repository.AuthorizationRepository()
|
||||
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
|
||||
repo.PrimaryKeyCondition(event.Aggregate().InstanceID, event.Aggregate().ID),
|
||||
roles,
|
||||
repo.SetUpdatedAt(event.CreatedAt()),
|
||||
)
|
||||
return err
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (a *authorizationRelationalProjection) reduceUserGrantRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
switch event.(type) {
|
||||
case *usergrant.UserGrantRemovedEvent, *usergrant.UserGrantCascadeRemovedEvent:
|
||||
// ok
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-dFtRl9", "reduce.wrong.event.type %v", []eventstore.EventType{usergrant.UserGrantRemovedType, usergrant.UserGrantCascadeRemovedType})
|
||||
}
|
||||
|
||||
return handler.NewStatement(event, func(ctx context.Context, ex handler.Executer, _ string) error {
|
||||
tx, ok := ex.(*sql.Tx)
|
||||
if !ok {
|
||||
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-FlZ55O", "reduce.wrong.db.pool %T", ex)
|
||||
}
|
||||
repo := repository.AuthorizationRepository()
|
||||
_, err := repo.Delete(ctx, v3_sql.SQLTx(tx),
|
||||
repo.PrimaryKeyCondition(event.Aggregate().InstanceID, event.Aggregate().ID),
|
||||
)
|
||||
return err
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (a *authorizationRelationalProjection) reduceUserGrantDeactivated(event eventstore.Event) (*handler.Statement, error) {
|
||||
_, ok := event.(*usergrant.UserGrantDeactivatedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-dFtRl0", "reduce.wrong.event.type %s", usergrant.UserGrantDeactivatedType)
|
||||
}
|
||||
return handler.NewStatement(event, func(ctx context.Context, ex handler.Executer, _ string) error {
|
||||
tx, ok := ex.(*sql.Tx)
|
||||
if !ok {
|
||||
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-FlZ55P", "reduce.wrong.db.pool %T", ex)
|
||||
}
|
||||
repo := repository.AuthorizationRepository()
|
||||
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
|
||||
repo.PrimaryKeyCondition(event.Aggregate().InstanceID, event.Aggregate().ID),
|
||||
nil,
|
||||
repo.SetUpdatedAt(event.CreatedAt()),
|
||||
repo.SetState(repoDomain.AuthorizationStateInactive),
|
||||
)
|
||||
return err
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (a *authorizationRelationalProjection) reduceUserGrantReactivated(event eventstore.Event) (*handler.Statement, error) {
|
||||
_, ok := event.(*usergrant.UserGrantReactivatedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-dFtRl1", "reduce.wrong.event.type %s", usergrant.UserGrantReactivatedType)
|
||||
}
|
||||
return handler.NewStatement(event, func(ctx context.Context, ex handler.Executer, _ string) error {
|
||||
tx, ok := ex.(*sql.Tx)
|
||||
if !ok {
|
||||
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-FlZ55Q", "reduce.wrong.db.pool %T", ex)
|
||||
}
|
||||
repo := repository.AuthorizationRepository()
|
||||
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
|
||||
repo.PrimaryKeyCondition(event.Aggregate().InstanceID, event.Aggregate().ID),
|
||||
nil,
|
||||
repo.SetUpdatedAt(event.CreatedAt()),
|
||||
repo.SetState(repoDomain.AuthorizationStateActive),
|
||||
)
|
||||
return err
|
||||
}), nil
|
||||
}
|
||||
@@ -97,6 +97,7 @@ var (
|
||||
ProjectRelationalProjection *handler.Handler
|
||||
ProjectRoleRelationalProjection *handler.Handler
|
||||
OrganizationMetadataRelationalProjection *handler.Handler
|
||||
AuthorizationRelationalProjection *handler.Handler
|
||||
ProjectGrantRelationalProjection *handler.Handler
|
||||
SettingsRelationalProjection *handler.Handler
|
||||
|
||||
@@ -225,6 +226,7 @@ func Create(ctx context.Context, sqlClient *database.DB, es handler.EventStore,
|
||||
ProjectRelationalProjection = newProjectRelationalProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["projects_relational"]))
|
||||
ProjectRoleRelationalProjection = newProjectRoleRelationalProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["project_roles_relational"]))
|
||||
OrganizationMetadataRelationalProjection = newOrgMetadataRelationalProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["organization_metadata_relational"]))
|
||||
AuthorizationRelationalProjection = newAuthorizationRelationalProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["authorizations_relational"]))
|
||||
ProjectGrantRelationalProjection = newProjectGrantRelationalProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["project_grant_relational"]))
|
||||
|
||||
newProjectionsList()
|
||||
@@ -420,6 +422,7 @@ func newProjectionsList() {
|
||||
ProjectRelationalProjection,
|
||||
ProjectRoleRelationalProjection,
|
||||
OrganizationMetadataRelationalProjection,
|
||||
AuthorizationRelationalProjection,
|
||||
ProjectGrantRelationalProjection,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user