mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 03:24:26 +00:00
feat(console): seo metatags, fix policy bugs, project options (#844)
* add seo service, index meta info * fix policy buttons, refresh * refresh after timeout * loading spinner for login policy, complexity * fix user form, add project role options * authtoken options * seo service lint * style lint * remove duplicate authmethod * en i18n * Update console/src/assets/i18n/en.json Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
This commit is contained in:
parent
c3b4c3f264
commit
b1d61afc8f
@ -43,6 +43,7 @@ import { GRPC_INTERCEPTORS } from './services/interceptors/grpc-interceptor';
|
|||||||
import { I18nInterceptor } from './services/interceptors/i18n.interceptor';
|
import { I18nInterceptor } from './services/interceptors/i18n.interceptor';
|
||||||
import { OrgInterceptor } from './services/interceptors/org.interceptor';
|
import { OrgInterceptor } from './services/interceptors/org.interceptor';
|
||||||
import { RefreshService } from './services/refresh.service';
|
import { RefreshService } from './services/refresh.service';
|
||||||
|
import { SeoService } from './services/seo.service';
|
||||||
import { StatehandlerProcessorService, StatehandlerProcessorServiceImpl } from './services/statehandler-processor.service';
|
import { StatehandlerProcessorService, StatehandlerProcessorServiceImpl } from './services/statehandler-processor.service';
|
||||||
import { StatehandlerService, StatehandlerServiceImpl } from './services/statehandler.service';
|
import { StatehandlerService, StatehandlerServiceImpl } from './services/statehandler.service';
|
||||||
import { StorageService } from './services/storage.service';
|
import { StorageService } from './services/storage.service';
|
||||||
@ -167,6 +168,7 @@ const authConfig: AuthConfig = {
|
|||||||
multi: true,
|
multi: true,
|
||||||
useClass: OrgInterceptor,
|
useClass: OrgInterceptor,
|
||||||
},
|
},
|
||||||
|
SeoService,
|
||||||
RefreshService,
|
RefreshService,
|
||||||
GrpcService,
|
GrpcService,
|
||||||
GrpcAuthService,
|
GrpcAuthService,
|
||||||
|
@ -97,19 +97,9 @@ export class IdpTableComponent implements OnInit {
|
|||||||
private async getData(limit: number, offset: number): Promise<void> {
|
private async getData(limit: number, offset: number): Promise<void> {
|
||||||
this.loadingSubject.next(true);
|
this.loadingSubject.next(true);
|
||||||
|
|
||||||
// let query: AdminIdpSearchQuery | MgmtIdpSearchQuery;
|
|
||||||
// if (this.service instanceof AdminService) {
|
|
||||||
// query = new AdminIdpSearchQuery();
|
|
||||||
// query.setKey(AdminIdpSearchKey.IDPSEARCHKEY_IDP_CONFIG_ID);
|
|
||||||
// } else if (this.service instanceof ManagementService) {
|
|
||||||
// query = new MgmtIdpSearchQuery();
|
|
||||||
// query.setKey(MgmtIdpSearchKey.IDPSEARCHKEY_PROVIDER_TYPE);
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.service.SearchIdps(limit, offset).then(resp => {
|
this.service.SearchIdps(limit, offset).then(resp => {
|
||||||
this.idpResult = resp.toObject();
|
this.idpResult = resp.toObject();
|
||||||
this.dataSource.data = this.idpResult.resultList;
|
this.dataSource.data = this.idpResult.resultList;
|
||||||
console.log(this.idpResult.resultList);
|
|
||||||
this.loadingSubject.next(false);
|
this.loadingSubject.next(false);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
[title]="'ORG.POLICY.LOGIN_POLICY.TITLECREATE' | translate"
|
[title]="'ORG.POLICY.LOGIN_POLICY.TITLECREATE' | translate"
|
||||||
[description]="(serviceType==PolicyComponentServiceType.MGMT ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '') | translate">
|
[description]="(serviceType==PolicyComponentServiceType.MGMT ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '') | translate">
|
||||||
|
|
||||||
<ng-template appHasRole
|
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
|
||||||
[appHasRole]="[serviceType === PolicyComponentServiceType.ADMIN ? 'iam.policy.delete' : 'org.policy.delete']">
|
|
||||||
<button matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()"
|
<div class="spinner-wr">
|
||||||
mat-stroked-button>
|
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
<ng-template appHasRole [appHasRole]="['policy.delete']">
|
||||||
|
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
||||||
|
matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
|
||||||
{{'ORG.POLICY.RESET' | translate}}
|
{{'ORG.POLICY.RESET' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spinner-wr {
|
||||||
|
margin: .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -33,9 +33,11 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
|
|
||||||
private sub: Subscription = new Subscription();
|
private sub: Subscription = new Subscription();
|
||||||
public service!: ManagementService | AdminService;
|
public service!: ManagementService | AdminService;
|
||||||
PolicyComponentServiceType: any = PolicyComponentServiceType;
|
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||||
public idps: MgmtIdpProviderView.AsObject[] | AdminIdpProviderView.AsObject[] = [];
|
public idps: MgmtIdpProviderView.AsObject[] | AdminIdpProviderView.AsObject[] = [];
|
||||||
|
|
||||||
|
public loading: boolean = false;
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private toast: ToastService,
|
private toast: ToastService,
|
||||||
@ -43,7 +45,6 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
private injector: Injector,
|
private injector: Injector,
|
||||||
) {
|
) {
|
||||||
this.sub = this.route.data.pipe(switchMap(data => {
|
this.sub = this.route.data.pipe(switchMap(data => {
|
||||||
console.log(data.serviceType);
|
|
||||||
this.serviceType = data.serviceType;
|
this.serviceType = data.serviceType;
|
||||||
switch (this.serviceType) {
|
switch (this.serviceType) {
|
||||||
case PolicyComponentServiceType.MGMT:
|
case PolicyComponentServiceType.MGMT:
|
||||||
@ -56,16 +57,20 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
|
|
||||||
return this.route.params;
|
return this.route.params;
|
||||||
})).subscribe(() => {
|
})).subscribe(() => {
|
||||||
|
this.fetchData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchData(): void {
|
||||||
this.getData().then(data => {
|
this.getData().then(data => {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.loginData = data.toObject();
|
this.loginData = data.toObject();
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.getIdps().then(idps => {
|
this.getIdps().then(idps => {
|
||||||
console.log(idps);
|
|
||||||
this.idps = idps;
|
this.idps = idps;
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy(): void {
|
public ngOnDestroy(): void {
|
||||||
@ -122,6 +127,10 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
public savePolicy(): void {
|
public savePolicy(): void {
|
||||||
this.updateData().then(() => {
|
this.updateData().then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.LOGIN_POLICY.SAVED', true);
|
this.toast.showInfo('ORG.POLICY.LOGIN_POLICY.SAVED', true);
|
||||||
|
this.loading = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fetchData();
|
||||||
|
}, 2000);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
@ -131,9 +140,10 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||||
(this.service as ManagementService).RemoveLoginPolicy().then(() => {
|
(this.service as ManagementService).RemoveLoginPolicy().then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
|
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
|
||||||
|
this.loading = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.getData();
|
this.fetchData();
|
||||||
}, 1000);
|
}, 2000);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
@ -151,7 +161,10 @@ export class LoginPolicyComponent implements OnDestroy {
|
|||||||
dialogRef.afterClosed().subscribe(resp => {
|
dialogRef.afterClosed().subscribe(resp => {
|
||||||
if (resp && resp.idp && resp.type) {
|
if (resp && resp.idp && resp.type) {
|
||||||
this.addIdp(resp.idp, resp.type).then(() => {
|
this.addIdp(resp.idp, resp.type).then(() => {
|
||||||
this.getData();
|
this.loading = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fetchData();
|
||||||
|
}, 2000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,7 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
@ -37,6 +38,7 @@ import { LoginPolicyComponent } from './login-policy.component';
|
|||||||
DetailLayoutModule,
|
DetailLayoutModule,
|
||||||
AddIdpDialogModule,
|
AddIdpDialogModule,
|
||||||
IdpTableModule,
|
IdpTableModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class LoginPolicyModule { }
|
export class LoginPolicyModule { }
|
||||||
|
@ -20,7 +20,7 @@ import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
|||||||
export class OrgIamPolicyComponent implements OnDestroy {
|
export class OrgIamPolicyComponent implements OnDestroy {
|
||||||
@Input() service!: AdminService;
|
@Input() service!: AdminService;
|
||||||
private managementService!: ManagementService;
|
private managementService!: ManagementService;
|
||||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
public serviceType!: PolicyComponentServiceType;
|
||||||
|
|
||||||
public iamData!: AdminOrgIamPolicyView.AsObject | MgmtOrgIamPolicyView.AsObject;
|
public iamData!: AdminOrgIamPolicyView.AsObject | MgmtOrgIamPolicyView.AsObject;
|
||||||
|
|
||||||
@ -47,11 +47,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
return this.route.params;
|
return this.route.params;
|
||||||
})).subscribe(_ => {
|
})).subscribe(_ => {
|
||||||
this.getData().then(data => {
|
this.fetchData();
|
||||||
if (data) {
|
|
||||||
this.iamData = data.toObject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +55,14 @@ export class OrgIamPolicyComponent implements OnDestroy {
|
|||||||
this.sub.unsubscribe();
|
this.sub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fetchData(): void {
|
||||||
|
this.getData().then(data => {
|
||||||
|
if (data) {
|
||||||
|
this.iamData = data.toObject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async getData(): Promise<AdminOrgIamPolicyView | MgmtOrgIamPolicyView | undefined> {
|
private async getData(): Promise<AdminOrgIamPolicyView | MgmtOrgIamPolicyView | undefined> {
|
||||||
switch (this.serviceType) {
|
switch (this.serviceType) {
|
||||||
case PolicyComponentServiceType.MGMT:
|
case PolicyComponentServiceType.MGMT:
|
||||||
@ -114,7 +118,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
|
|||||||
this.adminService.RemoveOrgIamPolicy(this.org.id).then(() => {
|
this.adminService.RemoveOrgIamPolicy(this.org.id).then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
|
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.getData();
|
this.fetchData();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
|
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
|
||||||
[title]="'ORG.POLICY.PWD_AGE.TITLE' | translate" [description]="'ORG.POLICY.PWD_AGE.DESCRIPTION' | translate">
|
[title]="'ORG.POLICY.PWD_AGE.TITLE' | translate" [description]="'ORG.POLICY.PWD_AGE.DESCRIPTION' | translate">
|
||||||
<ng-template appHasRole
|
<ng-template appHasRole [appHasRole]="['policy.delete']">
|
||||||
[appHasRole]="[serviceType === PolicyComponentServiceType.ADMIN ? 'iam.policy.delete' : 'org.policy.delete']">
|
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT" matTooltip="{{'ORG.POLICY.RESET' | translate}}"
|
||||||
<button matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()"
|
color="warn" (click)="removePolicy()" mat-stroked-button>
|
||||||
mat-stroked-button>
|
|
||||||
{{'ORG.POLICY.RESET' | translate}}
|
{{'ORG.POLICY.RESET' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -110,14 +110,20 @@ export class PasswordAgePolicyComponent implements OnDestroy {
|
|||||||
(this.service as ManagementService).CreatePasswordAgePolicy(
|
(this.service as ManagementService).CreatePasswordAgePolicy(
|
||||||
this.ageData.maxAgeDays,
|
this.ageData.maxAgeDays,
|
||||||
this.ageData.expireWarnDays,
|
this.ageData.expireWarnDays,
|
||||||
).catch(error => {
|
).then(() => {
|
||||||
|
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
||||||
|
this.getData();
|
||||||
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
(this.service as ManagementService).UpdatePasswordAgePolicy(
|
(this.service as ManagementService).UpdatePasswordAgePolicy(
|
||||||
this.ageData.maxAgeDays,
|
this.ageData.maxAgeDays,
|
||||||
this.ageData.expireWarnDays,
|
this.ageData.expireWarnDays,
|
||||||
).catch(error => {
|
).then(() => {
|
||||||
|
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
||||||
|
this.getData();
|
||||||
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -126,7 +132,10 @@ export class PasswordAgePolicyComponent implements OnDestroy {
|
|||||||
(this.service as AdminService).UpdateDefaultPasswordAgePolicy(
|
(this.service as AdminService).UpdateDefaultPasswordAgePolicy(
|
||||||
this.ageData.maxAgeDays,
|
this.ageData.maxAgeDays,
|
||||||
this.ageData.expireWarnDays,
|
this.ageData.expireWarnDays,
|
||||||
).catch(error => {
|
).then(() => {
|
||||||
|
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
||||||
|
this.getData();
|
||||||
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
|
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
|
||||||
[title]="'ORG.POLICY.PWD_COMPLEXITY.TITLE' | translate"
|
[title]="'ORG.POLICY.PWD_COMPLEXITY.TITLE' | translate"
|
||||||
[description]="'ORG.POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate">
|
[description]="'ORG.POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate">
|
||||||
|
|
||||||
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
|
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
|
||||||
|
|
||||||
<ng-template appHasRole
|
<div class="spinner-wr">
|
||||||
[appHasRole]="[serviceType === PolicyComponentServiceType.ADMIN ? 'iam.policy.delete' : 'org.policy.delete']">
|
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
|
||||||
<button matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()"
|
</div>
|
||||||
mat-stroked-button>
|
|
||||||
|
<ng-template appHasRole [appHasRole]="['policy.delete']">
|
||||||
|
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
||||||
|
matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
|
||||||
{{'ORG.POLICY.RESET' | translate}}
|
{{'ORG.POLICY.RESET' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spinner-wr {
|
||||||
|
margin: .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -23,6 +23,8 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
|||||||
|
|
||||||
private sub: Subscription = new Subscription();
|
private sub: Subscription = new Subscription();
|
||||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||||
|
|
||||||
|
public loading: boolean = false;
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private toast: ToastService,
|
private toast: ToastService,
|
||||||
@ -42,12 +44,19 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
|||||||
|
|
||||||
return this.route.params;
|
return this.route.params;
|
||||||
})).subscribe(() => {
|
})).subscribe(() => {
|
||||||
|
this.fetchData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public fetchData(): void {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
this.getData().then(data => {
|
this.getData().then(data => {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.complexityData = data.toObject();
|
this.complexityData = data.toObject();
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy(): void {
|
public ngOnDestroy(): void {
|
||||||
@ -69,7 +78,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
|||||||
this.service.removePasswordComplexityPolicy().then(() => {
|
this.service.removePasswordComplexityPolicy().then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
|
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.getData();
|
this.fetchData();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
|
@ -5,6 +5,7 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
@ -29,6 +30,7 @@ import { PasswordComplexityPolicyComponent } from './password-complexity-policy.
|
|||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
DetailLayoutModule,
|
DetailLayoutModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PasswordComplexityPolicyModule { }
|
export class PasswordComplexityPolicyModule { }
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
[title]="'ORG.POLICY.PWD_LOCKOUT.TITLE' | translate"
|
[title]="'ORG.POLICY.PWD_LOCKOUT.TITLE' | translate"
|
||||||
[description]="'ORG.POLICY.PWD_LOCKOUT.DESCRIPTION' | translate">
|
[description]="'ORG.POLICY.PWD_LOCKOUT.DESCRIPTION' | translate">
|
||||||
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
|
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
|
||||||
<ng-template appHasRole
|
|
||||||
[appHasRole]="[serviceType === PolicyComponentServiceType.ADMIN ? 'iam.policy.delete' : 'org.policy.delete']">
|
<ng-template appHasRole [appHasRole]="['policy.delete']">
|
||||||
<button matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()"
|
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT" matTooltip="{{'ORG.POLICY.RESET' | translate}}"
|
||||||
mat-stroked-button>
|
color="warn" (click)="removePolicy()" mat-stroked-button>
|
||||||
{{'ORG.POLICY.RESET' | translate}}
|
{{'ORG.POLICY.RESET' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -58,7 +58,6 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getData(): Promise<PasswordLockoutPolicyView | DefaultPasswordLockoutPolicyView> {
|
private getData(): Promise<PasswordLockoutPolicyView | DefaultPasswordLockoutPolicyView> {
|
||||||
|
|
||||||
switch (this.serviceType) {
|
switch (this.serviceType) {
|
||||||
case PolicyComponentServiceType.MGMT:
|
case PolicyComponentServiceType.MGMT:
|
||||||
return (this.service as ManagementService).GetPasswordLockoutPolicy();
|
return (this.service as ManagementService).GetPasswordLockoutPolicy();
|
||||||
@ -100,6 +99,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
|
|||||||
this.lockoutData.showLockoutFailure,
|
this.lockoutData.showLockoutFailure,
|
||||||
).then(() => {
|
).then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
||||||
|
this.getData();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
@ -110,6 +110,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
|
|||||||
this.lockoutData.showLockoutFailure,
|
this.lockoutData.showLockoutFailure,
|
||||||
).then(() => {
|
).then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
||||||
|
this.getData();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
@ -119,6 +120,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
|
|||||||
this.lockoutData.showLockoutFailure,
|
this.lockoutData.showLockoutFailure,
|
||||||
).then(() => {
|
).then(() => {
|
||||||
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
|
||||||
|
this.getData();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import { PolicyComponentType } from 'src/app/modules/policies/policy-component-t
|
|||||||
import { DefaultLoginPolicy, DefaultPasswordComplexityPolicyView, OrgIamPolicyView } from 'src/app/proto/generated/admin_pb';
|
import { DefaultLoginPolicy, DefaultPasswordComplexityPolicyView, OrgIamPolicyView } from 'src/app/proto/generated/admin_pb';
|
||||||
import { PolicyState } from 'src/app/proto/generated/management_pb';
|
import { PolicyState } from 'src/app/proto/generated/management_pb';
|
||||||
import { AdminService } from 'src/app/services/admin.service';
|
import { AdminService } from 'src/app/services/admin.service';
|
||||||
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-iam-policy-grid',
|
selector: 'app-iam-policy-grid',
|
||||||
@ -18,14 +19,25 @@ export class IamPolicyGridComponent {
|
|||||||
public PolicyComponentType: any = PolicyComponentType;
|
public PolicyComponentType: any = PolicyComponentType;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private authService: GrpcAuthService,
|
||||||
private adminService: AdminService,
|
private adminService: AdminService,
|
||||||
) {
|
) {
|
||||||
this.getData();
|
this.getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getData(): void {
|
private getData(): void {
|
||||||
|
|
||||||
|
this.authService.isAllowed(['policy.read']).subscribe(allowed => {
|
||||||
|
if (allowed) {
|
||||||
this.adminService.GetDefaultLoginPolicy().then(data => this.loginPolicy = data.toObject());
|
this.adminService.GetDefaultLoginPolicy().then(data => this.loginPolicy = data.toObject());
|
||||||
this.adminService.GetDefaultOrgIamPolicy().then(data => this.iamPolicy = data.toObject());
|
|
||||||
this.adminService.GetDefaultPasswordComplexityPolicy().then(data => this.complexityPolicy = data.toObject());
|
this.adminService.GetDefaultPasswordComplexityPolicy().then(data => this.complexityPolicy = data.toObject());
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.authService.isAllowed(['iam.policy.read']).subscribe(allowed => {
|
||||||
|
if (allowed) {
|
||||||
|
this.adminService.GetDefaultOrgIamPolicy().then(data => this.iamPolicy = data.toObject());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,11 +95,36 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<p class="full-width section-title">{{'APP.OIDC.TOKENSECTIONTITLE' | translate}}</p>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="formfield">
|
||||||
|
<mat-label>{{ 'APP.OIDC.TOKENTYPE' | translate }}</mat-label>
|
||||||
|
<mat-select formControlName="accessTokenType">
|
||||||
|
<mat-option *ngFor="let type of oidcTokenTypes" [value]="type">
|
||||||
|
{{ 'APP.OIDC.TOKENTYPE'+type | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-checkbox *ngIf="accessTokenType?.value === OIDCTokenType.OIDCTOKENTYPE_JWT" class="full-width"
|
||||||
|
formControlName="accessTokenRoleAssertion">
|
||||||
|
{{'APP.OIDC.ACCESSTOKENROLEASSERTION' | translate}}</mat-checkbox>
|
||||||
|
<p class="full-width desc">{{'APP.OIDC.ACCESSTOKENROLEASSERTION_DESCRIPTION' | translate}}</p>
|
||||||
|
<mat-checkbox class="full-width" formControlName="idTokenRoleAssertion">
|
||||||
|
{{'APP.OIDC.IDTOKENROLEASSERTION' | translate}}</mat-checkbox>
|
||||||
|
<p class="full-width desc">{{'APP.OIDC.IDTOKENROLEASSERTION_DESCRIPTION' | translate}}</p>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<p class="full-width section-title">{{'APP.OIDC.REDIRECTSECTIONTITLE' | translate}}</p>
|
||||||
|
|
||||||
<mat-slide-toggle color="primary" class="devmode" formControlName="devMode" name="devMode">
|
<mat-slide-toggle color="primary" class="devmode" formControlName="devMode" name="devMode">
|
||||||
{{ 'APP.OIDC.DEVMODE' | translate }}
|
{{ 'APP.OIDC.DEVMODE' | translate }}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
|
||||||
<p class="step-description">{{'APP.OIDC.DEVMODEDESC' | translate}}</p>
|
<p class="step-description" style="margin-bottom: 2rem;">{{'APP.OIDC.DEVMODEDESC' | translate}}</p>
|
||||||
<p class="step-description"
|
<p class="step-description"
|
||||||
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE">
|
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE">
|
||||||
{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</p>
|
{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</p>
|
||||||
|
@ -60,6 +60,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-width {
|
||||||
|
flex-basis: 100%;
|
||||||
|
margin-left: .5rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
color: var(--grey);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
.devmode {
|
.devmode {
|
||||||
flex: 1 1 100%;
|
flex: 1 1 100%;
|
||||||
margin: 1rem .5rem;
|
margin: 1rem .5rem;
|
||||||
@ -115,3 +130,10 @@
|
|||||||
.chip[color='green'] {
|
.chip[color='green'] {
|
||||||
background-color: #56a392 !important;
|
background-color: #56a392 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
flex-basis: 100%;
|
||||||
|
margin: 1.5rem .5rem;
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--grey);
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
OIDCConfig,
|
OIDCConfig,
|
||||||
OIDCGrantType,
|
OIDCGrantType,
|
||||||
OIDCResponseType,
|
OIDCResponseType,
|
||||||
|
OIDCTokenType,
|
||||||
ZitadelDocs,
|
ZitadelDocs,
|
||||||
} from 'src/app/proto/generated/management_pb';
|
} from 'src/app/proto/generated/management_pb';
|
||||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
@ -67,6 +68,11 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
|
OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public oidcTokenTypes: OIDCTokenType[] = [
|
||||||
|
OIDCTokenType.OIDCTOKENTYPE_BEARER,
|
||||||
|
OIDCTokenType.OIDCTOKENTYPE_JWT,
|
||||||
|
];
|
||||||
|
|
||||||
public AppState: any = AppState;
|
public AppState: any = AppState;
|
||||||
public appNameForm!: FormGroup;
|
public appNameForm!: FormGroup;
|
||||||
public appForm!: FormGroup;
|
public appForm!: FormGroup;
|
||||||
@ -80,6 +86,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public OIDCApplicationType: any = OIDCApplicationType;
|
public OIDCApplicationType: any = OIDCApplicationType;
|
||||||
public OIDCAuthMethodType: any = OIDCAuthMethodType;
|
public OIDCAuthMethodType: any = OIDCAuthMethodType;
|
||||||
|
public OIDCTokenType: any = OIDCTokenType;
|
||||||
|
|
||||||
public redirectControl: FormControl = new FormControl({ value: '', disabled: true });
|
public redirectControl: FormControl = new FormControl({ value: '', disabled: true });
|
||||||
public postRedirectControl: FormControl = new FormControl({ value: '', disabled: true });
|
public postRedirectControl: FormControl = new FormControl({ value: '', disabled: true });
|
||||||
@ -106,6 +113,9 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
grantTypesList: [{ value: [], disabled: true }],
|
grantTypesList: [{ value: [], disabled: true }],
|
||||||
applicationType: [{ value: '', disabled: true }],
|
applicationType: [{ value: '', disabled: true }],
|
||||||
authMethodType: [{ value: '', disabled: true }],
|
authMethodType: [{ value: '', disabled: true }],
|
||||||
|
accessTokenType: [{ value: '', disabled: true }],
|
||||||
|
accessTokenRoleAssertion: [{ value: false, disabled: true }],
|
||||||
|
idTokenRoleAssertion: [{ value: false, disabled: true }],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +230,9 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
this.app.oidcConfig.redirectUrisList = this.redirectUrisList;
|
this.app.oidcConfig.redirectUrisList = this.redirectUrisList;
|
||||||
this.app.oidcConfig.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
this.app.oidcConfig.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
||||||
this.app.oidcConfig.devMode = this.devMode?.value;
|
this.app.oidcConfig.devMode = this.devMode?.value;
|
||||||
|
this.app.oidcConfig.accessTokenType = this.accessTokenType?.value;
|
||||||
|
this.app.oidcConfig.accessTokenRoleAssertion = this.accessTokenRoleAssertion?.value;
|
||||||
|
this.app.oidcConfig.idTokenRoleAssertion = this.idTokenRoleAssertion?.value;
|
||||||
|
|
||||||
this.mgmtService
|
this.mgmtService
|
||||||
.UpdateOIDCAppConfig(this.projectId, this.app.id, this.app.oidcConfig)
|
.UpdateOIDCAppConfig(this.projectId, this.app.id, this.app.oidcConfig)
|
||||||
@ -280,4 +293,16 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
public get devMode(): AbstractControl | null {
|
public get devMode(): AbstractControl | null {
|
||||||
return this.appForm.get('devMode');
|
return this.appForm.get('devMode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get accessTokenType(): AbstractControl | null {
|
||||||
|
return this.appForm.get('accessTokenType');
|
||||||
|
}
|
||||||
|
|
||||||
|
public get idTokenRoleAssertion(): AbstractControl | null {
|
||||||
|
return this.appForm.get('idTokenRoleAssertion');
|
||||||
|
}
|
||||||
|
|
||||||
|
public get accessTokenRoleAssertion(): AbstractControl | null {
|
||||||
|
return this.appForm.get('accessTokenRoleAssertion');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,14 @@
|
|||||||
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.projectId, 'project.role.read']">
|
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.projectId, 'project.role.read']">
|
||||||
<app-card title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
|
<app-card title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
|
||||||
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
|
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
|
||||||
|
<p>{{'PROJECT.ROLE.OPTIONS' | translate}}</p>
|
||||||
|
<mat-checkbox [(ngModel)]="project.projectRoleAssertion" (change)="saveProject()">
|
||||||
|
{{'PROJECT.ROLE.ASSERTION' | translate}}</mat-checkbox>
|
||||||
|
<p class="desc">{{'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate}}</p>
|
||||||
|
<mat-checkbox [(ngModel)]="project.projectRoleCheck" (change)="saveProject()">
|
||||||
|
{{'PROJECT.ROLE.CHECK' | translate}}</mat-checkbox>
|
||||||
|
<p class="desc">{{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}</p>
|
||||||
|
<div class="divider"></div>
|
||||||
<app-project-roles
|
<app-project-roles
|
||||||
[disabled]="(['project.role.write$', 'project.role.write:'+ project.projectId]| hasRole | async) == false"
|
[disabled]="(['project.role.write$', 'project.role.write:'+ project.projectId]| hasRole | async) == false"
|
||||||
[actionsVisible]="true" [projectId]="projectId">
|
[actionsVisible]="true" [projectId]="projectId">
|
||||||
|
@ -76,3 +76,15 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
color: var(--grey);
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--grey);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
@ -191,7 +191,8 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public saveProject(): void {
|
public saveProject(): void {
|
||||||
this.mgmtService.UpdateProject(this.project.projectId, this.project.name).then(() => {
|
console.log(this.project);
|
||||||
|
this.mgmtService.UpdateProject(this.project.projectId, this.project).then(() => {
|
||||||
this.toast.showInfo('PROJECT.TOAST.UPDATED', true);
|
this.toast.showInfo('PROJECT.TOAST.UPDATED', true);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
|
@ -105,7 +105,9 @@ export class ExternalIdpsComponent implements OnInit {
|
|||||||
|
|
||||||
if (promise) {
|
if (promise) {
|
||||||
promise.then(_ => {
|
promise.then(_ => {
|
||||||
|
setTimeout(() => {
|
||||||
this.refreshPage();
|
this.refreshPage();
|
||||||
|
}, 1000);
|
||||||
}).catch((error: any) => {
|
}).catch((error: any) => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</app-card>
|
</app-card>
|
||||||
|
|
||||||
<ng-template appHasRole [appHasRole]="['user.read', 'user.read:'+user?.id]">
|
<ng-template appHasRole [appHasRole]="['user.read$', 'user.read:'+user?.id]">
|
||||||
<app-card *ngIf="user.human" title="{{ 'USER.PROFILE.TITLE' | translate }}">
|
<app-card *ngIf="user.human" title="{{ 'USER.PROFILE.TITLE' | translate }}">
|
||||||
<app-detail-form [disabled]="(canWrite$ | async) == false" [genders]="genders" [languages]="languages"
|
<app-detail-form [disabled]="(canWrite$ | async) == false" [genders]="genders" [languages]="languages"
|
||||||
[username]="user.userName" [user]="user.human" (submitData)="saveProfile($event)">
|
[username]="user.userName" [user]="user.human" (submitData)="saveProfile($event)">
|
||||||
@ -54,9 +54,8 @@
|
|||||||
</app-card>
|
</app-card>
|
||||||
|
|
||||||
<app-card *ngIf="user.machine" title="{{ 'USER.MACHINE.TITLE' | translate }}">
|
<app-card *ngIf="user.machine" title="{{ 'USER.MACHINE.TITLE' | translate }}">
|
||||||
<app-detail-form-machine
|
<app-detail-form-machine [disabled]="(canWrite$ | async) == false" [username]="user.userName"
|
||||||
[disabled]="(['user.write:' + user?.id, 'user.write$'] | hasRole | async) == false"
|
[user]="user.machine" (submitData)="saveMachine($event)">
|
||||||
[username]="user.userName" [user]="user.machine" (submitData)="saveMachine($event)">
|
|
||||||
</app-detail-form-machine>
|
</app-detail-form-machine>
|
||||||
</app-card>
|
</app-card>
|
||||||
|
|
||||||
|
@ -975,10 +975,12 @@ export class ManagementService {
|
|||||||
return this.grpcService.mgmt.createProject(req);
|
return this.grpcService.mgmt.createProject(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateProject(id: string, name: string): Promise<Project> {
|
public UpdateProject(id: string, projectView: ProjectView.AsObject): Promise<Project> {
|
||||||
const req = new ProjectUpdateRequest();
|
const req = new ProjectUpdateRequest();
|
||||||
req.setName(name);
|
|
||||||
req.setId(id);
|
req.setId(id);
|
||||||
|
req.setName(projectView.name);
|
||||||
|
req.setProjectRoleAssertion(projectView.projectRoleAssertion);
|
||||||
|
req.setProjectRoleCheck(projectView.projectRoleCheck);
|
||||||
return this.grpcService.mgmt.updateProject(req);
|
return this.grpcService.mgmt.updateProject(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1271,6 +1273,9 @@ export class ManagementService {
|
|||||||
req.setGrantTypesList(oidcConfig.grantTypesList);
|
req.setGrantTypesList(oidcConfig.grantTypesList);
|
||||||
req.setApplicationType(oidcConfig.applicationType);
|
req.setApplicationType(oidcConfig.applicationType);
|
||||||
req.setDevMode(oidcConfig.devMode);
|
req.setDevMode(oidcConfig.devMode);
|
||||||
|
req.setAccessTokenType(oidcConfig.accessTokenType);
|
||||||
|
req.setAccessTokenRoleAssertion(oidcConfig.accessTokenRoleAssertion);
|
||||||
|
req.setIdTokenRoleAssertion(oidcConfig.idTokenRoleAssertion);
|
||||||
return this.grpcService.mgmt.updateApplicationOIDCConfig(req);
|
return this.grpcService.mgmt.updateApplicationOIDCConfig(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
console/src/app/services/seo.service.ts
Normal file
38
console/src/app/services/seo.service.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Meta } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class SeoService {
|
||||||
|
constructor(private meta: Meta) { }
|
||||||
|
|
||||||
|
public generateTags(config: any): void {
|
||||||
|
// default values
|
||||||
|
config = {
|
||||||
|
title: 'ZITADEL Console',
|
||||||
|
description: 'Managementplatform for ZITADEL',
|
||||||
|
image: 'https://www.zitadel.ch/zitadel-social-preview25.png',
|
||||||
|
slug: '',
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.meta.updateTag({ property: 'og:type', content: 'website' });
|
||||||
|
this.meta.updateTag({ property: 'og:site_name', content: 'ZITADEL Console' });
|
||||||
|
this.meta.updateTag({ property: 'og:title', content: config.title });
|
||||||
|
this.meta.updateTag({ property: 'description', content: config.description });
|
||||||
|
this.meta.updateTag({ property: 'og:description', content: config.description });
|
||||||
|
if (config.image) {
|
||||||
|
this.meta.updateTag({ property: 'og:image', content: config.image });
|
||||||
|
}
|
||||||
|
this.meta.updateTag({ property: 'og:url', content: `https://${environment.production ? 'console.zitadel.ch' : 'console.zitadel.dev'}/${config.slug}` });
|
||||||
|
|
||||||
|
this.meta.updateTag({ property: 'twitter:card', content: 'summary' });
|
||||||
|
this.meta.updateTag({ property: 'og:site', content: '@zitadel_ch' });
|
||||||
|
this.meta.updateTag({ property: 'og:title', content: config.title });
|
||||||
|
this.meta.updateTag({ property: 'og:image', content: 'https://www.zitadel.ch/zitadel-social-preview25.png' });
|
||||||
|
this.meta.updateTag({ property: 'og:description', content: config.description });
|
||||||
|
}
|
||||||
|
}
|
@ -648,7 +648,12 @@
|
|||||||
"EDITDESCRIPTION": "Gebe die Daten für die zu ändernde Rolle ein.",
|
"EDITDESCRIPTION": "Gebe die Daten für die zu ändernde Rolle ein.",
|
||||||
"DELETE":"Rolle löschen",
|
"DELETE":"Rolle löschen",
|
||||||
"CREATIONDATE":"Erstelldatum",
|
"CREATIONDATE":"Erstelldatum",
|
||||||
"SELECTGROUPTOOLTIP":"Wähle alle Rollen der Gruppe {{group}} aus."
|
"SELECTGROUPTOOLTIP":"Wähle alle Rollen der Gruppe {{group}} aus.",
|
||||||
|
"OPTIONS":"Optionen",
|
||||||
|
"ASSERTION":"Rollen bei Authentisierung mitschicken",
|
||||||
|
"ASSERTION_DESCRIPTION":"Rolleninformationen werden der Authentisierung per Token, UserInfo Endpoint oder anderen Methoden bereitgestellt, die in Applikationseinstellungen definiert sind.",
|
||||||
|
"CHECK":"Rollen bei Authentisierung prüfen",
|
||||||
|
"CHECK_DESCRIPTION":"Ist das Attribut gesetzt, kann ein Benutzer nur mit einem entsprechenden Rolle authentifiziert werden."
|
||||||
},
|
},
|
||||||
"TABLE": {
|
"TABLE": {
|
||||||
"TOTAL": "Einträge gesamt:",
|
"TOTAL": "Einträge gesamt:",
|
||||||
@ -762,6 +767,8 @@
|
|||||||
"TYPE":"Anwendungstyp",
|
"TYPE":"Anwendungstyp",
|
||||||
"GRANT":"Berechtigungstypen",
|
"GRANT":"Berechtigungstypen",
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
|
"TOKENSECTIONTITLE":"AuthToken Optionen",
|
||||||
|
"REDIRECTSECTIONTITLE":"Weiterleitungseinstellungen",
|
||||||
"PROSWITCH":"Konfigurator überspringen",
|
"PROSWITCH":"Konfigurator überspringen",
|
||||||
"NAMEANDTYPESECTION":"Name und Typ",
|
"NAMEANDTYPESECTION":"Name und Typ",
|
||||||
"TITLEFIRST":"Gebe zuerst einen Namen ein.",
|
"TITLEFIRST":"Gebe zuerst einen Namen ein.",
|
||||||
@ -802,9 +809,16 @@
|
|||||||
"AUTHMETHOD0":"Basic",
|
"AUTHMETHOD0":"Basic",
|
||||||
"AUTHMETHOD1":"Post",
|
"AUTHMETHOD1":"Post",
|
||||||
"AUTHMETHOD2":"None",
|
"AUTHMETHOD2":"None",
|
||||||
|
"TOKENTYPE":"Auth Token Typ",
|
||||||
|
"TOKENTYPE0": "Bearer Token",
|
||||||
|
"TOKENTYPE1": "JWT",
|
||||||
"UNSECUREREDIRECT":"Ich hoffe, Du weisst, was Du tust.",
|
"UNSECUREREDIRECT":"Ich hoffe, Du weisst, was Du tust.",
|
||||||
"OVERVIEWSECTION":"Übersicht",
|
"OVERVIEWSECTION":"Übersicht",
|
||||||
"OVERVIEWTITLE":"Deine Konfiguration ist bereit. Du kannst sie hier nochmals prüfen."
|
"OVERVIEWTITLE":"Deine Konfiguration ist bereit. Du kannst sie hier nochmals prüfen.",
|
||||||
|
"ACCESSTOKENROLEASSERTION":"Benutzerrollen dem Access Token hinzufügen",
|
||||||
|
"ACCESSTOKENROLEASSERTION_DESCRIPTION":"Bei Auswahl werden dem Access Token die Rollen des Authentifizierten Benutzers hinzugefügt.",
|
||||||
|
"IDTOKENROLEASSERTION":"Benutzerrollen dem Id Token hinzufügen",
|
||||||
|
"IDTOKENROLEASSERTION_DESCRIPTION":"Bei Auswahl werden dem Id Token die Rollen des Authentifizierten Benutzers hinzugefügt."
|
||||||
},
|
},
|
||||||
"TOAST": {
|
"TOAST": {
|
||||||
"REACTIVATED":"Anwendung reaktiviert.",
|
"REACTIVATED":"Anwendung reaktiviert.",
|
||||||
|
@ -648,7 +648,12 @@
|
|||||||
"EDITDESCRIPTION": "Enter the new data for the role.",
|
"EDITDESCRIPTION": "Enter the new data for the role.",
|
||||||
"DELETE":"Delete Role",
|
"DELETE":"Delete Role",
|
||||||
"CREATIONDATE":"Created",
|
"CREATIONDATE":"Created",
|
||||||
"SELECTGROUPTOOLTIP":"Select all Roles of the group {{group}}."
|
"SELECTGROUPTOOLTIP":"Select all Roles of the group {{group}}.",
|
||||||
|
"OPTIONS":"Options",
|
||||||
|
"ASSERTION":"Assert Roles on Authentication.",
|
||||||
|
"ASSERTION_DESCRIPTION":"Roleinformation is sent as Token, Userinfo endpoint or other type, depending on your application settings.",
|
||||||
|
"CHECK":"Check roles on Authentication",
|
||||||
|
"CHECK_DESCRIPTION":"If set, users are only allowed to authenticate if any role is assigned to their account."
|
||||||
},
|
},
|
||||||
"TABLE": {
|
"TABLE": {
|
||||||
"TOTAL": "Entries total:",
|
"TOTAL": "Entries total:",
|
||||||
@ -762,6 +767,8 @@
|
|||||||
"TYPE":"Application Type",
|
"TYPE":"Application Type",
|
||||||
"GRANT":"Grant Types",
|
"GRANT":"Grant Types",
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
|
"TOKENSECTIONTITLE":"AuthToken Options",
|
||||||
|
"REDIRECTSECTIONTITLE":"Redirect Settings",
|
||||||
"PROSWITCH":"I'm a pro. Skip this wizard.",
|
"PROSWITCH":"I'm a pro. Skip this wizard.",
|
||||||
"NAMEANDTYPESECTION":"Name and Type",
|
"NAMEANDTYPESECTION":"Name and Type",
|
||||||
"TITLEFIRST":"Insert a name first.",
|
"TITLEFIRST":"Insert a name first.",
|
||||||
@ -802,9 +809,16 @@
|
|||||||
"AUTHMETHOD0":"Basic",
|
"AUTHMETHOD0":"Basic",
|
||||||
"AUTHMETHOD1":"Post",
|
"AUTHMETHOD1":"Post",
|
||||||
"AUTHMETHOD2":"None",
|
"AUTHMETHOD2":"None",
|
||||||
|
"TOKENTYPE":"Auth Token Type",
|
||||||
|
"TOKENTYPE0": "Bearer Token",
|
||||||
|
"TOKENTYPE1": "JWT",
|
||||||
"UNSECUREREDIRECT":"I sure hope you know what you are doing.",
|
"UNSECUREREDIRECT":"I sure hope you know what you are doing.",
|
||||||
"OVERVIEWSECTION":"Overview",
|
"OVERVIEWSECTION":"Overview",
|
||||||
"OVERVIEWTITLE":"You are now done. Review your configuration."
|
"OVERVIEWTITLE":"You are now done. Review your configuration.",
|
||||||
|
"ACCESSTOKENROLEASSERTION":"Add user roles to the access token",
|
||||||
|
"ACCESSTOKENROLEASSERTION_DESCRIPTION":"If selected, the roles of the authenticated user are added to the access token.",
|
||||||
|
"IDTOKENROLEASSERTION":"Add user roles to the id token",
|
||||||
|
"IDTOKENROLEASSERTION_DESCRIPTION":"If selected, the roles of the authenticated user are added to the id token."
|
||||||
},
|
},
|
||||||
"TOAST": {
|
"TOAST": {
|
||||||
"REACTIVATED":"Application reactivated.",
|
"REACTIVATED":"Application reactivated.",
|
||||||
|
@ -16,14 +16,19 @@
|
|||||||
<link rel="manifest" href="manifest.webmanifest">
|
<link rel="manifest" href="manifest.webmanifest">
|
||||||
<meta name="theme-color" content="#e6768b">
|
<meta name="theme-color" content="#e6768b">
|
||||||
|
|
||||||
|
|
||||||
<meta property="og:url" content="https://console.zitadel.dev" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:title" content="ZITADEL Console - Identity and Access Management" />
|
|
||||||
<meta property="og:description" content="Console Management Platform for ZITADEL IAM" />
|
|
||||||
<meta property="description" content="Console Management Platform for ZITADEL IAM" />
|
<meta property="description" content="Console Management Platform for ZITADEL IAM" />
|
||||||
|
<meta property="og:url" content="https://console.zitadel.ch" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:title" content="ZITADEL Console" />
|
||||||
|
<meta property="og:description" content="Console Management Platform for ZITADEL IAM" />
|
||||||
|
<meta property="description" content="Management Platform for ZITADEL IAM" />
|
||||||
|
<meta property="og:image" content="https://www.zitadel.ch/zitadel-social-preview25.png" />
|
||||||
|
|
||||||
<meta property="og:image" content="https://console.zitadel.dev/assets/images/zitadel-logo-dark.svg" />
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:site" content="@zitadel_ch">
|
||||||
|
<meta name="twitter:title" content="ZITADEL Console" />
|
||||||
|
<meta name="twitter:description" content="Management Platform for ZITADEL IAM" />
|
||||||
|
<meta name="twitter:image" content="https://www.zitadel.ch/zitadel-social-preview25.png">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
Loading…
Reference in New Issue
Block a user