feat(api): add possibility to retrieve user schemas (#7614)

This PR extends the user schema service (V3 API) with the possibility to ListUserSchemas and GetUserSchemaByID.
The previously started guide is extended to demonstrate how to retrieve the schema(s) and notes the generated revision property.
This commit is contained in:
Livio Spring
2024-03-22 14:26:13 +01:00
committed by GitHub
parent 5b301c7f96
commit 7494a7b6d9
29 changed files with 1597 additions and 19 deletions

View File

@@ -0,0 +1,203 @@
package projection
import (
"context"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
old_handler "github.com/zitadel/zitadel/internal/eventstore/handler"
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
"github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/repository/user/schema"
)
const (
UserSchemaTable = "projections.user_schemas"
UserSchemaIDCol = "id"
UserSchemaChangeDateCol = "change_date"
UserSchemaSequenceCol = "sequence"
UserSchemaInstanceIDCol = "instance_id"
UserSchemaStateCol = "state"
UserSchemaTypeCol = "type"
UserSchemaRevisionCol = "revision"
UserSchemaSchemaCol = "schema"
UserSchemaPossibleAuthenticatorsCol = "possible_authenticators"
)
type userSchemaProjection struct{}
func newUserSchemaProjection(ctx context.Context, config handler.Config) *handler.Handler {
return handler.NewHandler(ctx, &config, new(userSchemaProjection))
}
func (*userSchemaProjection) Name() string {
return UserSchemaTable
}
func (*userSchemaProjection) Init() *old_handler.Check {
return handler.NewTableCheck(
handler.NewTable([]*handler.InitColumn{
handler.NewColumn(UserSchemaIDCol, handler.ColumnTypeText),
handler.NewColumn(UserSchemaChangeDateCol, handler.ColumnTypeTimestamp),
handler.NewColumn(UserSchemaSequenceCol, handler.ColumnTypeInt64),
handler.NewColumn(UserSchemaStateCol, handler.ColumnTypeEnum),
handler.NewColumn(UserSchemaInstanceIDCol, handler.ColumnTypeText),
handler.NewColumn(UserSchemaTypeCol, handler.ColumnTypeText),
handler.NewColumn(UserSchemaRevisionCol, handler.ColumnTypeInt64),
handler.NewColumn(UserSchemaSchemaCol, handler.ColumnTypeJSONB, handler.Nullable()),
handler.NewColumn(UserSchemaPossibleAuthenticatorsCol, handler.ColumnTypeEnumArray, handler.Nullable()),
},
handler.NewPrimaryKey(UserSchemaInstanceIDCol, UserSchemaIDCol),
),
)
}
func (p *userSchemaProjection) Reducers() []handler.AggregateReducer {
return []handler.AggregateReducer{
{
Aggregate: schema.AggregateType,
EventReducers: []handler.EventReducer{
{
Event: schema.CreatedType,
Reduce: p.reduceCreated,
},
{
Event: schema.UpdatedType,
Reduce: p.reduceUpdated,
},
{
Event: schema.DeactivatedType,
Reduce: p.reduceDeactivated,
},
{
Event: schema.ReactivatedType,
Reduce: p.reduceReactivated,
},
{
Event: schema.DeletedType,
Reduce: p.reduceDeleted,
},
},
},
{
Aggregate: instance.AggregateType,
EventReducers: []handler.EventReducer{
{
Event: instance.InstanceRemovedEventType,
Reduce: reduceInstanceRemovedHelper(UserSchemaInstanceIDCol),
},
},
},
}
}
func (p *userSchemaProjection) reduceCreated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*schema.CreatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewCreateStatement(
event,
[]handler.Column{
handler.NewCol(UserSchemaIDCol, event.Aggregate().ID),
handler.NewCol(UserSchemaChangeDateCol, event.CreatedAt()),
handler.NewCol(UserSchemaSequenceCol, event.Sequence()),
handler.NewCol(UserSchemaInstanceIDCol, event.Aggregate().InstanceID),
handler.NewCol(UserSchemaStateCol, domain.UserSchemaStateActive),
handler.NewCol(UserSchemaTypeCol, e.SchemaType),
handler.NewCol(UserSchemaRevisionCol, 1),
handler.NewCol(UserSchemaSchemaCol, e.Schema),
handler.NewCol(UserSchemaPossibleAuthenticatorsCol, e.PossibleAuthenticators),
},
), nil
}
func (p *userSchemaProjection) reduceUpdated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*schema.UpdatedEvent](event)
if err != nil {
return nil, err
}
cols := []handler.Column{
handler.NewCol(UserSchemaChangeDateCol, event.CreatedAt()),
handler.NewCol(UserSchemaSequenceCol, event.Sequence()),
}
if e.SchemaType != nil {
cols = append(cols, handler.NewCol(UserSchemaTypeCol, *e.SchemaType))
}
if len(e.Schema) > 0 {
cols = append(cols, handler.NewCol(UserSchemaSchemaCol, e.Schema))
cols = append(cols, handler.NewIncrementCol(UserSchemaRevisionCol, 1))
}
if len(e.PossibleAuthenticators) > 0 {
cols = append(cols, handler.NewCol(UserSchemaPossibleAuthenticatorsCol, e.PossibleAuthenticators))
}
return handler.NewUpdateStatement(
event,
cols,
[]handler.Condition{
handler.NewCond(UserSchemaIDCol, event.Aggregate().ID),
handler.NewCond(UserSchemaInstanceIDCol, event.Aggregate().InstanceID),
},
), nil
}
func (p *userSchemaProjection) reduceDeactivated(event eventstore.Event) (*handler.Statement, error) {
_, err := assertEvent[*schema.DeactivatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(UserSchemaChangeDateCol, event.CreatedAt()),
handler.NewCol(UserSchemaSequenceCol, event.Sequence()),
handler.NewCol(UserSchemaStateCol, domain.UserSchemaStateInactive),
},
[]handler.Condition{
handler.NewCond(UserSchemaIDCol, event.Aggregate().ID),
handler.NewCond(UserSchemaInstanceIDCol, event.Aggregate().InstanceID),
},
), nil
}
func (p *userSchemaProjection) reduceReactivated(event eventstore.Event) (*handler.Statement, error) {
_, err := assertEvent[*schema.ReactivatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(UserSchemaChangeDateCol, event.CreatedAt()),
handler.NewCol(UserSchemaSequenceCol, event.Sequence()),
handler.NewCol(UserSchemaStateCol, domain.UserSchemaStateActive),
},
[]handler.Condition{
handler.NewCond(UserSchemaIDCol, event.Aggregate().ID),
handler.NewCond(UserSchemaInstanceIDCol, event.Aggregate().InstanceID),
},
), nil
}
func (p *userSchemaProjection) reduceDeleted(event eventstore.Event) (*handler.Statement, error) {
_, err := assertEvent[*schema.DeletedEvent](event)
if err != nil {
return nil, err
}
return handler.NewDeleteStatement(
event,
[]handler.Condition{
handler.NewCond(UserSchemaIDCol, event.Aggregate().ID),
handler.NewCond(UserSchemaInstanceIDCol, event.Aggregate().InstanceID),
},
), nil
}