diff --git a/console/src/app/modules/policies/notification-settings/notification-settings.component.ts b/console/src/app/modules/policies/notification-settings/notification-settings.component.ts
index c97418bbe..f2bfc3445 100644
--- a/console/src/app/modules/policies/notification-settings/notification-settings.component.ts
+++ b/console/src/app/modules/policies/notification-settings/notification-settings.component.ts
@@ -109,12 +109,6 @@ export class NotificationSettingsComponent implements OnInit {
public addSMSProvider(): void {
const dialogRef = this.dialog.open(DialogAddSMSProviderComponent, {
- data: {
- confirmKey: 'ACTIONS.DELETE',
- cancelKey: 'ACTIONS.CANCEL',
- titleKey: 'IDP.DELETE_TITLE',
- descriptionKey: 'IDP.DELETE_DESCRIPTION',
- },
width: '400px',
});
diff --git a/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.html b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.html
new file mode 100644
index 000000000..e4c360092
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.html
@@ -0,0 +1,81 @@
+
+ {{ 'SETTING.SECRETS.ADDGENERATOR' | translate }}
+
+
+
+
+
+
diff --git a/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.scss b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.scss
new file mode 100644
index 000000000..638a86322
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.scss
@@ -0,0 +1,43 @@
+.title {
+ font-size: 1.5rem;
+}
+
+.generator-type {
+ font-size: 1rem;
+}
+
+.type-form-field {
+ display: none;
+}
+
+.generator-form-field {
+ width: 100%;
+}
+
+.slide-toggle-wrapper {
+ display: grid;
+ grid-template-columns: 1fr;
+ column-gap: 1rem;
+
+ .slide-toggle {
+ margin: 0.5rem 0;
+
+ .slide-toggle-row {
+ display: flex;
+ align-items: center;
+
+ .icon {
+ margin: 0 0.5rem;
+ }
+ }
+ }
+}
+
+.action {
+ display: flex;
+ justify-content: space-between;
+
+ button {
+ border-radius: 0.5rem;
+ }
+}
diff --git a/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts
new file mode 100644
index 000000000..fe977eedc
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts
@@ -0,0 +1,91 @@
+import { Component, Inject } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
+import { UpdateSecretGeneratorRequest } from 'src/app/proto/generated/zitadel/admin_pb';
+import { SecretGeneratorType } from 'src/app/proto/generated/zitadel/settings_pb';
+
+@Component({
+ selector: 'cnsl-dialog-add-secret-generator',
+ templateUrl: './dialog-add-secret-generator.component.html',
+ styleUrls: ['./dialog-add-secret-generator.component.scss'],
+})
+export class DialogAddSecretGeneratorComponent {
+ public SecretGeneratorType: any = SecretGeneratorType;
+ public availableGenerators: SecretGeneratorType[] = [
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_INIT_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_VERIFY_EMAIL_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_VERIFY_PHONE_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_PASSWORD_RESET_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_PASSWORDLESS_INIT_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET,
+ ];
+ public req: UpdateSecretGeneratorRequest = new UpdateSecretGeneratorRequest();
+
+ public specsForm!: FormGroup;
+
+ constructor(
+ private fb: FormBuilder,
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public data: any,
+ ) {
+ this.specsForm = this.fb.group({
+ generatorType: [SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET, [Validators.required]],
+ expiry: [1, [Validators.required]],
+ includeDigits: [true, [Validators.required]],
+ includeLowerLetters: [true, [Validators.required]],
+ includeSymbols: [true, [Validators.required]],
+ includeUpperLetters: [true, [Validators.required]],
+ length: [6, [Validators.required]],
+ });
+
+ this.generatorType?.setValue(data.type);
+ }
+
+ public closeDialog(): void {
+ this.dialogRef.close();
+ }
+
+ public closeDialogWithRequest(): void {
+ this.req.setGeneratorType(this.generatorType?.value);
+
+ const expiry = new Duration().setSeconds((this.expiry?.value ?? 1) * 60 * 60);
+
+ this.req.setExpiry(expiry);
+ this.req.setIncludeDigits(this.includeDigits?.value);
+ this.req.setIncludeLowerLetters(this.includeLowerLetters?.value);
+ this.req.setIncludeSymbols(this.includeSymbols?.value);
+ this.req.setIncludeUpperLetters(this.includeUpperLetters?.value);
+ this.req.setLength(this.length?.value);
+
+ this.dialogRef.close(this.req);
+ }
+
+ public get generatorType(): AbstractControl | null {
+ return this.specsForm.get('generatorType');
+ }
+
+ public get expiry(): AbstractControl | null {
+ return this.specsForm.get('expiry');
+ }
+
+ public get includeDigits(): AbstractControl | null {
+ return this.specsForm.get('includeDigits');
+ }
+
+ public get includeLowerLetters(): AbstractControl | null {
+ return this.specsForm.get('includeLowerLetters');
+ }
+
+ public get includeSymbols(): AbstractControl | null {
+ return this.specsForm.get('includeSymbols');
+ }
+
+ public get includeUpperLetters(): AbstractControl | null {
+ return this.specsForm.get('includeUpperLetters');
+ }
+
+ public get length(): AbstractControl | null {
+ return this.specsForm.get('length');
+ }
+}
diff --git a/console/src/app/modules/policies/secret-generator/secret-generator.component.html b/console/src/app/modules/policies/secret-generator/secret-generator.component.html
new file mode 100644
index 000000000..2095bf31c
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/secret-generator.component.html
@@ -0,0 +1,15 @@
+
+
+
+{{ 'SETTING.SECRETS.TITLE' | translate }}
+
+
+
+
+
{{ 'SETTING.SECRETS.TYPE.' + gen | translate }}
+
+
+
+
diff --git a/console/src/app/modules/policies/secret-generator/secret-generator.component.scss b/console/src/app/modules/policies/secret-generator/secret-generator.component.scss
new file mode 100644
index 000000000..eeb77dcbe
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/secret-generator.component.scss
@@ -0,0 +1,29 @@
+.spinner-wr {
+ margin: 0.5rem 0;
+}
+
+.generators {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ column-gap: 1rem;
+ row-gap: 1rem;
+ margin-bottom: 2rem;
+ margin-top: 1.5rem;
+
+ @media only screen and (max-width: 600px) {
+ grid-template-columns: 1fr;
+ }
+
+ .generator {
+ .row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .title {
+ font-size: 1rem;
+ margin: 0;
+ }
+ }
+ }
+}
diff --git a/console/src/app/modules/policies/secret-generator/secret-generator.component.spec.ts b/console/src/app/modules/policies/secret-generator/secret-generator.component.spec.ts
new file mode 100644
index 000000000..7548a3230
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/secret-generator.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SecretGeneratorComponent } from './secret-generator.component';
+
+describe('OIDCConfigurationComponent', () => {
+ let component: SecretGeneratorComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [SecretGeneratorComponent],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SecretGeneratorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/console/src/app/modules/policies/secret-generator/secret-generator.component.ts b/console/src/app/modules/policies/secret-generator/secret-generator.component.ts
new file mode 100644
index 000000000..dc1e64497
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/secret-generator.component.ts
@@ -0,0 +1,107 @@
+import { Component, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { UpdateSecretGeneratorRequest, UpdateSecretGeneratorResponse } from 'src/app/proto/generated/zitadel/admin_pb';
+import { OIDCSettings, SecretGenerator, SecretGeneratorType } from 'src/app/proto/generated/zitadel/settings_pb';
+import { AdminService } from 'src/app/services/admin.service';
+import { ToastService } from 'src/app/services/toast.service';
+
+import { DialogAddSecretGeneratorComponent } from './dialog-add-secret-generator/dialog-add-secret-generator.component';
+
+@Component({
+ selector: 'cnsl-secret-generator',
+ templateUrl: './secret-generator.component.html',
+ styleUrls: ['./secret-generator.component.scss'],
+})
+export class SecretGeneratorComponent implements OnInit {
+ public generators: SecretGenerator.AsObject[] = [];
+ public oidcSettings!: OIDCSettings.AsObject;
+
+ public loading: boolean = false;
+
+ public readonly AVAILABLEGENERATORS: SecretGeneratorType[] = [
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_INIT_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_VERIFY_EMAIL_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_VERIFY_PHONE_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_PASSWORD_RESET_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_PASSWORDLESS_INIT_CODE,
+ SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET,
+ ];
+ constructor(private service: AdminService, private toast: ToastService, private dialog: MatDialog) {}
+
+ ngOnInit(): void {
+ this.fetchData();
+ }
+
+ private fetchData(): void {
+ this.service
+ .listSecretGenerators()
+ .then((generators) => {
+ if (generators.resultList) {
+ this.generators = generators.resultList;
+ console.log(this.generators);
+ }
+ })
+ .catch((error) => {
+ if (error.code === 5) {
+ } else {
+ this.toast.showError(error);
+ }
+ });
+ }
+
+ private updateData(): Promise | void {
+ const dialogRef = this.dialog.open(DialogAddSecretGeneratorComponent, {
+ data: {},
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe((req: UpdateSecretGeneratorRequest) => {
+ if (req) {
+ return (this.service as AdminService).updateSecretGenerator(req);
+ } else {
+ return;
+ }
+ });
+ }
+
+ public openGeneratorDialog(generatorType: SecretGeneratorType): void {
+ const dialogRef = this.dialog.open(DialogAddSecretGeneratorComponent, {
+ data: {
+ type: generatorType,
+ },
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe((req: UpdateSecretGeneratorRequest) => {
+ if (req) {
+ return (this.service as AdminService)
+ .updateSecretGenerator(req)
+ .then(() => {
+ this.toast.showInfo('SETTING.SECRETS.UPDATED', true);
+ })
+ .catch((error) => {
+ this.toast.showError(error);
+ });
+ } else {
+ return;
+ }
+ });
+ }
+
+ public savePolicy(): void {
+ const prom = this.updateData();
+ if (prom) {
+ prom
+ .then(() => {
+ this.toast.showInfo('SETTING.SMTP.SAVED', true);
+ this.loading = true;
+ setTimeout(() => {
+ this.fetchData();
+ }, 2000);
+ })
+ .catch((error) => {
+ this.toast.showError(error);
+ });
+ }
+ }
+}
diff --git a/console/src/app/modules/policies/secret-generator/secret-generator.module.ts b/console/src/app/modules/policies/secret-generator/secret-generator.module.ts
new file mode 100644
index 000000000..3c031ec9d
--- /dev/null
+++ b/console/src/app/modules/policies/secret-generator/secret-generator.module.ts
@@ -0,0 +1,35 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatIconModule } from '@angular/material/icon';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { MatSelectModule } from '@angular/material/select';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { TranslateModule } from '@ngx-translate/core';
+
+import { CardModule } from '../../card/card.module';
+import { FormFieldModule } from '../../form-field/form-field.module';
+import { InputModule } from '../../input/input.module';
+import { DialogAddSecretGeneratorComponent } from './dialog-add-secret-generator/dialog-add-secret-generator.component';
+import { SecretGeneratorComponent } from './secret-generator.component';
+
+@NgModule({
+ declarations: [SecretGeneratorComponent, DialogAddSecretGeneratorComponent],
+ imports: [
+ CommonModule,
+ MatIconModule,
+ CardModule,
+ FormsModule,
+ MatButtonModule,
+ FormFieldModule,
+ ReactiveFormsModule,
+ MatSlideToggleModule,
+ InputModule,
+ MatProgressSpinnerModule,
+ MatSelectModule,
+ TranslateModule,
+ ],
+ exports: [SecretGeneratorComponent, DialogAddSecretGeneratorComponent],
+})
+export class SecretGeneratorModule {}
diff --git a/console/src/app/modules/project-members/project-members.component.ts b/console/src/app/modules/project-members/project-members.component.ts
index 49ac969ef..93281c6e8 100644
--- a/console/src/app/modules/project-members/project-members.component.ts
+++ b/console/src/app/modules/project-members/project-members.component.ts
@@ -77,11 +77,9 @@ export class ProjectMembersComponent {
}),
new Breadcrumb({
type: BreadcrumbType.PROJECT,
- // name: this.project.name,
param: { key: 'projectid', value: (this.project as Project.AsObject).id },
routerLink: ['/projects', (this.project as Project.AsObject).id],
isZitadel: isZitadel,
- hideNav: true,
}),
];
breadcrumbService.setBreadcrumb(breadcrumbs);
diff --git a/console/src/app/modules/settings-list/settings-list.component.html b/console/src/app/modules/settings-list/settings-list.component.html
index 7e7414ff4..a408900b7 100644
--- a/console/src/app/modules/settings-list/settings-list.component.html
+++ b/console/src/app/modules/settings-list/settings-list.component.html
@@ -30,6 +30,10 @@
+
+
+
+
diff --git a/console/src/app/modules/settings-list/settings-list.module.ts b/console/src/app/modules/settings-list/settings-list.module.ts
index 2f839906c..4c1e17cc7 100644
--- a/console/src/app/modules/settings-list/settings-list.module.ts
+++ b/console/src/app/modules/settings-list/settings-list.module.ts
@@ -17,6 +17,7 @@ import { PasswordComplexityPolicyModule } from '../policies/password-complexity-
import { PasswordLockoutPolicyModule } from '../policies/password-lockout-policy/password-lockout-policy.module';
import { PrivacyPolicyModule } from '../policies/privacy-policy/privacy-policy.module';
import { PrivateLabelingPolicyModule } from '../policies/private-labeling-policy/private-labeling-policy.module';
+import { SecretGeneratorModule } from '../policies/secret-generator/secret-generator.module';
import { SidenavModule } from '../sidenav/sidenav.module';
import { SettingsListComponent } from './settings-list.component';
@@ -41,6 +42,7 @@ import { SettingsListComponent } from './settings-list.component';
HasRolePipeModule,
NotificationSettingsModule,
OIDCConfigurationModule,
+ SecretGeneratorModule,
],
exports: [SettingsListComponent],
})
diff --git a/console/src/app/modules/settings-list/settings.ts b/console/src/app/modules/settings-list/settings.ts
index 011ada8d7..2050ef3be 100644
--- a/console/src/app/modules/settings-list/settings.ts
+++ b/console/src/app/modules/settings-list/settings.ts
@@ -10,6 +10,11 @@ export const OIDC: SidenavSetting = {
i18nKey: 'SETTINGS.LIST.OIDC',
};
+export const SECRETS: SidenavSetting = {
+ id: 'secrets',
+ i18nKey: 'SETTINGS.LIST.SECRETS',
+};
+
export const LOGIN: SidenavSetting = {
id: 'login',
i18nKey: 'SETTINGS.LIST.LOGIN',
diff --git a/console/src/app/pages/domains/domains.component.scss b/console/src/app/pages/domains/domains.component.scss
index cbe4876e5..65396b2b0 100644
--- a/console/src/app/pages/domains/domains.component.scss
+++ b/console/src/app/pages/domains/domains.component.scss
@@ -38,7 +38,6 @@
display: flex;
flex-direction: row;
align-items: center;
- margin-bottom: -0.5rem;
.title {
font-size: 16px;
diff --git a/console/src/app/pages/instance-settings/instance-settings.component.ts b/console/src/app/pages/instance-settings/instance-settings.component.ts
index 1eeecbe88..b1ae05306 100644
--- a/console/src/app/pages/instance-settings/instance-settings.component.ts
+++ b/console/src/app/pages/instance-settings/instance-settings.component.ts
@@ -17,6 +17,7 @@ import {
NOTIFICATIONS,
OIDC,
PRIVACYPOLICY,
+ SECRETS,
} from '../../modules/settings-list/settings';
@Component({
@@ -43,6 +44,7 @@ export class InstanceSettingsComponent {
// others
PRIVACYPOLICY,
OIDC,
+ SECRETS,
];
constructor(breadcrumbService: BreadcrumbService, activatedRoute: ActivatedRoute) {
const breadcrumbs = [
diff --git a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.scss b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.scss
index 7df73ab32..f2fd39dd0 100644
--- a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.scss
+++ b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.scss
@@ -35,6 +35,7 @@
.domain-button {
margin-right: 1rem;
margin-bottom: 1rem;
+ display: block;
}
.btn-container {
diff --git a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts
index 3f942f81d..99ac5e3e3 100644
--- a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts
+++ b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts
@@ -1,13 +1,15 @@
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { Subscription } from 'rxjs';
+import { Subject, takeUntil } from 'rxjs';
import { Org } from 'src/app/proto/generated/zitadel/org_pb';
import { Role } from 'src/app/proto/generated/zitadel/project_pb';
-import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
+import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
+const ROUTEPARAM = 'projectid';
+
@Component({
selector: 'cnsl-project-grant-create',
templateUrl: './project-grant-create.component.html',
@@ -22,39 +24,52 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
public STEPS: number = 2;
public currentCreateStep: number = 1;
- private routeSubscription: Subscription = new Subscription();
+ private destroy$: Subject = new Subject();
constructor(
private route: ActivatedRoute,
private toast: ToastService,
private mgmtService: ManagementService,
- private authService: GrpcAuthService,
private _location: Location,
- ) { }
+ private breadcrumbService: BreadcrumbService,
+ ) {}
public ngOnInit(): void {
- this.routeSubscription = this.route.params.subscribe(params => {
+ this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
this.projectId = params.projectid;
+
+ const breadcrumbs = [
+ new Breadcrumb({
+ type: BreadcrumbType.ORG,
+ routerLink: ['/org'],
+ }),
+ new Breadcrumb({
+ type: BreadcrumbType.PROJECT,
+ name: '',
+ param: { key: ROUTEPARAM, value: this.projectId },
+ routerLink: ['/projects', this.projectId],
+ }),
+ ];
+ this.breadcrumbService.setBreadcrumb(breadcrumbs);
});
}
public ngOnDestroy(): void {
- this.routeSubscription.unsubscribe();
+ this.destroy$.next();
+ this.destroy$.complete();
}
public searchOrg(domain: string): void {
- this.mgmtService.getOrgByDomainGlobal(domain).then((ret) => {
- if (ret.org) {
- const tmp = ret.org;
- this.authService.getActiveOrg().then((org) => {
- if (tmp !== org) {
- this.org = tmp;
- }
- });
- this.org = ret.org;
- }
- }).catch(error => {
- this.toast.showError(error);
- });
+ this.mgmtService
+ .getOrgByDomainGlobal(domain)
+ .then((ret) => {
+ if (ret.org) {
+ const tmp = ret.org;
+ this.org = tmp;
+ }
+ })
+ .catch((error) => {
+ this.toast.showError(error);
+ });
}
public close(): void {
@@ -67,13 +82,13 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
.then(() => {
this.close();
})
- .catch(error => {
+ .catch((error) => {
this.toast.showError(error);
});
}
public selectRoles(roles: Role.AsObject[]): void {
- this.rolesKeyList = roles.map(role => role.key);
+ this.rolesKeyList = roles.map((role) => role.key);
}
public next(): void {
@@ -84,4 +99,3 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
this.currentCreateStep--;
}
}
-
diff --git a/console/src/app/services/admin.service.ts b/console/src/app/services/admin.service.ts
index fded3b3da..955b5d265 100644
--- a/console/src/app/services/admin.service.ts
+++ b/console/src/app/services/admin.service.ts
@@ -77,6 +77,8 @@ import {
GetPreviewLabelPolicyResponse,
GetPrivacyPolicyRequest,
GetPrivacyPolicyResponse,
+ GetSecretGeneratorRequest,
+ GetSecretGeneratorResponse,
GetSMSProviderRequest,
GetSMSProviderResponse,
GetSMTPConfigRequest,
@@ -98,6 +100,8 @@ import {
ListLoginPolicyMultiFactorsResponse,
ListLoginPolicySecondFactorsRequest,
ListLoginPolicySecondFactorsResponse,
+ ListSecretGeneratorsRequest,
+ ListSecretGeneratorsResponse,
ListSMSProvidersRequest,
ListSMSProvidersResponse,
ListViewsRequest,
@@ -174,6 +178,8 @@ import {
UpdatePasswordComplexityPolicyResponse,
UpdatePrivacyPolicyRequest,
UpdatePrivacyPolicyResponse,
+ UpdateSecretGeneratorRequest,
+ UpdateSecretGeneratorResponse,
UpdateSMTPConfigPasswordRequest,
UpdateSMTPConfigPasswordResponse,
UpdateSMTPConfigRequest,
@@ -579,6 +585,21 @@ export class AdminService {
return this.grpcService.admin.getFileSystemNotificationProvider(req, null).then((resp) => resp.toObject());
}
+ /* secrets generator */
+
+ public listSecretGenerators(): Promise {
+ const req = new ListSecretGeneratorsRequest();
+ return this.grpcService.admin.listSecretGenerators(req, null).then((resp) => resp.toObject());
+ }
+
+ public getSecretGenerator(req: GetSecretGeneratorRequest): Promise {
+ return this.grpcService.admin.getSecretGenerator(req, null).then((resp) => resp.toObject());
+ }
+
+ public updateSecretGenerator(req: UpdateSecretGeneratorRequest): Promise {
+ return this.grpcService.admin.updateSecretGenerator(req, null).then((resp) => resp.toObject());
+ }
+
/* org iam */
public getCustomOrgIAMPolicy(orgId: string): Promise {
diff --git a/console/src/app/services/toast.service.ts b/console/src/app/services/toast.service.ts
index 0b06e4843..c881dcd92 100644
--- a/console/src/app/services/toast.service.ts
+++ b/console/src/app/services/toast.service.ts
@@ -1,49 +1,61 @@
import { Injectable } from '@angular/core';
-import { MatSnackBar } from '@angular/material/snack-bar';
+import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarVerticalPosition } from '@angular/material/snack-bar';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
@Injectable({
- providedIn: 'root',
+ providedIn: 'root',
})
export class ToastService {
- constructor(
- private snackBar: MatSnackBar,
- private translate: TranslateService,
- ) {}
+ horizontalPosition: MatSnackBarHorizontalPosition = 'end';
+ verticalPosition: MatSnackBarVerticalPosition = 'top';
- public showInfo(message: string, i18nkey: boolean = false): void {
- if (i18nkey) {
- this.translate
- .get(message)
- .subscribe(data => {
- this.translate.get('ACTIONS.CLOSE').pipe(take(1)).subscribe(value => {
- this.showMessage(data, value, true);
- });
- });
- } else {
- this.translate.get('ACTIONS.CLOSE').pipe(take(1)).subscribe(value => {
- this.showMessage(message, value, true);
- });
- }
+ constructor(private snackBar: MatSnackBar, private translate: TranslateService) {}
+
+ public showInfo(message: string, i18nkey: boolean = false): void {
+ if (i18nkey) {
+ this.translate.get(message).subscribe((data) => {
+ this.translate
+ .get('ACTIONS.CLOSE')
+ .pipe(take(1))
+ .subscribe((value) => {
+ this.showMessage(data, value, true);
+ });
+ });
+ } else {
+ this.translate
+ .get('ACTIONS.CLOSE')
+ .pipe(take(1))
+ .subscribe((value) => {
+ this.showMessage(message, value, true);
+ });
}
+ }
- public showError(grpcError: any): void {
- const { message, code, metadata } = grpcError;
- if (code !== 16) {
- this.translate.get('ACTIONS.CLOSE').pipe(take(1)).subscribe(value => {
- this.showMessage(decodeURI(message), value, false);
- });
- }
+ public showError(grpcError: any): void {
+ const { message, code, metadata } = grpcError;
+ if (code !== 16) {
+ this.translate
+ .get('ACTIONS.CLOSE')
+ .pipe(take(1))
+ .subscribe((value) => {
+ this.showMessage(decodeURI(message), value, false);
+ });
}
+ }
- private showMessage(message: string, action: string, success: boolean): Observable {
- const ref = this.snackBar.open(message, action, {
- duration: 4000,
- panelClass: success ? "data-e2e-success" : "data-e2e-failure"
- });
+ private showMessage(message: string, action: string, success: boolean): Observable {
+ const ref = this.snackBar.open(message, action, {
+ data: {
+ message,
+ },
+ duration: success ? 4000 : 5000,
+ panelClass: success ? 'data-e2e-success' : 'data-e2e-failure',
+ horizontalPosition: this.horizontalPosition,
+ verticalPosition: this.verticalPosition,
+ });
- return ref.onAction();
- }
+ return ref.onAction();
+ }
}
diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
index 31ac3d263..7543ee270 100644
--- a/console/src/assets/i18n/de.json
+++ b/console/src/assets/i18n/de.json
@@ -821,7 +821,8 @@
"LOGINTEXTS": "Login Interface Texte",
"BRANDING": "Branding",
"PRIVACYPOLICY": "Datenschutzrichtlinie",
- "OIDC": "OIDC Konfiguration"
+ "OIDC": "OIDC Token Lifetime und Expiration",
+ "SECRETS": "Secret Erscheinungsbild"
},
"GROUPS": {
"NOTIFICATIONS": "Benachrichtigungen",
@@ -869,6 +870,27 @@
"REFRESHTOKENIDLEEXPIRATION": "Refresh Token Idle Expiration",
"INHOURS": "Stunden",
"INDAYS": "Tage"
+ },
+ "SECRETS": {
+ "TITLE": "Secret Erscheinungsbild",
+ "TYPES": "Schlüsseltypen",
+ "TYPE": {
+ "1": "Email Initialisierungscode",
+ "2": "Email Verifikationscode",
+ "3": "Telefonnummer Verificationscode",
+ "4": "Passwort Zurücksetzen Code",
+ "5": "Passwordless Initialisierungscode",
+ "6": "Applicationssecret"
+ },
+ "ADDGENERATOR": "Secret Erscheinungsbild definieren",
+ "GENERATORTYPE": "Typ",
+ "EXPIRY": "Ablauf (in Stunden)",
+ "INCLUDEDIGITS": "Enthält Zahlen",
+ "INCLUDESYMBOLS": "Enthält Symbole",
+ "INCLUDELOWERLETTERS": "Enthält Kleinbuchstaben",
+ "INCLUDEUPPERLETTERS": "Enthält Grossbuchstaben",
+ "LENGTH": "Länge",
+ "UPDATED": "Einstellungen geändert"
}
},
"POLICY": {
diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json
index b3e32db4a..62bb62bd0 100644
--- a/console/src/assets/i18n/en.json
+++ b/console/src/assets/i18n/en.json
@@ -821,7 +821,8 @@
"LOGINTEXTS": "Login Interface Texts",
"BRANDING": "Branding",
"PRIVACYPOLICY": "Privacy Policy",
- "OIDC": "OIDC Configuration"
+ "OIDC": "OIDC Token lifetime and expiration",
+ "SECRETS": "Secret Appearance"
},
"GROUPS": {
"NOTIFICATIONS": "Notifications",
@@ -869,6 +870,27 @@
"REFRESHTOKENIDLEEXPIRATION": "Refresh Token Idle Expiration",
"INHOURS": "hours",
"INDAYS": "Days"
+ },
+ "SECRETS": {
+ "TITLE": "Secret Appearance",
+ "TYPES": "Secret Types",
+ "TYPE": {
+ "1": "Initialization Mail",
+ "2": "Email verification",
+ "3": "Phone verification",
+ "4": "Password Reset",
+ "5": "Passwordless Initialization",
+ "6": "App Secret"
+ },
+ "ADDGENERATOR": "Define Secret Appearance",
+ "GENERATORTYPE": "Type",
+ "EXPIRY": "Expiration (in hours)",
+ "INCLUDEDIGITS": "Include Numbers",
+ "INCLUDESYMBOLS": "Include Symbols",
+ "INCLUDELOWERLETTERS": "Include Lower letters",
+ "INCLUDEUPPERLETTERS": "Include Upper letters",
+ "LENGTH": "Length",
+ "UPDATED": "Settings updated."
}
},
"POLICY": {
diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json
index c168652f0..0b095d6fd 100644
--- a/console/src/assets/i18n/it.json
+++ b/console/src/assets/i18n/it.json
@@ -821,7 +821,8 @@
"LOGINTEXTS": "Testi dell'interfaccia login",
"BRANDING": "Branding",
"PRIVACYPOLICY": "Informativa sulla privacy e TOS",
- "OIDC": "OIDC Configuration"
+ "OIDC": "OIDC Token lifetime e scadenza",
+ "SECRETS": "Aspetto dei segreti"
},
"GROUPS": {
"NOTIFICATIONS": "Notifiche",
@@ -869,6 +870,27 @@
"REFRESHTOKENIDLEEXPIRATION": "Refresh Token Idle Expiration",
"INHOURS": "ore",
"INDAYS": "giorni"
+ },
+ "SECRETS": {
+ "TITLE": "Aspetto dei segreti",
+ "TYPES": "Tipi di segreti",
+ "TYPE": {
+ "1": "Initializzazione email",
+ "2": "Verificazione dell' email",
+ "3": "Verificazione del numero di telefono",
+ "4": "Ripristino Password",
+ "5": "Inizializzazione Passwordless",
+ "6": "Segreto dell'applicazione"
+ },
+ "ADDGENERATOR": "Definisci aspetto",
+ "GENERATORTYPE": "Tipo",
+ "EXPIRY": "Scadenza (in ore)",
+ "INCLUDEDIGITS": "Contiene numeri",
+ "INCLUDESYMBOLS": "Contiene simboli",
+ "INCLUDELOWERLETTERS": "Contiene lettere minuscole",
+ "INCLUDEUPPERLETTERS": "Contiene lettere maiuscole",
+ "LENGTH": "Lunghezza",
+ "UPDATED": "Impostazioni aggiornati"
}
},
"POLICY": {
diff --git a/console/src/component-themes.scss b/console/src/component-themes.scss
index deef8577c..2792c3b89 100644
--- a/console/src/component-themes.scss
+++ b/console/src/component-themes.scss
@@ -12,6 +12,7 @@
@import 'src/app/modules/app-card/app-card.component';
@import 'src/app/modules/contributors/contributors.component';
@import 'src/app/modules/nav/nav.component';
+@import './styles/toast.scss';
@import 'src/app/modules/table-actions/table-actions.component';
@import 'src/app/modules/org-context/org-context.component.scss';
@import 'src/app/modules/action-keys/action-keys.component.scss';
@@ -95,6 +96,7 @@
@include user-detail-theme($theme);
@include instance-detail-theme($theme);
@include meta-theme($theme);
+ @include toast-theme($theme);
@include keyboard-shortcuts-theme($theme);
@include project-grant-illustration-theme($theme);
@include refresh-table-theme($theme);
diff --git a/console/src/styles/toast.scss b/console/src/styles/toast.scss
new file mode 100644
index 000000000..5ad34591a
--- /dev/null
+++ b/console/src/styles/toast.scss
@@ -0,0 +1,22 @@
+@use '@angular/material' as mat;
+
+@mixin toast-theme($theme) {
+ $primary: map-get($theme, primary);
+ $primary-color: mat.get-color-from-palette($primary, 500);
+ $primary-light-color: mat.get-color-from-palette($primary, 200);
+ $warn: map-get($theme, warn);
+ $warn-color: mat.get-color-from-palette($warn, 500);
+ $background: map-get($theme, background);
+ $foreground: map-get($theme, foreground);
+ $is-dark-theme: map-get($theme, is-dark);
+
+ // .data-e2e-success {
+ // background-color: map-get($background, cards) !important;
+ // color: var(--success) !important;
+ // }
+
+ .data-e2e-failure {
+ background-color: $warn-color !important;
+ color: map-get($foreground, text) !important;
+ }
+}