mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-28 21:13:42 +00:00
feat: label policy (#1708)
* feat: label policy proto extension * feat: label policy and activate event * feat: label policy asset events * feat: label policy asset commands * feat: add storage key * feat: storage key validation * feat: label policy asset tests * feat: label policy query side * feat: avatar * feat: avatar event * feat: human avatar * feat: avatar read side * feat: font on iam label policy * feat: label policy font * feat: possiblity to create bucket on put file * uplaoder * login policy logo * set bucket prefix * feat: avatar upload * feat: avatar upload * feat: use assets on command side * feat: fix human avatar removed event * feat: remove human avatar * feat: mock asset storage * feat: remove human avatar * fix(operator): add configuration of asset storage to zitadel operator * feat(console): private labeling policy (#1697) * private labeling component, routing, preview * font, colors, upload, i18n * show logo * fix: uniqueness (#1710) * fix: uniqueconstraint to lower * feat: change org * feat: org change test * feat: change org * fix: tests * fix: handle domain claims correctly * feat: update org Co-authored-by: fabi <fabienne.gerschwiler@gmail.com> * fix: handle domain claimed event correctly for service users (#1711) * fix: handle domain claimed event correctly on user view * fix: ignore domain claimed events for email notifications * fix: change org * handle org changed in read models correctly * fix: change org in user grant handler Co-authored-by: fabi <fabienne.gerschwiler@gmail.com> * fix: correct value (#1695) * docs(api): correct link (#1712) * upload service Co-authored-by: Livio Amstutz <livio.a@gmail.com> Co-authored-by: fabi <fabienne.gerschwiler@gmail.com> Co-authored-by: Florian Forster <florian@caos.ch> * feat: fix tests, * feat: remove assets from label policy * fix npm, set environment * lint ts * remove stylelinting * fix(operator): add mapping for console with changed unit tests * fix(operator): add secrets as env variables to pod * feat: remove human avatar * fix(operator): add secrets as env variables to pod * feat: map label policy * feat: labelpolicy, admin, mgmt, adv settings (#1715) * fetch label policy, mgmt, admin service * feat: advanced beh, links, add, update * lint ts * feat: watermark * feat: remove human avatar * feat: remove human avatar * feat: remove human avatar * feat: remove human avatar * feat: remove human avatar * feat: remove human avatar * feat: remove human avatar * feat: custom css * css * css * css * css * css * getobject * feat: dynamic handler * feat: varibale css * content info * css overwrite * feat: variablen css * feat: generate css file * feat: dark mode * feat: dark mode * fix logo css * feat: upload logos * dark mode with cookie * feat: handle images in login * avatar css and begin font * feat: avatar * feat: user avatar * caching of static assets in login * add avatar.js to main.html * feat: header dont show logo if no url * feat: label policy colors * feat: mock asset storage * feat: mock asset storage * feat: fix tests * feat: user avatar * feat: header logo * avatar * avatar * make it compatible with go 1.15 * feat: remove unused logos * fix handler * fix: styling error handling * fonts * fix: download func * switch to mux * fix: change upload api to assets * fix build * fix: download avatar * fix: download logos * fix: my avatar * font * fix: remove error msg popup possibility * fix: docs * fix: svalidate colors * rem msg popup from frontend * fix: email with private labeling * fix: tests * fix: email templates * fix: change migration version * fix: fix duplicate imports * fix(console): assets, service url, upload, policy current and preview (#1781) * upload endpoint, layout * fetch current, preview, fix upload * cleanup private labeling * fix linting * begin generated asset handler * generate asset api in dockerfile * features for label policy * features for label policy * features * flag for asset generator * change asset generator flag * fix label policy view in grpc * fix: layout, activate policy (#1786) * theme switcher up on top * change layout * activate policy * feat(console): label policy back color, layout (#1788) * theme switcher up on top * change layout * activate policy * fix overwrite value fc * reset policy, reset service * autosave policy, preview desc, layout impv * layout, i18n * background colors, inject material styles * load images * clean, lint * fix layout * set custom hex * fix content size conversion * remove font format in generated css * fix features for assets * fix(console): label policy colors, image downloads, preview (#1804) * load images * colors, images binding * lint * refresh emitter * lint * propagate font colors * upload error handling * label policy feature check * add blob in csp for console * log * fix: feature edits for label policy, refresh state on upload (#1807) * show error on load image, stop spinner * fix merge * fix migration versions * fix assets * fix csp * fix background color * scss * fix build * lint scss * fix statik for console * fix features check for label policy * cleanup * lint * public links * fix notifications * public links * feat: merge main * feat: fix translation files * fix migration * set api domain * fix logo in email * font face in email * font face in email * validate assets on upload * cleanup * add missing translations * add missing translations Co-authored-by: Livio Amstutz <livio.a@gmail.com> Co-authored-by: Stefan Benz <stefan@caos.ch> Co-authored-by: Max Peintner <max@caos.ch> Co-authored-by: Florian Forster <florian@caos.ch>
This commit is contained in:
parent
c0d9d86b09
commit
73d37459bb
@ -134,9 +134,13 @@ COPY --from=base /usr/local/bin /usr/local/bin/.
|
|||||||
COPY build/zitadel/generate-grpc.sh build/zitadel/generate-grpc.sh
|
COPY build/zitadel/generate-grpc.sh build/zitadel/generate-grpc.sh
|
||||||
COPY internal/protoc internal/protoc
|
COPY internal/protoc internal/protoc
|
||||||
COPY openapi/statik openapi/statik
|
COPY openapi/statik openapi/statik
|
||||||
|
COPY internal/api/assets/generator internal/api/assets/generator
|
||||||
|
COPY internal/config internal/config
|
||||||
|
COPY internal/errors internal/errors
|
||||||
|
|
||||||
RUN build/zitadel/generate-grpc.sh \
|
RUN build/zitadel/generate-grpc.sh \
|
||||||
&& go generate openapi/statik/generate.go
|
&& go generate openapi/statik/generate.go \
|
||||||
|
&& go run internal/api/assets/generator/asset_generator.go -directory=internal/api/assets/generator/
|
||||||
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
@ -163,6 +167,9 @@ COPY --from=go-stub /go/src/github.com/caos/zitadel/internal/protoc/protoc-gen-a
|
|||||||
COPY --from=go-stub /go/src/github.com/caos/zitadel/internal/protoc/protoc-gen-authoption/authoption/options.pb.go internal/protoc/protoc-gen-authoption/authoption/options.pb.go
|
COPY --from=go-stub /go/src/github.com/caos/zitadel/internal/protoc/protoc-gen-authoption/authoption/options.pb.go internal/protoc/protoc-gen-authoption/authoption/options.pb.go
|
||||||
COPY --from=go-stub /go/src/github.com/caos/zitadel/docs/apis/proto docs/docs/apis/proto
|
COPY --from=go-stub /go/src/github.com/caos/zitadel/docs/apis/proto docs/docs/apis/proto
|
||||||
|
|
||||||
|
COPY --from=go-stub /go/src/github.com/caos/zitadel/internal/api/assets/authz.go ./internal/api/assets/authz.go
|
||||||
|
COPY --from=go-stub /go/src/github.com/caos/zitadel/internal/api/assets/router.go ./internal/api/assets/router.go
|
||||||
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
## Go test
|
## Go test
|
||||||
|
@ -45,6 +45,7 @@ ZITADEL_AUTHORIZE=http://localhost:50002/oauth/v2
|
|||||||
ZITADEL_OAUTH=http://localhost:50002/oauth/v2
|
ZITADEL_OAUTH=http://localhost:50002/oauth/v2
|
||||||
ZITADEL_CONSOLE=http://localhost:4200
|
ZITADEL_CONSOLE=http://localhost:4200
|
||||||
ZITADEL_COOKIE_DOMAIN=localhost
|
ZITADEL_COOKIE_DOMAIN=localhost
|
||||||
|
ZITADEL_API_DOMAIN=http://localhost:50002
|
||||||
|
|
||||||
#caching is used in UI's and API's
|
#caching is used in UI's and API's
|
||||||
ZITADEL_CACHE_MAXAGE=12h
|
ZITADEL_CACHE_MAXAGE=12h
|
||||||
|
@ -5,8 +5,10 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing"
|
admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing"
|
||||||
"github.com/caos/zitadel/internal/api"
|
"github.com/caos/zitadel/internal/api"
|
||||||
|
"github.com/caos/zitadel/internal/api/assets"
|
||||||
internal_authz "github.com/caos/zitadel/internal/api/authz"
|
internal_authz "github.com/caos/zitadel/internal/api/authz"
|
||||||
"github.com/caos/zitadel/internal/api/grpc/admin"
|
"github.com/caos/zitadel/internal/api/grpc/admin"
|
||||||
"github.com/caos/zitadel/internal/api/grpc/auth"
|
"github.com/caos/zitadel/internal/api/grpc/auth"
|
||||||
@ -20,11 +22,13 @@ 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"
|
||||||
|
"github.com/caos/zitadel/internal/id"
|
||||||
mgmt_es "github.com/caos/zitadel/internal/management/repository/eventsourcing"
|
mgmt_es "github.com/caos/zitadel/internal/management/repository/eventsourcing"
|
||||||
"github.com/caos/zitadel/internal/notification"
|
"github.com/caos/zitadel/internal/notification"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
"github.com/caos/zitadel/internal/setup"
|
"github.com/caos/zitadel/internal/setup"
|
||||||
"github.com/caos/zitadel/internal/static/s3"
|
"github.com/caos/zitadel/internal/static"
|
||||||
|
static_config "github.com/caos/zitadel/internal/static/config"
|
||||||
metrics "github.com/caos/zitadel/internal/telemetry/metrics/config"
|
metrics "github.com/caos/zitadel/internal/telemetry/metrics/config"
|
||||||
tracing "github.com/caos/zitadel/internal/telemetry/tracing/config"
|
tracing "github.com/caos/zitadel/internal/telemetry/tracing/config"
|
||||||
"github.com/caos/zitadel/internal/ui"
|
"github.com/caos/zitadel/internal/ui"
|
||||||
@ -37,7 +41,7 @@ type Config struct {
|
|||||||
Log logging.Config
|
Log logging.Config
|
||||||
Tracing tracing.TracingConfig
|
Tracing tracing.TracingConfig
|
||||||
Metrics metrics.MetricsConfig
|
Metrics metrics.MetricsConfig
|
||||||
AssetStorage s3.AssetStorage
|
AssetStorage static_config.AssetStorageConfig
|
||||||
InternalAuthZ internal_authz.Config
|
InternalAuthZ internal_authz.Config
|
||||||
SystemDefaults sd.SystemDefaults
|
SystemDefaults sd.SystemDefaults
|
||||||
|
|
||||||
@ -72,6 +76,7 @@ var (
|
|||||||
managementEnabled = flag.Bool("management", true, "enable management api")
|
managementEnabled = flag.Bool("management", true, "enable management api")
|
||||||
authEnabled = flag.Bool("auth", true, "enable auth api")
|
authEnabled = flag.Bool("auth", true, "enable auth api")
|
||||||
oidcEnabled = flag.Bool("oidc", true, "enable oidc api")
|
oidcEnabled = flag.Bool("oidc", true, "enable oidc api")
|
||||||
|
assetsEnabled = flag.Bool("assets", true, "enable assets api")
|
||||||
loginEnabled = flag.Bool("login", true, "enable login ui")
|
loginEnabled = flag.Bool("login", true, "enable login ui")
|
||||||
consoleEnabled = flag.Bool("console", true, "enable console ui")
|
consoleEnabled = flag.Bool("console", true, "enable console ui")
|
||||||
notificationEnabled = flag.Bool("notification", true, "enable notification handler")
|
notificationEnabled = flag.Bool("notification", true, "enable notification handler")
|
||||||
@ -114,11 +119,15 @@ func startZitadel(configPaths []string) {
|
|||||||
}
|
}
|
||||||
authZRepo, err := authz.Start(ctx, conf.AuthZ, conf.InternalAuthZ, conf.SystemDefaults, queries)
|
authZRepo, err := authz.Start(ctx, conf.AuthZ, conf.InternalAuthZ, conf.SystemDefaults, queries)
|
||||||
logging.Log("MAIN-s9KOw").OnError(err).Fatal("error starting authz repo")
|
logging.Log("MAIN-s9KOw").OnError(err).Fatal("error starting authz repo")
|
||||||
|
verifier := internal_authz.Start(authZRepo)
|
||||||
esCommands, err := eventstore.StartWithUser(conf.EventstoreBase, conf.Commands.Eventstore)
|
esCommands, err := eventstore.StartWithUser(conf.EventstoreBase, conf.Commands.Eventstore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Log("ZITAD-iRCMm").OnError(err).Fatal("cannot start eventstore for commands")
|
logging.Log("ZITAD-iRCMm").OnError(err).Fatal("cannot start eventstore for commands")
|
||||||
}
|
}
|
||||||
commands, err := command.StartCommands(esCommands, conf.SystemDefaults, conf.InternalAuthZ, authZRepo)
|
store, err := conf.AssetStorage.Config.NewStorage()
|
||||||
|
logging.Log("ZITAD-Bfhe2").OnError(err).Fatal("Unable to start asset storage")
|
||||||
|
|
||||||
|
commands, err := command.StartCommands(esCommands, conf.SystemDefaults, conf.InternalAuthZ, store, authZRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Log("ZITAD-bmNiJ").OnError(err).Fatal("cannot start commands")
|
logging.Log("ZITAD-bmNiJ").OnError(err).Fatal("cannot start commands")
|
||||||
}
|
}
|
||||||
@ -128,21 +137,21 @@ func startZitadel(configPaths []string) {
|
|||||||
logging.Log("MAIN-9oRw6").OnError(err).Fatal("error starting auth repo")
|
logging.Log("MAIN-9oRw6").OnError(err).Fatal("error starting auth repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
startAPI(ctx, conf, authZRepo, authRepo, commands, queries)
|
startAPI(ctx, conf, verifier, authZRepo, authRepo, commands, queries, store)
|
||||||
startUI(ctx, conf, authRepo, commands, queries)
|
startUI(ctx, conf, authRepo, commands, queries, store)
|
||||||
|
|
||||||
if *notificationEnabled {
|
if *notificationEnabled {
|
||||||
notification.Start(ctx, conf.Notification, conf.SystemDefaults, commands)
|
notification.Start(ctx, conf.Notification, conf.SystemDefaults, commands, store != nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
logging.Log("MAIN-s8d2h").Info("stopping zitadel")
|
logging.Log("MAIN-s8d2h").Info("stopping zitadel")
|
||||||
}
|
}
|
||||||
|
|
||||||
func startUI(ctx context.Context, conf *Config, authRepo *auth_es.EsRepository, command *command.Commands, query *query.Queries) {
|
func startUI(ctx context.Context, conf *Config, authRepo *auth_es.EsRepository, command *command.Commands, query *query.Queries, staticStorage static.Storage) {
|
||||||
uis := ui.Create(conf.UI)
|
uis := ui.Create(conf.UI)
|
||||||
if *loginEnabled {
|
if *loginEnabled {
|
||||||
login, prefix := login.Start(conf.UI.Login, command, query, authRepo, conf.SystemDefaults, *localDevMode)
|
login, prefix := login.Start(conf.UI.Login, command, query, authRepo, staticStorage, conf.SystemDefaults, *localDevMode)
|
||||||
uis.RegisterHandler(prefix, login.Handler())
|
uis.RegisterHandler(prefix, login.Handler())
|
||||||
}
|
}
|
||||||
if *consoleEnabled {
|
if *consoleEnabled {
|
||||||
@ -153,12 +162,12 @@ func startUI(ctx context.Context, conf *Config, authRepo *auth_es.EsRepository,
|
|||||||
uis.Start(ctx)
|
uis.Start(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsRepository, authRepo *auth_es.EsRepository, command *command.Commands, query *query.Queries) {
|
func startAPI(ctx context.Context, conf *Config, verifier *internal_authz.TokenVerifier, authZRepo *authz_repo.EsRepository, authRepo *auth_es.EsRepository, command *command.Commands, query *query.Queries, static static.Storage) {
|
||||||
roles := make([]string, len(conf.InternalAuthZ.RolePermissionMappings))
|
roles := make([]string, len(conf.InternalAuthZ.RolePermissionMappings))
|
||||||
for i, role := range conf.InternalAuthZ.RolePermissionMappings {
|
for i, role := range conf.InternalAuthZ.RolePermissionMappings {
|
||||||
roles[i] = role.Role
|
roles[i] = role.Role
|
||||||
}
|
}
|
||||||
repo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, roles)
|
repo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, static, roles, *localDevMode)
|
||||||
logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo")
|
logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo")
|
||||||
|
|
||||||
apis := api.Create(conf.API, conf.InternalAuthZ, authZRepo, authRepo, repo, conf.SystemDefaults)
|
apis := api.Create(conf.API, conf.InternalAuthZ, authZRepo, authRepo, repo, conf.SystemDefaults)
|
||||||
@ -166,9 +175,9 @@ func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsReposit
|
|||||||
if *adminEnabled {
|
if *adminEnabled {
|
||||||
apis.RegisterServer(ctx, admin.CreateServer(command, query, repo, conf.SystemDefaults.Domain))
|
apis.RegisterServer(ctx, admin.CreateServer(command, query, repo, conf.SystemDefaults.Domain))
|
||||||
}
|
}
|
||||||
if *managementEnabled {
|
managementRepo, err := mgmt_es.Start(conf.Mgmt, conf.SystemDefaults, roles, query, static)
|
||||||
managementRepo, err := mgmt_es.Start(conf.Mgmt, conf.SystemDefaults, roles, query)
|
|
||||||
logging.Log("API-Gd2qq").OnError(err).Fatal("error starting management repo")
|
logging.Log("API-Gd2qq").OnError(err).Fatal("error starting management repo")
|
||||||
|
if *managementEnabled {
|
||||||
apis.RegisterServer(ctx, management.CreateServer(command, query, managementRepo, conf.SystemDefaults))
|
apis.RegisterServer(ctx, management.CreateServer(command, query, managementRepo, conf.SystemDefaults))
|
||||||
}
|
}
|
||||||
if *authEnabled {
|
if *authEnabled {
|
||||||
@ -178,6 +187,10 @@ func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsReposit
|
|||||||
op := oidc.NewProvider(ctx, conf.API.OIDC, command, query, authRepo, conf.SystemDefaults.KeyConfig.EncryptionConfig, *localDevMode)
|
op := oidc.NewProvider(ctx, conf.API.OIDC, command, query, authRepo, conf.SystemDefaults.KeyConfig.EncryptionConfig, *localDevMode)
|
||||||
apis.RegisterHandler("/oauth/v2", op.HttpHandler())
|
apis.RegisterHandler("/oauth/v2", op.HttpHandler())
|
||||||
}
|
}
|
||||||
|
if *assetsEnabled {
|
||||||
|
assetsHandler := assets.NewHandler(command, verifier, conf.InternalAuthZ, id.SonyFlakeGenerator, static, managementRepo)
|
||||||
|
apis.RegisterHandler("/assets/v1", assetsHandler)
|
||||||
|
}
|
||||||
|
|
||||||
openAPIHandler, err := openapi.Start()
|
openAPIHandler, err := openapi.Start()
|
||||||
logging.Log("ZITAD-8pRk1").OnError(err).Fatal("Unable to start openapi handler")
|
logging.Log("ZITAD-8pRk1").OnError(err).Fatal("Unable to start openapi handler")
|
||||||
@ -196,7 +209,7 @@ func startSetup(configPaths []string) {
|
|||||||
es, err := eventstore.Start(conf.Eventstore)
|
es, err := eventstore.Start(conf.Eventstore)
|
||||||
logging.Log("MAIN-Ddt3").OnError(err).Fatal("cannot start eventstore")
|
logging.Log("MAIN-Ddt3").OnError(err).Fatal("cannot start eventstore")
|
||||||
|
|
||||||
commands, err := command.StartCommands(es, conf.SystemDefaults, conf.InternalAuthZ, nil)
|
commands, err := command.StartCommands(es, conf.SystemDefaults, conf.InternalAuthZ, nil, nil)
|
||||||
logging.Log("MAIN-dsjrr").OnError(err).Fatal("cannot start command side")
|
logging.Log("MAIN-dsjrr").OnError(err).Fatal("cannot start command side")
|
||||||
|
|
||||||
err = setup.Execute(ctx, conf.SetUp, conf.SystemDefaults.IamID, commands)
|
err = setup.Execute(ctx, conf.SetUp, conf.SystemDefaults.IamID, commands)
|
||||||
|
File diff suppressed because one or more lines are too long
@ -19,6 +19,7 @@ AssetStorage:
|
|||||||
SecretAccessKey: $ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY
|
SecretAccessKey: $ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY
|
||||||
SSL: $ZITADEL_ASSET_STORAGE_SSL
|
SSL: $ZITADEL_ASSET_STORAGE_SSL
|
||||||
Location: $ZITADEL_ASSET_STORAGE_LOCATION
|
Location: $ZITADEL_ASSET_STORAGE_LOCATION
|
||||||
|
BucketPrefix: $ZITADEL_ASSET_STORAGE_BUCKET_PREFIX
|
||||||
|
|
||||||
Metrics:
|
Metrics:
|
||||||
Type: 'otel'
|
Type: 'otel'
|
||||||
@ -279,6 +280,10 @@ UI:
|
|||||||
Cache:
|
Cache:
|
||||||
MaxAge: $ZITADEL_CACHE_MAXAGE
|
MaxAge: $ZITADEL_CACHE_MAXAGE
|
||||||
SharedMaxAge: $ZITADEL_CACHE_SHARED_MAXAGE
|
SharedMaxAge: $ZITADEL_CACHE_SHARED_MAXAGE
|
||||||
|
StaticCache:
|
||||||
|
Type: bigcache
|
||||||
|
Config:
|
||||||
|
MaxCacheSizeInByte: 52428800 #50MB
|
||||||
Console:
|
Console:
|
||||||
EnvOverwriteDir: $ZITADEL_CONSOLE_ENV_DIR
|
EnvOverwriteDir: $ZITADEL_CONSOLE_ENV_DIR
|
||||||
ShortCache:
|
ShortCache:
|
||||||
@ -290,6 +295,7 @@ UI:
|
|||||||
CSPDomain: $ZITADEL_DEFAULT_DOMAIN
|
CSPDomain: $ZITADEL_DEFAULT_DOMAIN
|
||||||
|
|
||||||
Notification:
|
Notification:
|
||||||
|
APIDomain: $ZITADEL_API_DOMAIN
|
||||||
Repository:
|
Repository:
|
||||||
DefaultLanguage: 'de'
|
DefaultLanguage: 'de'
|
||||||
Domain: $ZITADEL_DEFAULT_DOMAIN
|
Domain: $ZITADEL_DEFAULT_DOMAIN
|
||||||
|
@ -26,6 +26,7 @@ import { from, Observable } from 'rxjs';
|
|||||||
import { OnboardingModule } from 'src/app/modules/onboarding/onboarding.module';
|
import { OnboardingModule } from 'src/app/modules/onboarding/onboarding.module';
|
||||||
import { RegExpPipeModule } from 'src/app/pipes/regexp-pipe/regexp-pipe.module';
|
import { RegExpPipeModule } from 'src/app/pipes/regexp-pipe/regexp-pipe.module';
|
||||||
import { SubscriptionService } from 'src/app/services/subscription.service';
|
import { SubscriptionService } from 'src/app/services/subscription.service';
|
||||||
|
import { UploadService } from 'src/app/services/upload.service';
|
||||||
|
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
@ -180,6 +181,7 @@ const authConfig: AuthConfig = {
|
|||||||
AuthenticationService,
|
AuthenticationService,
|
||||||
GrpcAuthService,
|
GrpcAuthService,
|
||||||
SubscriptionService,
|
SubscriptionService,
|
||||||
|
UploadService,
|
||||||
{ provide: 'windowObject', useValue: window },
|
{ provide: 'windowObject', useValue: window },
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
|
28
console/src/app/directives/dropzone/dropzone.directive.ts
Normal file
28
console/src/app/directives/dropzone/dropzone.directive.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Directive, EventEmitter, HostListener, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[cnslDropzone]',
|
||||||
|
})
|
||||||
|
export class DropzoneDirective {
|
||||||
|
@Output() dropped: EventEmitter<FileList> = new EventEmitter<FileList>();
|
||||||
|
@Output() hovered: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@HostListener('drop', ['$event'])
|
||||||
|
onDrop($event: DragEvent): void {
|
||||||
|
$event.preventDefault();
|
||||||
|
this.dropped.emit($event.dataTransfer?.files);
|
||||||
|
this.hovered.emit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('dragover', ['$event'])
|
||||||
|
onDragOver($event: any): void {
|
||||||
|
$event.preventDefault();
|
||||||
|
this.hovered.emit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('dragleave', ['$event'])
|
||||||
|
onDragLeave($event: any): void {
|
||||||
|
$event.preventDefault();
|
||||||
|
this.hovered.emit(false);
|
||||||
|
}
|
||||||
|
}
|
19
console/src/app/directives/dropzone/dropzone.module.ts
Normal file
19
console/src/app/directives/dropzone/dropzone.module.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
import { DropzoneDirective } from './dropzone.directive';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
DropzoneDirective,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
DropzoneDirective,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class DropzoneModule { }
|
@ -120,9 +120,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<span class="left-desc">{{'FEATURES.DATA.LABELPOLICY' | translate}}</span>
|
<span class="left-desc">{{'FEATURES.DATA.LABELPOLICYPRIVATELABEL' | translate}}</span>
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.labelPolicy"
|
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.labelPolicyPrivateLabel"
|
||||||
|
[disabled]="(['iam.features.write'] | hasRole | async) == false">
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<span class="left-desc">{{'FEATURES.DATA.LABELPOLICYWATERMARK' | translate}}</span>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.labelPolicyWatermark"
|
||||||
[disabled]="(['iam.features.write'] | hasRole | async) == false">
|
[disabled]="(['iam.features.write'] | hasRole | async) == false">
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
</div>
|
</div>
|
||||||
|
@ -158,7 +158,8 @@ export class FeaturesComponent implements OnDestroy {
|
|||||||
req.setLoginPolicyFactors(this.features.loginPolicyFactors);
|
req.setLoginPolicyFactors(this.features.loginPolicyFactors);
|
||||||
req.setLoginPolicyPasswordless(this.features.loginPolicyPasswordless);
|
req.setLoginPolicyPasswordless(this.features.loginPolicyPasswordless);
|
||||||
req.setPasswordComplexityPolicy(this.features.passwordComplexityPolicy);
|
req.setPasswordComplexityPolicy(this.features.passwordComplexityPolicy);
|
||||||
req.setLabelPolicy(this.features.labelPolicy);
|
req.setLabelPolicyPrivateLabel(this.features.labelPolicyPrivateLabel);
|
||||||
|
req.setLabelPolicyWatermark(this.features.labelPolicyWatermark);
|
||||||
req.setCustomDomain(this.features.customDomain);
|
req.setCustomDomain(this.features.customDomain);
|
||||||
|
|
||||||
this.adminService.setOrgFeatures(req).then(() => {
|
this.adminService.setOrgFeatures(req).then(() => {
|
||||||
@ -177,7 +178,8 @@ export class FeaturesComponent implements OnDestroy {
|
|||||||
dreq.setLoginPolicyFactors(this.features.loginPolicyFactors);
|
dreq.setLoginPolicyFactors(this.features.loginPolicyFactors);
|
||||||
dreq.setLoginPolicyPasswordless(this.features.loginPolicyPasswordless);
|
dreq.setLoginPolicyPasswordless(this.features.loginPolicyPasswordless);
|
||||||
dreq.setPasswordComplexityPolicy(this.features.passwordComplexityPolicy);
|
dreq.setPasswordComplexityPolicy(this.features.passwordComplexityPolicy);
|
||||||
dreq.setLabelPolicy(this.features.labelPolicy);
|
dreq.setLabelPolicyPrivateLabel(this.features.labelPolicyPrivateLabel);
|
||||||
|
dreq.setLabelPolicyWatermark(this.features.labelPolicyWatermark);
|
||||||
dreq.setCustomDomain(this.features.customDomain);
|
dreq.setCustomDomain(this.features.customDomain);
|
||||||
|
|
||||||
this.adminService.setDefaultFeatures(dreq).then(() => {
|
this.adminService.setDefaultFeatures(dreq).then(() => {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
$primary: map-get($theme, primary);
|
$primary: map-get($theme, primary);
|
||||||
$primary-color: mat.get-color-from-palette($primary, 500);
|
$primary-color: mat.get-color-from-palette($primary, 500);
|
||||||
$is-dark-theme: map-get($theme, is-dark);
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
.ng-untouched {
|
.ng-untouched {
|
||||||
.cnsl-error {
|
.cnsl-error {
|
||||||
@ -29,6 +30,10 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
color: mat.get-color-from-palette($foreground, text);
|
||||||
|
}
|
||||||
|
|
||||||
// Wrapper for the hints and error messages.
|
// Wrapper for the hints and error messages.
|
||||||
.cnsl-form-field-subscript-wrapper {
|
.cnsl-form-field-subscript-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -8,17 +8,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
flex-wrap: wrap;
|
||||||
padding-bottom: .5rem;
|
padding-bottom: .5rem;
|
||||||
|
margin: 0 -.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
.step {
|
.step {
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
max-width: 280px;
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
margin: 0 .5rem;
|
margin: 1rem .5rem;
|
||||||
border: 1px solid var(--grey);
|
border: 1px solid #8795a150;
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -26,6 +27,10 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
|
@media only screen and (min-width: 899px) {
|
||||||
|
max-width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
h6 {
|
h6 {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -46,14 +51,6 @@
|
|||||||
display: block;
|
display: block;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
|
||||||
|
|
||||||
import { LabelPolicyComponent } from './label-policy.component';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: LabelPolicyComponent,
|
|
||||||
data: {
|
|
||||||
animation: 'DetailPage',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forChild(routes)],
|
|
||||||
exports: [RouterModule],
|
|
||||||
})
|
|
||||||
export class LabelPolicyRoutingModule { }
|
|
@ -1,19 +0,0 @@
|
|||||||
<app-detail-layout [backRouterLink]="['/iam/policies']" [title]="'POLICY.LABEL.TITLE' | translate"
|
|
||||||
[description]="'POLICY.LABEL.DESCRIPTION' | translate">
|
|
||||||
|
|
||||||
<p class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</p>
|
|
||||||
|
|
||||||
<div class="content" *ngIf="labelData">
|
|
||||||
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl
|
|
||||||
[(ngModel)]="labelData.hideLoginNameSuffix">
|
|
||||||
{{'POLICY.DATA.HIDELOGINNAMESUFFIX' | translate}}
|
|
||||||
</mat-slide-toggle>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-container">
|
|
||||||
<button (click)="savePolicy()" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
|
|
||||||
}}</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
|
|
||||||
</app-detail-layout>
|
|
@ -1,23 +0,0 @@
|
|||||||
.content {
|
|
||||||
padding-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.default {
|
|
||||||
color: var(--color-main);
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-top: 3rem;
|
|
||||||
display: block;
|
|
||||||
padding: .5rem 4rem;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { LabelPolicyComponent } from './label-policy.component';
|
|
||||||
|
|
||||||
describe('LabelPolicyComponent', () => {
|
|
||||||
let component: LabelPolicyComponent;
|
|
||||||
let fixture: ComponentFixture<LabelPolicyComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [LabelPolicyComponent],
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(LabelPolicyComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,71 +0,0 @@
|
|||||||
import { Component, OnDestroy } from '@angular/core';
|
|
||||||
import { ActivatedRoute } from '@angular/router';
|
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
import { GetLabelPolicyResponse, UpdateLabelPolicyRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
|
||||||
import { LabelPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
|
||||||
import { AdminService } from 'src/app/services/admin.service';
|
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
|
||||||
|
|
||||||
import { CnslLinks } from '../../links/links.component';
|
|
||||||
import { IAM_COMPLEXITY_LINK, IAM_LOGIN_POLICY_LINK, IAM_POLICY_LINK } from '../../policy-grid/policy-links';
|
|
||||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-label-policy',
|
|
||||||
templateUrl: './label-policy.component.html',
|
|
||||||
styleUrls: ['./label-policy.component.scss'],
|
|
||||||
})
|
|
||||||
export class LabelPolicyComponent implements OnDestroy {
|
|
||||||
public labelData!: LabelPolicy.AsObject;
|
|
||||||
|
|
||||||
private sub: Subscription = new Subscription();
|
|
||||||
|
|
||||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
|
||||||
public nextLinks: CnslLinks[] = [
|
|
||||||
IAM_COMPLEXITY_LINK,
|
|
||||||
IAM_POLICY_LINK,
|
|
||||||
IAM_LOGIN_POLICY_LINK,
|
|
||||||
];
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private toast: ToastService,
|
|
||||||
private adminService: AdminService,
|
|
||||||
) {
|
|
||||||
this.route.params.subscribe(() => {
|
|
||||||
this.getData().then(data => {
|
|
||||||
if (data?.policy) {
|
|
||||||
this.labelData = data.policy;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnDestroy(): void {
|
|
||||||
this.sub.unsubscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getData(): Promise<GetLabelPolicyResponse.AsObject> {
|
|
||||||
return this.adminService.getLabelPolicy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public savePolicy(): void {
|
|
||||||
const req = new UpdateLabelPolicyRequest();
|
|
||||||
req.setPrimaryColor(this.labelData.primaryColor);
|
|
||||||
req.setSecondaryColor(this.labelData.secondaryColor);
|
|
||||||
req.setHideLoginNameSuffix(this.labelData.hideLoginNameSuffix);
|
|
||||||
this.adminService.updateLabelPolicy(req).then(() => {
|
|
||||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
|
||||||
}).catch(error => {
|
|
||||||
this.toast.showError(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isDefault(): boolean {
|
|
||||||
if (this.labelData) {
|
|
||||||
return (this.labelData as LabelPolicy.AsObject).isDefault;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
|
||||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
|
||||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
|
||||||
import { InputModule } from 'src/app/modules/input/input.module';
|
|
||||||
|
|
||||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
|
||||||
import { LinksModule } from '../../links/links.module';
|
|
||||||
import { LabelPolicyRoutingModule } from './label-policy-routing.module';
|
|
||||||
import { LabelPolicyComponent } from './label-policy.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [LabelPolicyComponent],
|
|
||||||
imports: [
|
|
||||||
LabelPolicyRoutingModule,
|
|
||||||
CommonModule,
|
|
||||||
FormsModule,
|
|
||||||
InputModule,
|
|
||||||
MatButtonModule,
|
|
||||||
MatSlideToggleModule,
|
|
||||||
MatIconModule,
|
|
||||||
HasRoleModule,
|
|
||||||
MatTooltipModule,
|
|
||||||
TranslateModule,
|
|
||||||
DetailLayoutModule,
|
|
||||||
LinksModule,
|
|
||||||
InfoSectionModule,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class LabelPolicyModule { }
|
|
@ -22,10 +22,11 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
import { CnslLinks } from '../../links/links.component';
|
import { CnslLinks } from '../../links/links.component';
|
||||||
import {
|
import {
|
||||||
IAM_COMPLEXITY_LINK,
|
IAM_COMPLEXITY_LINK,
|
||||||
IAM_LABEL_LINK,
|
|
||||||
IAM_POLICY_LINK,
|
IAM_POLICY_LINK,
|
||||||
|
IAM_PRIVATELABEL_LINK,
|
||||||
ORG_COMPLEXITY_LINK,
|
ORG_COMPLEXITY_LINK,
|
||||||
ORG_IAM_POLICY_LINK,
|
ORG_IAM_POLICY_LINK,
|
||||||
|
ORG_PRIVATELABEL_LINK,
|
||||||
} from '../../policy-grid/policy-links';
|
} from '../../policy-grid/policy-links';
|
||||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||||
import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
|
import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
|
||||||
@ -69,6 +70,7 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
this.nextLinks = [
|
this.nextLinks = [
|
||||||
ORG_COMPLEXITY_LINK,
|
ORG_COMPLEXITY_LINK,
|
||||||
ORG_IAM_POLICY_LINK,
|
ORG_IAM_POLICY_LINK,
|
||||||
|
ORG_PRIVATELABEL_LINK,
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case PolicyComponentServiceType.ADMIN:
|
case PolicyComponentServiceType.ADMIN:
|
||||||
@ -80,7 +82,7 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
this.nextLinks = [
|
this.nextLinks = [
|
||||||
IAM_COMPLEXITY_LINK,
|
IAM_COMPLEXITY_LINK,
|
||||||
IAM_POLICY_LINK,
|
IAM_POLICY_LINK,
|
||||||
IAM_LABEL_LINK,
|
IAM_PRIVATELABEL_LINK,
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -96,7 +98,7 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
if (resp.policy) {
|
if (resp.policy) {
|
||||||
this.loginData = resp.policy;
|
this.loginData = resp.policy;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.disabled = this.isDefault ?? false;
|
this.disabled = ((this.loginData as LoginPolicy.AsObject)?.isDefault) ?? false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.getIdps().then(resp => {
|
this.getIdps().then(resp => {
|
||||||
|
@ -14,10 +14,11 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
import { CnslLinks } from '../../links/links.component';
|
import { CnslLinks } from '../../links/links.component';
|
||||||
import {
|
import {
|
||||||
IAM_COMPLEXITY_LINK,
|
IAM_COMPLEXITY_LINK,
|
||||||
IAM_LABEL_LINK,
|
|
||||||
IAM_LOGIN_POLICY_LINK,
|
IAM_LOGIN_POLICY_LINK,
|
||||||
|
IAM_PRIVATELABEL_LINK,
|
||||||
ORG_COMPLEXITY_LINK,
|
ORG_COMPLEXITY_LINK,
|
||||||
ORG_LOGIN_POLICY_LINK,
|
ORG_LOGIN_POLICY_LINK,
|
||||||
|
ORG_PRIVATELABEL_LINK,
|
||||||
} from '../../policy-grid/policy-links';
|
} from '../../policy-grid/policy-links';
|
||||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||||
|
|
||||||
@ -55,12 +56,13 @@ export class OrgIamPolicyComponent implements OnDestroy {
|
|||||||
this.nextLinks = [
|
this.nextLinks = [
|
||||||
ORG_COMPLEXITY_LINK,
|
ORG_COMPLEXITY_LINK,
|
||||||
ORG_LOGIN_POLICY_LINK,
|
ORG_LOGIN_POLICY_LINK,
|
||||||
|
ORG_PRIVATELABEL_LINK,
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
this.nextLinks = [
|
this.nextLinks = [
|
||||||
IAM_COMPLEXITY_LINK,
|
IAM_COMPLEXITY_LINK,
|
||||||
IAM_LOGIN_POLICY_LINK,
|
IAM_LOGIN_POLICY_LINK,
|
||||||
IAM_LABEL_LINK,
|
IAM_PRIVATELABEL_LINK,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return this.route.params;
|
return this.route.params;
|
||||||
|
@ -15,11 +15,12 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
|
|
||||||
import { CnslLinks } from '../../links/links.component';
|
import { CnslLinks } from '../../links/links.component';
|
||||||
import {
|
import {
|
||||||
IAM_LABEL_LINK,
|
|
||||||
IAM_LOGIN_POLICY_LINK,
|
IAM_LOGIN_POLICY_LINK,
|
||||||
IAM_POLICY_LINK,
|
IAM_POLICY_LINK,
|
||||||
|
IAM_PRIVATELABEL_LINK,
|
||||||
ORG_IAM_POLICY_LINK,
|
ORG_IAM_POLICY_LINK,
|
||||||
ORG_LOGIN_POLICY_LINK,
|
ORG_LOGIN_POLICY_LINK,
|
||||||
|
ORG_PRIVATELABEL_LINK,
|
||||||
} from '../../policy-grid/policy-links';
|
} from '../../policy-grid/policy-links';
|
||||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
|||||||
this.nextLinks = [
|
this.nextLinks = [
|
||||||
ORG_IAM_POLICY_LINK,
|
ORG_IAM_POLICY_LINK,
|
||||||
ORG_LOGIN_POLICY_LINK,
|
ORG_LOGIN_POLICY_LINK,
|
||||||
|
ORG_PRIVATELABEL_LINK,
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case PolicyComponentServiceType.ADMIN:
|
case PolicyComponentServiceType.ADMIN:
|
||||||
@ -60,7 +62,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
|||||||
this.nextLinks = [
|
this.nextLinks = [
|
||||||
IAM_POLICY_LINK,
|
IAM_POLICY_LINK,
|
||||||
IAM_LOGIN_POLICY_LINK,
|
IAM_LOGIN_POLICY_LINK,
|
||||||
IAM_LABEL_LINK,
|
IAM_PRIVATELABEL_LINK,
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ export enum PolicyComponentType {
|
|||||||
COMPLEXITY = 'complexity',
|
COMPLEXITY = 'complexity',
|
||||||
IAM = 'iam',
|
IAM = 'iam',
|
||||||
LOGIN = 'login',
|
LOGIN = 'login',
|
||||||
LABEL = 'label',
|
PRIVATELABEL = 'privatelabel',
|
||||||
}
|
}
|
||||||
export enum PolicyComponentServiceType {
|
export enum PolicyComponentServiceType {
|
||||||
MGMT = 'mgmt',
|
MGMT = 'mgmt',
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
<div class="form-row">
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{name}} (current {{color}})</cnsl-label>
|
||||||
|
<input cnslInput [(ngModel)]="previewColor" (keydown.enter)="name ? emitPreview(previewColor) : null" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<button matTooltip="{{'ACTIONS.SET' | translate}}" (click)="emitPreview(previewColor)" mat-icon-button><mat-icon>check</mat-icon></button>
|
||||||
|
</div>
|
||||||
|
<div class="color-selector">
|
||||||
|
<div *ngFor="let c of colors" class="circle mat-elevation-z3"
|
||||||
|
[ngClass]="{'active': color == c.color || previewColor == c.color}"
|
||||||
|
(click)="emitPreview(c.color)" [ngStyle]="{'background-color': c.color}">
|
||||||
|
<span *ngIf="previewColor == c.color">P</span>
|
||||||
|
<span *ngIf="color == c.color">C</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,52 @@
|
|||||||
|
.title {
|
||||||
|
// font-size: 1rem;
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
|
||||||
|
&.border {
|
||||||
|
border-top: 1px solid var(--grey);
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
.formfield {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-bottom: .9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 0 -.25rem;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
background-color: #cd5c5c;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: .25rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border: 3px solid #ffffff90;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ColorComponent } from './color.component';
|
||||||
|
|
||||||
|
describe('ColorComponent', () => {
|
||||||
|
let component: ColorComponent;
|
||||||
|
let fixture: ComponentFixture<ColorComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ColorComponent],
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ColorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,118 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
|
||||||
|
import { ColorType } from '../private-labeling-policy.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'cnsl-color',
|
||||||
|
templateUrl: './color.component.html',
|
||||||
|
styleUrls: ['./color.component.scss'],
|
||||||
|
})
|
||||||
|
export class ColorComponent implements OnInit {
|
||||||
|
public PRIMARY: Array<{ name: string; color: string; }> = [
|
||||||
|
{ name: 'red', color: '#f44336' },
|
||||||
|
{ name: 'pink', color: '#e91e63' },
|
||||||
|
{ name: 'purple', color: '#9c27b0' },
|
||||||
|
{ name: 'deeppurple', color: '#673ab7' },
|
||||||
|
{ name: 'indigo', color: '#3f51b5' },
|
||||||
|
{ name: 'blue', color: '#2196f3' },
|
||||||
|
{ name: 'lightblue', color: '#03a9f4' },
|
||||||
|
{ name: 'cyan', color: '#00bcd4' },
|
||||||
|
{ name: 'teal', color: '#009688' },
|
||||||
|
{ name: 'green', color: '#4caf50' },
|
||||||
|
{ name: 'lightgreen', color: '#8bc34a' },
|
||||||
|
{ name: 'lime', color: '#cddc39' },
|
||||||
|
{ name: 'yellow', color: '#ffeb3b' },
|
||||||
|
{ name: 'amber', color: '#ffc107' },
|
||||||
|
{ name: 'orange', color: '#fb8c00' },
|
||||||
|
{ name: 'deeporange', color: '#ff5722' },
|
||||||
|
{ name: 'brown', color: '#795548' },
|
||||||
|
{ name: 'grey', color: '#9e9e9e' },
|
||||||
|
{ name: 'bluegrey', color: '#607d8b' },
|
||||||
|
{ name: 'white', color: '#ffffff' },
|
||||||
|
];
|
||||||
|
|
||||||
|
public WARN: Array<{ name: string; color: string; }> = [
|
||||||
|
{ name: 'red', color: '#f44336' },
|
||||||
|
{ name: 'pink', color: '#e91e63' },
|
||||||
|
{ name: 'purple', color: '#9c27b0' },
|
||||||
|
{ name: 'deeppurple', color: '#673ab7' },
|
||||||
|
];
|
||||||
|
|
||||||
|
public FONTLIGHT: Array<{ name: string; color: string; }> = [
|
||||||
|
{ name: 'gray-500', color: '#6b7280' },
|
||||||
|
{ name: 'gray-600', color: '#4b5563' },
|
||||||
|
{ name: 'gray-700', color: '#374151' },
|
||||||
|
{ name: 'gray-800', color: '#1f2937' },
|
||||||
|
{ name: 'gray-900', color: '#111827' },
|
||||||
|
{ name: 'black', color: '#000000' },
|
||||||
|
];
|
||||||
|
|
||||||
|
public FONTDARK: Array<{ name: string; color: string; }> = [
|
||||||
|
{ name: 'white', color: '#ffffff' },
|
||||||
|
{ name: 'gray-50', color: '#f9fafb' },
|
||||||
|
{ name: 'gray-100', color: '#f3f4f6' },
|
||||||
|
{ name: 'gray-200', color: '#e5e7eb' },
|
||||||
|
{ name: 'gray-300', color: '#d1d5db' },
|
||||||
|
{ name: 'gray-400', color: '#9ca3af' },
|
||||||
|
{ name: 'gray-500', color: '#6b7280' },
|
||||||
|
];
|
||||||
|
|
||||||
|
public BACKGROUNDLIGHT: Array<{ name: string; color: string; }> = [
|
||||||
|
{ name: 'white', color: '#ffffff' },
|
||||||
|
{ name: 'gray-50', color: '#f9fafb' },
|
||||||
|
{ name: 'gray-100', color: '#f3f4f6' },
|
||||||
|
{ name: 'gray-200', color: '#e5e7eb' },
|
||||||
|
{ name: 'gray-300', color: '#d1d5db' },
|
||||||
|
{ name: 'gray-400', color: '#9ca3af' },
|
||||||
|
{ name: 'gray-500', color: '#6b7280' },
|
||||||
|
];
|
||||||
|
|
||||||
|
public BACKGROUNDDARK: Array<{ name: string; color: string; }> = [
|
||||||
|
{ name: 'gray-500', color: '#6b7280' },
|
||||||
|
{ name: 'gray-600', color: '#4b5563' },
|
||||||
|
{ name: 'gray-700', color: '#374151' },
|
||||||
|
{ name: 'gray-800', color: '#1f2937' },
|
||||||
|
{ name: 'gray-900', color: '#111827' },
|
||||||
|
{ name: 'black', color: '#000000' },
|
||||||
|
];
|
||||||
|
|
||||||
|
public colors: Array<{ name: string; color: string; }> = this.PRIMARY;
|
||||||
|
|
||||||
|
@Input() colorType: ColorType = ColorType.PRIMARY;
|
||||||
|
@Input() color: string = '';
|
||||||
|
@Input() previewColor: string = '';
|
||||||
|
@Input() name: string = '';
|
||||||
|
@Output() previewChanged: EventEmitter<string> = new EventEmitter();
|
||||||
|
|
||||||
|
public emitPreview(color: string): void {
|
||||||
|
this.previewColor = color;
|
||||||
|
this.previewChanged.emit(this.previewColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
|
||||||
|
switch (this.colorType) {
|
||||||
|
case ColorType.PRIMARY:
|
||||||
|
this.colors = this.PRIMARY;
|
||||||
|
break;
|
||||||
|
case ColorType.WARN:
|
||||||
|
this.colors = this.WARN;
|
||||||
|
break;
|
||||||
|
case ColorType.FONTDARK:
|
||||||
|
this.colors = this.FONTDARK;
|
||||||
|
break;
|
||||||
|
case ColorType.FONTLIGHT:
|
||||||
|
this.colors = this.FONTLIGHT;
|
||||||
|
break;
|
||||||
|
case ColorType.BACKGROUNDDARK:
|
||||||
|
this.colors = this.BACKGROUNDDARK;
|
||||||
|
break;
|
||||||
|
case ColorType.BACKGROUNDLIGHT:
|
||||||
|
this.colors = this.BACKGROUNDLIGHT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.colors = this.PRIMARY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<div class="preview" *ngIf="policy">
|
||||||
|
<span class="label">{{label}}</span>
|
||||||
|
<div class="dashed" [ngClass]="{'dark': theme === Theme.DARK, 'light': theme === Theme.LIGHT}" [style.background]="theme == Theme.DARK ? policy.backgroundColorDark : policy.backgroundColor">
|
||||||
|
<div class="login-wrapper" [style.color]="theme == Theme.DARK ? policy.fontColorDark : policy.fontColor">
|
||||||
|
<img *ngIf="images['previewLogo'] && theme == Theme.LIGHT" [src]="images['previewLogo']" alt="logo-mock" />
|
||||||
|
<img *ngIf="!images['previewLogo'] && theme == Theme.LIGHT" src="../../../../assets/images/zitadel-logo-dark.svg" alt="logo-mock" />
|
||||||
|
|
||||||
|
<img *ngIf="images['previewDarkLogo'] && theme == Theme.DARK" [src]="images['previewDarkLogo']" alt="logo-mock" />
|
||||||
|
<img *ngIf="!images['previewDarkLogo'] && theme == Theme.DARK" src="../../../../assets/images/zitadel-logo-light.svg" alt="logo-mock" />
|
||||||
|
|
||||||
|
<h1>{{'POLICY.PRIVATELABELING.PREVIEW.TITLE' | translate}}</h1>
|
||||||
|
<p class="desc-text">{{'POLICY.PRIVATELABELING.PREVIEW.SECOND' | translate}}</p>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>Loginname</cnsl-label>
|
||||||
|
<input cnslInput value="road.runner"/>
|
||||||
|
</cnsl-form-field>
|
||||||
|
|
||||||
|
<div class="error-msg" [style.color]="theme == Theme.DARK ? policy.warnColorDark : policy.warnColor">
|
||||||
|
<i class="las la-exclamation-circle" [style.color]="theme == Theme.DARK ? policy.warnColorDark : policy.warnColor"></i>
|
||||||
|
<span [style.color]="theme == Theme.DARK ? policy.warnColorDark : policy.warnColor">{{'POLICY.PRIVATELABELING.PREVIEW.ERROR' | translate}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-wrapper">
|
||||||
|
<button mat-stroked-button>{{'POLICY.PRIVATELABELING.PREVIEW.SECONDARYBUTTON' | translate}}</button>
|
||||||
|
<button *ngIf="theme == Theme.DARK" mat-raised-button [style.background]="policy.primaryColorDark" [style.color]="policy.primaryColorDark == '#ffffff' ? '#000000' : '#ffffff'">{{'POLICY.PRIVATELABELING.PREVIEW.PRIMARYBUTTON' | translate}}</button>
|
||||||
|
<button *ngIf="theme == Theme.LIGHT" mat-raised-button [style.background]="policy.primaryColor" [style.color]="policy.primaryColor == '#ffffff' ? '#000000' : '#ffffff'">{{'POLICY.PRIVATELABELING.PREVIEW.PRIMARYBUTTON' | translate}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,92 @@
|
|||||||
|
.preview {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
* {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--grey);
|
||||||
|
font-size: 12px;
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashed {
|
||||||
|
border: 2px dashed rgba(#697386, .5);
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 100px 20px;
|
||||||
|
|
||||||
|
.login-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 360px;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1000px) {
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 160px;
|
||||||
|
max-height: 150px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formfield {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-wrapper {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-msg {
|
||||||
|
align-self: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
outline: none;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.light {
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
.login-wrapper *:not(.cnsl-label):not(.mat-button-wrapper) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark {
|
||||||
|
background: #212224;
|
||||||
|
|
||||||
|
.login-wrapper *:not(.cnsl-label):not(.mat-button-wrapper) {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PreviewComponent } from './preview.component';
|
||||||
|
|
||||||
|
describe('PreviewComponent', () => {
|
||||||
|
let component: PreviewComponent;
|
||||||
|
let fixture: ComponentFixture<PreviewComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [PreviewComponent],
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PreviewComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,35 @@
|
|||||||
|
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { Observable, of, Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { LabelPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||||
|
|
||||||
|
import { Preview, Theme } from '../private-labeling-policy.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'cnsl-preview',
|
||||||
|
templateUrl: './preview.component.html',
|
||||||
|
styleUrls: ['./preview.component.scss'],
|
||||||
|
})
|
||||||
|
export class PreviewComponent implements OnInit, OnDestroy {
|
||||||
|
@Input() preview: Preview = Preview.PREVIEW;
|
||||||
|
@Input() policy!: LabelPolicy.AsObject;
|
||||||
|
@Input() label: string = 'PREVIEW';
|
||||||
|
@Input() images: { [imagekey: string]: any; } = {};
|
||||||
|
@Input() theme: Theme = Theme.DARK;
|
||||||
|
@Input() refresh: Observable<void> = of();
|
||||||
|
private destroyed$: Subject<void> = new Subject();
|
||||||
|
public Theme: any = Theme;
|
||||||
|
public Preview: any = Preview;
|
||||||
|
constructor(private chd: ChangeDetectorRef) { }
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.refresh.pipe(takeUntil(this.destroyed$)).subscribe(() => {
|
||||||
|
this.chd.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnDestroy(): void {
|
||||||
|
this.destroyed$.next();
|
||||||
|
this.destroyed$.complete();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { PrivateLabelingPolicyComponent } from './private-labeling-policy.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: PrivateLabelingPolicyComponent,
|
||||||
|
data: {
|
||||||
|
animation: 'DetailPage',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class PrivateLabelingPolicyRoutingModule { }
|
@ -0,0 +1,254 @@
|
|||||||
|
<div class="policy enlarged-container">
|
||||||
|
<div class="header">
|
||||||
|
<a [routerLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']" mat-icon-button>
|
||||||
|
<mat-icon class="icon">arrow_back</mat-icon>
|
||||||
|
</a>
|
||||||
|
<div class="col">
|
||||||
|
<h1>{{'POLICY.PRIVATELABELING.TITLE' | translate}}</h1>
|
||||||
|
<p>{{'POLICY.PRIVATELABELING.DESCRIPTION' | translate}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="desc">{{'POLICY.PRIVATELABELING.PREVIEW_DESCRIPTION' | translate}}</p>
|
||||||
|
<p class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</p>
|
||||||
|
|
||||||
|
<div class="spinner-wr">
|
||||||
|
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template appHasRole [appHasRole]="['policy.delete']">
|
||||||
|
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
||||||
|
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
|
||||||
|
{{'POLICY.RESET' | translate}}
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<div class="top-row">
|
||||||
|
<div>
|
||||||
|
<p>{{'POLICY.PRIVATELABELING.THEME' | translate}}</p>
|
||||||
|
<div class="theme-changer">
|
||||||
|
<button (click)="theme = Theme.LIGHT" matTooltip="{{'POLICY.PRIVATELABELING.LIGHT' | translate}}" class="light" [ngClass]="{'active': theme === Theme.LIGHT}" >
|
||||||
|
<i class="icon las la-edit"></i>
|
||||||
|
</button>
|
||||||
|
<button (click)="theme = Theme.DARK" matTooltip="{{'POLICY.PRIVATELABELING.DARK' | translate}}" class="dark" [ngClass]="{'active': theme === Theme.DARK}" >
|
||||||
|
<i class="icon las la-edit"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="activate-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false" mat-raised-button color="primary" (click)="activatePolicy()">
|
||||||
|
{{'POLICY.PRIVATELABELING.ACTIVATEPREVIEW' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="previewData && data" class="lab-policy-content">
|
||||||
|
|
||||||
|
<mat-accordion class="settings">
|
||||||
|
<mat-expansion-panel class="expansion">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
<div class="panel-title">
|
||||||
|
<i class="icon las la-image"></i>
|
||||||
|
Logo</div>
|
||||||
|
</mat-panel-title>
|
||||||
|
<mat-panel-description>
|
||||||
|
|
||||||
|
</mat-panel-description>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<p class="description">Your Logo will be used in the Login itself, while the icon is used for smaller UI elements like in the organisation switcher in console</p>
|
||||||
|
|
||||||
|
<!-- <span class="title">{{ theme === Theme.DARK ? ('POLICY.PRIVATELABELING.DARK' | translate) : ('POLICY.PRIVATELABELING.LIGHT' | translate)}}</span> -->
|
||||||
|
<div class="logo-setup-wrapper">
|
||||||
|
<div class="part">
|
||||||
|
<span class="label">Logo</span>
|
||||||
|
<mat-spinner class="spinner" color="primary" diameter="25" *ngIf="loadingImages"></mat-spinner>
|
||||||
|
<container [ngSwitch]="theme">
|
||||||
|
<div class="logo-view" *ngSwitchCase="Theme.DARK">
|
||||||
|
<img matTooltip="Preview" class="prev" *ngIf="images['previewDarkLogo']" [src]="images['previewDarkLogo']" alt="dark logo preview"/>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<img matTooltip="Current" class="curr" *ngIf="images['darkLogo']" [src]="images['darkLogo']" alt="dark logo"/>
|
||||||
|
</div>
|
||||||
|
<div class="logo-view" *ngSwitchCase="Theme.LIGHT">
|
||||||
|
<img matTooltip="Preview" class="prev" *ngIf="images['previewLogo']" [src]="images['previewLogo']" alt="logo preview"/>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<img matTooltip="Current" class="curr" *ngIf="images['logo']" [src]="images['logo']" alt="logo"/>
|
||||||
|
</div>
|
||||||
|
</container>
|
||||||
|
<div class="dropzone" cnslDropzone (hovered)="toggleHoverLogo(theme, $event)"
|
||||||
|
(dropped)="onDropLogo(theme, $event)"
|
||||||
|
[class.hovering]="isHoveringOverDarkLogo">
|
||||||
|
<label class="file-label">
|
||||||
|
<input #selectedFile style="display: none;" class="file-input" type="file" (change)="onDropLogo(theme, $event.target.files)">
|
||||||
|
<input class="btn" mat-raised-button type="button" [value]="'POLICY.PRIVATELABELING.BTN' | translate" (click)="selectedFile.click();" />
|
||||||
|
|
||||||
|
<i class="icon las la-cloud-upload-alt"></i>
|
||||||
|
<span>{{isHoveringOverDarkLogo ? 'Release': 'Drop your Logo here'}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="part">
|
||||||
|
<span class="label">Icon</span>
|
||||||
|
<mat-spinner class="spinner" color="primary" diameter="25" *ngIf="loadingImages"></mat-spinner>
|
||||||
|
<container [ngSwitch]="theme">
|
||||||
|
<div class="logo-view" *ngSwitchCase="Theme.DARK">
|
||||||
|
<img matTooltip="Preview" class="prev" *ngIf="images['previewDarkIcon']" [src]="images['previewDarkIcon']" alt="dark icon preview"/>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<img matTooltip="Current" class="curr" *ngIf="images['darkIcon']" [src]="images['darkIcon']" alt="dark icon"/>
|
||||||
|
</div>
|
||||||
|
<div class="logo-view" *ngSwitchCase="Theme.LIGHT">
|
||||||
|
<img matTooltip="Preview" class="prev" *ngIf="images['previewIcon']" [src]="images['previewIcon']" alt="icon preview"/>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<img matTooltip="Current" class="curr" *ngIf="images['icon']" [src]="images['icon']" alt="icon"/>
|
||||||
|
</div>
|
||||||
|
</container>
|
||||||
|
<div class="dropzone" cnslDropzone (hovered)="toggleHoverIcon(theme, $event)"
|
||||||
|
(dropped)="onDropIcon(theme, $event)"
|
||||||
|
[class.hovering]="isHoveringOverDarkIcon">
|
||||||
|
<label class="file-label">
|
||||||
|
<input #selectedFileIcon style="display: none;" class="file-input" type="file" (change)="onDropIcon(theme, $event.target.files)">
|
||||||
|
<input class="btn" mat-raised-button type="button" [value]="'POLICY.PRIVATELABELING.BTN' | translate" (click)="selectedFileIcon.click();" />
|
||||||
|
|
||||||
|
<i class="icon las la-cloud-upload-alt"></i>
|
||||||
|
<span>{{isHoveringOverDarkIcon ? 'Release': 'Drop your Logo here'}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
<mat-expansion-panel class="expansion" [expanded]="true">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
<div class="panel-title">
|
||||||
|
<i class="icon las la-palette"></i>
|
||||||
|
{{'POLICY.PRIVATELABELING.COLORS' | translate}}</div>
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<!-- <span class="title">{{ theme === Theme.DARK ? ('POLICY.PRIVATELABELING.DARK' | translate) : ('POLICY.PRIVATELABELING.LIGHT' | translate)}}</span> -->
|
||||||
|
|
||||||
|
<ng-container *ngIf="theme==Theme.DARK">
|
||||||
|
<div class="colors" *ngIf="data && previewData">
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.BACKGROUNDDARK"(previewChanged)="previewData.backgroundColorDark = $event; savePolicy()" name="Background Color Dark" [color]="data.backgroundColorDark" [previewColor]="previewData.backgroundColorDark"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.PRIMARY"(previewChanged)="previewData.primaryColorDark = $event; savePolicy()" name="Preview Primary Color Dark" [color]="data.primaryColorDark" [previewColor]="previewData.primaryColorDark"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.WARN" (previewChanged)="previewData.warnColorDark = $event; savePolicy()" name="Preview Warn Color Dark" [color]="data.warnColorDark" [previewColor]="previewData.warnColorDark"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.FONTDARK"(previewChanged)="previewData.fontColorDark = $event; savePolicy()" name="Font Color Dark" [color]="data.fontColorDark" [previewColor]="previewData.fontColorDark"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="theme==Theme.LIGHT">
|
||||||
|
<div class="colors" *ngIf="data && previewData">
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.BACKGROUNDLIGHT" (previewChanged)="previewData.backgroundColor = $event; savePolicy()" name="Background Color Light" [color]="data.backgroundColor" [previewColor]="previewData.backgroundColor"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.PRIMARY" (previewChanged)="previewData.primaryColor = $event; savePolicy()" name="Preview Primary Color Light" [color]="data.primaryColor" [previewColor]="previewData.primaryColor"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.WARN" name="Preview Warn Color Light" (previewChanged)="previewData.warnColor= $event; savePolicy()" [color]="data.warnColor" [previewColor]="previewData.warnColor"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color">
|
||||||
|
<cnsl-color [colorType]="ColorType.FONTLIGHT" (previewChanged)="previewData.fontColor = $event; savePolicy()" name="Font Color" [color]="data.fontColor" [previewColor]="previewData.fontColor"></cnsl-color>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
<mat-expansion-panel class="expansion">
|
||||||
|
<mat-expansion-panel-header class="header">
|
||||||
|
<mat-panel-title>
|
||||||
|
<div class="panel-title">
|
||||||
|
<i class="icon las la-font"></i>
|
||||||
|
{{'POLICY.PRIVATELABELING.FONT' | translate}}</div>
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="fonts">
|
||||||
|
<div class="font-preview">
|
||||||
|
<mat-icon>text_fields</mat-icon>
|
||||||
|
<span>ABC • abc • 123</span>
|
||||||
|
<span>_</span>
|
||||||
|
<span>Upload your favorite font for the UI</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dropzone" cnslDropzone (hovered)="toggleHoverFont($event)"
|
||||||
|
(dropped)="onDropFont($event)"
|
||||||
|
[class.hovering]="isHoveringOverFont">
|
||||||
|
<label class="file-label">
|
||||||
|
<input #selectedFontFile style="display: none;" class="file-input" type="file" (change)="onDropFont($event.target.files)">
|
||||||
|
<input class="btn" mat-raised-button type="button" [value]="'POLICY.PRIVATELABELING.BTN' | translate" (click)="selectedFontFile.click();" />
|
||||||
|
|
||||||
|
<i class="icon las la-cloud-upload-alt"></i>
|
||||||
|
<span >{{isHoveringOverFont ? 'Release': 'Drop your Logo here'}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
<mat-expansion-panel class="expansion">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
<div class="panel-title">
|
||||||
|
<i class="icon las la-universal-access"></i>
|
||||||
|
{{'POLICY.PRIVATELABELING.ADVANCEDBEHAVIOR' | translate}}
|
||||||
|
</div>
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="adv-container" *ngIf="previewData">
|
||||||
|
|
||||||
|
<ng-container
|
||||||
|
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false">
|
||||||
|
<cnsl-info-section class="info" type="WARN">{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||||
|
'label_policy.private_label'})}}
|
||||||
|
</cnsl-info-section>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl
|
||||||
|
[(ngModel)]="previewData.hideLoginNameSuffix" (change)="savePolicy()">
|
||||||
|
{{'POLICY.DATA.HIDELOGINNAMESUFFIX' | translate}}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
|
||||||
|
<ng-container
|
||||||
|
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.watermark'] | hasFeature | async) == false">
|
||||||
|
<cnsl-info-section class="info" type="WARN">{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||||
|
'label_policy.watermark'})}}
|
||||||
|
</cnsl-info-section>
|
||||||
|
</ng-container>
|
||||||
|
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.watermark'] | hasFeature | async) == false"
|
||||||
|
[(ngModel)]="previewData.disableWatermark" (change)="saveWatermark()">
|
||||||
|
{{'POLICY.DATA.DISABLEWATERMARK' | translate}}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
||||||
|
|
||||||
|
<div class="preview-wrapper">
|
||||||
|
<!-- <cnsl-preview class="prev" label="CURRENT CONFIG" [policy]="data"></cnsl-preview> -->
|
||||||
|
<div class="col">
|
||||||
|
<button color="primary" mat-raised-button class="preview-changer" (click)="preview = preview == Preview.PREVIEW ? Preview.CURRENT : Preview.PREVIEW" matTooltip="{{'POLICY.PRIVATELABELING.CHANGEVIEW' | translate}}" [ngClass]="{'active': preview === Preview.PREVIEW}" >
|
||||||
|
<span><span [ngClass]="{'strong': preview == Preview.PREVIEW}">P</span> / <span [ngClass]="{'strong': preview == Preview.CURRENT}">C</span></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<cnsl-preview *ngIf="preview === Preview.CURRENT" [refresh]="refreshPreview" [images]="images" [preview]="preview" [theme]="theme" class="prev" label="CURRENT" [policy]="data"></cnsl-preview>
|
||||||
|
<cnsl-preview *ngIf="preview === Preview.PREVIEW" [refresh]="refreshPreview" [images]="images" [preview]="preview" [theme]="theme" class="prev" label="PREVIEW" [policy]="previewData"></cnsl-preview>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
|
||||||
|
</div>
|
@ -0,0 +1,398 @@
|
|||||||
|
@use '~@angular/material' as mat;
|
||||||
|
|
||||||
|
@import './preview/preview.component.scss';
|
||||||
|
|
||||||
|
@mixin private-label-theme($theme) {
|
||||||
|
$primary: map-get($theme, primary);
|
||||||
|
$primary-color: mat.get-color-from-palette($primary, 500);
|
||||||
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
|
|
||||||
|
.policy {
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 1rem;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.default {
|
||||||
|
color: var(--color-main);
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--grey);
|
||||||
|
max-width: 800px;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner-wr {
|
||||||
|
margin: .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-changer {
|
||||||
|
display: flex;
|
||||||
|
margin: 1rem -.5rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid #81868a50;
|
||||||
|
margin: 0 .5rem;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
background-color: black;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.icon {
|
||||||
|
visibility: visible;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light {
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.icon {
|
||||||
|
visibility: visible;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.activate-button {
|
||||||
|
border-radius: 50%;
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-changer {
|
||||||
|
display: flex;
|
||||||
|
margin: 0 -.25rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid #81868a50;
|
||||||
|
margin: 0 .25rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
background-color: black;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
transform: scale(1.1);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
visibility: visible;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light {
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
transform: scale(1.1);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
visibility: visible;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lab-policy-content {
|
||||||
|
padding-top: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 0 -1rem;
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
.expansion {
|
||||||
|
background: if($is-dark-theme, #2d2e30, #fff) !important;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropzone {
|
||||||
|
outline: none;
|
||||||
|
height: 150px;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: if($is-dark-theme, #2d2e30, #fff);
|
||||||
|
border: 1px solid if($is-dark-theme, #4a4b4b, #ddd);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: all .2s ease-in-out;
|
||||||
|
|
||||||
|
.file-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
background-color: inherit;
|
||||||
|
border: 1px solid if($is-dark-theme, #ffffff20, #000);
|
||||||
|
color: if($is-dark-theme, white, #000);
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hovering {
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow:
|
||||||
|
if(
|
||||||
|
$is-dark-theme,
|
||||||
|
(inset 26px 26px 52px #252628, inset -26px -26px 52px #353638),
|
||||||
|
(inset 26px 26px 52px #d4d4d4, inset -26px -26px 52px #fff)
|
||||||
|
);
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
color: if($is-dark-theme, white, black);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
color: if($is-dark-theme, white, black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-setup-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.part {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--grey);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-view {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.prev,
|
||||||
|
.curr {
|
||||||
|
height: 50px;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fill-space {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.colors {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.color {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fonts {
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-preview {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 30px 50px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-selector {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 0 -.25rem;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
|
||||||
|
.font {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: .5rem;
|
||||||
|
margin: .25rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 2px solid if($is-dark-theme, #ffffff30, #00000030);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border: 2px solid if($is-dark-theme, #fff, #000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adv-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-wrapper {
|
||||||
|
margin: 0 1rem;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
position: relative;
|
||||||
|
min-height: 600px;
|
||||||
|
|
||||||
|
.preview-changer {
|
||||||
|
position: absolute;
|
||||||
|
top: .5rem;
|
||||||
|
left: .5rem;
|
||||||
|
border-radius: 10px !important;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: if($is-dark-theme, #ffffff50, #00000050);
|
||||||
|
}
|
||||||
|
|
||||||
|
.strong {
|
||||||
|
color: if($is-dark-theme, #fff, #000);
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1000px) {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.preview-wrapper {
|
||||||
|
.col {
|
||||||
|
min-width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 3rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PrivateLabelingPolicyComponent } from './private-labeling-policy.component';
|
||||||
|
|
||||||
|
describe('PrivateLabelingPolicyComponent', () => {
|
||||||
|
let component: PrivateLabelingPolicyComponent;
|
||||||
|
let fixture: ComponentFixture<PrivateLabelingPolicyComponent>;
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [PrivateLabelingPolicyComponent],
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PrivateLabelingPolicyComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,511 @@
|
|||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { Component, EventEmitter, Injector, OnDestroy, Type } from '@angular/core';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
import {
|
||||||
|
GetLabelPolicyResponse as AdminGetLabelPolicyResponse,
|
||||||
|
GetPreviewLabelPolicyResponse as AdminGetPreviewLabelPolicyResponse,
|
||||||
|
UpdateLabelPolicyRequest,
|
||||||
|
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||||
|
import {
|
||||||
|
AddCustomLabelPolicyRequest,
|
||||||
|
GetLabelPolicyResponse as MgmtGetLabelPolicyResponse,
|
||||||
|
GetPreviewLabelPolicyResponse as MgmtGetPreviewLabelPolicyResponse,
|
||||||
|
UpdateCustomLabelPolicyRequest,
|
||||||
|
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||||
|
import { LabelPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||||
|
import { AdminService } from 'src/app/services/admin.service';
|
||||||
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { DownloadEndpoint, UploadEndpoint, UploadService } from 'src/app/services/upload.service';
|
||||||
|
|
||||||
|
import { CnslLinks } from '../../links/links.component';
|
||||||
|
import { IAM_COMPLEXITY_LINK, IAM_LOGIN_POLICY_LINK, IAM_POLICY_LINK } from '../../policy-grid/policy-links';
|
||||||
|
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||||
|
|
||||||
|
export enum Theme {
|
||||||
|
DARK,
|
||||||
|
LIGHT,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Preview {
|
||||||
|
CURRENT,
|
||||||
|
PREVIEW,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ColorType {
|
||||||
|
BACKGROUND,
|
||||||
|
PRIMARY,
|
||||||
|
WARN,
|
||||||
|
FONTDARK,
|
||||||
|
FONTLIGHT,
|
||||||
|
BACKGROUNDDARK,
|
||||||
|
BACKGROUNDLIGHT,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-private-labeling-policy',
|
||||||
|
templateUrl: './private-labeling-policy.component.html',
|
||||||
|
styleUrls: ['./private-labeling-policy.component.scss'],
|
||||||
|
})
|
||||||
|
export class PrivateLabelingPolicyComponent implements OnDestroy {
|
||||||
|
public theme: Theme = Theme.LIGHT;
|
||||||
|
public preview: Preview = Preview.PREVIEW;
|
||||||
|
|
||||||
|
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||||
|
public service!: ManagementService | AdminService;
|
||||||
|
|
||||||
|
public previewData!: LabelPolicy.AsObject;
|
||||||
|
public data!: LabelPolicy.AsObject;
|
||||||
|
|
||||||
|
public images: { [key: string]: any; } = {};
|
||||||
|
|
||||||
|
public panelOpenState: boolean = false;
|
||||||
|
public isHoveringOverDarkLogo: boolean = false;
|
||||||
|
public isHoveringOverDarkIcon: boolean = false;
|
||||||
|
public isHoveringOverLightLogo: boolean = false;
|
||||||
|
public isHoveringOverLightIcon: boolean = false;
|
||||||
|
public isHoveringOverFont: boolean = false;
|
||||||
|
|
||||||
|
private sub: Subscription = new Subscription();
|
||||||
|
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||||
|
|
||||||
|
public loading: boolean = false;
|
||||||
|
public nextLinks: CnslLinks[] = [
|
||||||
|
IAM_COMPLEXITY_LINK,
|
||||||
|
IAM_POLICY_LINK,
|
||||||
|
IAM_LOGIN_POLICY_LINK,
|
||||||
|
];
|
||||||
|
|
||||||
|
public Theme: any = Theme;
|
||||||
|
public Preview: any = Preview;
|
||||||
|
public ColorType: any = ColorType;
|
||||||
|
|
||||||
|
public refreshPreview: EventEmitter<void> = new EventEmitter();
|
||||||
|
public loadingImages: boolean = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private toast: ToastService,
|
||||||
|
private injector: Injector,
|
||||||
|
private uploadService: UploadService,
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
) {
|
||||||
|
this.sub = this.route.data.pipe(switchMap(data => {
|
||||||
|
this.serviceType = data.serviceType;
|
||||||
|
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||||
|
break;
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.route.params;
|
||||||
|
})).subscribe(() => {
|
||||||
|
this.fetchData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleHoverLogo(theme: Theme, isHovering: boolean): void {
|
||||||
|
if (theme === Theme.DARK) {
|
||||||
|
this.isHoveringOverDarkLogo = isHovering;
|
||||||
|
}
|
||||||
|
if (theme === Theme.LIGHT) {
|
||||||
|
this.isHoveringOverLightLogo = isHovering;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleHoverFont(isHovering: boolean): void {
|
||||||
|
this.isHoveringOverFont = isHovering;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onDropLogo(theme: Theme, filelist: FileList): Promise<any> | void {
|
||||||
|
const file = filelist.item(0);
|
||||||
|
if (file) {
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
if (theme === Theme.DARK) {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
return this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.MGMTDARKLOGO, formData));
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
return this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.IAMDARKLOGO, formData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (theme === Theme.LIGHT) {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
return this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.MGMTLIGHTLOGO, formData));
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
return this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.IAMLIGHTLOGO, formData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public onDropFont(filelist: FileList): Promise<any> | void {
|
||||||
|
const file = filelist.item(0);
|
||||||
|
if (file) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
return this.uploadService.upload(UploadEndpoint.MGMTFONT, formData);
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
return this.uploadService.upload(UploadEndpoint.IAMFONT, formData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleHoverIcon(theme: Theme, isHovering: boolean): void {
|
||||||
|
if (theme === Theme.DARK) {
|
||||||
|
this.isHoveringOverDarkIcon = isHovering;
|
||||||
|
}
|
||||||
|
if (theme === Theme.LIGHT) {
|
||||||
|
this.isHoveringOverLightIcon = isHovering;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public onDropIcon(theme: Theme, filelist: FileList): void {
|
||||||
|
const file = filelist.item(0);
|
||||||
|
if (file) {
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
if (theme === Theme.DARK) {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.MGMTDARKICON, formData));
|
||||||
|
break;
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.IAMDARKICON, formData));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (theme === Theme.LIGHT) {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.MGMTLIGHTICON, formData));
|
||||||
|
break;
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
this.handleUploadPromise(this.uploadService.upload(UploadEndpoint.IAMLIGHTICON, formData));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleUploadPromise(task: Promise<any>): Promise<any> {
|
||||||
|
return task.then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.UPLOADSUCCESS', true);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loadingImages = true;
|
||||||
|
this.getPreviewData().then(data => {
|
||||||
|
|
||||||
|
if (data.policy) {
|
||||||
|
this.previewData = data.policy;
|
||||||
|
this.loadPreviewImages();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}).catch(error => this.toast.showError(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
public fetchData(): void {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
this.getPreviewData().then(data => {
|
||||||
|
console.log('preview', data);
|
||||||
|
this.loadingImages = true;
|
||||||
|
|
||||||
|
if (data.policy) {
|
||||||
|
this.previewData = data.policy;
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
|
this.loadPreviewImages();
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.getData().then(data => {
|
||||||
|
console.log('data', data);
|
||||||
|
|
||||||
|
if (data.policy) {
|
||||||
|
this.data = data.policy;
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
|
this.loadImages();
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadImages(): void {
|
||||||
|
if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||||
|
if (this.data.logoUrlDark) {
|
||||||
|
this.loadAsset('darkLogo', DownloadEndpoint.IAMDARKLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.data.iconUrlDark) {
|
||||||
|
this.loadAsset('darkIcon', DownloadEndpoint.IAMDARKICONPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.data.logoUrl) {
|
||||||
|
this.loadAsset('logo', DownloadEndpoint.IAMLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.data.iconUrl) {
|
||||||
|
this.loadAsset('icon', DownloadEndpoint.IAMICONPREVIEW);
|
||||||
|
}
|
||||||
|
} else if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||||
|
if (this.data.logoUrlDark) {
|
||||||
|
this.loadAsset('darkLogo', DownloadEndpoint.MGMTDARKLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.data.iconUrlDark) {
|
||||||
|
this.loadAsset('darkIcon', DownloadEndpoint.MGMTDARKICONPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.data.logoUrl) {
|
||||||
|
this.loadAsset('logo', DownloadEndpoint.MGMTLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.data.iconUrl) {
|
||||||
|
this.loadAsset('icon', DownloadEndpoint.MGMTICONPREVIEW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadPreviewImages(): void {
|
||||||
|
if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||||
|
if (this.previewData.logoUrlDark) {
|
||||||
|
this.loadAsset('previewDarkLogo', DownloadEndpoint.IAMDARKLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.previewData.iconUrlDark) {
|
||||||
|
this.loadAsset('previewDarkIcon', DownloadEndpoint.IAMDARKICONPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.previewData.logoUrl) {
|
||||||
|
this.loadAsset('previewLogo', DownloadEndpoint.IAMLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.previewData.iconUrl) {
|
||||||
|
this.loadAsset('previewIcon', DownloadEndpoint.IAMICONPREVIEW);
|
||||||
|
}
|
||||||
|
} else if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||||
|
if (this.previewData.logoUrlDark) {
|
||||||
|
this.loadAsset('previewDarkLogo', DownloadEndpoint.MGMTDARKLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.previewData.iconUrlDark) {
|
||||||
|
this.loadAsset('previewDarkIcon', DownloadEndpoint.MGMTDARKICONPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.previewData.logoUrl) {
|
||||||
|
this.loadAsset('previewLogo', DownloadEndpoint.MGMTLOGOPREVIEW);
|
||||||
|
}
|
||||||
|
if (this.previewData.iconUrl) {
|
||||||
|
this.loadAsset('previewIcon', DownloadEndpoint.MGMTICONPREVIEW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnDestroy(): void {
|
||||||
|
this.sub.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getPreviewData():
|
||||||
|
Promise<MgmtGetPreviewLabelPolicyResponse.AsObject |
|
||||||
|
AdminGetPreviewLabelPolicyResponse.AsObject |
|
||||||
|
MgmtGetLabelPolicyResponse.AsObject |
|
||||||
|
AdminGetLabelPolicyResponse.AsObject> {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
return (this.service as ManagementService).getPreviewLabelPolicy();
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
return (this.service as AdminService).getPreviewLabelPolicy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getData():
|
||||||
|
Promise<MgmtGetPreviewLabelPolicyResponse.AsObject |
|
||||||
|
AdminGetPreviewLabelPolicyResponse.AsObject |
|
||||||
|
MgmtGetLabelPolicyResponse.AsObject |
|
||||||
|
AdminGetLabelPolicyResponse.AsObject> {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
return (this.service as ManagementService).getLabelPolicy();
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
return (this.service as AdminService).getLabelPolicy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadAsset(imagekey: string, url: string): Promise<any> {
|
||||||
|
return this.uploadService.load(`${url}`).then(data => {
|
||||||
|
const objectURL = URL.createObjectURL(data);
|
||||||
|
this.images[imagekey] = this.sanitizer.bypassSecurityTrustUrl(objectURL);
|
||||||
|
this.refreshPreview.emit();
|
||||||
|
this.loadingImages = false;
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
this.loadingImages = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public removePolicy(): void {
|
||||||
|
if (this.service instanceof ManagementService) {
|
||||||
|
this.service.resetPasswordComplexityPolicyToDefault().then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fetchData();
|
||||||
|
}, 1000);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public savePolicy(): void {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
if ((this.previewData as LabelPolicy.AsObject).isDefault) {
|
||||||
|
const req0 = new AddCustomLabelPolicyRequest();
|
||||||
|
this.overwriteValues(req0);
|
||||||
|
|
||||||
|
(this.service as ManagementService).addCustomLabelPolicy(req0).then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
}).catch((error: HttpErrorResponse) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const req1 = new UpdateCustomLabelPolicyRequest();
|
||||||
|
this.overwriteValues(req1);
|
||||||
|
|
||||||
|
(this.service as ManagementService).updateCustomLabelPolicy(req1).then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
const req = new UpdateLabelPolicyRequest();
|
||||||
|
this.overwriteValues(req);
|
||||||
|
(this.service as AdminService).updateLabelPolicy(req).then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveWatermark(): void {
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
if ((this.previewData as LabelPolicy.AsObject).isDefault) {
|
||||||
|
const req0 = new AddCustomLabelPolicyRequest();
|
||||||
|
req0.setDisableWatermark(this.previewData.disableWatermark);
|
||||||
|
|
||||||
|
(this.service as ManagementService).addCustomLabelPolicy(req0).then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
}).catch((error: HttpErrorResponse) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const req1 = new UpdateCustomLabelPolicyRequest();
|
||||||
|
req1.setDisableWatermark(this.previewData.disableWatermark);
|
||||||
|
|
||||||
|
(this.service as ManagementService).updateCustomLabelPolicy(req1).then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
const req = new UpdateLabelPolicyRequest();
|
||||||
|
req.setDisableWatermark(this.data.disableWatermark);
|
||||||
|
|
||||||
|
(this.service as AdminService).updateLabelPolicy(req).then(() => {
|
||||||
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isDefault(): boolean {
|
||||||
|
if (this.previewData && this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||||
|
return (this.previewData as LabelPolicy.AsObject).isDefault;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public overwriteValues(req: AddCustomLabelPolicyRequest | UpdateCustomLabelPolicyRequest): void {
|
||||||
|
req.setBackgroundColorDark(this.previewData.backgroundColorDark);
|
||||||
|
req.setBackgroundColor(this.previewData.backgroundColor);
|
||||||
|
|
||||||
|
req.setFontColorDark(this.previewData.fontColorDark);
|
||||||
|
req.setFontColor(this.previewData.fontColor);
|
||||||
|
|
||||||
|
req.setPrimaryColorDark(this.previewData.primaryColorDark);
|
||||||
|
req.setPrimaryColor(this.previewData.primaryColor);
|
||||||
|
|
||||||
|
req.setWarnColorDark(this.previewData.warnColorDark);
|
||||||
|
req.setWarnColor(this.previewData.warnColor);
|
||||||
|
|
||||||
|
req.setDisableWatermark(this.previewData.disableWatermark);
|
||||||
|
req.setHideLoginNameSuffix(this.previewData.hideLoginNameSuffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public activatePolicy(): Promise<any> {
|
||||||
|
// dialog warning
|
||||||
|
switch (this.serviceType) {
|
||||||
|
case PolicyComponentServiceType.MGMT:
|
||||||
|
return (this.service as ManagementService).activateCustomLabelPolicy().then(() => {
|
||||||
|
this.toast.showInfo('POLICY.PRIVATELABELING.ACTIVATED', true);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loadingImages = true;
|
||||||
|
this.getData().then(data => {
|
||||||
|
|
||||||
|
if (data.policy) {
|
||||||
|
this.data = data.policy;
|
||||||
|
this.loadImages();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
case PolicyComponentServiceType.ADMIN:
|
||||||
|
return (this.service as AdminService).activateLabelPolicy().then(() => {
|
||||||
|
this.toast.showInfo('POLICY.PRIVATELABELING.ACTIVATED', true);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loadingImages = true;
|
||||||
|
this.getData().then(data => {
|
||||||
|
|
||||||
|
if (data.policy) {
|
||||||
|
this.data = data.policy;
|
||||||
|
this.loadImages();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public resetPolicy(): Promise<any> {
|
||||||
|
return (this.service as ManagementService).resetLabelPolicyToDefault().then(() => {
|
||||||
|
this.toast.showInfo('POLICY.PRIVATELABELING.RESET', true);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fetchData();
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||||
|
import { HasFeaturePipeModule } from 'src/app/pipes/has-feature-pipe/has-feature-pipe.module';
|
||||||
|
|
||||||
|
import { DropzoneModule } from '../../../directives/dropzone/dropzone.module';
|
||||||
|
import { DetailLayoutModule } from '../../detail-layout/detail-layout.module';
|
||||||
|
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||||
|
import { InputModule } from '../../input/input.module';
|
||||||
|
import { LinksModule } from '../../links/links.module';
|
||||||
|
import { ColorComponent } from './color/color.component';
|
||||||
|
import { PreviewComponent } from './preview/preview.component';
|
||||||
|
import { PrivateLabelingPolicyRoutingModule } from './private-labeling-policy-routing.module';
|
||||||
|
import { PrivateLabelingPolicyComponent } from './private-labeling-policy.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
PrivateLabelingPolicyComponent,
|
||||||
|
PreviewComponent,
|
||||||
|
ColorComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
PrivateLabelingPolicyRoutingModule,
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
InputModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatSlideToggleModule,
|
||||||
|
MatIconModule,
|
||||||
|
HasRoleModule,
|
||||||
|
MatTooltipModule,
|
||||||
|
TranslateModule,
|
||||||
|
DetailLayoutModule,
|
||||||
|
DropzoneModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
LinksModule,
|
||||||
|
MatExpansionModule,
|
||||||
|
InfoSectionModule,
|
||||||
|
HasFeaturePipeModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class PrivateLabelingPolicyModule { }
|
@ -75,6 +75,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
|
||||||
|
<div class="p-item card">
|
||||||
|
<div class="avatar">
|
||||||
|
<i class="icon las la-gem"></i>
|
||||||
|
</div>
|
||||||
|
<div class="title">
|
||||||
|
<span>{{'POLICY.PRIVATELABELING_POLICY.TITLE' | translate}}</span>
|
||||||
|
<button mat-icon-button disabled>
|
||||||
|
<i class="icon las la-check-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="desc">
|
||||||
|
{{'POLICY.PRIVATELABELING_POLICY.DESCRIPTION' | translate}}</p>
|
||||||
|
<!-- <cnsl-info-section class="warn"
|
||||||
|
*ngIf="type == PolicyGridType.ORG && (['password_complexity_policy'] | hasFeature | async) == false"
|
||||||
|
type="WARN">
|
||||||
|
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||||
|
'password_complexity_policy'})}}
|
||||||
|
</cnsl-info-section> -->
|
||||||
|
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<div class="btn-wrapper">
|
||||||
|
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
|
||||||
|
<button
|
||||||
|
[routerLink]="[type == PolicyGridType.IAM ? '/iam' : type == PolicyGridType.ORG ? '/org' : '','policy', PolicyComponentType.PRIVATELABEL ]"
|
||||||
|
mat-stroked-button>{{'POLICY.BTN_EDIT' | translate}}</button>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
<ng-template appHasRole
|
<ng-template appHasRole
|
||||||
[appHasRole]="type == PolicyGridType.IAM ? ['iam.policy.read'] : type == PolicyGridType.ORG ? ['policy.read'] : []">
|
[appHasRole]="type == PolicyGridType.IAM ? ['iam.policy.read'] : type == PolicyGridType.ORG ? ['policy.read'] : []">
|
||||||
<div class="p-item card">
|
<div class="p-item card">
|
||||||
@ -101,40 +133,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-container *ngIf="type === PolicyGridType.IAM">
|
|
||||||
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
|
|
||||||
<div class="p-item card">
|
|
||||||
<div class="avatar">
|
|
||||||
<i class="icon las la-envelope"></i>
|
|
||||||
</div>
|
|
||||||
<div class="title">
|
|
||||||
<span>{{'POLICY.LABEL.TITLE' | translate}}</span>
|
|
||||||
<button mat-icon-button disabled>
|
|
||||||
<i class="icon las la-check-circle"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="desc">
|
|
||||||
{{'POLICY.LABEL.DESCRIPTION' | translate}}</p>
|
|
||||||
|
|
||||||
<cnsl-info-section class="warn"
|
|
||||||
*ngIf="type == PolicyGridType.ORG && (['label_policy'] | hasFeature | async) == false" type="WARN">
|
|
||||||
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
|
||||||
'label_policy'})}}
|
|
||||||
</cnsl-info-section>
|
|
||||||
|
|
||||||
<span class="fill-space"></span>
|
|
||||||
<div class="btn-wrapper">
|
|
||||||
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
|
|
||||||
<button
|
|
||||||
[routerLink]="[type == PolicyGridType.IAM ? '/iam' : type == PolicyGridType.ORG ? '/org' : '','policy', PolicyComponentType.LABEL ]"
|
|
||||||
mat-stroked-button
|
|
||||||
[disabled]="type == PolicyGridType.ORG && (['label_policy'] | hasFeature | async) == false">
|
|
||||||
{{'POLICY.BTN_EDIT' | translate}}</button>
|
|
||||||
</ng-template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
</div>
|
@ -21,14 +21,13 @@ export const IAM_LOGIN_POLICY_LINK = {
|
|||||||
withRole: ['iam.policy.read'],
|
withRole: ['iam.policy.read'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const IAM_LABEL_LINK = {
|
export const IAM_PRIVATELABEL_LINK = {
|
||||||
i18nTitle: 'POLICY.LABEL.TITLE',
|
i18nTitle: 'POLICY.LABEL.TITLE',
|
||||||
i18nDesc: 'POLICY.LABEL.DESCRIPTION',
|
i18nDesc: 'POLICY.LABEL.DESCRIPTION',
|
||||||
routerLink: ['/iam', 'policy', PolicyComponentType.LABEL],
|
routerLink: ['/iam', 'policy', PolicyComponentType.PRIVATELABEL],
|
||||||
withRole: ['iam.policy.read'],
|
withRole: ['iam.policy.read'],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const ORG_COMPLEXITY_LINK = {
|
export const ORG_COMPLEXITY_LINK = {
|
||||||
i18nTitle: 'POLICY.PWD_COMPLEXITY.TITLE',
|
i18nTitle: 'POLICY.PWD_COMPLEXITY.TITLE',
|
||||||
i18nDesc: 'POLICY.PWD_COMPLEXITY.DESCRIPTION',
|
i18nDesc: 'POLICY.PWD_COMPLEXITY.DESCRIPTION',
|
||||||
@ -49,3 +48,11 @@ export const ORG_LOGIN_POLICY_LINK = {
|
|||||||
routerLink: ['/org', 'policy', PolicyComponentType.LOGIN],
|
routerLink: ['/org', 'policy', PolicyComponentType.LOGIN],
|
||||||
withRole: ['policy.read'],
|
withRole: ['policy.read'],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const ORG_PRIVATELABEL_LINK = {
|
||||||
|
i18nTitle: 'POLICY.LABEL.TITLE',
|
||||||
|
i18nDesc: 'POLICY.LABEL.DESCRIPTION',
|
||||||
|
routerLink: ['/org', 'policy', PolicyComponentType.PRIVATELABEL],
|
||||||
|
withRole: ['policy.read'],
|
||||||
|
};
|
||||||
|
@ -84,6 +84,14 @@ const routes: Routes = [
|
|||||||
loadChildren: () => import('src/app/modules/policies/password-lockout-policy/password-lockout-policy.module')
|
loadChildren: () => import('src/app/modules/policies/password-lockout-policy/password-lockout-policy.module')
|
||||||
.then(m => m.PasswordLockoutPolicyModule),
|
.then(m => m.PasswordLockoutPolicyModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: PolicyComponentType.PRIVATELABEL,
|
||||||
|
data: {
|
||||||
|
serviceType: PolicyComponentServiceType.ADMIN,
|
||||||
|
},
|
||||||
|
loadChildren: () => import('src/app/modules/policies/private-labeling-policy/private-labeling-policy.module')
|
||||||
|
.then(m => m.PrivateLabelingPolicyModule),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: PolicyComponentType.COMPLEXITY,
|
path: PolicyComponentType.COMPLEXITY,
|
||||||
data: {
|
data: {
|
||||||
@ -108,14 +116,6 @@ const routes: Routes = [
|
|||||||
loadChildren: () => import('src/app/modules/policies/login-policy/login-policy.module')
|
loadChildren: () => import('src/app/modules/policies/login-policy/login-policy.module')
|
||||||
.then(m => m.LoginPolicyModule),
|
.then(m => m.LoginPolicyModule),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: PolicyComponentType.LABEL,
|
|
||||||
data: {
|
|
||||||
serviceType: PolicyComponentServiceType.ADMIN,
|
|
||||||
},
|
|
||||||
loadChildren: () => import('src/app/modules/policies/label-policy/label-policy.module')
|
|
||||||
.then(m => m.LabelPolicyModule),
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -73,7 +73,7 @@ h2 {
|
|||||||
|
|
||||||
.new-desc {
|
.new-desc {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #818a8a;
|
color: var(--grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-domain-deactivated {
|
.custom-domain-deactivated {
|
||||||
|
@ -68,6 +68,14 @@ const routes: Routes = [
|
|||||||
loadChildren: () => import('src/app/modules/policies/password-lockout-policy/password-lockout-policy.module')
|
loadChildren: () => import('src/app/modules/policies/password-lockout-policy/password-lockout-policy.module')
|
||||||
.then(m => m.PasswordLockoutPolicyModule),
|
.then(m => m.PasswordLockoutPolicyModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: PolicyComponentType.PRIVATELABEL,
|
||||||
|
data: {
|
||||||
|
serviceType: PolicyComponentServiceType.MGMT,
|
||||||
|
},
|
||||||
|
loadChildren: () => import('src/app/modules/policies/private-labeling-policy/private-labeling-policy.module')
|
||||||
|
.then(m => m.PrivateLabelingPolicyModule),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: PolicyComponentType.COMPLEXITY,
|
path: PolicyComponentType.COMPLEXITY,
|
||||||
data: {
|
data: {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
ActivateLabelPolicyRequest,
|
||||||
|
ActivateLabelPolicyResponse,
|
||||||
AddCustomOrgIAMPolicyRequest,
|
AddCustomOrgIAMPolicyRequest,
|
||||||
AddCustomOrgIAMPolicyResponse,
|
AddCustomOrgIAMPolicyResponse,
|
||||||
AddIAMMemberRequest,
|
AddIAMMemberRequest,
|
||||||
@ -37,6 +39,8 @@ import {
|
|||||||
GetPasswordComplexityPolicyResponse,
|
GetPasswordComplexityPolicyResponse,
|
||||||
GetPasswordLockoutPolicyRequest,
|
GetPasswordLockoutPolicyRequest,
|
||||||
GetPasswordLockoutPolicyResponse,
|
GetPasswordLockoutPolicyResponse,
|
||||||
|
GetPreviewLabelPolicyRequest,
|
||||||
|
GetPreviewLabelPolicyResponse,
|
||||||
IDPQuery,
|
IDPQuery,
|
||||||
ListFailedEventsRequest,
|
ListFailedEventsRequest,
|
||||||
ListFailedEventsResponse,
|
ListFailedEventsResponse,
|
||||||
@ -64,6 +68,16 @@ import {
|
|||||||
RemoveIDPFromLoginPolicyResponse,
|
RemoveIDPFromLoginPolicyResponse,
|
||||||
RemoveIDPRequest,
|
RemoveIDPRequest,
|
||||||
RemoveIDPResponse,
|
RemoveIDPResponse,
|
||||||
|
RemoveLabelPolicyFontRequest,
|
||||||
|
RemoveLabelPolicyFontResponse,
|
||||||
|
RemoveLabelPolicyIconDarkRequest,
|
||||||
|
RemoveLabelPolicyIconDarkResponse,
|
||||||
|
RemoveLabelPolicyIconRequest,
|
||||||
|
RemoveLabelPolicyIconResponse,
|
||||||
|
RemoveLabelPolicyLogoDarkRequest,
|
||||||
|
RemoveLabelPolicyLogoDarkResponse,
|
||||||
|
RemoveLabelPolicyLogoRequest,
|
||||||
|
RemoveLabelPolicyLogoResponse,
|
||||||
RemoveMultiFactorFromLoginPolicyRequest,
|
RemoveMultiFactorFromLoginPolicyRequest,
|
||||||
RemoveMultiFactorFromLoginPolicyResponse,
|
RemoveMultiFactorFromLoginPolicyResponse,
|
||||||
RemoveSecondFactorFromLoginPolicyRequest,
|
RemoveSecondFactorFromLoginPolicyRequest,
|
||||||
@ -281,6 +295,47 @@ export class AdminService {
|
|||||||
return this.grpcService.admin.updateLabelPolicy(req, null).then(resp => resp.toObject());
|
return this.grpcService.admin.updateLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPreviewLabelPolicy(): Promise<GetPreviewLabelPolicyResponse.AsObject> {
|
||||||
|
const req = new GetPreviewLabelPolicyRequest();
|
||||||
|
return this.grpcService.admin.getPreviewLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public activateLabelPolicy():
|
||||||
|
Promise<ActivateLabelPolicyResponse.AsObject> {
|
||||||
|
const req = new ActivateLabelPolicyRequest();
|
||||||
|
return this.grpcService.admin.activateLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyFont():
|
||||||
|
Promise<RemoveLabelPolicyFontResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyFontRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyFont(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyIcon():
|
||||||
|
Promise<RemoveLabelPolicyIconResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyIconRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyIcon(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyIconDark():
|
||||||
|
Promise<RemoveLabelPolicyIconDarkResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyIconDarkRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyIconDark(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyLogo():
|
||||||
|
Promise<RemoveLabelPolicyLogoResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyLogoRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyLogo(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyLogoDark():
|
||||||
|
Promise<RemoveLabelPolicyLogoDarkResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyLogoDarkRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyLogoDark(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
/* login */
|
/* login */
|
||||||
|
|
||||||
public getLoginPolicy(
|
public getLoginPolicy(
|
||||||
|
@ -3,15 +3,29 @@ import { Empty } from 'google-protobuf/google/protobuf/empty_pb';
|
|||||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RemoveLabelPolicyFontRequest,
|
||||||
|
RemoveLabelPolicyFontResponse,
|
||||||
|
RemoveLabelPolicyIconDarkRequest,
|
||||||
|
RemoveLabelPolicyIconDarkResponse,
|
||||||
|
RemoveLabelPolicyIconRequest,
|
||||||
|
RemoveLabelPolicyIconResponse,
|
||||||
|
RemoveLabelPolicyLogoDarkRequest,
|
||||||
|
RemoveLabelPolicyLogoDarkResponse,
|
||||||
|
} from '../proto/generated/zitadel/admin_pb';
|
||||||
import { AppQuery } from '../proto/generated/zitadel/app_pb';
|
import { AppQuery } from '../proto/generated/zitadel/app_pb';
|
||||||
import { KeyType } from '../proto/generated/zitadel/auth_n_key_pb';
|
import { KeyType } from '../proto/generated/zitadel/auth_n_key_pb';
|
||||||
import { ChangeQuery } from '../proto/generated/zitadel/change_pb';
|
import { ChangeQuery } from '../proto/generated/zitadel/change_pb';
|
||||||
import { IDPOwnerType } from '../proto/generated/zitadel/idp_pb';
|
import { IDPOwnerType } from '../proto/generated/zitadel/idp_pb';
|
||||||
import {
|
import {
|
||||||
|
ActivateCustomLabelPolicyRequest,
|
||||||
|
ActivateCustomLabelPolicyResponse,
|
||||||
AddAPIAppRequest,
|
AddAPIAppRequest,
|
||||||
AddAPIAppResponse,
|
AddAPIAppResponse,
|
||||||
AddAppKeyRequest,
|
AddAppKeyRequest,
|
||||||
AddAppKeyResponse,
|
AddAppKeyResponse,
|
||||||
|
AddCustomLabelPolicyRequest,
|
||||||
|
AddCustomLabelPolicyResponse,
|
||||||
AddCustomLoginPolicyRequest,
|
AddCustomLoginPolicyRequest,
|
||||||
AddCustomLoginPolicyResponse,
|
AddCustomLoginPolicyResponse,
|
||||||
AddCustomPasswordAgePolicyRequest,
|
AddCustomPasswordAgePolicyRequest,
|
||||||
@ -74,6 +88,8 @@ import {
|
|||||||
GenerateOrgDomainValidationResponse,
|
GenerateOrgDomainValidationResponse,
|
||||||
GetAppByIDRequest,
|
GetAppByIDRequest,
|
||||||
GetAppByIDResponse,
|
GetAppByIDResponse,
|
||||||
|
GetDefaultLabelPolicyRequest,
|
||||||
|
GetDefaultLabelPolicyResponse,
|
||||||
GetDefaultPasswordComplexityPolicyRequest,
|
GetDefaultPasswordComplexityPolicyRequest,
|
||||||
GetDefaultPasswordComplexityPolicyResponse,
|
GetDefaultPasswordComplexityPolicyResponse,
|
||||||
GetFeaturesRequest,
|
GetFeaturesRequest,
|
||||||
@ -88,6 +104,8 @@ import {
|
|||||||
GetHumanProfileResponse,
|
GetHumanProfileResponse,
|
||||||
GetIAMRequest,
|
GetIAMRequest,
|
||||||
GetIAMResponse,
|
GetIAMResponse,
|
||||||
|
GetLabelPolicyRequest,
|
||||||
|
GetLabelPolicyResponse,
|
||||||
GetLoginPolicyRequest,
|
GetLoginPolicyRequest,
|
||||||
GetLoginPolicyResponse,
|
GetLoginPolicyResponse,
|
||||||
GetMyOrgRequest,
|
GetMyOrgRequest,
|
||||||
@ -106,6 +124,8 @@ import {
|
|||||||
GetPasswordComplexityPolicyResponse,
|
GetPasswordComplexityPolicyResponse,
|
||||||
GetPasswordLockoutPolicyRequest,
|
GetPasswordLockoutPolicyRequest,
|
||||||
GetPasswordLockoutPolicyResponse,
|
GetPasswordLockoutPolicyResponse,
|
||||||
|
GetPreviewLabelPolicyRequest,
|
||||||
|
GetPreviewLabelPolicyResponse,
|
||||||
GetProjectByIDRequest,
|
GetProjectByIDRequest,
|
||||||
GetProjectByIDResponse,
|
GetProjectByIDResponse,
|
||||||
GetProjectGrantByIDRequest,
|
GetProjectGrantByIDRequest,
|
||||||
@ -192,6 +212,8 @@ import {
|
|||||||
RemoveAppKeyResponse,
|
RemoveAppKeyResponse,
|
||||||
RemoveAppRequest,
|
RemoveAppRequest,
|
||||||
RemoveAppResponse,
|
RemoveAppResponse,
|
||||||
|
RemoveCustomLabelPolicyLogoRequest,
|
||||||
|
RemoveCustomLabelPolicyLogoResponse,
|
||||||
RemoveHumanAuthFactorOTPRequest,
|
RemoveHumanAuthFactorOTPRequest,
|
||||||
RemoveHumanAuthFactorOTPResponse,
|
RemoveHumanAuthFactorOTPResponse,
|
||||||
RemoveHumanAuthFactorU2FRequest,
|
RemoveHumanAuthFactorU2FRequest,
|
||||||
@ -234,6 +256,8 @@ import {
|
|||||||
ResendHumanInitializationRequest,
|
ResendHumanInitializationRequest,
|
||||||
ResendHumanInitializationResponse,
|
ResendHumanInitializationResponse,
|
||||||
ResendHumanPhoneVerificationRequest,
|
ResendHumanPhoneVerificationRequest,
|
||||||
|
ResetLabelPolicyToDefaultRequest,
|
||||||
|
ResetLabelPolicyToDefaultResponse,
|
||||||
ResetLoginPolicyToDefaultRequest,
|
ResetLoginPolicyToDefaultRequest,
|
||||||
ResetLoginPolicyToDefaultResponse,
|
ResetLoginPolicyToDefaultResponse,
|
||||||
ResetPasswordAgePolicyToDefaultRequest,
|
ResetPasswordAgePolicyToDefaultRequest,
|
||||||
@ -250,6 +274,8 @@ import {
|
|||||||
UpdateAPIAppConfigResponse,
|
UpdateAPIAppConfigResponse,
|
||||||
UpdateAppRequest,
|
UpdateAppRequest,
|
||||||
UpdateAppResponse,
|
UpdateAppResponse,
|
||||||
|
UpdateCustomLabelPolicyRequest,
|
||||||
|
UpdateCustomLabelPolicyResponse,
|
||||||
UpdateCustomLoginPolicyRequest,
|
UpdateCustomLoginPolicyRequest,
|
||||||
UpdateCustomLoginPolicyResponse,
|
UpdateCustomLoginPolicyResponse,
|
||||||
UpdateCustomPasswordAgePolicyRequest,
|
UpdateCustomPasswordAgePolicyRequest,
|
||||||
@ -718,6 +744,72 @@ export class ManagementService {
|
|||||||
|
|
||||||
// Policy
|
// Policy
|
||||||
|
|
||||||
|
public getLabelPolicy(): Promise<GetLabelPolicyResponse.AsObject> {
|
||||||
|
const req = new GetLabelPolicyRequest();
|
||||||
|
return this.grpcService.mgmt.getLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateCustomLabelPolicy(req: UpdateCustomLabelPolicyRequest):
|
||||||
|
Promise<UpdateCustomLabelPolicyResponse.AsObject> {
|
||||||
|
return this.grpcService.mgmt.updateCustomLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public resetLabelPolicyToDefault():
|
||||||
|
Promise<ResetLabelPolicyToDefaultResponse.AsObject> {
|
||||||
|
const req = new ResetLabelPolicyToDefaultRequest();
|
||||||
|
return this.grpcService.mgmt.resetLabelPolicyToDefault(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public addCustomLabelPolicy(req: AddCustomLabelPolicyRequest):
|
||||||
|
Promise<AddCustomLabelPolicyResponse.AsObject> {
|
||||||
|
return this.grpcService.mgmt.addCustomLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDefaultLabelPolicy(req: GetDefaultLabelPolicyRequest): Promise<GetDefaultLabelPolicyResponse.AsObject> {
|
||||||
|
return this.grpcService.mgmt.getDefaultLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPreviewLabelPolicy(): Promise<GetPreviewLabelPolicyResponse.AsObject> {
|
||||||
|
const req = new GetPreviewLabelPolicyRequest();
|
||||||
|
return this.grpcService.mgmt.getPreviewLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public activateCustomLabelPolicy():
|
||||||
|
Promise<ActivateCustomLabelPolicyResponse.AsObject> {
|
||||||
|
const req = new ActivateCustomLabelPolicyRequest();
|
||||||
|
return this.grpcService.mgmt.activateCustomLabelPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyFont():
|
||||||
|
Promise<RemoveLabelPolicyFontResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyFontRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyFont(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyIcon():
|
||||||
|
Promise<RemoveLabelPolicyIconResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyIconRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyIcon(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyIconDark():
|
||||||
|
Promise<RemoveLabelPolicyIconDarkResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyIconDarkRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyIconDark(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeCustomLabelPolicyLogo():
|
||||||
|
Promise<RemoveCustomLabelPolicyLogoResponse.AsObject> {
|
||||||
|
const req = new RemoveCustomLabelPolicyLogoRequest();
|
||||||
|
return this.grpcService.mgmt.removeCustomLabelPolicyLogo(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeLabelPolicyLogoDark():
|
||||||
|
Promise<RemoveLabelPolicyLogoDarkResponse.AsObject> {
|
||||||
|
const req = new RemoveLabelPolicyLogoDarkRequest();
|
||||||
|
return this.grpcService.admin.removeLabelPolicyLogoDark(req, null).then(resp => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
public getOrgIAMPolicy(): Promise<GetOrgIAMPolicyResponse.AsObject> {
|
public getOrgIAMPolicy(): Promise<GetOrgIAMPolicyResponse.AsObject> {
|
||||||
const req = new GetOrgIAMPolicyRequest();
|
const req = new GetOrgIAMPolicyRequest();
|
||||||
return this.grpcService.mgmt.getOrgIAMPolicy(req, null).then(resp => resp.toObject());
|
return this.grpcService.mgmt.getOrgIAMPolicy(req, null).then(resp => resp.toObject());
|
||||||
|
106
console/src/app/services/upload.service.ts
Normal file
106
console/src/app/services/upload.service.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { Org } from '../proto/generated/zitadel/org_pb';
|
||||||
|
import { StorageService } from './storage.service';
|
||||||
|
|
||||||
|
const ORG_STORAGE_KEY = 'organization';
|
||||||
|
const authorizationKey = 'Authorization';
|
||||||
|
const orgKey = 'x-zitadel-orgid';
|
||||||
|
|
||||||
|
const bearerPrefix = 'Bearer';
|
||||||
|
const accessTokenStorageKey = 'access_token';
|
||||||
|
|
||||||
|
export enum UploadEndpoint {
|
||||||
|
IAMFONT = 'iam/policy/label/font',
|
||||||
|
MGMTFONT = 'org/policy/label/font',
|
||||||
|
|
||||||
|
IAMDARKLOGO = 'iam/policy/label/logo/dark',
|
||||||
|
IAMLIGHTLOGO = 'iam/policy/label/logo',
|
||||||
|
IAMDARKICON = 'iam/policy/label/icon/dark',
|
||||||
|
IAMLIGHTICON = 'iam/policy/label/icon',
|
||||||
|
|
||||||
|
MGMTDARKLOGO = 'org/policy/label/logo/dark',
|
||||||
|
MGMTLIGHTLOGO = 'org/policy/label/logo',
|
||||||
|
MGMTDARKICON = 'org/policy/label/icon/dark',
|
||||||
|
MGMTLIGHTICON = 'org/policy/label/icon',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DownloadEndpoint {
|
||||||
|
IAMFONT = 'iam/policy/label/font',
|
||||||
|
MGMTFONT = 'org/policy/label/font',
|
||||||
|
|
||||||
|
IAMDARKLOGO = 'iam/policy/label/logo/dark',
|
||||||
|
IAMLOGO = 'iam/policy/label/logo',
|
||||||
|
IAMDARKICON = 'iam/policy/label/icon/dark',
|
||||||
|
IAMICON = 'iam/policy/label/icon',
|
||||||
|
|
||||||
|
MGMTDARKLOGO = 'org/policy/label/logo/dark',
|
||||||
|
MGMTLOGO = 'org/policy/label/logo',
|
||||||
|
MGMTDARKICON = 'org/policy/label/icon/dark',
|
||||||
|
MGMTICON = 'org/policy/label/icon',
|
||||||
|
|
||||||
|
IAMDARKLOGOPREVIEW = 'iam/policy/label/logo/dark/_preview',
|
||||||
|
IAMLOGOPREVIEW = 'iam/policy/label/logo/_preview',
|
||||||
|
IAMDARKICONPREVIEW = 'iam/policy/label/icon/dark/_preview',
|
||||||
|
IAMICONPREVIEW = 'iam/policy/label/icon/_preview',
|
||||||
|
|
||||||
|
MGMTDARKLOGOPREVIEW = 'org/policy/label/logo/dark/_preview',
|
||||||
|
MGMTLOGOPREVIEW = 'org/policy/label/logo/_preview',
|
||||||
|
MGMTDARKICONPREVIEW = 'org/policy/label/icon/dark/_preview',
|
||||||
|
MGMTICONPREVIEW = 'org/policy/label/icon/_preview',
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class UploadService {
|
||||||
|
private serviceUrl: string = '';
|
||||||
|
private accessToken: string = '';
|
||||||
|
private org!: Org.AsObject;
|
||||||
|
constructor(private http: HttpClient, private storageService: StorageService) {
|
||||||
|
|
||||||
|
http.get('./assets/environment.json')
|
||||||
|
.toPromise().then((data: any) => {
|
||||||
|
if (data && data.uploadServiceUrl) {
|
||||||
|
this.serviceUrl = data.uploadServiceUrl;
|
||||||
|
const aT = this.storageService.getItem(accessTokenStorageKey);
|
||||||
|
|
||||||
|
if (aT) {
|
||||||
|
this.accessToken = aT;
|
||||||
|
}
|
||||||
|
|
||||||
|
const org: Org.AsObject | null = (this.storageService.getItem(ORG_STORAGE_KEY));
|
||||||
|
|
||||||
|
if (org) {
|
||||||
|
this.org = org;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public upload(endpoint: UploadEndpoint, body: any): Promise<any> {
|
||||||
|
return this.http.post(`${this.serviceUrl}/assets/v1/${endpoint}`,
|
||||||
|
body,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
[authorizationKey]: `${bearerPrefix} ${this.accessToken}`,
|
||||||
|
[orgKey]: `${this.org.id}`,
|
||||||
|
},
|
||||||
|
}).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
public load(endpoint: string): Promise<any> {
|
||||||
|
return this.http.get(`${this.serviceUrl}/assets/v1/${endpoint}`,
|
||||||
|
|
||||||
|
{
|
||||||
|
responseType: 'blob',
|
||||||
|
headers: {
|
||||||
|
[authorizationKey]: `${bearerPrefix} ${this.accessToken}`,
|
||||||
|
[orgKey]: `${this.org.id}`,
|
||||||
|
},
|
||||||
|
}).toPromise();
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"authServiceUrl": "https://api.zitadel.dev",
|
"authServiceUrl": "https://api.zitadel.io",
|
||||||
"mgmtServiceUrl": "https://api.zitadel.dev",
|
"mgmtServiceUrl": "https://api.zitadel.io",
|
||||||
"adminServiceUrl":"https://api.zitadel.dev",
|
"adminServiceUrl":"https://api.zitadel.io",
|
||||||
"subscriptionServiceUrl":"https://sub.zitadel.dev",
|
"subscriptionServiceUrl":"https://sub.zitadel.io",
|
||||||
"issuer": "https://issuer.zitadel.dev",
|
"uploadServiceUrl":"https://api.zitadel.io",
|
||||||
"clientid": "70669160379706195@zitadel"
|
"issuer": "https://issuer.zitadel.io",
|
||||||
|
"clientid": "69234247558357051@zitadel"
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
|
"SET":"Übernehmen",
|
||||||
"SHOW":"Aufklappen",
|
"SHOW":"Aufklappen",
|
||||||
"HIDE":"Zuklappen",
|
"HIDE":"Zuklappen",
|
||||||
"SAVE": "Speichern",
|
"SAVE": "Speichern",
|
||||||
@ -613,7 +614,8 @@
|
|||||||
"LOGINPOLICYFACTORS": "Login Richtlinie: Mltifaktoren - benutzerdefiniert",
|
"LOGINPOLICYFACTORS": "Login Richtlinie: Mltifaktoren - benutzerdefiniert",
|
||||||
"LOGINPOLICYPASSWORDLESS": "Login Richtlinie: Passwortlose Authentifizierung - benutzerdefiniert",
|
"LOGINPOLICYPASSWORDLESS": "Login Richtlinie: Passwortlose Authentifizierung - benutzerdefiniert",
|
||||||
"LOGINPOLICYCOMPLEXITYPOLICY": "Passwortkomplexitäts Richtlinie - benutzerdefiniert",
|
"LOGINPOLICYCOMPLEXITYPOLICY": "Passwortkomplexitäts Richtlinie - benutzerdefiniert",
|
||||||
"LABELPOLICY": "Label Richtlinie - benutzerdefiniert",
|
"LABELPOLICYPRIVATELABEL": "Label Richtlinie - benutzerdefiniert",
|
||||||
|
"LABELPOLICYWATERMARK": "Label Richtlinie - Wasserzeichen",
|
||||||
"CUSTOMDOMAIN": "Domänen Verifikation - verfügbar"
|
"CUSTOMDOMAIN": "Domänen Verifikation - verfügbar"
|
||||||
},
|
},
|
||||||
"TIERSTATES": {
|
"TIERSTATES": {
|
||||||
@ -636,6 +638,28 @@
|
|||||||
"NUMBERERROR": "Das Password muss eine Ziffer beinhalten.",
|
"NUMBERERROR": "Das Password muss eine Ziffer beinhalten.",
|
||||||
"PATTERNERROR": "Das Passwort erfüllt nicht die vorgeschriebene Richtlinie."
|
"PATTERNERROR": "Das Passwort erfüllt nicht die vorgeschriebene Richtlinie."
|
||||||
},
|
},
|
||||||
|
"PRIVATELABELING": {
|
||||||
|
"TITLE":"Private Labeling",
|
||||||
|
"DESCRIPTION":"Verleihe dem Login deinen benutzerdefinierten Style und passe das Verhalten an.",
|
||||||
|
"PREVIEW_DESCRIPTION":"Änderungen dieser Richtlinie werden automatisch in der Preview Umgebung verfügbar. Um die Preview zu Testen muss dem login flow der scope 'x-preview' mitgegeben werden.",
|
||||||
|
"BTN":"Datei auswählen",
|
||||||
|
"ACTIVATEPREVIEW":"Konfiguration übernehmen",
|
||||||
|
"DARK":"Dunkler Modus",
|
||||||
|
"LIGHT":"Heller Modus",
|
||||||
|
"CHANGEVIEW":"Ansicht wechseln",
|
||||||
|
"ACTIVATED":"Richtlinie wurde LIVE geschaltet",
|
||||||
|
"THEME":"Modus",
|
||||||
|
"COLORS":"Farben",
|
||||||
|
"FONT":"Schrift",
|
||||||
|
"ADVANCEDBEHAVIOR":"Erweitertes Verhalten",
|
||||||
|
"PREVIEW": {
|
||||||
|
"TITLE":"Anmeldung",
|
||||||
|
"SECOND":"mit ZITADEL-Konto anmelden.",
|
||||||
|
"ERROR":"Benutzer konnte nicht gefunden werden!",
|
||||||
|
"PRIMARYBUTTON":"weiter",
|
||||||
|
"SECONDARYBUTTON":"registrieren"
|
||||||
|
}
|
||||||
|
},
|
||||||
"PWD_AGE": {
|
"PWD_AGE": {
|
||||||
"TITLE": "Gültigkeitsdauer für Passwörter",
|
"TITLE": "Gültigkeitsdauer für Passwörter",
|
||||||
"DESCRIPTION": "Du kannst eine Richtlinie für die maximale Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie löst eine Warnung nach Ablauf einer festgelegten Gültigkeitsdauer aus."
|
"DESCRIPTION": "Du kannst eine Richtlinie für die maximale Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie löst eine Warnung nach Ablauf einer festgelegten Gültigkeitsdauer aus."
|
||||||
@ -648,6 +672,10 @@
|
|||||||
"TITLE": "Zugangseinstellungen IAM",
|
"TITLE": "Zugangseinstellungen IAM",
|
||||||
"DESCRIPTION": "Definiere die Zugangseistellungen für Benutzer."
|
"DESCRIPTION": "Definiere die Zugangseistellungen für Benutzer."
|
||||||
},
|
},
|
||||||
|
"PRIVATELABELING_POLICY": {
|
||||||
|
"TITLE": "Private Labeling",
|
||||||
|
"DESCRIPTION": "Definiere das Erscheinungsbild des Logins."
|
||||||
|
},
|
||||||
"LOGIN_POLICY": {
|
"LOGIN_POLICY": {
|
||||||
"TITLE": "Login Richtlinien",
|
"TITLE": "Login Richtlinien",
|
||||||
"DESCRIPTION": "Definiere die Loginmethoden für Benutzer",
|
"DESCRIPTION": "Definiere die Loginmethoden für Benutzer",
|
||||||
@ -655,13 +683,6 @@
|
|||||||
"DESCRIPTIONCREATEMGMT": "Nutzer können sich mit den verfügbaren Idps authentifizieren. Achtung: Es kann zwischen System- und organisationsspezifischen Providern gewählt werden.",
|
"DESCRIPTIONCREATEMGMT": "Nutzer können sich mit den verfügbaren Idps authentifizieren. Achtung: Es kann zwischen System- und organisationsspezifischen Providern gewählt werden.",
|
||||||
"SAVED": "Erfolgreich gespeichert."
|
"SAVED": "Erfolgreich gespeichert."
|
||||||
},
|
},
|
||||||
"LABEL": {
|
|
||||||
"TITLE": "Email Labelling Einstellungen",
|
|
||||||
"DESCRIPTION": "Definieren Sie das Erscheinungsbild Ihrer Benachrichtigungs-Mails",
|
|
||||||
"PRIMARYCOLOR": "Hintergrundfarbe",
|
|
||||||
"SECONDARYCOLOR": "Schriftfarbe",
|
|
||||||
"SAVED": "Erfolgreich gespeichert."
|
|
||||||
},
|
|
||||||
"DEFAULTLABEL": "Die aktuelle Richtlinie entspricht der IAM-Standard Einstellung.",
|
"DEFAULTLABEL": "Die aktuelle Richtlinie entspricht der IAM-Standard Einstellung.",
|
||||||
"BTN_INSTALL": "Installieren",
|
"BTN_INSTALL": "Installieren",
|
||||||
"BTN_EDIT": "Modifizieren",
|
"BTN_EDIT": "Modifizieren",
|
||||||
@ -685,14 +706,19 @@
|
|||||||
"ALLOWREGISTER_DESC": "Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers.",
|
"ALLOWREGISTER_DESC": "Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers.",
|
||||||
"FORCEMFA": "Mfa erzwingen",
|
"FORCEMFA": "Mfa erzwingen",
|
||||||
"FORCEMFA_DESC": "Ist die Option gewählt, müssen Benutzer einen zweiten Faktor für den Login verwenden.",
|
"FORCEMFA_DESC": "Ist die Option gewählt, müssen Benutzer einen zweiten Faktor für den Login verwenden.",
|
||||||
"HIDEPASSWORDRESET": "Passwort vergessen, nicht anzeigen",
|
"HIDEPASSWORDRESET": "Passwort vergessen ausblenden",
|
||||||
"FORCEMFA_DESC": "Ist die Option gewählt, ist es nicht möglich im Login das Passwort zurück zusetzen via Passwort vergessen Link."
|
"HIDEPASSWORDRESET_DESC": "Ist die Option gewählt, ist es nicht möglich im Login das Passwort zurück zusetzen via Passwort vergessen Link.",
|
||||||
|
"HIDELOGINNAMESUFFIX":"Loginname Suffix ausblenden",
|
||||||
|
"ERRORMSGPOPUP":"Fehler als Dialog Fenster",
|
||||||
|
"DISABLEWATERMARK":"Wasserzeichen ausblenden"
|
||||||
},
|
},
|
||||||
"RESET": "Richtlinie zurücksetzen",
|
"RESET": "Richtlinie zurücksetzen",
|
||||||
"CREATECUSTOM": "Benutzerdefinierte Richtlinie erstellen",
|
"CREATECUSTOM": "Benutzerdefinierte Richtlinie erstellen",
|
||||||
"TOAST": {
|
"TOAST": {
|
||||||
"SET": "Richtline erfolgreich gesetzt!",
|
"SET": "Richtline erfolgreich gesetzt!",
|
||||||
"RESETSUCCESS": "Richtline zurückgesetzt!"
|
"RESETSUCCESS": "Richtline zurückgesetzt!",
|
||||||
|
"UPLOADSUCCESS": "Upload erfolgreich",
|
||||||
|
"UPLOADFAILED":"Upload fehlgeschlagen!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ORG_DETAIL": {
|
"ORG_DETAIL": {
|
||||||
|
@ -104,6 +104,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
|
"SET":"Set",
|
||||||
"SHOW":"Show",
|
"SHOW":"Show",
|
||||||
"HIDE":"Hide",
|
"HIDE":"Hide",
|
||||||
"SAVE": "Save",
|
"SAVE": "Save",
|
||||||
@ -613,7 +614,8 @@
|
|||||||
"LOGINPOLICYFACTORS": "Login Policy: Multifactors - custom",
|
"LOGINPOLICYFACTORS": "Login Policy: Multifactors - custom",
|
||||||
"LOGINPOLICYPASSWORDLESS": "Login Policy: Passwordless Authentication - custom",
|
"LOGINPOLICYPASSWORDLESS": "Login Policy: Passwordless Authentication - custom",
|
||||||
"LOGINPOLICYCOMPLEXITYPOLICY": "Password Complexity Policy - custom",
|
"LOGINPOLICYCOMPLEXITYPOLICY": "Password Complexity Policy - custom",
|
||||||
"LABELPOLICY": "Labeling Policy - custom",
|
"LABELPOLICYPRIVATELABEL": "Label Richtlinie - benutzerdefiniert",
|
||||||
|
"LABELPOLICYWATERMARK": "Label Richtlinie - Wasserzeichen",
|
||||||
"CUSTOMDOMAIN": "Domain Verification - available"
|
"CUSTOMDOMAIN": "Domain Verification - available"
|
||||||
},
|
},
|
||||||
"TIERSTATES": {
|
"TIERSTATES": {
|
||||||
@ -636,6 +638,28 @@
|
|||||||
"NUMBERERROR": "The password must include a digit.",
|
"NUMBERERROR": "The password must include a digit.",
|
||||||
"PATTERNERROR": "The password does not meet the required pattern."
|
"PATTERNERROR": "The password does not meet the required pattern."
|
||||||
},
|
},
|
||||||
|
"PRIVATELABELING": {
|
||||||
|
"TITLE":"Private Labeling",
|
||||||
|
"DESCRIPTION":"Give the login your personalized style and modify its behavior.",
|
||||||
|
"PREVIEW_DESCRIPTION":"Changes of the policy will automatically deployed to preview environment. To view those changes, a 'x-preview' scope will have to be added to your login scopes.",
|
||||||
|
"BTN":"Select File",
|
||||||
|
"ACTIVATEPREVIEW":"Set preview as current configuration",
|
||||||
|
"DARK":"Dark Mode",
|
||||||
|
"LIGHT":"Lighg Mode",
|
||||||
|
"CHANGEVIEW":"Change View",
|
||||||
|
"ACTIVATED":"Policy changes are now LIVE",
|
||||||
|
"THEME":"Theme",
|
||||||
|
"COLORS":"Colors",
|
||||||
|
"FONT":"Font",
|
||||||
|
"ADVANCEDBEHAVIOR":"Advanced Behavior",
|
||||||
|
"PREVIEW": {
|
||||||
|
"TITLE":"Login",
|
||||||
|
"SECOND":"login with your ZITADEL-Account.",
|
||||||
|
"ERROR":"User could not be found!",
|
||||||
|
"PRIMARYBUTTON":"next",
|
||||||
|
"SECONDARYBUTTON":"register"
|
||||||
|
}
|
||||||
|
},
|
||||||
"PWD_AGE": {
|
"PWD_AGE": {
|
||||||
"TITLE": "Password Aging",
|
"TITLE": "Password Aging",
|
||||||
"DESCRIPTION": "You can set a policy for the aging of passwords. This policy emits a warning after the specific aging time has elapsed."
|
"DESCRIPTION": "You can set a policy for the aging of passwords. This policy emits a warning after the specific aging time has elapsed."
|
||||||
@ -648,6 +672,12 @@
|
|||||||
"TITLE": "IAM Access Preferences",
|
"TITLE": "IAM Access Preferences",
|
||||||
"DESCRIPTION": "Define access properties of your users."
|
"DESCRIPTION": "Define access properties of your users."
|
||||||
},
|
},
|
||||||
|
"PRIVATELABELING_POLICY": {
|
||||||
|
"TITLE": "Private Labeling",
|
||||||
|
"BTN":"Select File",
|
||||||
|
"DESCRIPTION": "Customize the appearance of the Login",
|
||||||
|
"ACTIVATEPREVIEW":"Activate Configuration"
|
||||||
|
},
|
||||||
"LOGIN_POLICY": {
|
"LOGIN_POLICY": {
|
||||||
"TITLE": "Login Policy",
|
"TITLE": "Login Policy",
|
||||||
"DESCRIPTION": "Define how Users can be authenticated and configure Identity Providers",
|
"DESCRIPTION": "Define how Users can be authenticated and configure Identity Providers",
|
||||||
@ -655,13 +685,6 @@
|
|||||||
"DESCRIPTIONCREATEMGMT": "Users can choose from the available identity providers below. Note: You can use System-set providers as well as providers set for your organisation only.",
|
"DESCRIPTIONCREATEMGMT": "Users can choose from the available identity providers below. Note: You can use System-set providers as well as providers set for your organisation only.",
|
||||||
"SAVED": "Saved successfully!"
|
"SAVED": "Saved successfully!"
|
||||||
},
|
},
|
||||||
"LABEL": {
|
|
||||||
"TITLE": "Email Labelling Settings",
|
|
||||||
"DESCRIPTION": "Change the look of your emails.",
|
|
||||||
"PRIMARYCOLOR": "Background color",
|
|
||||||
"SECONDARYCOLOR": "Font color",
|
|
||||||
"SAVED": "Saved successfully"
|
|
||||||
},
|
|
||||||
"DEFAULTLABEL": "The currently set guideline corresponds to the standard setting set by the IAM Administrator.",
|
"DEFAULTLABEL": "The currently set guideline corresponds to the standard setting set by the IAM Administrator.",
|
||||||
"BTN_INSTALL": "Setup",
|
"BTN_INSTALL": "Setup",
|
||||||
"BTN_EDIT": "Modify",
|
"BTN_EDIT": "Modify",
|
||||||
@ -686,13 +709,18 @@
|
|||||||
"FORCEMFA": "Force MFA",
|
"FORCEMFA": "Force MFA",
|
||||||
"FORCEMFA_DESC": "If the option is selected, users have to configure a second factor for login.",
|
"FORCEMFA_DESC": "If the option is selected, users have to configure a second factor for login.",
|
||||||
"HIDEPASSWORDRESET": "Hide Password reset",
|
"HIDEPASSWORDRESET": "Hide Password reset",
|
||||||
"FORCEMFA_DESC": "If the option is selected, the user can't reset his password in the login process."
|
"HIDEPASSWORDRESET_DESC": "If the option is selected, the user can't reset his password in the login process.",
|
||||||
|
"HIDELOGINNAMESUFFIX":"Hide Loginname suffix",
|
||||||
|
"ERRORMSGPOPUP":"Show Error in Dialog",
|
||||||
|
"DISABLEWATERMARK":"Disable Watermark"
|
||||||
},
|
},
|
||||||
"RESET": "Reset Policy",
|
"RESET": "Reset Policy",
|
||||||
"CREATECUSTOM": "Create Custom Policy",
|
"CREATECUSTOM": "Create Custom Policy",
|
||||||
"TOAST": {
|
"TOAST": {
|
||||||
"SET": "Policy set successfully!",
|
"SET": "Policy set successfully!",
|
||||||
"RESETSUCCESS": "Policy reset successfully!"
|
"RESETSUCCESS": "Policy reset successfully!",
|
||||||
|
"UPLOADSUCCESS": "Uploaded successfully!",
|
||||||
|
"UPLOADFAILED":"Upload failed!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ORG_DETAIL": {
|
"ORG_DETAIL": {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
@import 'src/app/modules/meta-layout/meta.scss';
|
@import 'src/app/modules/meta-layout/meta.scss';
|
||||||
@import 'src/app/modules/zitadel-tier/zitadel-tier.component.scss';
|
@import 'src/app/modules/zitadel-tier/zitadel-tier.component.scss';
|
||||||
@import 'src/app/modules/onboarding/onboarding.component.scss';
|
@import 'src/app/modules/onboarding/onboarding.component.scss';
|
||||||
|
@import 'src/app/modules/policies/private-labeling-policy/private-labeling-policy.component.scss';
|
||||||
|
|
||||||
@mixin component-themes($theme) {
|
@mixin component-themes($theme) {
|
||||||
@include avatar-theme($theme);
|
@include avatar-theme($theme);
|
||||||
@ -42,4 +43,5 @@
|
|||||||
@include info-section-theme($theme);
|
@include info-section-theme($theme);
|
||||||
@include onboarding-theme($theme);
|
@include onboarding-theme($theme);
|
||||||
@include tier-theme($theme);
|
@include tier-theme($theme);
|
||||||
|
@include private-label-theme($theme);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,6 @@ $dark-accent: mat.define-palette(mat.$pink-palette);
|
|||||||
$dark-warn: mat.define-palette(mat.$red-palette);
|
$dark-warn: mat.define-palette(mat.$red-palette);
|
||||||
|
|
||||||
$light-theme: mat.define-light-theme($light-primary, $light-accent, $light-warn);
|
$light-theme: mat.define-light-theme($light-primary, $light-accent, $light-warn);
|
||||||
|
|
||||||
$dark-theme: mat.define-dark-theme($dark-primary, $dark-accent, $dark-warn);
|
$dark-theme: mat.define-dark-theme($dark-primary, $dark-accent, $dark-warn);
|
||||||
|
|
||||||
$custom-typography: mat.define-typography-config($font-family: 'Lato');
|
$custom-typography: mat.define-typography-config($font-family: 'Lato');
|
||||||
|
@ -266,6 +266,16 @@ Returns the label policy defined by the administrators of ZITADEL
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetPreviewLabelPolicy
|
||||||
|
|
||||||
|
> **rpc** GetPreviewLabelPolicy([GetPreviewLabelPolicyRequest](#getpreviewlabelpolicyrequest))
|
||||||
|
[GetPreviewLabelPolicyResponse](#getpreviewlabelpolicyresponse)
|
||||||
|
|
||||||
|
Returns the preview label policy defined by the administrators of ZITADEL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### UpdateLabelPolicy
|
### UpdateLabelPolicy
|
||||||
|
|
||||||
> **rpc** UpdateLabelPolicy([UpdateLabelPolicyRequest](#updatelabelpolicyrequest))
|
> **rpc** UpdateLabelPolicy([UpdateLabelPolicyRequest](#updatelabelpolicyrequest))
|
||||||
@ -277,6 +287,66 @@ it impacts all organisations without a customised policy
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ActivateLabelPolicy
|
||||||
|
|
||||||
|
> **rpc** ActivateLabelPolicy([ActivateLabelPolicyRequest](#activatelabelpolicyrequest))
|
||||||
|
[ActivateLabelPolicyResponse](#activatelabelpolicyresponse)
|
||||||
|
|
||||||
|
Activates all changes of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyLogo
|
||||||
|
|
||||||
|
> **rpc** RemoveLabelPolicyLogo([RemoveLabelPolicyLogoRequest](#removelabelpolicylogorequest))
|
||||||
|
[RemoveLabelPolicyLogoResponse](#removelabelpolicylogoresponse)
|
||||||
|
|
||||||
|
Removes the logo of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyLogoDark
|
||||||
|
|
||||||
|
> **rpc** RemoveLabelPolicyLogoDark([RemoveLabelPolicyLogoDarkRequest](#removelabelpolicylogodarkrequest))
|
||||||
|
[RemoveLabelPolicyLogoDarkResponse](#removelabelpolicylogodarkresponse)
|
||||||
|
|
||||||
|
Removes the logo dark of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyIcon
|
||||||
|
|
||||||
|
> **rpc** RemoveLabelPolicyIcon([RemoveLabelPolicyIconRequest](#removelabelpolicyiconrequest))
|
||||||
|
[RemoveLabelPolicyIconResponse](#removelabelpolicyiconresponse)
|
||||||
|
|
||||||
|
Removes the icon of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyIconDark
|
||||||
|
|
||||||
|
> **rpc** RemoveLabelPolicyIconDark([RemoveLabelPolicyIconDarkRequest](#removelabelpolicyicondarkrequest))
|
||||||
|
[RemoveLabelPolicyIconDarkResponse](#removelabelpolicyicondarkresponse)
|
||||||
|
|
||||||
|
Removes the logo dark of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyFont
|
||||||
|
|
||||||
|
> **rpc** RemoveLabelPolicyFont([RemoveLabelPolicyFontRequest](#removelabelpolicyfontrequest))
|
||||||
|
[RemoveLabelPolicyFontResponse](#removelabelpolicyfontresponse)
|
||||||
|
|
||||||
|
Removes the font of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetLoginPolicy
|
### GetLoginPolicy
|
||||||
|
|
||||||
> **rpc** GetLoginPolicy([GetLoginPolicyRequest](#getloginpolicyrequest))
|
> **rpc** GetLoginPolicy([GetLoginPolicyRequest](#getloginpolicyrequest))
|
||||||
@ -570,6 +640,23 @@ failed event. You can find out if it worked on the `failure_count`
|
|||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
|
|
||||||
|
### ActivateLabelPolicyRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ActivateLabelPolicyResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### AddCustomOrgIAMPolicyRequest
|
### AddCustomOrgIAMPolicyRequest
|
||||||
|
|
||||||
|
|
||||||
@ -975,6 +1062,23 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetPreviewLabelPolicyRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetPreviewLabelPolicyResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| policy | zitadel.policy.v1.LabelPolicy | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### HealthzRequest
|
### HealthzRequest
|
||||||
This is an empty request
|
This is an empty request
|
||||||
|
|
||||||
@ -1316,6 +1420,91 @@ This is an empty response
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyFontRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyFontResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyIconDarkRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyIconDarkResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyIconRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyIconResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyLogoDarkRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyLogoDarkResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyLogoRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveLabelPolicyLogoResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### RemoveMultiFactorFromLoginPolicyRequest
|
### RemoveMultiFactorFromLoginPolicyRequest
|
||||||
|
|
||||||
|
|
||||||
@ -1422,6 +1611,8 @@ This is an empty response
|
|||||||
| label_policy | bool | - | |
|
| label_policy | bool | - | |
|
||||||
| custom_domain | bool | - | |
|
| custom_domain | bool | - | |
|
||||||
| login_policy_password_reset | bool | - | |
|
| login_policy_password_reset | bool | - | |
|
||||||
|
| label_policy_private_label | bool | - | |
|
||||||
|
| label_policy_watermark | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1458,6 +1649,8 @@ This is an empty response
|
|||||||
| label_policy | bool | - | |
|
| label_policy | bool | - | |
|
||||||
| custom_domain | bool | - | |
|
| custom_domain | bool | - | |
|
||||||
| login_policy_password_reset | bool | - | |
|
| login_policy_password_reset | bool | - | |
|
||||||
|
| label_policy_private_label | bool | - | |
|
||||||
|
| label_policy_watermark | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1669,9 +1862,16 @@ This is an empty response
|
|||||||
|
|
||||||
| Field | Type | Description | Validation |
|
| Field | Type | Description | Validation |
|
||||||
| ----- | ---- | ----------- | ----------- |
|
| ----- | ---- | ----------- | ----------- |
|
||||||
| primary_color | string | - | string.min_len: 1<br /> string.max_len: 50<br /> |
|
| primary_color | string | - | string.max_len: 50<br /> |
|
||||||
| secondary_color | string | - | string.min_len: 1<br /> string.max_len: 50<br /> |
|
|
||||||
| hide_login_name_suffix | bool | - | |
|
| hide_login_name_suffix | bool | - | |
|
||||||
|
| warn_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| background_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| font_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| primary_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| background_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| warn_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| font_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| disable_watermark | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,6 +220,16 @@ Removed the phone number of the authorized user
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveMyAvatar
|
||||||
|
|
||||||
|
> **rpc** RemoveMyAvatar([RemoveMyAvatarRequest](#removemyavatarrequest))
|
||||||
|
[RemoveMyAvatarResponse](#removemyavatarresponse)
|
||||||
|
|
||||||
|
Remove my avatar
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ListMyLinkedIDPs
|
### ListMyLinkedIDPs
|
||||||
|
|
||||||
> **rpc** ListMyLinkedIDPs([ListMyLinkedIDPsRequest](#listmylinkedidpsrequest))
|
> **rpc** ListMyLinkedIDPs([ListMyLinkedIDPsRequest](#listmylinkedidpsrequest))
|
||||||
@ -820,6 +830,23 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveMyAvatarRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveMyAvatarResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### RemoveMyLinkedIDPRequest
|
### RemoveMyLinkedIDPRequest
|
||||||
|
|
||||||
|
|
||||||
|
@ -293,6 +293,16 @@ An sms will be sent to the given phone number to finish the phone verification p
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveMyAvatar
|
||||||
|
|
||||||
|
> **rpc** RemoveMyAvatar([RemoveHumanAvatarRequest](#removehumanavatarrequest))
|
||||||
|
[RemoveHumanAvatarResponse](#removehumanavatarresponse)
|
||||||
|
|
||||||
|
Removes the avatar number of the human
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### SetHumanInitialPassword
|
### SetHumanInitialPassword
|
||||||
|
|
||||||
> **rpc** SetHumanInitialPassword([SetHumanInitialPasswordRequest](#sethumaninitialpasswordrequest))
|
> **rpc** SetHumanInitialPassword([SetHumanInitialPasswordRequest](#sethumaninitialpasswordrequest))
|
||||||
@ -1581,7 +1591,18 @@ The password lockout policy is not used at the moment
|
|||||||
> **rpc** GetLabelPolicy([GetLabelPolicyRequest](#getlabelpolicyrequest))
|
> **rpc** GetLabelPolicy([GetLabelPolicyRequest](#getlabelpolicyrequest))
|
||||||
[GetLabelPolicyResponse](#getlabelpolicyresponse)
|
[GetLabelPolicyResponse](#getlabelpolicyresponse)
|
||||||
|
|
||||||
Returns the label policy of the organisation
|
Returns the active label policy of the organisation
|
||||||
|
With this policy the private labeling can be configured (colors, etc.)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetPreviewLabelPolicy
|
||||||
|
|
||||||
|
> **rpc** GetPreviewLabelPolicy([GetPreviewLabelPolicyRequest](#getpreviewlabelpolicyrequest))
|
||||||
|
[GetPreviewLabelPolicyResponse](#getpreviewlabelpolicyresponse)
|
||||||
|
|
||||||
|
Returns the preview label policy of the organisation
|
||||||
With this policy the private labeling can be configured (colors, etc.)
|
With this policy the private labeling can be configured (colors, etc.)
|
||||||
|
|
||||||
|
|
||||||
@ -1620,6 +1641,66 @@ With this policy the private labeling can be configured (colors, etc.)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ActivateCustomLabelPolicy
|
||||||
|
|
||||||
|
> **rpc** ActivateCustomLabelPolicy([ActivateCustomLabelPolicyRequest](#activatecustomlabelpolicyrequest))
|
||||||
|
[ActivateCustomLabelPolicyResponse](#activatecustomlabelpolicyresponse)
|
||||||
|
|
||||||
|
Activates all changes of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyLogo
|
||||||
|
|
||||||
|
> **rpc** RemoveCustomLabelPolicyLogo([RemoveCustomLabelPolicyLogoRequest](#removecustomlabelpolicylogorequest))
|
||||||
|
[RemoveCustomLabelPolicyLogoResponse](#removecustomlabelpolicylogoresponse)
|
||||||
|
|
||||||
|
Removes the logo of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyLogoDark
|
||||||
|
|
||||||
|
> **rpc** RemoveCustomLabelPolicyLogoDark([RemoveCustomLabelPolicyLogoDarkRequest](#removecustomlabelpolicylogodarkrequest))
|
||||||
|
[RemoveCustomLabelPolicyLogoDarkResponse](#removecustomlabelpolicylogodarkresponse)
|
||||||
|
|
||||||
|
Removes the logo dark of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyIcon
|
||||||
|
|
||||||
|
> **rpc** RemoveCustomLabelPolicyIcon([RemoveCustomLabelPolicyIconRequest](#removecustomlabelpolicyiconrequest))
|
||||||
|
[RemoveCustomLabelPolicyIconResponse](#removecustomlabelpolicyiconresponse)
|
||||||
|
|
||||||
|
Removes the icon of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyIconDark
|
||||||
|
|
||||||
|
> **rpc** RemoveCustomLabelPolicyIconDark([RemoveCustomLabelPolicyIconDarkRequest](#removecustomlabelpolicyicondarkrequest))
|
||||||
|
[RemoveCustomLabelPolicyIconDarkResponse](#removecustomlabelpolicyicondarkresponse)
|
||||||
|
|
||||||
|
Removes the logo dark of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyFont
|
||||||
|
|
||||||
|
> **rpc** RemoveCustomLabelPolicyFont([RemoveCustomLabelPolicyFontRequest](#removecustomlabelpolicyfontrequest))
|
||||||
|
[RemoveCustomLabelPolicyFontResponse](#removecustomlabelpolicyfontresponse)
|
||||||
|
|
||||||
|
Removes the font of the label policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ResetLabelPolicyToDefault
|
### ResetLabelPolicyToDefault
|
||||||
|
|
||||||
> **rpc** ResetLabelPolicyToDefault([ResetLabelPolicyToDefaultRequest](#resetlabelpolicytodefaultrequest))
|
> **rpc** ResetLabelPolicyToDefault([ResetLabelPolicyToDefaultRequest](#resetlabelpolicytodefaultrequest))
|
||||||
@ -1725,6 +1806,23 @@ Change OIDC identity provider configuration of the organisation
|
|||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
|
|
||||||
|
### ActivateCustomLabelPolicyRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ActivateCustomLabelPolicyResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### AddAPIAppRequest
|
### AddAPIAppRequest
|
||||||
|
|
||||||
|
|
||||||
@ -1785,9 +1883,16 @@ Change OIDC identity provider configuration of the organisation
|
|||||||
|
|
||||||
| Field | Type | Description | Validation |
|
| Field | Type | Description | Validation |
|
||||||
| ----- | ---- | ----------- | ----------- |
|
| ----- | ---- | ----------- | ----------- |
|
||||||
| primary_color | string | - | string.min_len: 1<br /> string.max_len: 50<br /> |
|
| primary_color | string | - | string.max_len: 50<br /> |
|
||||||
| secondary_color | string | - | string.min_len: 1<br /> string.max_len: 50<br /> |
|
| hide_login_name_suffix | bool | hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.ch/concepts#Reserved_Scopes | |
|
||||||
| hide_login_name_suffix | bool | - | |
|
| warn_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| background_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| font_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| primary_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| background_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| warn_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| font_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| disable_watermark | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -3074,6 +3179,24 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetPreviewLabelPolicyRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetPreviewLabelPolicyResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| policy | zitadel.policy.v1.LabelPolicy | - | |
|
||||||
|
| is_default | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetProjectByIDRequest
|
### GetProjectByIDRequest
|
||||||
|
|
||||||
|
|
||||||
@ -4251,6 +4374,91 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyFontRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyFontResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyIconDarkRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyIconDarkResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyIconRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyIconResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyLogoDarkRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyLogoDarkResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyLogoRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveCustomLabelPolicyLogoResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### RemoveHumanAuthFactorOTPRequest
|
### RemoveHumanAuthFactorOTPRequest
|
||||||
|
|
||||||
|
|
||||||
@ -4296,6 +4504,28 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveHumanAvatarRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| user_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveHumanAvatarResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### RemoveHumanLinkedIDPRequest
|
### RemoveHumanLinkedIDPRequest
|
||||||
|
|
||||||
|
|
||||||
@ -4995,9 +5225,16 @@ This is an empty request
|
|||||||
|
|
||||||
| Field | Type | Description | Validation |
|
| Field | Type | Description | Validation |
|
||||||
| ----- | ---- | ----------- | ----------- |
|
| ----- | ---- | ----------- | ----------- |
|
||||||
| primary_color | string | - | string.min_len: 1<br /> string.max_len: 50<br /> |
|
| primary_color | string | - | string.max_len: 50<br /> |
|
||||||
| secondary_color | string | - | string.min_len: 1<br /> string.max_len: 50<br /> |
|
|
||||||
| hide_login_name_suffix | bool | - | |
|
| hide_login_name_suffix | bool | - | |
|
||||||
|
| warn_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| background_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| font_color | string | - | string.max_len: 50<br /> |
|
||||||
|
| primary_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| background_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| warn_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| font_color_dark | string | - | string.max_len: 50<br /> |
|
||||||
|
| disable_watermark | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,10 +16,22 @@ title: zitadel/policy.proto
|
|||||||
| Field | Type | Description | Validation |
|
| Field | Type | Description | Validation |
|
||||||
| ----- | ---- | ----------- | ----------- |
|
| ----- | ---- | ----------- | ----------- |
|
||||||
| details | zitadel.v1.ObjectDetails | - | |
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
| primary_color | string | - | |
|
| primary_color | string | hex value for primary color | |
|
||||||
| secondary_color | string | - | |
|
| is_default | bool | defines if the organisation's admin changed the policy | |
|
||||||
| is_default | bool | - | |
|
| hide_login_name_suffix | bool | hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.ch/concepts#Reserved_Scopes | |
|
||||||
| hide_login_name_suffix | bool | - | |
|
| warn_color | string | hex value for secondary color | |
|
||||||
|
| background_color | string | hex value for background color | |
|
||||||
|
| font_color | string | hex value for font color | |
|
||||||
|
| primary_color_dark | string | hex value for primary color dark theme | |
|
||||||
|
| background_color_dark | string | hex value for background color dark theme | |
|
||||||
|
| warn_color_dark | string | hex value for warn color dark theme | |
|
||||||
|
| font_color_dark | string | hex value for font color dark theme | |
|
||||||
|
| disable_watermark | bool | - | |
|
||||||
|
| logo_url | string | - | |
|
||||||
|
| icon_url | string | - | |
|
||||||
|
| logo_url_dark | string | - | |
|
||||||
|
| icon_url_dark | string | - | |
|
||||||
|
| font_url | string | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -43,10 +43,12 @@ require (
|
|||||||
github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8 // indirect
|
github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8 // indirect
|
||||||
github.com/kevinburke/twilio-go v0.0.0-20200810163702-320748330fac
|
github.com/kevinburke/twilio-go v0.0.0-20200810163702-320748330fac
|
||||||
github.com/lib/pq v1.9.0
|
github.com/lib/pq v1.9.0
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||||
github.com/manifoldco/promptui v0.7.0
|
github.com/manifoldco/promptui v0.7.0
|
||||||
github.com/mattn/go-colorable v0.1.8 // indirect; indirect github.com/mitchellh/copystructure v1.0.0 // indirect
|
github.com/mattn/go-colorable v0.1.8 // indirect; indirect github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
github.com/minio/minio-go/v7 v7.0.10
|
github.com/minio/minio-go/v7 v7.0.10
|
||||||
github.com/mitchellh/copystructure v1.1.2 // indirect
|
github.com/mitchellh/copystructure v1.1.2 // indirect
|
||||||
|
github.com/muesli/gamut v0.2.0
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.1.2
|
github.com/nicksnyder/go-i18n/v2 v2.1.2
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pquerna/otp v1.2.0
|
github.com/pquerna/otp v1.2.0
|
||||||
|
20
go.sum
20
go.sum
@ -60,6 +60,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/DataDog/sketches-go v0.0.1 h1:RtG+76WKgZuz6FIaGsjoPePmadDBkuD/KC6+ZWu78b8=
|
github.com/DataDog/sketches-go v0.0.1 h1:RtG+76WKgZuz6FIaGsjoPePmadDBkuD/KC6+ZWu78b8=
|
||||||
@ -342,6 +343,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@ -632,6 +635,10 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9
|
|||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
|
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
|
||||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU=
|
github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU=
|
||||||
@ -704,6 +711,13 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
|||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/muesli/clusters v0.0.0-20180605185049-a07a36e67d36/go.mod h1:mw5KDqUj0eLj/6DUNINLVJNoPTFkEuGMHtJsXLviLkY=
|
||||||
|
github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 h1:p4A2Jx7Lm3NV98VRMKlyWd3nqf8obft8NfXlAUmqd3I=
|
||||||
|
github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762/go.mod h1:mw5KDqUj0eLj/6DUNINLVJNoPTFkEuGMHtJsXLviLkY=
|
||||||
|
github.com/muesli/gamut v0.2.0 h1:IZbl/hQzChTXtqDSXL8CDtjdRt58LivY03bGCm1yDyU=
|
||||||
|
github.com/muesli/gamut v0.2.0/go.mod h1:kz1+UJqI1thNtocJlowyqG2o0FNsN0W534VoMVsR9/Y=
|
||||||
|
github.com/muesli/kmeans v0.2.1 h1:ja5AnwfyDCVBCANrAfXr2pOh292FQnSeu1lySACDJU0=
|
||||||
|
github.com/muesli/kmeans v0.2.1/go.mod h1:eNyybq0tX9/iBEP6EMU4Y7dpmGK0uEhODdZpnG1a/iQ=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
@ -901,6 +915,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
|
|||||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
|
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||||
|
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||||
@ -908,6 +924,8 @@ github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0B
|
|||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b h1:tnWgqoOBmInkt5pbLjagwNVjjT4RdJhFHzL1ebCSRh8=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@ -1007,6 +1025,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
|
|||||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
|
||||||
|
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
@ -300,7 +300,15 @@ func (repo *IAMRepository) GetOrgIAMPolicy(ctx context.Context) (*iam_model.OrgI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
|
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
|
||||||
policy, err := repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
|
policy, err := repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStateActive))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iam_es_model.LabelPolicyViewToModel(policy), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *IAMRepository) GetDefaultPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
|
||||||
|
policy, err := repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStatePreview))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
@ -30,8 +31,8 @@ func (h *handler) Eventstore() v1.Eventstore {
|
|||||||
return h.es
|
return h.es
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, defaults systemdefaults.SystemDefaults) []query.Handler {
|
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, defaults systemdefaults.SystemDefaults, static static.Storage, localDevMode bool) []query.Handler {
|
||||||
return []query.Handler{
|
handlers := []query.Handler{
|
||||||
newOrg(
|
newOrg(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}),
|
||||||
newIAMMember(
|
newIAMMember(
|
||||||
@ -66,6 +67,13 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
|||||||
newFeatures(
|
newFeatures(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("Features"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("Features"), errorCount, es}),
|
||||||
}
|
}
|
||||||
|
if static != nil {
|
||||||
|
handlers = append(handlers, newStyling(
|
||||||
|
handler{view, bulkLimit, configs.cycleDuration("Styling"), errorCount, es},
|
||||||
|
static,
|
||||||
|
localDevMode))
|
||||||
|
}
|
||||||
|
return handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (configs Configs) cycleDuration(viewModel string) time.Duration {
|
func (configs Configs) cycleDuration(viewModel string) time.Duration {
|
||||||
|
@ -2,6 +2,8 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
||||||
@ -77,8 +79,25 @@ func (p *LabelPolicy) processLabelPolicy(event *es_models.Event) (err error) {
|
|||||||
switch event.Type {
|
switch event.Type {
|
||||||
case model.LabelPolicyAdded:
|
case model.LabelPolicyAdded:
|
||||||
err = policy.AppendEvent(event)
|
err = policy.AppendEvent(event)
|
||||||
case model.LabelPolicyChanged:
|
case model.LabelPolicyChanged,
|
||||||
policy, err = p.view.LabelPolicyByAggregateID(event.AggregateID)
|
model.LabelPolicyLogoAdded,
|
||||||
|
model.LabelPolicyLogoRemoved,
|
||||||
|
model.LabelPolicyIconAdded,
|
||||||
|
model.LabelPolicyIconRemoved,
|
||||||
|
model.LabelPolicyLogoDarkAdded,
|
||||||
|
model.LabelPolicyLogoDarkRemoved,
|
||||||
|
model.LabelPolicyIconDarkAdded,
|
||||||
|
model.LabelPolicyIconDarkRemoved,
|
||||||
|
model.LabelPolicyFontAdded,
|
||||||
|
model.LabelPolicyFontRemoved,
|
||||||
|
model.LabelPolicyAssetsRemoved:
|
||||||
|
policy, err = p.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = policy.AppendEvent(event)
|
||||||
|
case model.LabelPolicyActivated:
|
||||||
|
policy, err = p.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
298
internal/admin/repository/eventsourcing/handler/styling.go
Normal file
298
internal/admin/repository/eventsourcing/handler/styling.go
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/lucasb-eyer/go-colorful"
|
||||||
|
"github.com/muesli/gamut"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
|
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||||
|
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||||
|
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
stylingTable = "adminapi.styling"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Styling struct {
|
||||||
|
handler
|
||||||
|
static static.Storage
|
||||||
|
subscription *v1.Subscription
|
||||||
|
devMode bool
|
||||||
|
resourceUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStyling(handler handler, static static.Storage, localDevMode bool) *Styling {
|
||||||
|
h := &Styling{
|
||||||
|
handler: handler,
|
||||||
|
static: static,
|
||||||
|
}
|
||||||
|
prefix := ""
|
||||||
|
if localDevMode {
|
||||||
|
prefix = "/login"
|
||||||
|
}
|
||||||
|
h.resourceUrl = prefix + "/resources/dynamic" //TODO: ?
|
||||||
|
|
||||||
|
h.subscribe()
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) subscribe() {
|
||||||
|
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||||
|
go func() {
|
||||||
|
for event := range m.subscription.Events {
|
||||||
|
query.ReduceEvent(m, event)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) ViewModel() string {
|
||||||
|
return stylingTable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *Styling) AggregateTypes() []es_models.AggregateType {
|
||||||
|
return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) CurrentSequence() (uint64, error) {
|
||||||
|
sequence, err := m.view.GetLatestStylingSequence()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return sequence.CurrentSequence, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) EventQuery() (*es_models.SearchQuery, error) {
|
||||||
|
sequence, err := m.view.GetLatestStylingSequence()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return es_models.NewSearchQuery().
|
||||||
|
AggregateTypeFilter(m.AggregateTypes()...).
|
||||||
|
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) Reduce(event *es_models.Event) (err error) {
|
||||||
|
switch event.AggregateType {
|
||||||
|
case model.OrgAggregate, iam_es_model.IAMAggregate:
|
||||||
|
err = m.processLabelPolicy(event)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) processLabelPolicy(event *es_models.Event) (err error) {
|
||||||
|
policy := new(iam_model.LabelPolicyView)
|
||||||
|
switch event.Type {
|
||||||
|
case iam_es_model.LabelPolicyAdded, model.LabelPolicyAdded:
|
||||||
|
err = policy.AppendEvent(event)
|
||||||
|
case iam_es_model.LabelPolicyChanged, model.LabelPolicyChanged,
|
||||||
|
iam_es_model.LabelPolicyLogoAdded, model.LabelPolicyLogoAdded,
|
||||||
|
iam_es_model.LabelPolicyLogoRemoved, model.LabelPolicyLogoRemoved,
|
||||||
|
iam_es_model.LabelPolicyIconAdded, model.LabelPolicyIconAdded,
|
||||||
|
iam_es_model.LabelPolicyIconRemoved, model.LabelPolicyIconRemoved,
|
||||||
|
iam_es_model.LabelPolicyLogoDarkAdded, model.LabelPolicyLogoDarkAdded,
|
||||||
|
iam_es_model.LabelPolicyLogoDarkRemoved, model.LabelPolicyLogoDarkRemoved,
|
||||||
|
iam_es_model.LabelPolicyIconDarkAdded, model.LabelPolicyIconDarkAdded,
|
||||||
|
iam_es_model.LabelPolicyIconDarkRemoved, model.LabelPolicyIconDarkRemoved,
|
||||||
|
iam_es_model.LabelPolicyFontAdded, model.LabelPolicyFontAdded,
|
||||||
|
iam_es_model.LabelPolicyFontRemoved, model.LabelPolicyFontRemoved,
|
||||||
|
iam_es_model.LabelPolicyAssetsRemoved, model.LabelPolicyAssetsRemoved:
|
||||||
|
policy, err = m.view.StylingByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = policy.AppendEvent(event)
|
||||||
|
|
||||||
|
case iam_es_model.LabelPolicyActivated, model.LabelPolicyActivated:
|
||||||
|
policy, err = m.view.StylingByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = policy.AppendEvent(event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = m.generateStylingFile(policy)
|
||||||
|
default:
|
||||||
|
return m.view.ProcessedStylingSequence(event)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.view.PutStyling(policy, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) OnError(event *es_models.Event, err error) error {
|
||||||
|
logging.LogWithFields("SPOOL-2m9fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler")
|
||||||
|
return spooler.HandleError(event, err, m.view.GetLatestLabelPolicyFailedEvent, m.view.ProcessedLabelPolicyFailedEvent, m.view.ProcessedLabelPolicySequence, m.errorCountUntilSkip)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) OnSuccess() error {
|
||||||
|
return spooler.HandleSuccess(m.view.UpdateLabelPolicySpoolerRunTimestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) generateStylingFile(policy *iam_model.LabelPolicyView) error {
|
||||||
|
reader, size, err := m.writeFile(policy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.uploadFilesToBucket(policy.AggregateID, "text/css", reader, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) writeFile(policy *iam_model.LabelPolicyView) (io.Reader, int64, error) {
|
||||||
|
cssContent := ""
|
||||||
|
cssContent += fmt.Sprint(":root {")
|
||||||
|
if policy.PrimaryColor != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.PrimaryColor)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-primary-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if policy.BackgroundColor != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.BackgroundColor)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-background-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if policy.WarnColor != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.WarnColor)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-warn-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var fontname string
|
||||||
|
if policy.FontURL != "" {
|
||||||
|
split := strings.Split(policy.FontURL, "/")
|
||||||
|
fontname = split[len(split)-1]
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-font-family: %s;", fontname)
|
||||||
|
}
|
||||||
|
cssContent += fmt.Sprint("}")
|
||||||
|
if policy.FontURL != "" {
|
||||||
|
cssContent += fmt.Sprintf(fontFaceTemplate, fontname, m.resourceUrl, policy.AggregateID, policy.FontURL)
|
||||||
|
}
|
||||||
|
cssContent += fmt.Sprint(".lgn-dark-theme {")
|
||||||
|
if policy.PrimaryColorDark != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.PrimaryColorDark)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-primary-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if policy.BackgroundColorDark != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.BackgroundColorDark)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-background-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if policy.WarnColorDark != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.WarnColorDark)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-warn-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if policy.FontColorDark != "" {
|
||||||
|
palette := m.generateColorPaletteRGBA255(policy.FontColorDark)
|
||||||
|
for i, color := range palette {
|
||||||
|
cssContent += fmt.Sprintf("--zitadel-color-font-%v: %s;", i, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cssContent += fmt.Sprint("}")
|
||||||
|
|
||||||
|
data := []byte(cssContent)
|
||||||
|
buffer := bytes.NewBuffer(data)
|
||||||
|
return buffer, int64(buffer.Len()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const fontFaceTemplate = `
|
||||||
|
@font-face {
|
||||||
|
font-family: '%s';
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(%s?orgId=%s&filename=%s);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
func (m *Styling) uploadFilesToBucket(aggregateID, contentType string, reader io.Reader, size int64) error {
|
||||||
|
fileName := domain.CssPath + "/" + domain.CssVariablesFileName
|
||||||
|
_, err := m.static.PutObject(context.Background(), aggregateID, fileName, contentType, reader, size, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Styling) generateColorPaletteRGBA255(hex string) map[string]string {
|
||||||
|
palette := make(map[string]string)
|
||||||
|
defaultColor := gamut.Hex(hex)
|
||||||
|
|
||||||
|
color50, ok := colorful.MakeColor(gamut.Lighter(defaultColor, 1.0))
|
||||||
|
if ok {
|
||||||
|
palette["50"] = cssRGB(color50.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color100, ok := colorful.MakeColor(gamut.Lighter(defaultColor, 0.8))
|
||||||
|
if ok {
|
||||||
|
palette["100"] = cssRGB(color100.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color200, ok := colorful.MakeColor(gamut.Lighter(defaultColor, 0.6))
|
||||||
|
if ok {
|
||||||
|
palette["200"] = cssRGB(color200.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color300, ok := colorful.MakeColor(gamut.Lighter(defaultColor, 0.4))
|
||||||
|
if ok {
|
||||||
|
palette["300"] = cssRGB(color300.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color400, ok := colorful.MakeColor(gamut.Lighter(defaultColor, 0.1))
|
||||||
|
if ok {
|
||||||
|
palette["400"] = cssRGB(color400.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color500, ok := colorful.MakeColor(defaultColor)
|
||||||
|
if ok {
|
||||||
|
palette["500"] = cssRGB(color500.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color600, ok := colorful.MakeColor(gamut.Darker(defaultColor, 0.1))
|
||||||
|
if ok {
|
||||||
|
palette["600"] = cssRGB(color600.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color700, ok := colorful.MakeColor(gamut.Darker(defaultColor, 0.2))
|
||||||
|
if ok {
|
||||||
|
palette["700"] = cssRGB(color700.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color800, ok := colorful.MakeColor(gamut.Darker(defaultColor, 0.3))
|
||||||
|
if ok {
|
||||||
|
palette["800"] = cssRGB(color800.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
color900, ok := colorful.MakeColor(gamut.Darker(defaultColor, 0.4))
|
||||||
|
if ok {
|
||||||
|
palette["900"] = cssRGB(color900.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
colorContrast, ok := colorful.MakeColor(gamut.Contrast(defaultColor))
|
||||||
|
if ok {
|
||||||
|
palette["contrast"] = cssRGB(colorContrast.RGB255())
|
||||||
|
}
|
||||||
|
|
||||||
|
return palette
|
||||||
|
}
|
||||||
|
|
||||||
|
func cssRGB(r, g, b uint8) string {
|
||||||
|
return fmt.Sprintf("rgb(%v, %v, %v)", r, g, b)
|
||||||
|
}
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/config/types"
|
"github.com/caos/zitadel/internal/config/types"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
es_spol "github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
es_spol "github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -28,7 +29,7 @@ type EsRepository struct {
|
|||||||
eventstore.UserRepo
|
eventstore.UserRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRepository, error) {
|
func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, static static.Storage, roles []string, localDevMode bool) (*EsRepository, error) {
|
||||||
es, err := v1.Start(conf.Eventstore)
|
es, err := v1.Start(conf.Eventstore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -42,7 +43,7 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
|
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults, static, localDevMode)
|
||||||
|
|
||||||
return &EsRepository{
|
return &EsRepository{
|
||||||
spooler: spool,
|
spooler: spool,
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/handler"
|
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/handler"
|
||||||
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
||||||
@ -17,12 +18,12 @@ type SpoolerConfig struct {
|
|||||||
Handlers handler.Configs
|
Handlers handler.Configs
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, defaults systemdefaults.SystemDefaults) *spooler.Spooler {
|
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, defaults systemdefaults.SystemDefaults, static static.Storage, localDevMode bool) *spooler.Spooler {
|
||||||
spoolerConfig := spooler.Config{
|
spoolerConfig := spooler.Config{
|
||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
Locker: &locker{dbClient: sql},
|
Locker: &locker{dbClient: sql},
|
||||||
ConcurrentWorkers: c.ConcurrentWorkers,
|
ConcurrentWorkers: c.ConcurrentWorkers,
|
||||||
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, defaults),
|
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, defaults, static, localDevMode),
|
||||||
}
|
}
|
||||||
spool := spoolerConfig.New()
|
spool := spoolerConfig.New()
|
||||||
spool.Start()
|
spool.Start()
|
||||||
|
@ -11,8 +11,8 @@ const (
|
|||||||
labelPolicyTable = "adminapi.label_policies"
|
labelPolicyTable = "adminapi.label_policies"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyView, error) {
|
func (v *View) LabelPolicyByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
|
||||||
return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID)
|
return view.GetLabelPolicyByAggregateIDAndState(v.Db, labelPolicyTable, aggregateID, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
|
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
|
||||||
|
44
internal/admin/repository/eventsourcing/view/styling.go
Normal file
44
internal/admin/repository/eventsourcing/view/styling.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
stylingTyble = "adminapi.styling"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *View) StylingByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
|
||||||
|
return view.GetLabelPolicyByAggregateIDAndState(v.Db, stylingTyble, aggregateID, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) PutStyling(policy *model.LabelPolicyView, event *models.Event) error {
|
||||||
|
err := view.PutLabelPolicy(v.Db, stylingTyble, policy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.ProcessedStylingSequence(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) GetLatestStylingSequence() (*global_view.CurrentSequence, error) {
|
||||||
|
return v.latestSequence(stylingTyble)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) ProcessedStylingSequence(event *models.Event) error {
|
||||||
|
return v.saveCurrentSequence(stylingTyble, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) UpdateStylingSpoolerRunTimestamp() error {
|
||||||
|
return v.updateSpoolerRunSequence(stylingTyble)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) GetLatestStylingFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||||
|
return v.latestFailedEvent(stylingTyble, sequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) ProcessedStylingFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||||
|
return v.saveFailedEvent(failedEvent)
|
||||||
|
}
|
@ -24,6 +24,7 @@ type IAMRepository interface {
|
|||||||
ExternalIDPsByIDPConfigIDFromDefaultPolicy(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error)
|
ExternalIDPsByIDPConfigIDFromDefaultPolicy(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error)
|
||||||
|
|
||||||
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||||
|
GetDefaultPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||||
|
|
||||||
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||||
|
|
||||||
|
194
internal/api/assets/asset.go
Normal file
194
internal/api/assets/asset.go
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
|
||||||
|
"github.com/caos/zitadel/internal/command"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/id"
|
||||||
|
"github.com/caos/zitadel/internal/management/repository"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
errorHandler ErrorHandler
|
||||||
|
storage static.Storage
|
||||||
|
commands *command.Commands
|
||||||
|
authInterceptor *http_mw.AuthInterceptor
|
||||||
|
idGenerator id.Generator
|
||||||
|
orgRepo repository.OrgRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) AuthInterceptor() *http_mw.AuthInterceptor {
|
||||||
|
return h.authInterceptor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Commands() *command.Commands {
|
||||||
|
return h.commands
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) ErrorHandler() ErrorHandler {
|
||||||
|
return DefaultErrorHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Storage() static.Storage {
|
||||||
|
return h.storage
|
||||||
|
}
|
||||||
|
|
||||||
|
type Uploader interface {
|
||||||
|
Callback(ctx context.Context, info *domain.AssetInfo, orgID string, commands *command.Commands) error
|
||||||
|
ObjectName(data authz.CtxData) (string, error)
|
||||||
|
BucketName(data authz.CtxData) string
|
||||||
|
ContentTypeAllowed(contentType string) bool
|
||||||
|
MaxFileSize() int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Downloader interface {
|
||||||
|
ObjectName(ctx context.Context, path string) (string, error)
|
||||||
|
BucketName(ctx context.Context, id string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorHandler func(http.ResponseWriter, *http.Request, error)
|
||||||
|
|
||||||
|
func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
|
logging.Log("ASSET-g5ef1").WithError(err).WithField("uri", r.RequestURI).Error("error occurred on asset api")
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(
|
||||||
|
commands *command.Commands,
|
||||||
|
verifier *authz.TokenVerifier,
|
||||||
|
authConfig authz.Config,
|
||||||
|
idGenerator id.Generator,
|
||||||
|
storage static.Storage,
|
||||||
|
orgRepo repository.OrgRepository,
|
||||||
|
) http.Handler {
|
||||||
|
h := &Handler{
|
||||||
|
commands: commands,
|
||||||
|
errorHandler: DefaultErrorHandler,
|
||||||
|
authInterceptor: http_mw.AuthorizationInterceptor(verifier, authConfig),
|
||||||
|
idGenerator: idGenerator,
|
||||||
|
storage: storage,
|
||||||
|
orgRepo: orgRepo,
|
||||||
|
}
|
||||||
|
|
||||||
|
verifier.RegisterServer("Management-API", "assets", AssetsService_AuthMethods) //TODO: separate api?
|
||||||
|
router := mux.NewRouter()
|
||||||
|
RegisterRoutes(router, h)
|
||||||
|
router.PathPrefix("/{id}").Methods("GET").HandlerFunc(DownloadHandleFunc(h, h.GetFile()))
|
||||||
|
return router
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetFile() Downloader {
|
||||||
|
return &publicFileDownloader{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type publicFileDownloader struct{}
|
||||||
|
|
||||||
|
func (l *publicFileDownloader) ObjectName(_ context.Context, path string) (string, error) {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *publicFileDownloader) BucketName(_ context.Context, id string) string {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxMemory = 2 << 20
|
||||||
|
const paramFile = "file"
|
||||||
|
|
||||||
|
func UploadHandleFunc(s AssetsService, uploader Uploader) func(http.ResponseWriter, *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
ctxData := authz.GetCtxData(ctx)
|
||||||
|
err := r.ParseMultipartForm(maxMemory)
|
||||||
|
file, handler, err := r.FormFile(paramFile)
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err = file.Close()
|
||||||
|
logging.Log("UPLOAD-GDg34").OnError(err).Warn("could not close file")
|
||||||
|
}()
|
||||||
|
contentType := handler.Header.Get("content-type")
|
||||||
|
size := handler.Size
|
||||||
|
if !uploader.ContentTypeAllowed(contentType) {
|
||||||
|
s.ErrorHandler()(w, r, caos_errs.ThrowInvalidArgument(nil, "UPLOAD-Dbvfs", "invalid content-type"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if size > uploader.MaxFileSize() {
|
||||||
|
s.ErrorHandler()(w, r, caos_errs.ThrowInvalidArgumentf(nil, "UPLOAD-Bfb32", "file to big, max file size is %v", uploader.MaxFileSize()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bucketName := uploader.BucketName(ctxData)
|
||||||
|
objectName, err := uploader.ObjectName(ctxData)
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info, err := s.Commands().UploadAsset(ctx, bucketName, objectName, contentType, file, size)
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = uploader.Callback(ctx, info, ctxData.OrgID, s.Commands())
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DownloadHandleFunc(s AssetsService, downloader Downloader) func(http.ResponseWriter, *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if s.Storage() == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := r.Context()
|
||||||
|
id := mux.Vars(r)["id"]
|
||||||
|
bucketName := downloader.BucketName(ctx, id)
|
||||||
|
path := ""
|
||||||
|
if id != "" {
|
||||||
|
path = strings.Split(r.RequestURI, id+"/")[1]
|
||||||
|
}
|
||||||
|
objectName, err := downloader.ObjectName(ctx, path)
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if objectName == "" {
|
||||||
|
s.ErrorHandler()(w, r, caos_errs.ThrowNotFound(nil, "UPLOAD-adf4f", "file not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reader, getInfo, err := s.Storage().GetObject(ctx, bucketName, objectName)
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info, err := getInfo()
|
||||||
|
if err != nil {
|
||||||
|
s.ErrorHandler()(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("content-length", strconv.FormatInt(info.Size, 10))
|
||||||
|
w.Header().Set("content-type", info.ContentType)
|
||||||
|
w.Header().Set("ETag", info.ETag)
|
||||||
|
w.Write(data)
|
||||||
|
}
|
||||||
|
}
|
119
internal/api/assets/generator/asset.yaml
Normal file
119
internal/api/assets/generator/asset.yaml
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
Services:
|
||||||
|
IAM:
|
||||||
|
Prefix: "/iam"
|
||||||
|
Methods:
|
||||||
|
DefaultLabelPolicyLogo:
|
||||||
|
Path: "/policy/label/logo"
|
||||||
|
HasDarkMode: true
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: iam.policy.write
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: iam.policy.read
|
||||||
|
- Name: GetPreview
|
||||||
|
Comment:
|
||||||
|
Type: preview
|
||||||
|
Permission: iam.policy.read
|
||||||
|
DefaultLabelPolicyIcon:
|
||||||
|
Path: "/policy/label/icon"
|
||||||
|
HasDarkMode: true
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: iam.policy.write
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: iam.policy.read
|
||||||
|
- Name: GetPreview
|
||||||
|
Comment:
|
||||||
|
Type: preview
|
||||||
|
Permission: iam.policy.read
|
||||||
|
DefaultLabelPolicyFont:
|
||||||
|
Path: "/policy/label/font"
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: iam.policy.write
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: iam.policy.read
|
||||||
|
- Name: GetPreview
|
||||||
|
Comment:
|
||||||
|
Type: preview
|
||||||
|
Permission: iam.policy.read
|
||||||
|
Org:
|
||||||
|
Prefix: "/org"
|
||||||
|
Methods:
|
||||||
|
OrgLabelPolicyLogo:
|
||||||
|
Path: "/policy/label/logo"
|
||||||
|
Feature: "label_policy.private_label"
|
||||||
|
HasDarkMode: true
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: policy.write
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: policy.read
|
||||||
|
- Name: GetPreview
|
||||||
|
Comment:
|
||||||
|
Type: preview
|
||||||
|
Permission: policy.read
|
||||||
|
OrgLabelPolicyIcon:
|
||||||
|
Path: "/policy/label/icon"
|
||||||
|
Feature: "label_policy.private_label"
|
||||||
|
HasDarkMode: true
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: policy.write
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: policy.read
|
||||||
|
- Name: GetPreview
|
||||||
|
Comment:
|
||||||
|
Type: preview
|
||||||
|
Permission: policy.read
|
||||||
|
OrgLabelPolicyFont:
|
||||||
|
Path: "/policy/label/font"
|
||||||
|
Feature: "label_policy.private_label"
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: policy.write
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: policy.read
|
||||||
|
- Name: GetPreview
|
||||||
|
Comment:
|
||||||
|
Type: preview
|
||||||
|
Permission: policy.read
|
||||||
|
Users:
|
||||||
|
Prefix: "/users"
|
||||||
|
Methods:
|
||||||
|
MyUserAvatar:
|
||||||
|
Path: "/me/avatar"
|
||||||
|
Features: "label_policy.private_label"
|
||||||
|
Handlers:
|
||||||
|
- Name: Upload
|
||||||
|
Comment:
|
||||||
|
Type: upload
|
||||||
|
Permission: authenticated
|
||||||
|
- Name: Get
|
||||||
|
Comment:
|
||||||
|
Type: download
|
||||||
|
Permission: authenticated
|
200
internal/api/assets/generator/asset_generator.go
Normal file
200
internal/api/assets/generator/asset_generator.go
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
directory = flag.String("directory", "./", "working directory: asset.yaml must be in this directory, files will be generated into parent directory")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
configFile := *directory + "asset.yaml"
|
||||||
|
authz, err := os.OpenFile(*directory+"../authz.go", os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0755)
|
||||||
|
logging.Log("ASSETS-Gn31f").OnError(err).Fatal("cannot open authz file")
|
||||||
|
router, err := os.OpenFile(*directory+"../router.go", os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0755)
|
||||||
|
logging.Log("ASSETS-ABen3").OnError(err).Fatal("cannot open router file")
|
||||||
|
GenerateAssetHandler(configFile, authz, router)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Method struct {
|
||||||
|
Path string
|
||||||
|
Feature string
|
||||||
|
HasDarkMode bool
|
||||||
|
Handlers []Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
Name string
|
||||||
|
Comment string
|
||||||
|
Type HandlerType
|
||||||
|
Permission string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Handler) Method() string {
|
||||||
|
if a.Type == MethodTypeUpload {
|
||||||
|
return "POST"
|
||||||
|
}
|
||||||
|
return "GET"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Handler) PathSuffix() string {
|
||||||
|
if a.Type == MethodTypePreview {
|
||||||
|
return "/_preview"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Handler) MethodReturn() string {
|
||||||
|
if a.Type == MethodTypeUpload {
|
||||||
|
return "Uploader"
|
||||||
|
}
|
||||||
|
if a.Type == MethodTypeDownload {
|
||||||
|
return "Downloader"
|
||||||
|
}
|
||||||
|
if a.Type == MethodTypePreview {
|
||||||
|
return "Downloader"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Handler) HandlerType() string {
|
||||||
|
if a.Type == MethodTypeUpload {
|
||||||
|
return "UploadHandleFunc"
|
||||||
|
}
|
||||||
|
if a.Type == MethodTypeDownload {
|
||||||
|
return "DownloadHandleFunc"
|
||||||
|
}
|
||||||
|
if a.Type == MethodTypePreview {
|
||||||
|
return "DownloadHandleFunc"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandlerType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
MethodTypeUpload = "upload"
|
||||||
|
MethodTypeDownload = "download"
|
||||||
|
MethodTypePreview = "preview"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Services map[string]Service
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
Prefix string
|
||||||
|
Methods map[string]Method
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateAssetHandler(configFilePath string, output io.Writer, output2 io.Writer) {
|
||||||
|
conf := new(struct {
|
||||||
|
Services Services
|
||||||
|
})
|
||||||
|
err := config.Read(conf, configFilePath)
|
||||||
|
logging.Log("ASSETS-Dgbn4").OnError(err).Fatal("cannot read config")
|
||||||
|
tmplAuthz, err := template.New("").Parse(authzTmpl)
|
||||||
|
logging.Log("ASSETS-BGbbg").OnError(err).Fatal("cannot parse authz template")
|
||||||
|
tmplRouter, err := template.New("").Parse(routerTmpl)
|
||||||
|
logging.Log("ASSETS-gh4rq").OnError(err).Fatal("cannot parse router template")
|
||||||
|
data := &struct {
|
||||||
|
GoPkgName string
|
||||||
|
Name string
|
||||||
|
Prefix string
|
||||||
|
Services Services
|
||||||
|
}{
|
||||||
|
GoPkgName: "assets",
|
||||||
|
Name: "AssetsService",
|
||||||
|
Prefix: "/assets/v1",
|
||||||
|
Services: conf.Services,
|
||||||
|
}
|
||||||
|
err = tmplAuthz.Execute(output, data)
|
||||||
|
logging.Log("ASSETS-BHngj").OnError(err).Fatal("cannot generate authz")
|
||||||
|
err = tmplRouter.Execute(output2, data)
|
||||||
|
logging.Log("ASSETS-Bfd41").OnError(err).Fatal("cannot generate router")
|
||||||
|
}
|
||||||
|
|
||||||
|
const authzTmpl = `package {{.GoPkgName}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {{.Name}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
{{ $prefix := .Prefix }}
|
||||||
|
var {{.Name}}_AuthMethods = authz.MethodMapping {
|
||||||
|
{{ range $service := .Services}}
|
||||||
|
{{ range $method := .Methods}}
|
||||||
|
{{ range $handler := .Handlers}}
|
||||||
|
{{ if (or $method.Feature $handler.Permission) }}
|
||||||
|
"{{$handler.Method}}:{{$prefix}}{{$service.Prefix}}{{$method.Path}}{{$handler.PathSuffix}}": authz.Option{
|
||||||
|
Permission: "{{$handler.Permission}}",
|
||||||
|
Feature: "{{$method.Feature}}",
|
||||||
|
},
|
||||||
|
{{ if $method.HasDarkMode }}
|
||||||
|
"{{$handler.Method}}:{{$prefix}}{{$service.Prefix}}{{$method.Path}}/dark{{$handler.PathSuffix}}": authz.Option{
|
||||||
|
Permission: "{{$handler.Permission}}",
|
||||||
|
Feature: "{{$method.Feature}}",
|
||||||
|
},
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const routerTmpl = `package {{.GoPkgName}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
|
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
|
||||||
|
"github.com/caos/zitadel/internal/command"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
|
)
|
||||||
|
|
||||||
|
type {{.Name}} interface {
|
||||||
|
AuthInterceptor() *http_mw.AuthInterceptor
|
||||||
|
Commands() *command.Commands
|
||||||
|
ErrorHandler() ErrorHandler
|
||||||
|
Storage() static.Storage
|
||||||
|
|
||||||
|
{{ range $service := .Services}}
|
||||||
|
{{ range $methodName, $method := .Methods}}
|
||||||
|
{{ range $handler := .Handlers}}
|
||||||
|
{{$handler.Name}}{{$methodName}}() {{if $handler.MethodReturn}}{{$handler.MethodReturn}}{{end}}
|
||||||
|
{{ if $method.HasDarkMode }}
|
||||||
|
{{$handler.Name}}{{$methodName}}Dark() {{if $handler.MethodReturn}}{{$handler.MethodReturn}}{{end}}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterRoutes(router *mux.Router, s {{.Name}}) {
|
||||||
|
|
||||||
|
router.Use(s.AuthInterceptor().Handler)
|
||||||
|
|
||||||
|
{{ range $service := .Services}}
|
||||||
|
{{ range $methodName, $method := .Methods}}
|
||||||
|
{{ range $handler := .Handlers}}
|
||||||
|
router.Path("{{$service.Prefix}}{{$method.Path}}{{$handler.PathSuffix}}").Methods("{{$handler.Method}}").HandlerFunc({{if $handler.HandlerType}}{{$handler.HandlerType}}(s, {{end}}s.{{$handler.Name}}{{$methodName}}(){{if $handler.HandlerType}}){{end}})
|
||||||
|
{{ if $method.HasDarkMode }}
|
||||||
|
router.Path("{{$service.Prefix}}{{$method.Path}}/dark{{$handler.PathSuffix}}").Methods("{{$handler.Method}}").HandlerFunc({{if $handler.HandlerType}}{{$handler.HandlerType}}(s, {{end}}s.{{$handler.Name}}{{$methodName}}Dark(){{if $handler.HandlerType}}){{end}})
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
`
|
377
internal/api/assets/login_policy.go
Normal file
377
internal/api/assets/login_policy.go
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
"github.com/caos/zitadel/internal/command"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/iam/model"
|
||||||
|
"github.com/caos/zitadel/internal/id"
|
||||||
|
"github.com/caos/zitadel/internal/management/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) UploadDefaultLabelPolicyLogo() Uploader {
|
||||||
|
return &labelPolicyLogoUploader{h.idGenerator, false, true, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadDefaultLabelPolicyLogoDark() Uploader {
|
||||||
|
return &labelPolicyLogoUploader{h.idGenerator, true, true, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadOrgLabelPolicyLogo() Uploader {
|
||||||
|
return &labelPolicyLogoUploader{h.idGenerator, false, false, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadOrgLabelPolicyLogoDark() Uploader {
|
||||||
|
return &labelPolicyLogoUploader{h.idGenerator, true, false, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelPolicyLogoUploader struct {
|
||||||
|
idGenerator id.Generator
|
||||||
|
darkMode bool
|
||||||
|
defaultPolicy bool
|
||||||
|
contentTypes []string
|
||||||
|
maxSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoUploader) ContentTypeAllowed(contentType string) bool {
|
||||||
|
for _, ct := range l.contentTypes {
|
||||||
|
if strings.HasPrefix(contentType, ct) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoUploader) MaxFileSize() int64 {
|
||||||
|
return l.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoUploader) ObjectName(_ authz.CtxData) (string, error) {
|
||||||
|
suffixID, err := l.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
prefix := domain.LabelPolicyLogoPath
|
||||||
|
if l.darkMode {
|
||||||
|
return prefix + "-" + domain.Dark + "-" + suffixID, nil
|
||||||
|
}
|
||||||
|
return prefix + "-" + suffixID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoUploader) BucketName(ctxData authz.CtxData) string {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
return domain.IAMID
|
||||||
|
}
|
||||||
|
return ctxData.OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoUploader) Callback(ctx context.Context, info *domain.AssetInfo, orgID string, commands *command.Commands) error {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
if l.darkMode {
|
||||||
|
_, err := commands.AddLogoDarkDefaultLabelPolicy(ctx, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := commands.AddLogoDefaultLabelPolicy(ctx, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if l.darkMode {
|
||||||
|
_, err := commands.AddLogoDarkLabelPolicy(ctx, orgID, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := commands.AddLogoLabelPolicy(ctx, orgID, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetDefaultLabelPolicyLogo() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetDefaultLabelPolicyLogoDark() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewDefaultLabelPolicyLogo() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewDefaultLabelPolicyLogoDark() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetOrgLabelPolicyLogo() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetOrgLabelPolicyLogoDark() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewOrgLabelPolicyLogo() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewOrgLabelPolicyLogoDark() Downloader {
|
||||||
|
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelPolicyLogoDownloader struct {
|
||||||
|
org repository.OrgRepository
|
||||||
|
darkMode bool
|
||||||
|
defaultPolicy bool
|
||||||
|
preview bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoDownloader) ObjectName(ctx context.Context, path string) (string, error) {
|
||||||
|
policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.org)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if l.darkMode {
|
||||||
|
return policy.LogoDarkURL, nil
|
||||||
|
}
|
||||||
|
return policy.LogoURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyLogoDownloader) BucketName(ctx context.Context, id string) string {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
return domain.IAMID
|
||||||
|
}
|
||||||
|
return authz.GetCtxData(ctx).OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadDefaultLabelPolicyIcon() Uploader {
|
||||||
|
return &labelPolicyIconUploader{h.idGenerator, false, true, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadDefaultLabelPolicyIconDark() Uploader {
|
||||||
|
return &labelPolicyIconUploader{h.idGenerator, true, true, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadOrgLabelPolicyIcon() Uploader {
|
||||||
|
return &labelPolicyIconUploader{h.idGenerator, false, false, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadOrgLabelPolicyIconDark() Uploader {
|
||||||
|
return &labelPolicyIconUploader{h.idGenerator, true, false, []string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelPolicyIconUploader struct {
|
||||||
|
idGenerator id.Generator
|
||||||
|
darkMode bool
|
||||||
|
defaultPolicy bool
|
||||||
|
contentTypes []string
|
||||||
|
maxSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconUploader) ContentTypeAllowed(contentType string) bool {
|
||||||
|
for _, ct := range l.contentTypes {
|
||||||
|
if strings.HasPrefix(contentType, ct) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconUploader) MaxFileSize() int64 {
|
||||||
|
return l.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconUploader) ObjectName(_ authz.CtxData) (string, error) {
|
||||||
|
suffixID, err := l.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
prefix := domain.LabelPolicyIconPath
|
||||||
|
if l.darkMode {
|
||||||
|
return prefix + "-" + domain.Dark + "-" + suffixID, nil
|
||||||
|
}
|
||||||
|
return prefix + "-" + suffixID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconUploader) BucketName(ctxData authz.CtxData) string {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
return domain.IAMID
|
||||||
|
}
|
||||||
|
return ctxData.OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconUploader) Callback(ctx context.Context, info *domain.AssetInfo, orgID string, commands *command.Commands) error {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
if l.darkMode {
|
||||||
|
_, err := commands.AddIconDarkDefaultLabelPolicy(ctx, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := commands.AddIconDefaultLabelPolicy(ctx, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.darkMode {
|
||||||
|
_, err := commands.AddIconDarkLabelPolicy(ctx, orgID, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := commands.AddIconLabelPolicy(ctx, orgID, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetDefaultLabelPolicyIcon() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetDefaultLabelPolicyIconDark() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewDefaultLabelPolicyIcon() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewDefaultLabelPolicyIconDark() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetOrgLabelPolicyIcon() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetOrgLabelPolicyIconDark() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewOrgLabelPolicyIcon() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewOrgLabelPolicyIconDark() Downloader {
|
||||||
|
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelPolicyIconDownloader struct {
|
||||||
|
org repository.OrgRepository
|
||||||
|
darkMode bool
|
||||||
|
defaultPolicy bool
|
||||||
|
preview bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconDownloader) ObjectName(ctx context.Context, path string) (string, error) {
|
||||||
|
policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.org)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if l.darkMode {
|
||||||
|
return policy.IconDarkURL, nil
|
||||||
|
}
|
||||||
|
return policy.IconURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyIconDownloader) BucketName(ctx context.Context, id string) string {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
return domain.IAMID
|
||||||
|
}
|
||||||
|
return authz.GetCtxData(ctx).OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadDefaultLabelPolicyFont() Uploader {
|
||||||
|
return &labelPolicyFontUploader{h.idGenerator, true, []string{"font/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UploadOrgLabelPolicyFont() Uploader {
|
||||||
|
return &labelPolicyFontUploader{h.idGenerator, false, []string{"font/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelPolicyFontUploader struct {
|
||||||
|
idGenerator id.Generator
|
||||||
|
defaultPolicy bool
|
||||||
|
contentTypes []string
|
||||||
|
maxSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontUploader) ContentTypeAllowed(contentType string) bool {
|
||||||
|
for _, ct := range l.contentTypes {
|
||||||
|
if strings.HasPrefix(contentType, ct) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontUploader) MaxFileSize() int64 {
|
||||||
|
return l.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontUploader) ObjectName(_ authz.CtxData) (string, error) {
|
||||||
|
suffixID, err := l.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
prefix := domain.LabelPolicyFontPath
|
||||||
|
return prefix + "-" + suffixID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontUploader) BucketName(ctxData authz.CtxData) string {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
return domain.IAMID
|
||||||
|
}
|
||||||
|
return ctxData.OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontUploader) Callback(ctx context.Context, info *domain.AssetInfo, orgID string, commands *command.Commands) error {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
_, err := commands.AddFontDefaultLabelPolicy(ctx, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := commands.AddFontLabelPolicy(ctx, orgID, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetDefaultLabelPolicyFont() Downloader {
|
||||||
|
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: true, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewDefaultLabelPolicyFont() Downloader {
|
||||||
|
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: true, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetOrgLabelPolicyFont() Downloader {
|
||||||
|
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: false, preview: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetPreviewOrgLabelPolicyFont() Downloader {
|
||||||
|
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: true, preview: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelPolicyFontDownloader struct {
|
||||||
|
org repository.OrgRepository
|
||||||
|
defaultPolicy bool
|
||||||
|
preview bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontDownloader) ObjectName(ctx context.Context, path string) (string, error) {
|
||||||
|
policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.org)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return policy.FontURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelPolicyFontDownloader) BucketName(ctx context.Context, id string) string {
|
||||||
|
if l.defaultPolicy {
|
||||||
|
return domain.IAMID
|
||||||
|
}
|
||||||
|
return authz.GetCtxData(ctx).OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLabelPolicy(ctx context.Context, defaultPolicy, preview bool, orgRepo repository.OrgRepository) (*model.LabelPolicyView, error) {
|
||||||
|
if defaultPolicy {
|
||||||
|
if preview {
|
||||||
|
return orgRepo.GetPreviewDefaultLabelPolicy(ctx)
|
||||||
|
}
|
||||||
|
return orgRepo.GetDefaultLabelPolicy(ctx)
|
||||||
|
}
|
||||||
|
if preview {
|
||||||
|
return orgRepo.GetPreviewLabelPolicy(ctx)
|
||||||
|
}
|
||||||
|
return orgRepo.GetLabelPolicy(ctx)
|
||||||
|
}
|
59
internal/api/assets/user_avatar.go
Normal file
59
internal/api/assets/user_avatar.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
"github.com/caos/zitadel/internal/command"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) UploadMyUserAvatar() Uploader {
|
||||||
|
return &myHumanAvatarUploader{[]string{"image/"}, 1 << 19}
|
||||||
|
}
|
||||||
|
|
||||||
|
type myHumanAvatarUploader struct {
|
||||||
|
contentTypes []string
|
||||||
|
maxSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarUploader) ContentTypeAllowed(contentType string) bool {
|
||||||
|
for _, ct := range l.contentTypes {
|
||||||
|
if strings.HasPrefix(contentType, ct) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarUploader) MaxFileSize() int64 {
|
||||||
|
return l.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarUploader) ObjectName(ctxData authz.CtxData) (string, error) {
|
||||||
|
return domain.GetHumanAvatarAssetPath(ctxData.UserID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarUploader) BucketName(ctxData authz.CtxData) string {
|
||||||
|
return ctxData.OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarUploader) Callback(ctx context.Context, info *domain.AssetInfo, orgID string, commands *command.Commands) error {
|
||||||
|
_, err := commands.AddHumanAvatar(ctx, orgID, authz.GetCtxData(ctx).UserID, info.Key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) GetMyUserAvatar() Downloader {
|
||||||
|
return &myHumanAvatarDownloader{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type myHumanAvatarDownloader struct{}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarDownloader) ObjectName(ctx context.Context, path string) (string, error) {
|
||||||
|
return domain.GetHumanAvatarAssetPath(authz.GetCtxData(ctx).UserID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *myHumanAvatarDownloader) BucketName(ctx context.Context, id string) string {
|
||||||
|
return authz.GetCtxData(ctx).OrgID
|
||||||
|
}
|
@ -71,7 +71,8 @@ func setDefaultFeaturesRequestToDomain(req *admin_pb.SetDefaultFeaturesRequest)
|
|||||||
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
||||||
LoginPolicyPasswordReset: req.LoginPolicyPasswordReset,
|
LoginPolicyPasswordReset: req.LoginPolicyPasswordReset,
|
||||||
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
||||||
LabelPolicy: req.LabelPolicy,
|
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
|
||||||
|
LabelPolicyWatermark: req.LabelPolicyWatermark,
|
||||||
CustomDomain: req.CustomDomain,
|
CustomDomain: req.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +91,8 @@ func setOrgFeaturesRequestToDomain(req *admin_pb.SetOrgFeaturesRequest) *domain.
|
|||||||
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
||||||
LoginPolicyPasswordReset: req.LoginPolicyPasswordReset,
|
LoginPolicyPasswordReset: req.LoginPolicyPasswordReset,
|
||||||
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
||||||
LabelPolicy: req.LabelPolicy,
|
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
|
||||||
|
LabelPolicyWatermark: req.LabelPolicyWatermark,
|
||||||
CustomDomain: req.CustomDomain,
|
CustomDomain: req.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,14 @@ func (s *Server) GetLabelPolicy(ctx context.Context, req *admin_pb.GetLabelPolic
|
|||||||
return &admin_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
return &admin_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetPreviewLabelPolicy(ctx context.Context, req *admin_pb.GetPreviewLabelPolicyRequest) (*admin_pb.GetPreviewLabelPolicyResponse, error) {
|
||||||
|
policy, err := s.iam.GetDefaultPreviewLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.GetPreviewLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) UpdateLabelPolicy(ctx context.Context, req *admin_pb.UpdateLabelPolicyRequest) (*admin_pb.UpdateLabelPolicyResponse, error) {
|
func (s *Server) UpdateLabelPolicy(ctx context.Context, req *admin_pb.UpdateLabelPolicyRequest) (*admin_pb.UpdateLabelPolicyResponse, error) {
|
||||||
policy, err := s.command.ChangeDefaultLabelPolicy(ctx, updateLabelPolicyToDomain(req))
|
policy, err := s.command.ChangeDefaultLabelPolicy(ctx, updateLabelPolicyToDomain(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -29,3 +37,87 @@ func (s *Server) UpdateLabelPolicy(ctx context.Context, req *admin_pb.UpdateLabe
|
|||||||
),
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) ActivateLabelPolicy(ctx context.Context, req *admin_pb.ActivateLabelPolicyRequest) (*admin_pb.ActivateLabelPolicyResponse, error) {
|
||||||
|
policy, err := s.command.ActivateDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.ActivateLabelPolicyResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveLabelPolicyLogo(ctx context.Context, req *admin_pb.RemoveLabelPolicyLogoRequest) (*admin_pb.RemoveLabelPolicyLogoResponse, error) {
|
||||||
|
policy, err := s.command.RemoveLogoDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.RemoveLabelPolicyLogoResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveLabelPolicyLogoDark(ctx context.Context, req *admin_pb.RemoveLabelPolicyLogoDarkRequest) (*admin_pb.RemoveLabelPolicyLogoDarkResponse, error) {
|
||||||
|
policy, err := s.command.RemoveLogoDarkDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.RemoveLabelPolicyLogoDarkResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveLabelPolicyIcon(ctx context.Context, req *admin_pb.RemoveLabelPolicyIconRequest) (*admin_pb.RemoveLabelPolicyIconResponse, error) {
|
||||||
|
policy, err := s.command.RemoveIconDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.RemoveLabelPolicyIconResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveLabelPolicyIconDark(ctx context.Context, req *admin_pb.RemoveLabelPolicyIconDarkRequest) (*admin_pb.RemoveLabelPolicyIconDarkResponse, error) {
|
||||||
|
policy, err := s.command.RemoveIconDarkDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.RemoveLabelPolicyIconDarkResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveLabelPolicyFont(ctx context.Context, req *admin_pb.RemoveLabelPolicyFontRequest) (*admin_pb.RemoveLabelPolicyFontResponse, error) {
|
||||||
|
policy, err := s.command.RemoveFontDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.RemoveLabelPolicyFontResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -8,7 +8,14 @@ import (
|
|||||||
func updateLabelPolicyToDomain(policy *admin_pb.UpdateLabelPolicyRequest) *domain.LabelPolicy {
|
func updateLabelPolicyToDomain(policy *admin_pb.UpdateLabelPolicyRequest) *domain.LabelPolicy {
|
||||||
return &domain.LabelPolicy{
|
return &domain.LabelPolicy{
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
BackgroundColor: policy.BackgroundColor,
|
||||||
|
WarnColor: policy.WarnColor,
|
||||||
|
FontColor: policy.FontColor,
|
||||||
|
PrimaryColorDark: policy.PrimaryColorDark,
|
||||||
|
BackgroundColorDark: policy.BackgroundColorDark,
|
||||||
|
WarnColorDark: policy.WarnColorDark,
|
||||||
|
FontColorDark: policy.FontColorDark,
|
||||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
|
DisableWatermark: policy.DisableWatermark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
internal/api/grpc/auth/avatar.go
Normal file
20
internal/api/grpc/auth/avatar.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||||
|
auth_pb "github.com/caos/zitadel/pkg/grpc/auth"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) RemoveMyAvatar(ctx context.Context, req *auth_pb.RemoveMyAvatarRequest) (*auth_pb.RemoveMyAvatarResponse, error) {
|
||||||
|
ctxData := authz.GetCtxData(ctx)
|
||||||
|
objectDetails, err := s.command.RemoveHumanAvatar(ctx, ctxData.ResourceOwner, ctxData.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &auth_pb.RemoveMyAvatarResponse{
|
||||||
|
Details: object.DomainToChangeDetailsPb(objectDetails),
|
||||||
|
}, nil
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
"github.com/caos/zitadel/internal/api/grpc/server"
|
"github.com/caos/zitadel/internal/api/grpc/server"
|
||||||
"github.com/caos/zitadel/internal/auth/repository"
|
"github.com/caos/zitadel/internal/auth/repository"
|
||||||
@ -8,7 +10,6 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/command"
|
"github.com/caos/zitadel/internal/command"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
"github.com/caos/zitadel/pkg/grpc/auth"
|
"github.com/caos/zitadel/pkg/grpc/auth"
|
||||||
"google.golang.org/grpc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ auth.AuthServiceServer = (*Server)(nil)
|
var _ auth.AuthServiceServer = (*Server)(nil)
|
||||||
|
@ -23,8 +23,10 @@ func FeaturesFromModel(features *features_model.FeaturesView) *features_pb.Featu
|
|||||||
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
|
||||||
LoginPolicyPasswordReset: features.LoginPolicyPasswordReset,
|
LoginPolicyPasswordReset: features.LoginPolicyPasswordReset,
|
||||||
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
|
||||||
LabelPolicy: features.LabelPolicy,
|
LabelPolicy: features.LabelPolicyPrivateLabel,
|
||||||
CustomDomain: features.CustomDomain,
|
CustomDomain: features.CustomDomain,
|
||||||
|
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
|
||||||
|
LabelPolicyWatermark: features.LabelPolicyWatermark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,15 @@ func (s *Server) GetLabelPolicy(ctx context.Context, req *mgmt_pb.GetLabelPolicy
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &mgmt_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
return &mgmt_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy), IsDefault: policy.Default}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetPreviewLabelPolicy(ctx context.Context, req *mgmt_pb.GetPreviewLabelPolicyRequest) (*mgmt_pb.GetPreviewLabelPolicyResponse, error) {
|
||||||
|
policy, err := s.org.GetPreviewLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.GetPreviewLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLabelPolicyRequest) (*mgmt_pb.GetDefaultLabelPolicyResponse, error) {
|
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLabelPolicyRequest) (*mgmt_pb.GetDefaultLabelPolicyResponse, error) {
|
||||||
@ -53,6 +61,20 @@ func (s *Server) UpdateCustomLabelPolicy(ctx context.Context, req *mgmt_pb.Updat
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) ActivateCustomLabelPolicy(ctx context.Context, req *mgmt_pb.ActivateCustomLabelPolicyRequest) (*mgmt_pb.ActivateCustomLabelPolicyResponse, error) {
|
||||||
|
policy, err := s.command.ActivateLabelPolicy(ctx, authz.GetCtxData(ctx).OrgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.ActivateCustomLabelPolicyResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) ResetLabelPolicyToDefault(ctx context.Context, req *mgmt_pb.ResetLabelPolicyToDefaultRequest) (*mgmt_pb.ResetLabelPolicyToDefaultResponse, error) {
|
func (s *Server) ResetLabelPolicyToDefault(ctx context.Context, req *mgmt_pb.ResetLabelPolicyToDefaultRequest) (*mgmt_pb.ResetLabelPolicyToDefaultResponse, error) {
|
||||||
objectDetails, err := s.command.RemoveLabelPolicy(ctx, authz.GetCtxData(ctx).OrgID)
|
objectDetails, err := s.command.RemoveLabelPolicy(ctx, authz.GetCtxData(ctx).OrgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -62,3 +84,73 @@ func (s *Server) ResetLabelPolicyToDefault(ctx context.Context, req *mgmt_pb.Res
|
|||||||
Details: object.DomainToChangeDetailsPb(objectDetails),
|
Details: object.DomainToChangeDetailsPb(objectDetails),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveCustomLabelPolicyLogo(ctx context.Context, req *mgmt_pb.RemoveCustomLabelPolicyLogoRequest) (*mgmt_pb.RemoveCustomLabelPolicyLogoResponse, error) {
|
||||||
|
policy, err := s.command.RemoveLogoDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.RemoveCustomLabelPolicyLogoResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveCustomLabelPolicyLogoDark(ctx context.Context, req *mgmt_pb.RemoveCustomLabelPolicyLogoDarkRequest) (*mgmt_pb.RemoveCustomLabelPolicyLogoDarkResponse, error) {
|
||||||
|
policy, err := s.command.RemoveLogoDarkDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.RemoveCustomLabelPolicyLogoDarkResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveCustomLabelPolicyIcon(ctx context.Context, req *mgmt_pb.RemoveCustomLabelPolicyIconRequest) (*mgmt_pb.RemoveCustomLabelPolicyIconResponse, error) {
|
||||||
|
policy, err := s.command.RemoveIconDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.RemoveCustomLabelPolicyIconResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveCustomLabelPolicyIconDark(ctx context.Context, req *mgmt_pb.RemoveCustomLabelPolicyIconDarkRequest) (*mgmt_pb.RemoveCustomLabelPolicyIconDarkResponse, error) {
|
||||||
|
policy, err := s.command.RemoveIconDarkDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.RemoveCustomLabelPolicyIconDarkResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveCustomLabelPolicyFont(ctx context.Context, req *mgmt_pb.RemoveCustomLabelPolicyFontRequest) (*mgmt_pb.RemoveCustomLabelPolicyFontResponse, error) {
|
||||||
|
policy, err := s.command.RemoveFontDefaultLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.RemoveCustomLabelPolicyFontResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
policy.Sequence,
|
||||||
|
policy.EventDate,
|
||||||
|
policy.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -8,15 +8,27 @@ import (
|
|||||||
func addLabelPolicyToDomain(p *mgmt_pb.AddCustomLabelPolicyRequest) *domain.LabelPolicy {
|
func addLabelPolicyToDomain(p *mgmt_pb.AddCustomLabelPolicyRequest) *domain.LabelPolicy {
|
||||||
return &domain.LabelPolicy{
|
return &domain.LabelPolicy{
|
||||||
PrimaryColor: p.PrimaryColor,
|
PrimaryColor: p.PrimaryColor,
|
||||||
SecondaryColor: p.SecondaryColor,
|
BackgroundColor: p.BackgroundColor,
|
||||||
|
WarnColor: p.WarnColor,
|
||||||
|
PrimaryColorDark: p.PrimaryColorDark,
|
||||||
|
BackgroundColorDark: p.BackgroundColorDark,
|
||||||
|
WarnColorDark: p.WarnColorDark,
|
||||||
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
||||||
|
DisableWatermark: p.DisableWatermark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLabelPolicyToDomain(p *mgmt_pb.UpdateCustomLabelPolicyRequest) *domain.LabelPolicy {
|
func updateLabelPolicyToDomain(p *mgmt_pb.UpdateCustomLabelPolicyRequest) *domain.LabelPolicy {
|
||||||
return &domain.LabelPolicy{
|
return &domain.LabelPolicy{
|
||||||
PrimaryColor: p.PrimaryColor,
|
PrimaryColor: p.PrimaryColor,
|
||||||
SecondaryColor: p.SecondaryColor,
|
BackgroundColor: p.BackgroundColor,
|
||||||
|
WarnColor: p.WarnColor,
|
||||||
|
FontColor: p.FontColor,
|
||||||
|
PrimaryColorDark: p.PrimaryColorDark,
|
||||||
|
BackgroundColorDark: p.BackgroundColorDark,
|
||||||
|
WarnColorDark: p.WarnColorDark,
|
||||||
|
FontColorDark: p.FontColorDark,
|
||||||
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
||||||
|
DisableWatermark: p.DisableWatermark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ func (s *Server) GetLoginPolicy(ctx context.Context, req *mgmt_pb.GetLoginPolicy
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &mgmt_pb.GetLoginPolicyResponse{Policy: policy_grpc.ModelLoginPolicyToPb(policy)}, nil
|
return &mgmt_pb.GetLoginPolicyResponse{Policy: policy_grpc.ModelLoginPolicyToPb(policy), IsDefault: policy.Default}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetDefaultLoginPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLoginPolicyRequest) (*mgmt_pb.GetDefaultLoginPolicyResponse, error) {
|
func (s *Server) GetDefaultLoginPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLoginPolicyRequest) (*mgmt_pb.GetDefaultLoginPolicyResponse, error) {
|
||||||
|
@ -15,6 +15,7 @@ func (s *Server) GetPasswordAgePolicy(ctx context.Context, req *mgmt_pb.GetPassw
|
|||||||
}
|
}
|
||||||
return &mgmt_pb.GetPasswordAgePolicyResponse{
|
return &mgmt_pb.GetPasswordAgePolicyResponse{
|
||||||
Policy: policy_grpc.ModelPasswordAgePolicyToPb(policy),
|
Policy: policy_grpc.ModelPasswordAgePolicyToPb(policy),
|
||||||
|
IsDefault: policy.Default,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ func (s *Server) GetPasswordComplexityPolicy(ctx context.Context, req *mgmt_pb.G
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &mgmt_pb.GetPasswordComplexityPolicyResponse{Policy: policy_grpc.ModelPasswordComplexityPolicyToPb(policy)}, nil
|
return &mgmt_pb.GetPasswordComplexityPolicyResponse{Policy: policy_grpc.ModelPasswordComplexityPolicyToPb(policy), IsDefault: policy.Default}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetDefaultPasswordComplexityPolicy(ctx context.Context, req *mgmt_pb.GetDefaultPasswordComplexityPolicyRequest) (*mgmt_pb.GetDefaultPasswordComplexityPolicyResponse, error) {
|
func (s *Server) GetDefaultPasswordComplexityPolicy(ctx context.Context, req *mgmt_pb.GetDefaultPasswordComplexityPolicyRequest) (*mgmt_pb.GetDefaultPasswordComplexityPolicyResponse, error) {
|
||||||
|
@ -13,7 +13,7 @@ func (s *Server) GetPasswordLockoutPolicy(ctx context.Context, req *mgmt_pb.GetP
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &mgmt_pb.GetPasswordLockoutPolicyResponse{Policy: policy_grpc.ModelPasswordLockoutPolicyToPb(policy)}, nil
|
return &mgmt_pb.GetPasswordLockoutPolicyResponse{Policy: policy_grpc.ModelPasswordLockoutPolicyToPb(policy), IsDefault: policy.Default}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetDefaultPasswordLockoutPolicy(ctx context.Context, req *mgmt_pb.GetDefaultPasswordLockoutPolicyRequest) (*mgmt_pb.GetDefaultPasswordLockoutPolicyResponse, error) {
|
func (s *Server) GetDefaultPasswordLockoutPolicy(ctx context.Context, req *mgmt_pb.GetDefaultPasswordLockoutPolicyRequest) (*mgmt_pb.GetDefaultPasswordLockoutPolicyResponse, error) {
|
||||||
|
@ -323,6 +323,17 @@ func (s *Server) ResendHumanPhoneVerification(ctx context.Context, req *mgmt_pb.
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveHumanAvatar(ctx context.Context, req *mgmt_pb.RemoveHumanAvatarRequest) (*mgmt_pb.RemoveHumanAvatarResponse, error) {
|
||||||
|
ctxData := authz.GetCtxData(ctx)
|
||||||
|
objectDetails, err := s.command.RemoveHumanAvatar(ctx, ctxData.OrgID, req.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.RemoveHumanAvatarResponse{
|
||||||
|
Details: object.DomainToChangeDetailsPb(objectDetails),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) SetHumanInitialPassword(ctx context.Context, req *mgmt_pb.SetHumanInitialPasswordRequest) (*mgmt_pb.SetHumanInitialPasswordResponse, error) {
|
func (s *Server) SetHumanInitialPassword(ctx context.Context, req *mgmt_pb.SetHumanInitialPasswordRequest) (*mgmt_pb.SetHumanInitialPasswordResponse, error) {
|
||||||
objectDetails, err := s.command.SetPassword(ctx, authz.GetCtxData(ctx).OrgID, req.UserId, req.Password, true)
|
objectDetails, err := s.command.SetPassword(ctx, authz.GetCtxData(ctx).OrgID, req.UserId, req.Password, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,7 +10,20 @@ func ModelLabelPolicyToPb(policy *model.LabelPolicyView) *policy_pb.LabelPolicy
|
|||||||
return &policy_pb.LabelPolicy{
|
return &policy_pb.LabelPolicy{
|
||||||
IsDefault: policy.Default,
|
IsDefault: policy.Default,
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
BackgroundColor: policy.BackgroundColor,
|
||||||
|
FontColor: policy.FontColor,
|
||||||
|
WarnColor: policy.WarnColor,
|
||||||
|
PrimaryColorDark: policy.PrimaryColorDark,
|
||||||
|
BackgroundColorDark: policy.BackgroundColorDark,
|
||||||
|
WarnColorDark: policy.WarnColorDark,
|
||||||
|
FontColorDark: policy.FontColorDark,
|
||||||
|
FontUrl: policy.FontURL,
|
||||||
|
LogoUrl: policy.LogoURL,
|
||||||
|
LogoUrlDark: policy.LogoDarkURL,
|
||||||
|
IconUrl: policy.IconURL,
|
||||||
|
IconUrlDark: policy.IconDarkURL,
|
||||||
|
|
||||||
|
DisableWatermark: policy.DisableWatermark,
|
||||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
Details: object.ToViewDetailsPb(
|
Details: object.ToViewDetailsPb(
|
||||||
policy.Sequence,
|
policy.Sequence,
|
||||||
|
@ -80,6 +80,14 @@ func RemoteIPStringFromRequest(r *http.Request) string {
|
|||||||
return r.RemoteAddr
|
return r.RemoteAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAuthorization(r *http.Request) string {
|
||||||
|
return r.Header.Get(Authorization)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOrgID(r *http.Request) string {
|
||||||
|
return r.Header.Get(ZitadelOrgID)
|
||||||
|
}
|
||||||
|
|
||||||
func GetForwardedFor(headers http.Header) (string, bool) {
|
func GetForwardedFor(headers http.Header) (string, bool) {
|
||||||
forwarded, ok := headers[ForwardedFor]
|
forwarded, ok := headers[ForwardedFor]
|
||||||
if ok {
|
if ok {
|
||||||
|
71
internal/api/http/middleware/auth_interceptor.go
Normal file
71
internal/api/http/middleware/auth_interceptor.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
http_util "github.com/caos/zitadel/internal/api/http"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthInterceptor struct {
|
||||||
|
verifier *authz.TokenVerifier
|
||||||
|
authConfig authz.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) *AuthInterceptor {
|
||||||
|
return &AuthInterceptor{
|
||||||
|
verifier: verifier,
|
||||||
|
authConfig: authConfig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AuthInterceptor) Handler(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx, err := authorize(r, a.verifier, a.authConfig)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AuthInterceptor) HandlerFunc(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx, err := authorize(r, a.verifier, a.authConfig)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpReq struct{}
|
||||||
|
|
||||||
|
func authorize(r *http.Request, verifier *authz.TokenVerifier, authConfig authz.Config) (_ context.Context, err error) {
|
||||||
|
ctx := r.Context()
|
||||||
|
authOpt, needsToken := verifier.CheckAuthMethod(r.Method + ":" + r.RequestURI)
|
||||||
|
if !needsToken {
|
||||||
|
return ctx, nil
|
||||||
|
}
|
||||||
|
authCtx, span := tracing.NewServerInterceptorSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
authToken := http_util.GetAuthorization(r)
|
||||||
|
if authToken == "" {
|
||||||
|
return nil, errors.New("auth header missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxSetter, err := authz.CheckUserAuthorization(authCtx, &httpReq{}, authToken, http_util.GetOrgID(r), verifier, authConfig, authOpt, r.RequestURI) //TODO: permission
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
span.End()
|
||||||
|
return ctxSetter(ctx), nil
|
||||||
|
}
|
@ -248,7 +248,7 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAge
|
|||||||
if request.RequestedOrgID == "" {
|
if request.RequestedOrgID == "" {
|
||||||
username = user.PreferredLoginName
|
username = user.PreferredLoginName
|
||||||
}
|
}
|
||||||
request.SetUserInfo(user.ID, username, user.PreferredLoginName, user.DisplayName, user.ResourceOwner)
|
request.SetUserInfo(user.ID, username, user.PreferredLoginName, user.DisplayName, user.AvatarKey, user.ResourceOwner)
|
||||||
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
|
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +466,7 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", user.ResourceOwner)
|
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,7 +509,7 @@ func (repo *AuthRequestRepo) checkExternalUserLogin(request *domain.AuthRequest,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
request.SetUserInfo(externalIDP.UserID, "", "", "", externalIDP.ResourceOwner)
|
request.SetUserInfo(externalIDP.UserID, "", "", "", "", externalIDP.ResourceOwner)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,6 +614,7 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *domain.AuthRequest)
|
|||||||
DisplayName: session.DisplayName,
|
DisplayName: session.DisplayName,
|
||||||
UserName: session.UserName,
|
UserName: session.UserName,
|
||||||
LoginName: session.LoginName,
|
LoginName: session.LoginName,
|
||||||
|
AvatarKey: session.AvatarKey,
|
||||||
UserSessionState: auth_req_model.UserSessionStateToDomain(session.State),
|
UserSessionState: auth_req_model.UserSessionStateToDomain(session.State),
|
||||||
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
||||||
}
|
}
|
||||||
@ -710,9 +711,9 @@ func (repo *AuthRequestRepo) getLoginPolicy(ctx context.Context, orgID string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (repo *AuthRequestRepo) getLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error) {
|
func (repo *AuthRequestRepo) getLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error) {
|
||||||
policy, err := repo.View.LabelPolicyByAggregateID(orgID)
|
policy, err := repo.View.LabelPolicyByAggregateIDAndState(orgID, int32(domain.LabelPolicyStateActive))
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
policy, err = repo.View.LabelPolicyByAggregateID(repo.IAMID)
|
policy, err = repo.View.LabelPolicyByAggregateIDAndState(repo.IAMID, int32(domain.LabelPolicyStateActive))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
"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/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
@ -103,3 +104,14 @@ func (repo *OrgRepository) GetMyPasswordComplexityPolicy(ctx context.Context) (*
|
|||||||
}
|
}
|
||||||
return iam_view_model.PasswordComplexityViewToModel(policy), err
|
return iam_view_model.PasswordComplexityViewToModel(policy), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *OrgRepository) GetLabelPolicy(ctx context.Context, orgID string) (*iam_model.LabelPolicyView, error) {
|
||||||
|
orgPolicy, err := repo.View.LabelPolicyByAggregateIDAndState(orgID, int32(domain.LabelPolicyStateActive))
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
orgPolicy, err = repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStateActive))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iam_view_model.LabelPolicyViewToModel(orgPolicy), nil
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
@ -79,8 +81,19 @@ func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) {
|
|||||||
switch event.Type {
|
switch event.Type {
|
||||||
case iam_es_model.LabelPolicyAdded, model.LabelPolicyAdded:
|
case iam_es_model.LabelPolicyAdded, model.LabelPolicyAdded:
|
||||||
err = policy.AppendEvent(event)
|
err = policy.AppendEvent(event)
|
||||||
case iam_es_model.LabelPolicyChanged, model.LabelPolicyChanged:
|
case iam_es_model.LabelPolicyChanged, model.LabelPolicyChanged,
|
||||||
policy, err = m.view.LabelPolicyByAggregateID(event.AggregateID)
|
iam_es_model.LabelPolicyActivated, model.LabelPolicyActivated,
|
||||||
|
iam_es_model.LabelPolicyLogoAdded, model.LabelPolicyLogoAdded,
|
||||||
|
iam_es_model.LabelPolicyLogoRemoved, model.LabelPolicyLogoRemoved,
|
||||||
|
iam_es_model.LabelPolicyIconAdded, model.LabelPolicyIconAdded,
|
||||||
|
iam_es_model.LabelPolicyIconRemoved, model.LabelPolicyIconRemoved,
|
||||||
|
iam_es_model.LabelPolicyLogoDarkAdded, model.LabelPolicyLogoDarkAdded,
|
||||||
|
iam_es_model.LabelPolicyLogoDarkRemoved, model.LabelPolicyLogoDarkRemoved,
|
||||||
|
iam_es_model.LabelPolicyIconDarkAdded, model.LabelPolicyIconDarkAdded,
|
||||||
|
iam_es_model.LabelPolicyIconDarkRemoved, model.LabelPolicyIconDarkRemoved,
|
||||||
|
iam_es_model.LabelPolicyFontAdded, model.LabelPolicyFontAdded,
|
||||||
|
iam_es_model.LabelPolicyFontRemoved, model.LabelPolicyFontRemoved:
|
||||||
|
policy, err = m.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,8 @@ func (u *User) ProcessUser(event *es_models.Event) (err error) {
|
|||||||
es_model.HumanProfileChanged,
|
es_model.HumanProfileChanged,
|
||||||
es_model.HumanEmailChanged,
|
es_model.HumanEmailChanged,
|
||||||
es_model.HumanEmailVerified,
|
es_model.HumanEmailVerified,
|
||||||
|
es_model.HumanAvatarAdded,
|
||||||
|
es_model.HumanAvatarRemoved,
|
||||||
es_model.HumanPhoneChanged,
|
es_model.HumanPhoneChanged,
|
||||||
es_model.HumanPhoneVerified,
|
es_model.HumanPhoneVerified,
|
||||||
es_model.HumanPhoneRemoved,
|
es_model.HumanPhoneRemoved,
|
||||||
|
@ -111,6 +111,8 @@ func (u *UserSession) Reduce(event *models.Event) (err error) {
|
|||||||
es_model.HumanPasswordChanged,
|
es_model.HumanPasswordChanged,
|
||||||
es_model.HumanMFAOTPRemoved,
|
es_model.HumanMFAOTPRemoved,
|
||||||
es_model.HumanProfileChanged,
|
es_model.HumanProfileChanged,
|
||||||
|
es_model.HumanAvatarAdded,
|
||||||
|
es_model.HumanAvatarRemoved,
|
||||||
es_model.DomainClaimed,
|
es_model.DomainClaimed,
|
||||||
es_model.UserUserNameChanged,
|
es_model.UserUserNameChanged,
|
||||||
es_model.HumanExternalIDPRemoved,
|
es_model.HumanExternalIDPRemoved,
|
||||||
@ -167,5 +169,6 @@ func (u *UserSession) fillUserInfo(session *view_model.UserSessionView, id strin
|
|||||||
session.UserName = user.UserName
|
session.UserName = user.UserName
|
||||||
session.LoginName = user.PreferredLoginName
|
session.LoginName = user.PreferredLoginName
|
||||||
session.DisplayName = user.DisplayName
|
session.DisplayName = user.DisplayName
|
||||||
|
session.AvatarKey = user.AvatarKey
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ const (
|
|||||||
labelPolicyTable = "auth.label_policies"
|
labelPolicyTable = "auth.label_policies"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyView, error) {
|
func (v *View) LabelPolicyByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
|
||||||
return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID)
|
return view.GetLabelPolicyByAggregateIDAndState(v.Db, labelPolicyTable, aggregateID, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
|
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
|
||||||
|
@ -12,4 +12,5 @@ type OrgRepository interface {
|
|||||||
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
|
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
|
||||||
GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error)
|
GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error)
|
||||||
GetMyPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
|
GetMyPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
|
||||||
|
GetLabelPolicy(ctx context.Context, orgID string) (*iam_model.LabelPolicyView, error)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
|
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
@ -130,13 +131,21 @@ func checkFeatures(features *features_view_model.FeaturesView, requiredFeatures
|
|||||||
if err := checkLoginPolicyFeatures(features, requiredFeature); err != nil {
|
if err := checkLoginPolicyFeatures(features, requiredFeature); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if requiredFeature == domain.FeaturePasswordComplexityPolicy && !features.PasswordComplexityPolicy {
|
if requiredFeature == domain.FeaturePasswordComplexityPolicy {
|
||||||
|
if !features.PasswordComplexityPolicy {
|
||||||
return MissingFeatureErr(requiredFeature)
|
return MissingFeatureErr(requiredFeature)
|
||||||
}
|
}
|
||||||
if requiredFeature == domain.FeatureLabelPolicy && !features.PasswordComplexityPolicy {
|
continue
|
||||||
return MissingFeatureErr(requiredFeature)
|
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(requiredFeature, domain.FeatureLabelPolicy) {
|
||||||
|
if err := checkLabelPolicyFeatures(features, requiredFeature); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return MissingFeatureErr(requiredFeature)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -175,6 +184,20 @@ func checkLoginPolicyFeatures(features *features_view_model.FeaturesView, requir
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkLabelPolicyFeatures(features *features_view_model.FeaturesView, requiredFeature string) error {
|
||||||
|
switch requiredFeature {
|
||||||
|
case domain.FeatureLabelPolicyPrivateLabel:
|
||||||
|
if !features.LabelPolicyPrivateLabel {
|
||||||
|
return MissingFeatureErr(requiredFeature)
|
||||||
|
}
|
||||||
|
case domain.FeatureLabelPolicyWatermark:
|
||||||
|
if !features.LabelPolicyWatermark {
|
||||||
|
return MissingFeatureErr(requiredFeature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func MissingFeatureErr(feature string) error {
|
func MissingFeatureErr(feature string) error {
|
||||||
return caos_errs.ThrowPermissionDeniedf(nil, "AUTH-Dvgsf", "missing feature %v", feature)
|
return caos_errs.ThrowPermissionDeniedf(nil, "AUTH-Dvgsf", "missing feature %v", feature)
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,14 @@ import (
|
|||||||
proj_repo "github.com/caos/zitadel/internal/repository/project"
|
proj_repo "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"
|
||||||
usr_grant_repo "github.com/caos/zitadel/internal/repository/usergrant"
|
usr_grant_repo "github.com/caos/zitadel/internal/repository/usergrant"
|
||||||
|
"github.com/caos/zitadel/internal/static"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
webauthn_helper "github.com/caos/zitadel/internal/webauthn"
|
webauthn_helper "github.com/caos/zitadel/internal/webauthn"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Commands struct {
|
type Commands struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
|
static static.Storage
|
||||||
idGenerator id.Generator
|
idGenerator id.Generator
|
||||||
iamDomain string
|
iamDomain string
|
||||||
zitadelRoles []authz.RoleMapping
|
zitadelRoles []authz.RoleMapping
|
||||||
@ -58,9 +60,10 @@ type Config struct {
|
|||||||
Eventstore types.SQLUser
|
Eventstore types.SQLUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartCommands(eventstore *eventstore.Eventstore, defaults sd.SystemDefaults, authZConfig authz.Config, authZRepo *authz_repo.EsRepository) (repo *Commands, err error) {
|
func StartCommands(eventstore *eventstore.Eventstore, defaults sd.SystemDefaults, authZConfig authz.Config, staticStore static.Storage, authZRepo *authz_repo.EsRepository) (repo *Commands, err error) {
|
||||||
repo = &Commands{
|
repo = &Commands{
|
||||||
eventstore: eventstore,
|
eventstore: eventstore,
|
||||||
|
static: staticStore,
|
||||||
idGenerator: id.SonyFlakeGenerator,
|
idGenerator: id.SonyFlakeGenerator,
|
||||||
iamDomain: defaults.Domain,
|
iamDomain: defaults.Domain,
|
||||||
zitadelRoles: authZConfig.RolePermissionMappings,
|
zitadelRoles: authZConfig.RolePermissionMappings,
|
||||||
|
54
internal/command/existing_label_policies_model.go
Normal file
54
internal/command/existing_label_policies_model.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/repository/iam"
|
||||||
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExistingLabelPoliciesReadModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
aggregateIDs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExistingLabelPoliciesReadModel(ctx context.Context) *ExistingLabelPoliciesReadModel {
|
||||||
|
return &ExistingLabelPoliciesReadModel{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rm *ExistingLabelPoliciesReadModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
rm.WriteModel.AppendEvents(events...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rm *ExistingLabelPoliciesReadModel) Reduce() error {
|
||||||
|
for _, event := range rm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *iam.LabelPolicyAddedEvent,
|
||||||
|
*org.LabelPolicyAddedEvent:
|
||||||
|
rm.aggregateIDs = append(rm.aggregateIDs, e.Aggregate().ID)
|
||||||
|
case *org.LabelPolicyRemovedEvent:
|
||||||
|
for i := len(rm.aggregateIDs) - 1; i >= 0; i-- {
|
||||||
|
if rm.aggregateIDs[i] == e.Aggregate().ID {
|
||||||
|
copy(rm.aggregateIDs[i:], rm.aggregateIDs[i+1:])
|
||||||
|
rm.aggregateIDs[len(rm.aggregateIDs)-1] = ""
|
||||||
|
rm.aggregateIDs = rm.aggregateIDs[:len(rm.aggregateIDs)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rm *ExistingLabelPoliciesReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(
|
||||||
|
eventstore.ColumnsEvent,
|
||||||
|
iam.AggregateType,
|
||||||
|
org.AggregateType).
|
||||||
|
EventTypes(
|
||||||
|
iam.LabelPolicyAddedEventType,
|
||||||
|
org.LabelPolicyAddedEventType,
|
||||||
|
org.LabelPolicyRemovedEventType,
|
||||||
|
)
|
||||||
|
}
|
@ -23,7 +23,8 @@ type FeaturesWriteModel struct {
|
|||||||
LoginPolicyUsernameLogin bool
|
LoginPolicyUsernameLogin bool
|
||||||
LoginPolicyPasswordReset bool
|
LoginPolicyPasswordReset bool
|
||||||
PasswordComplexityPolicy bool
|
PasswordComplexityPolicy bool
|
||||||
LabelPolicy bool
|
LabelPolicyPrivateLabel bool
|
||||||
|
LabelPolicyWatermark bool
|
||||||
CustomDomain bool
|
CustomDomain bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,13 @@ func (wm *FeaturesWriteModel) Reduce() error {
|
|||||||
wm.PasswordComplexityPolicy = *e.PasswordComplexityPolicy
|
wm.PasswordComplexityPolicy = *e.PasswordComplexityPolicy
|
||||||
}
|
}
|
||||||
if e.LabelPolicy != nil {
|
if e.LabelPolicy != nil {
|
||||||
wm.LabelPolicy = *e.LabelPolicy
|
wm.LabelPolicyPrivateLabel = *e.LabelPolicy
|
||||||
|
}
|
||||||
|
if e.LabelPolicyPrivateLabel != nil {
|
||||||
|
wm.LabelPolicyPrivateLabel = *e.LabelPolicyPrivateLabel
|
||||||
|
}
|
||||||
|
if e.LabelPolicyWatermark != nil {
|
||||||
|
wm.LabelPolicyWatermark = *e.LabelPolicyWatermark
|
||||||
}
|
}
|
||||||
if e.CustomDomain != nil {
|
if e.CustomDomain != nil {
|
||||||
wm.CustomDomain = *e.CustomDomain
|
wm.CustomDomain = *e.CustomDomain
|
||||||
|
@ -49,8 +49,16 @@ func writeModelToLabelPolicy(wm *LabelPolicyWriteModel) *domain.LabelPolicy {
|
|||||||
return &domain.LabelPolicy{
|
return &domain.LabelPolicy{
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
PrimaryColor: wm.PrimaryColor,
|
PrimaryColor: wm.PrimaryColor,
|
||||||
SecondaryColor: wm.SecondaryColor,
|
BackgroundColor: wm.BackgroundColor,
|
||||||
|
WarnColor: wm.WarnColor,
|
||||||
|
FontColor: wm.FontColor,
|
||||||
|
PrimaryColorDark: wm.PrimaryColorDark,
|
||||||
|
BackgroundColorDark: wm.BackgroundColorDark,
|
||||||
|
WarnColorDark: wm.WarnColorDark,
|
||||||
|
FontColorDark: wm.FontColorDark,
|
||||||
HideLoginNameSuffix: wm.HideLoginNameSuffix,
|
HideLoginNameSuffix: wm.HideLoginNameSuffix,
|
||||||
|
ErrorMsgPopup: wm.ErrorMsgPopup,
|
||||||
|
DisableWatermark: wm.DisableWatermark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +184,8 @@ func writeModelToFeatures(wm *FeaturesWriteModel) *domain.Features {
|
|||||||
LoginPolicyRegistration: wm.LoginPolicyRegistration,
|
LoginPolicyRegistration: wm.LoginPolicyRegistration,
|
||||||
LoginPolicyUsernameLogin: wm.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: wm.LoginPolicyUsernameLogin,
|
||||||
PasswordComplexityPolicy: wm.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: wm.PasswordComplexityPolicy,
|
||||||
LabelPolicy: wm.LabelPolicy,
|
LabelPolicyPrivateLabel: wm.LabelPolicyPrivateLabel,
|
||||||
|
LabelPolicyWatermark: wm.LabelPolicyWatermark,
|
||||||
|
CustomDomain: wm.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,8 @@ func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *IAM
|
|||||||
features.LoginPolicyRegistration,
|
features.LoginPolicyRegistration,
|
||||||
features.LoginPolicyUsernameLogin,
|
features.LoginPolicyUsernameLogin,
|
||||||
features.PasswordComplexityPolicy,
|
features.PasswordComplexityPolicy,
|
||||||
features.LabelPolicy,
|
features.LabelPolicyPrivateLabel,
|
||||||
|
features.LabelPolicyWatermark,
|
||||||
features.CustomDomain,
|
features.CustomDomain,
|
||||||
)
|
)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
@ -61,5 +62,7 @@ func (c *Commands) getDefaultFeatures(ctx context.Context) (*domain.Features, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return writeModelToFeatures(&existingFeatures.FeaturesWriteModel), nil
|
features := writeModelToFeatures(&existingFeatures.FeaturesWriteModel)
|
||||||
|
features.IsDefault = true
|
||||||
|
return features, nil
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,8 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
|||||||
loginPolicyRegistration,
|
loginPolicyRegistration,
|
||||||
loginPolicyUsernameLogin,
|
loginPolicyUsernameLogin,
|
||||||
passwordComplexityPolicy,
|
passwordComplexityPolicy,
|
||||||
labelPolicy,
|
labelPolicyPrivateLabel,
|
||||||
|
labelPolicyWatermark,
|
||||||
customDomain bool,
|
customDomain bool,
|
||||||
) (*iam.FeaturesSetEvent, bool) {
|
) (*iam.FeaturesSetEvent, bool) {
|
||||||
|
|
||||||
@ -101,8 +102,11 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
|||||||
if wm.PasswordComplexityPolicy != passwordComplexityPolicy {
|
if wm.PasswordComplexityPolicy != passwordComplexityPolicy {
|
||||||
changes = append(changes, features.ChangePasswordComplexityPolicy(passwordComplexityPolicy))
|
changes = append(changes, features.ChangePasswordComplexityPolicy(passwordComplexityPolicy))
|
||||||
}
|
}
|
||||||
if wm.LabelPolicy != labelPolicy {
|
if wm.LabelPolicyPrivateLabel != labelPolicyPrivateLabel {
|
||||||
changes = append(changes, features.ChangeLabelPolicy(labelPolicy))
|
changes = append(changes, features.ChangeLabelPolicyPrivateLabel(labelPolicyPrivateLabel))
|
||||||
|
}
|
||||||
|
if wm.LabelPolicyWatermark != labelPolicyWatermark {
|
||||||
|
changes = append(changes, features.ChangeLabelPolicyWatermark(labelPolicyWatermark))
|
||||||
}
|
}
|
||||||
if wm.CustomDomain != customDomain {
|
if wm.CustomDomain != customDomain {
|
||||||
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
||||||
|
@ -29,8 +29,8 @@ func (c *Commands) AddDefaultLabelPolicy(ctx context.Context, policy *domain.Lab
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) addDefaultLabelPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMLabelPolicyWriteModel, policy *domain.LabelPolicy) (eventstore.EventPusher, error) {
|
func (c *Commands) addDefaultLabelPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMLabelPolicyWriteModel, policy *domain.LabelPolicy) (eventstore.EventPusher, error) {
|
||||||
if !policy.IsValid() {
|
if err := policy.IsValid(); err != nil {
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-3m9fo", "Errors.IAM.LabelPolicy.Invalid")
|
return nil, err
|
||||||
}
|
}
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
err := c.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,13 +40,26 @@ func (c *Commands) addDefaultLabelPolicy(ctx context.Context, iamAgg *eventstore
|
|||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
|
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
return iam_repo.NewLabelPolicyAddedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor, policy.HideLoginNameSuffix), nil
|
return iam_repo.NewLabelPolicyAddedEvent(
|
||||||
|
ctx,
|
||||||
|
iamAgg,
|
||||||
|
policy.PrimaryColor,
|
||||||
|
policy.BackgroundColor,
|
||||||
|
policy.WarnColor,
|
||||||
|
policy.FontColor,
|
||||||
|
policy.PrimaryColorDark,
|
||||||
|
policy.BackgroundColorDark,
|
||||||
|
policy.WarnColorDark,
|
||||||
|
policy.FontColorDark,
|
||||||
|
policy.HideLoginNameSuffix,
|
||||||
|
policy.ErrorMsgPopup,
|
||||||
|
policy.DisableWatermark), nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) ChangeDefaultLabelPolicy(ctx context.Context, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) {
|
func (c *Commands) ChangeDefaultLabelPolicy(ctx context.Context, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) {
|
||||||
if !policy.IsValid() {
|
if err := policy.IsValid(); err != nil {
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-33m8f", "Errors.IAM.LabelPolicy.Invalid")
|
return nil, err
|
||||||
}
|
}
|
||||||
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,7 +70,20 @@ func (c *Commands) ChangeDefaultLabelPolicy(ctx context.Context, policy *domain.
|
|||||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor, policy.HideLoginNameSuffix)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
||||||
|
ctx,
|
||||||
|
iamAgg,
|
||||||
|
policy.PrimaryColor,
|
||||||
|
policy.BackgroundColor,
|
||||||
|
policy.WarnColor,
|
||||||
|
policy.FontColor,
|
||||||
|
policy.PrimaryColorDark,
|
||||||
|
policy.BackgroundColorDark,
|
||||||
|
policy.WarnColorDark,
|
||||||
|
policy.FontColorDark,
|
||||||
|
policy.HideLoginNameSuffix,
|
||||||
|
policy.ErrorMsgPopup,
|
||||||
|
policy.DisableWatermark)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
@ -73,6 +99,275 @@ func (c *Commands) ChangeDefaultLabelPolicy(ctx context.Context, policy *domain.
|
|||||||
return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil
|
return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) ActivateDefaultLabelPolicy(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-6M23e", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyActivatedEvent(ctx, iamAgg))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) AddLogoDefaultLabelPolicy(ctx context.Context, storageKey string) (*domain.ObjectDetails, error) {
|
||||||
|
if storageKey == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-3m20c", "Errors.Assets.EmptyKey")
|
||||||
|
}
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-Qw0pd", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyLogoAddedEvent(ctx, iamAgg, storageKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) RemoveLogoDefaultLabelPolicy(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-Xc8Kf", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.RemoveAsset(ctx, domain.IAMID, existingPolicy.LogoKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyLogoRemovedEvent(ctx, iamAgg, existingPolicy.LogoKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) AddIconDefaultLabelPolicy(ctx context.Context, storageKey string) (*domain.ObjectDetails, error) {
|
||||||
|
if storageKey == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-yxE4f", "Errors.Assets.EmptyKey")
|
||||||
|
}
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-1yMx0", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyIconAddedEvent(ctx, iamAgg, storageKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) RemoveIconDefaultLabelPolicy(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-4M0qw", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
err = c.RemoveAsset(ctx, domain.IAMID, existingPolicy.IconKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyIconRemovedEvent(ctx, iamAgg, existingPolicy.IconKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) AddLogoDarkDefaultLabelPolicy(ctx context.Context, storageKey string) (*domain.ObjectDetails, error) {
|
||||||
|
if storageKey == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-4fMs9", "Errors.Assets.EmptyKey")
|
||||||
|
}
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-ZR9fs", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyLogoDarkAddedEvent(ctx, iamAgg, storageKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) RemoveLogoDarkDefaultLabelPolicy(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-3FGds", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
err = c.RemoveAsset(ctx, domain.IAMID, existingPolicy.LogoDarkKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyLogoDarkRemovedEvent(ctx, iamAgg, existingPolicy.LogoDarkKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) AddIconDarkDefaultLabelPolicy(ctx context.Context, storageKey string) (*domain.ObjectDetails, error) {
|
||||||
|
if storageKey == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-1cxM3", "Errors.Assets.EmptyKey")
|
||||||
|
}
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-vMsf9", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyIconDarkAddedEvent(ctx, iamAgg, storageKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) RemoveIconDarkDefaultLabelPolicy(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-2nc7F", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
err = c.RemoveAsset(ctx, domain.IAMID, existingPolicy.IconDarkKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyIconDarkRemovedEvent(ctx, iamAgg, existingPolicy.IconDarkKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) AddFontDefaultLabelPolicy(ctx context.Context, storageKey string) (*domain.ObjectDetails, error) {
|
||||||
|
if storageKey == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-1N8fs", "Errors.Assets.EmptyKey")
|
||||||
|
}
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-1N8fE", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyFontAddedEvent(ctx, iamAgg, storageKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) RemoveFontDefaultLabelPolicy(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||||
|
existingPolicy, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-Tk0gw", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
|
}
|
||||||
|
err = c.RemoveAsset(ctx, domain.IAMID, existingPolicy.FontKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, iam_repo.NewLabelPolicyFontRemovedEvent(ctx, iamAgg, existingPolicy.FontKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) defaultLabelPolicyWriteModelByID(ctx context.Context) (policy *IAMLabelPolicyWriteModel, err error) {
|
func (c *Commands) defaultLabelPolicyWriteModelByID(ctx context.Context) (policy *IAMLabelPolicyWriteModel, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
@ -84,3 +379,13 @@ func (c *Commands) defaultLabelPolicyWriteModelByID(ctx context.Context) (policy
|
|||||||
}
|
}
|
||||||
return writeModel, nil
|
return writeModel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) getDefaultLabelPolicy(ctx context.Context) (*domain.LabelPolicy, error) {
|
||||||
|
policyWriteModel, err := c.defaultLabelPolicyWriteModelByID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
policy := writeModelToLabelPolicy(&policyWriteModel.LabelPolicyWriteModel)
|
||||||
|
policy.Default = true
|
||||||
|
return policy, nil
|
||||||
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user