mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-16 21:08:00 +00:00
0e181b218c
This PR adds the functionality to manage user schemas through the new user schema service. It includes the possibility to create a basic JSON schema and also provides a way on defining permissions (read, write) for owner and self context with an annotation. Further annotations for OIDC claims and SAML attribute mappings will follow. A guide on how to create a schema and assign permissions has been started. It will be extended though out the process of implementing the schema and users based on those. Note: This feature is in an early stage and therefore not enabled by default. To test it out, please enable the UserSchema feature flag on your instance / system though the feature service.
151 lines
5.3 KiB
Go
151 lines
5.3 KiB
Go
package schema
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
|
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
schema "github.com/zitadel/zitadel/pkg/grpc/user/schema/v3alpha"
|
|
)
|
|
|
|
func (s *Server) CreateUserSchema(ctx context.Context, req *schema.CreateUserSchemaRequest) (*schema.CreateUserSchemaResponse, error) {
|
|
if err := checkUserSchemaEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
userSchema, err := createUserSchemaToCommand(req, authz.GetInstance(ctx).InstanceID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
id, details, err := s.command.CreateUserSchema(ctx, userSchema)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &schema.CreateUserSchemaResponse{
|
|
Id: id,
|
|
Details: object.DomainToDetailsPb(details),
|
|
}, nil
|
|
}
|
|
|
|
func (s *Server) UpdateUserSchema(ctx context.Context, req *schema.UpdateUserSchemaRequest) (*schema.UpdateUserSchemaResponse, error) {
|
|
if err := checkUserSchemaEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
userSchema, err := updateUserSchemaToCommand(req, authz.GetInstance(ctx).InstanceID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
details, err := s.command.UpdateUserSchema(ctx, userSchema)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &schema.UpdateUserSchemaResponse{
|
|
Details: object.DomainToDetailsPb(details),
|
|
}, nil
|
|
}
|
|
func (s *Server) DeactivateUserSchema(ctx context.Context, req *schema.DeactivateUserSchemaRequest) (*schema.DeactivateUserSchemaResponse, error) {
|
|
if err := checkUserSchemaEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
details, err := s.command.DeactivateUserSchema(ctx, req.GetId(), authz.GetInstance(ctx).InstanceID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &schema.DeactivateUserSchemaResponse{
|
|
Details: object.DomainToDetailsPb(details),
|
|
}, nil
|
|
}
|
|
func (s *Server) ReactivateUserSchema(ctx context.Context, req *schema.ReactivateUserSchemaRequest) (*schema.ReactivateUserSchemaResponse, error) {
|
|
if err := checkUserSchemaEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
details, err := s.command.ReactivateUserSchema(ctx, req.GetId(), authz.GetInstance(ctx).InstanceID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &schema.ReactivateUserSchemaResponse{
|
|
Details: object.DomainToDetailsPb(details),
|
|
}, nil
|
|
}
|
|
func (s *Server) DeleteUserSchema(ctx context.Context, req *schema.DeleteUserSchemaRequest) (*schema.DeleteUserSchemaResponse, error) {
|
|
if err := checkUserSchemaEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
details, err := s.command.DeleteUserSchema(ctx, req.GetId(), authz.GetInstance(ctx).InstanceID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &schema.DeleteUserSchemaResponse{
|
|
Details: object.DomainToDetailsPb(details),
|
|
}, nil
|
|
}
|
|
|
|
func checkUserSchemaEnabled(ctx context.Context) error {
|
|
if authz.GetInstance(ctx).Features().UserSchema {
|
|
return nil
|
|
}
|
|
return zerrors.ThrowPreconditionFailed(nil, "SCHEMA-SFjk3", "Errors.UserSchema.NotEnabled")
|
|
}
|
|
|
|
func createUserSchemaToCommand(req *schema.CreateUserSchemaRequest, resourceOwner string) (*command.CreateUserSchema, error) {
|
|
schema, err := req.GetSchema().MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &command.CreateUserSchema{
|
|
ResourceOwner: resourceOwner,
|
|
Type: req.GetType(),
|
|
Schema: schema,
|
|
PossibleAuthenticators: authenticatorsToDomain(req.GetPossibleAuthenticators()),
|
|
}, nil
|
|
}
|
|
|
|
func updateUserSchemaToCommand(req *schema.UpdateUserSchemaRequest, resourceOwner string) (*command.UpdateUserSchema, error) {
|
|
schema, err := req.GetSchema().MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &command.UpdateUserSchema{
|
|
ID: req.GetId(),
|
|
ResourceOwner: resourceOwner,
|
|
Type: req.Type,
|
|
Schema: schema,
|
|
PossibleAuthenticators: authenticatorsToDomain(req.GetPossibleAuthenticators()),
|
|
}, nil
|
|
}
|
|
|
|
func authenticatorsToDomain(authenticators []schema.AuthenticatorType) []domain.AuthenticatorType {
|
|
types := make([]domain.AuthenticatorType, len(authenticators))
|
|
for i, authenticator := range authenticators {
|
|
types[i] = authenticatorTypeToDomain(authenticator)
|
|
}
|
|
return types
|
|
}
|
|
|
|
func authenticatorTypeToDomain(authenticator schema.AuthenticatorType) domain.AuthenticatorType {
|
|
switch authenticator {
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_UNSPECIFIED:
|
|
return domain.AuthenticatorTypeUnspecified
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_USERNAME:
|
|
return domain.AuthenticatorTypeUsername
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_PASSWORD:
|
|
return domain.AuthenticatorTypePassword
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_WEBAUTHN:
|
|
return domain.AuthenticatorTypeWebAuthN
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_TOTP:
|
|
return domain.AuthenticatorTypeTOTP
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_OTP_EMAIL:
|
|
return domain.AuthenticatorTypeOTPEmail
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_OTP_SMS:
|
|
return domain.AuthenticatorTypeOTPSMS
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_AUTHENTICATION_KEY:
|
|
return domain.AuthenticatorTypeAuthenticationKey
|
|
case schema.AuthenticatorType_AUTHENTICATOR_TYPE_IDENTITY_PROVIDER:
|
|
return domain.AuthenticatorTypeIdentityProvider
|
|
default:
|
|
return domain.AuthenticatorTypeUnspecified
|
|
}
|
|
}
|