fix(console): auth response interceptor, new assets, async route guard, pipe modules cleanup, disable custom idp editation for orgs, refresh list on idp creation (#793)
* chore(deps-dev): bump @angular/cli from 10.0.8 to 10.1.3 in /console (#785) Bumps [@angular/cli](https://github.com/angular/angular-cli) from 10.0.8 to 10.1.3. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/compare/v10.0.8...v10.1.3) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @angular-devkit/build-angular in /console (#784) Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1000.8 to 0.1001.3. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/commits) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <max@caos.ch> * chore(deps-dev): bump @angular/language-service in /console (#783) Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 10.1.0 to 10.1.3. - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/10.1.3/packages/language-service) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump stylelint from 13.7.1 to 13.7.2 in /console (#782) Bumps [stylelint](https://github.com/stylelint/stylelint) from 13.7.1 to 13.7.2. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint/compare/13.7.1...13.7.2) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump karma from 5.2.1 to 5.2.3 in /console (#781) Bumps [karma](https://github.com/karma-runner/karma) from 5.2.1 to 5.2.3. - [Release notes](https://github.com/karma-runner/karma/releases) - [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md) - [Commits](https://github.com/karma-runner/karma/compare/v5.2.1...v5.2.3) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump moment from 2.27.0 to 2.29.0 in /console (#780) Bumps [moment](https://github.com/moment/moment) from 2.27.0 to 2.29.0. - [Release notes](https://github.com/moment/moment/releases) - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.27.0...2.29.0) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/node from 14.6.4 to 14.11.2 in /console (#778) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.6.4 to 14.11.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump prettier from 2.1.1 to 2.1.2 in /console (#757) Bumps [prettier](https://github.com/prettier/prettier) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.1.1...2.1.2) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump ts-protoc-gen from 0.12.0 to 0.13.0 in /console (#737) Bumps [ts-protoc-gen](https://github.com/improbable-eng/ts-protoc-gen) from 0.12.0 to 0.13.0. - [Release notes](https://github.com/improbable-eng/ts-protoc-gen/releases) - [Changelog](https://github.com/improbable-eng/ts-protoc-gen/blob/master/CHANGELOG.md) - [Commits](https://github.com/improbable-eng/ts-protoc-gen/compare/0.12.0...0.13.0) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump jasmine-spec-reporter in /console (#762) Bumps [jasmine-spec-reporter](https://github.com/bcaudan/jasmine-spec-reporter) from 5.0.2 to 6.0.0. - [Release notes](https://github.com/bcaudan/jasmine-spec-reporter/releases) - [Changelog](https://github.com/bcaudan/jasmine-spec-reporter/blob/master/CHANGELOG.md) - [Commits](https://github.com/bcaudan/jasmine-spec-reporter/compare/v5.0.2...v6.0.0) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <max@caos.ch> * fix: package * change html lang to translation lang * disable detail view org idp * catch errorcode 16 in auth response interceptor * new icons * refactor pipes, idp table config * fix router guard * lint * allowed commonjs deps * Update console/src/assets/i18n/en.json Co-authored-by: Florian Forster <florian@caos.ch> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <florian@caos.ch> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Florian Forster <florian@caos.ch>
@@ -1,12 +1,12 @@
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { OverlayContainer } from '@angular/cdk/overlay';
|
||||
import { ViewportScroller } from '@angular/common';
|
||||
import { DOCUMENT, ViewportScroller } from '@angular/common';
|
||||
import { Component, HostBinding, Inject, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { MatIconRegistry } from '@angular/material/icon';
|
||||
import { MatDrawer } from '@angular/material/sidenav';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { Router, RouterOutlet } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { LangChangeEvent, TranslateService } from '@ngx-translate/core';
|
||||
import { Observable, of, Subscription } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@@ -70,6 +70,7 @@ export class AppComponent implements OnDestroy {
|
||||
private toast: ToastService,
|
||||
private router: Router,
|
||||
update: UpdateService,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
) {
|
||||
console.log('%cWait!', 'text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; color: #5282c1; font-size: 50px');
|
||||
console.log('%cInserting something here could give attackers access to your zitadel account.', 'color: red; font-size: 18px');
|
||||
@@ -160,6 +161,10 @@ export class AppComponent implements OnDestroy {
|
||||
|
||||
this.isDarkTheme = this.themeService.isDarkTheme;
|
||||
this.isDarkTheme.subscribe(thema => this.onSetTheme(thema ? 'dark-theme' : 'light-theme'));
|
||||
|
||||
this.translate.onLangChange.subscribe((language: LangChangeEvent) => {
|
||||
this.document.documentElement.lang = language.lang;
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
@@ -202,6 +207,8 @@ export class AppComponent implements OnDestroy {
|
||||
this.profile = userprofile;
|
||||
const lang = userprofile.preferredLanguage.match(/en|de/) ? userprofile.preferredLanguage : 'en';
|
||||
this.translate.use(lang);
|
||||
console.log(this.document.documentElement.lang);
|
||||
this.document.documentElement.lang = lang;
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
import { AuthConfig, OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
|
||||
import { QuicklinkModule } from 'ngx-quicklink';
|
||||
import { RegExpPipeModule } from 'src/app/pipes/regexp-pipe.module';
|
||||
import { RegExpPipeModule } from 'src/app/pipes/regexp-pipe/regexp-pipe.module';
|
||||
|
||||
import { environment } from '../environments/environment';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
@@ -32,7 +32,7 @@ import { AccountsCardModule } from './modules/accounts-card/accounts-card.module
|
||||
import { AvatarModule } from './modules/avatar/avatar.module';
|
||||
import { WarnDialogModule } from './modules/warn-dialog/warn-dialog.module';
|
||||
import { SignedoutComponent } from './pages/signedout/signedout.component';
|
||||
import { HasRolePipeModule } from './pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from './pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { GrpcAuthService } from './services/grpc-auth.service';
|
||||
import { GrpcService } from './services/grpc.service';
|
||||
import { AuthInterceptor } from './services/interceptors/auth.interceptor';
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { filter, first, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { GrpcAuthService } from '../services/grpc-auth.service';
|
||||
|
||||
@@ -15,6 +16,11 @@ export class RoleGuard implements CanActivate {
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot,
|
||||
): Observable<boolean> {
|
||||
return this.authService.isAllowed(route.data['roles']);
|
||||
return this.authService.fetchedZitadelPermissions.pipe(
|
||||
filter((permissionsFetched) => !!permissionsFetched),
|
||||
first(),
|
||||
).pipe(
|
||||
switchMap(_ => this.authService.isAllowed(route.data['roles'])),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -4,9 +4,9 @@ import { NgModule } from '@angular/core';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ScrollableModule } from 'src/app/directives/scrollable/scrollable.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { ChangesComponent } from './changes.component';
|
||||
|
||||
|
@@ -1,20 +1,23 @@
|
||||
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
|
||||
[timestamp]="idpResult?.viewTimestamp" [selection]="selection">
|
||||
emitRefreshOnPreviousRoute="/iam/idp/create" [timestamp]="idpResult?.viewTimestamp" [selection]="selection">
|
||||
<ng-template appHasRole [appHasRole]="['iam.write']" actions>
|
||||
<button (click)="deactivateSelectedIdps()" matTooltip="{{'IDP.DEACTIVATE' | translate}}" class="icon-button"
|
||||
mat-icon-button *ngIf="selection.hasValue() && serviceType!=PolicyComponentServiceType.MGMT" [disabled]="disabled">
|
||||
mat-icon-button *ngIf="selection.hasValue() && serviceType!=PolicyComponentServiceType.MGMT"
|
||||
[disabled]="disabled">
|
||||
<mat-icon svgIcon="mdi_account_cancel"></mat-icon>
|
||||
</button>
|
||||
<button (click)="reactivateSelectedIdps()" matTooltip="{{'IDP.ACTIVATE' | translate}}" class="icon-button"
|
||||
mat-icon-button *ngIf="selection.hasValue() && serviceType!=PolicyComponentServiceType.MGMT" [disabled]="disabled">
|
||||
mat-icon-button *ngIf="selection.hasValue() && serviceType!=PolicyComponentServiceType.MGMT"
|
||||
[disabled]="disabled">
|
||||
<mat-icon svgIcon="mdi_account_check_outline"></mat-icon>
|
||||
</button>
|
||||
<button color="warn" (click)="removeSelectedIdps()" matTooltip="{{'IDP.DELETE' | translate}}"
|
||||
class="icon-button" mat-icon-button *ngIf="selection.hasValue() && serviceType!=PolicyComponentServiceType.MGMT" [disabled]="disabled">
|
||||
class="icon-button" mat-icon-button
|
||||
*ngIf="selection.hasValue() && serviceType!=PolicyComponentServiceType.MGMT" [disabled]="disabled">
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
<a class="add-button" [routerLink]="createRouterLink" color="primary" mat-raised-button [disabled]="disabled"
|
||||
*ngIf="serviceType!=PolicyComponentServiceType.MGMT">
|
||||
*ngIf="serviceType!=PolicyComponentServiceType.MGMT">
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
</ng-template>
|
||||
@@ -74,13 +77,22 @@
|
||||
{{idp.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'IDP.TYPE' | translate }} </th>
|
||||
<td class="pointer" mat-cell *matCellDef="let idp">
|
||||
{{'IDP.TYPES.'+idp.providerType | translate }} </td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="data-row" mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||
[routerLink]="row.id ? [serviceType == PolicyComponentServiceType.ADMIN ? '/iam' : '/org', 'idp', row.id ]: null">
|
||||
<tr class="data-row"
|
||||
[ngClass]="{'disabled': serviceType==PolicyComponentServiceType.MGMT && row?.providerType == IdpProviderType.IDPPROVIDERTYPE_SYSTEM}"
|
||||
mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||
[routerLink]="serviceType==PolicyComponentServiceType.ADMIN ? routerLinkForRow(row): null">
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<mat-paginator #paginator class="paginator" [length]="idpResult?.totalResult || 0" [pageSize]="10"
|
||||
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></mat-paginator>
|
||||
</div>
|
||||
</app-refresh-table>
|
||||
</app-refresh-table>
|
@@ -32,6 +32,10 @@
|
||||
|
||||
tr {
|
||||
outline: none;
|
||||
|
||||
&.disabled * {
|
||||
color: #8795a1;
|
||||
}
|
||||
}
|
||||
|
||||
.add-button {
|
||||
@@ -57,14 +61,22 @@ tr {
|
||||
.flex-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 2px 0;
|
||||
width: 250px;
|
||||
|
||||
.key {
|
||||
margin-right: 1rem;
|
||||
font-size: 14px;
|
||||
margin-right: .5rem;
|
||||
font-size: 12px;
|
||||
flex: 1 0 50%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
flex: 1 0 50%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
|
@@ -6,7 +6,7 @@ import { RouterLink } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { IdpSearchResponse as AdminIdpSearchResponse, IdpView as AdminIdpView } from 'src/app/proto/generated/admin_pb';
|
||||
import { IdpView as MgmtIdpView } from 'src/app/proto/generated/management_pb';
|
||||
import { IdpProviderType, IdpView as MgmtIdpView } from 'src/app/proto/generated/management_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';
|
||||
@@ -31,6 +31,7 @@ export class IdpTableComponent implements OnInit {
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public IdpProviderType: any = IdpProviderType;
|
||||
@Input() public displayedColumns: string[] = ['select', 'name', 'config', 'creationDate', 'changeDate', 'state'];
|
||||
|
||||
@Output() public changedSelection: EventEmitter<Array<AdminIdpView.AsObject | MgmtIdpView.AsObject>>
|
||||
@@ -44,6 +45,9 @@ export class IdpTableComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getData(10, 0);
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
this.displayedColumns = ['select', 'name', 'config', 'creationDate', 'changeDate', 'state', 'type'];
|
||||
}
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
@@ -96,9 +100,10 @@ export class IdpTableComponent implements OnInit {
|
||||
// let query: AdminIdpSearchQuery | MgmtIdpSearchQuery;
|
||||
// if (this.service instanceof AdminService) {
|
||||
// query = new AdminIdpSearchQuery();
|
||||
// query.setKey(AdminIdpSearchKey.)
|
||||
// query.setKey(AdminIdpSearchKey.IDPSEARCHKEY_IDP_CONFIG_ID);
|
||||
// } else if (this.service instanceof ManagementService) {
|
||||
// return ['/org', 'idp', 'create'];
|
||||
// query = new MgmtIdpSearchQuery();
|
||||
// query.setKey(MgmtIdpSearchKey.IDPSEARCHKEY_PROVIDER_TYPE);
|
||||
// }
|
||||
|
||||
this.service.SearchIdps(limit, offset).then(resp => {
|
||||
@@ -123,4 +128,15 @@ export class IdpTableComponent implements OnInit {
|
||||
return ['/org', 'idp', 'create'];
|
||||
}
|
||||
}
|
||||
|
||||
public routerLinkForRow(row: MgmtIdpView.AsObject | AdminIdpView.AsObject): any {
|
||||
if (row.id) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
return ['/org', 'idp', row.id];
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
return ['/iam', 'idp', row.id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,8 +11,9 @@ import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
import { TruncatePipeModule } from 'src/app/pipes/truncate-pipe/truncate-pipe.module';
|
||||
|
||||
import { IdpTableComponent } from './idp-table.component';
|
||||
|
||||
@@ -34,6 +35,7 @@ import { IdpTableComponent } from './idp-table.component';
|
||||
RouterModule,
|
||||
RefreshTableModule,
|
||||
HasRoleModule,
|
||||
TruncatePipeModule,
|
||||
],
|
||||
exports: [
|
||||
IdpTableComponent,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<app-detail-layout [backRouterLink]="backroutes" [title]="'ORG.POLICY.LOGIN_POLICY.TITLECREATE' | translate"
|
||||
[description]="'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATE' | translate">
|
||||
[description]="serviceType==PolicyComponentServiceType.MGMT ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '' | translate">
|
||||
<ng-container *ngIf="(['policy.delete'] | hasRole | async) && serviceType == PolicyComponentServiceType.MGMT">
|
||||
<!--<button matTooltip="{{'ORG.POLICY.DELETE' | translate}}" color="warn" (click)="deletePolicy()"
|
||||
mat-stroked-button>
|
||||
@@ -19,14 +19,14 @@
|
||||
<span class="left-desc">{{'ORG.POLICY.DATA.ALLOWREGISTER' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="loginData.allowRegister"
|
||||
[disabled]="serviceType==PolicyComponentServiceType.MGMT">
|
||||
[disabled]="serviceType==PolicyComponentServiceType.MGMT">
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="left-desc">{{'ORG.POLICY.DATA.ALLOWEXTERNALIDP' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [disabled]="serviceType==PolicyComponentServiceType.MGMT"
|
||||
[(ngModel)]="loginData.allowExternalIdp">
|
||||
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl
|
||||
[disabled]="serviceType==PolicyComponentServiceType.MGMT" [(ngModel)]="loginData.allowExternalIdp">
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</div>
|
||||
@@ -35,7 +35,8 @@
|
||||
|
||||
<div class="idps">
|
||||
<div class="idp" *ngFor="let idp of idps">
|
||||
<mat-icon *ngIf="serviceType!=PolicyComponentServiceType.MGMT" (click)="removeIdp(idp)" class="rm">remove_circle</mat-icon>
|
||||
<mat-icon *ngIf="serviceType!=PolicyComponentServiceType.MGMT" (click)="removeIdp(idp)" class="rm">
|
||||
remove_circle</mat-icon>
|
||||
<span>{{idp.name}}</span>
|
||||
<span class="meta">{{ 'IDP.TYPE' | translate }}: {{ 'IDP.TYPES.'+idp.type | translate }}</span>
|
||||
<span class="meta">{{ 'IDP.ID' | translate }}: {{idp.idpConfigId}}</span>
|
||||
@@ -46,16 +47,17 @@
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button (click)="savePolicy()" color="primary" type="submit" [disabled]="serviceType==PolicyComponentServiceType.MGMT"
|
||||
<button (click)="savePolicy()" color="primary" type="submit"
|
||||
[disabled]="serviceType==PolicyComponentServiceType.MGMT"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['org.idp.read']">
|
||||
<app-card title="{{ 'IDP.LIST.TITLE' | translate }}" description="{{ 'IDP.LIST.DESCRIPTION' | translate }}">
|
||||
<app-idp-table [service]="service" [serviceType]="serviceType"
|
||||
[disabled]="(['iam.idp.write'] | hasRole | async) == false">
|
||||
</app-idp-table>
|
||||
</app-card>
|
||||
<app-card title="{{ 'IDP.LIST.TITLE' | translate }}" description="{{ 'IDP.LIST.DESCRIPTION' | translate }}">
|
||||
<app-idp-table [service]="service" [serviceType]="serviceType"
|
||||
[disabled]="(['iam.idp.write'] | hasRole | async) == false">
|
||||
</app-idp-table>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
</app-detail-layout>
|
||||
</app-detail-layout>
|
@@ -2,21 +2,21 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
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 { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { IdpTableModule } from 'src/app/modules/idp-table/idp-table.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { AddIdpDialogModule } from './add-idp-dialog/add-idp-dialog.module';
|
||||
import { LoginPolicyRoutingModule } from './login-policy-routing.module';
|
||||
import { LoginPolicyComponent } from './login-policy.component';
|
||||
import { IdpTableModule } from 'src/app/modules/idp-table/idp-table.module';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LoginPolicyComponent],
|
||||
|
@@ -17,7 +17,7 @@ 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 { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { RefreshTableModule } from '../refresh-table/refresh-table.module';
|
||||
import { ProjectMembersRoutingModule } from './project-members-routing.module';
|
||||
|
@@ -15,9 +15,9 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { RefreshTableModule } from '../refresh-table/refresh-table.module';
|
||||
import { ProjectRoleDetailComponent } from './project-role-detail/project-role-detail.component';
|
||||
|
@@ -6,13 +6,12 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { RefreshTableComponent } from './refresh-table.component';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [RefreshTableComponent],
|
||||
imports: [
|
||||
|
@@ -13,9 +13,9 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { AvatarModule } from '../avatar/avatar.module';
|
||||
import { RefreshTableModule } from '../refresh-table/refresh-table.module';
|
||||
|
@@ -17,7 +17,7 @@ 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 { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { IamMembersRoutingModule } from './iam-members-routing.module';
|
||||
import { IamMembersComponent } from './iam-members.component';
|
||||
|
@@ -24,22 +24,27 @@ const routes: Routes = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'idp/create',
|
||||
loadChildren: () => import('src/app/modules/idp-create/idp-create.module').then(m => m.IdpCreateModule),
|
||||
canActivate: [AuthGuard, RoleGuard],
|
||||
data: {
|
||||
roles: ['iam.idp.write'],
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'idp/:id',
|
||||
loadChildren: () => import('src/app/modules/idp/idp.module').then(m => m.IdpModule),
|
||||
canActivate: [AuthGuard, RoleGuard],
|
||||
data: {
|
||||
roles: ['iam.idp.read'],
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
path: 'idp',
|
||||
children: [
|
||||
{
|
||||
path: 'create',
|
||||
loadChildren: () => import('src/app/modules/idp-create/idp-create.module').then(m => m.IdpCreateModule),
|
||||
canActivate: [AuthGuard, RoleGuard],
|
||||
data: {
|
||||
roles: ['iam.idp.write'],
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
loadChildren: () => import('src/app/modules/idp/idp.module').then(m => m.IdpModule),
|
||||
canActivate: [AuthGuard, RoleGuard],
|
||||
data: {
|
||||
roles: ['iam.idp.read'],
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: `policy/${PolicyComponentType.LOGIN}`,
|
||||
|
@@ -22,9 +22,9 @@ import { ContributorsModule } from 'src/app/modules/contributors/contributors.mo
|
||||
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { FailedEventsComponent } from './failed-events/failed-events.component';
|
||||
import { IamPolicyGridComponent } from './iam-policy-grid/iam-policy-grid.component';
|
||||
|
@@ -11,7 +11,7 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { PasswordComplexityViewModule } from 'src/app/modules/password-complexity-view/password-complexity-view.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { OrgCreateRoutingModule } from './org-create-routing.module';
|
||||
import { OrgCreateComponent } from './org-create.component';
|
||||
|
@@ -17,7 +17,7 @@ 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 { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { OrgMembersRoutingModule } from './org-members-routing.module';
|
||||
import { OrgMembersComponent } from './org-members.component';
|
||||
|
@@ -39,7 +39,6 @@ const routes: Routes = [
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'policy',
|
||||
children: [
|
||||
|
@@ -19,7 +19,7 @@ import { ContributorsModule } from 'src/app/modules/contributors/contributors.mo
|
||||
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { WarnDialogModule } from 'src/app/modules/warn-dialog/warn-dialog.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { ChangesModule } from '../../modules/changes/changes.module';
|
||||
import { AddDomainDialogModule } from './org-detail/add-domain-dialog/add-domain-dialog.module';
|
||||
|
@@ -25,9 +25,9 @@ import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { GrantedProjectDetailComponent } from './granted-project-detail/granted-project-detail.component';
|
||||
import { GrantedProjectGridComponent } from './granted-project-list/granted-project-grid/granted-project-grid.component';
|
||||
|
@@ -24,9 +24,9 @@ import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
|
||||
import { WarnDialogModule } from 'src/app/modules/warn-dialog/warn-dialog.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { ApplicationGridComponent } from './application-grid/application-grid.component';
|
||||
import { ApplicationsComponent } from './applications/applications.component';
|
||||
|
@@ -20,9 +20,9 @@ import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { OwnedProjectGridComponent } from './owned-project-list/owned-project-grid/owned-project-grid.component';
|
||||
import { OwnedProjectListComponent } from './owned-project-list/owned-project-list.component';
|
||||
|
@@ -15,7 +15,7 @@ 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 { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { ProjectGrantDetailRoutingModule } from './project-grant-detail-routing.module';
|
||||
import { ProjectGrantDetailComponent } from './project-grant-detail.component';
|
||||
|
@@ -18,7 +18,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { SearchUserAutocompleteModule } from 'src/app/modules/search-user-autocomplete/search-user-autocomplete.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import {
|
||||
ProjectGrantMembersCreateDialogModule,
|
||||
|
@@ -13,7 +13,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { ProjectGrantCreateRoutingModule } from './project-grant-create-routing.module';
|
||||
import { ProjectGrantCreateComponent } from './project-grant-create.component';
|
||||
|
@@ -2,8 +2,8 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { ShowKeyDialogComponent } from './show-key-dialog.component';
|
||||
|
||||
|
@@ -12,8 +12,8 @@ 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 { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { MembershipDetailComponent } from './membership-detail.component';
|
||||
|
||||
|
@@ -26,9 +26,9 @@ import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
|
||||
import { WarnDialogModule } from 'src/app/modules/warn-dialog/warn-dialog.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { AuthUserDetailComponent } from './auth-user-detail/auth-user-detail.component';
|
||||
import { AuthUserMfaComponent } from './auth-user-detail/auth-user-mfa/auth-user-mfa.component';
|
||||
@@ -37,6 +37,7 @@ import { DialogOtpComponent } from './auth-user-detail/dialog-otp/dialog-otp.com
|
||||
import { ThemeSettingComponent } from './auth-user-detail/theme-setting/theme-setting.component';
|
||||
import { DetailFormMachineModule } from './detail-form-machine/detail-form-machine.module';
|
||||
import { DetailFormModule } from './detail-form/detail-form.module';
|
||||
import { ExternalIdpsComponent } from './external-idps/external-idps.component';
|
||||
import { AddKeyDialogModule } from './machine-keys/add-key-dialog/add-key-dialog.module';
|
||||
import { MachineKeysComponent } from './machine-keys/machine-keys.component';
|
||||
import { ShowKeyDialogModule } from './machine-keys/show-key-dialog/show-key-dialog.module';
|
||||
@@ -45,7 +46,6 @@ import { PasswordComponent } from './password/password.component';
|
||||
import { UserDetailRoutingModule } from './user-detail-routing.module';
|
||||
import { UserDetailComponent } from './user-detail/user-detail.component';
|
||||
import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
import { ExternalIdpsComponent } from './external-idps/external-idps.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@@ -15,7 +15,7 @@ import { AvatarModule } from 'src/app/modules/avatar/avatar.module';
|
||||
import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { UserListRoutingModule } from './user-list-routing.module';
|
||||
import { UserListComponent } from './user-list.component';
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { GrpcAuthService } from '../services/grpc-auth.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
|
||||
@Pipe({
|
||||
name: 'hasRole',
|
17
console/src/app/pipes/truncate-pipe/truncate-pipe.module.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { TruncatePipePipe } from './truncate-pipe.pipe';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [TruncatePipePipe],
|
||||
imports: [
|
||||
CommonModule,
|
||||
],
|
||||
exports: [
|
||||
TruncatePipePipe,
|
||||
],
|
||||
})
|
||||
export class TruncatePipeModule { }
|
13
console/src/app/pipes/truncate-pipe/truncate-pipe.pipe.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'truncate',
|
||||
})
|
||||
export class TruncatePipePipe implements PipeTransform {
|
||||
transform(value: string, ...args: unknown[]): unknown {
|
||||
const limit = args.length > 0 ? parseInt(args[0] as string, 10) : 20;
|
||||
const trail = args.length > 1 ? args[1] : '...';
|
||||
return value.length > limit ? value.substring(0, limit) + trail : value;
|
||||
}
|
||||
|
||||
}
|
@@ -44,6 +44,8 @@ export class GrpcAuthService {
|
||||
private _activeOrgChanged: Subject<Org.AsObject> = new Subject();
|
||||
public user!: Observable<UserProfileView.AsObject>;
|
||||
private zitadelPermissions: BehaviorSubject<string[]> = new BehaviorSubject(['user.resourceowner']);
|
||||
public readonly fetchedZitadelPermissions: BehaviorSubject<boolean> = new BehaviorSubject(false as boolean);
|
||||
|
||||
private cachedOrgs: Org.AsObject[] = [];
|
||||
|
||||
constructor(
|
||||
@@ -125,6 +127,12 @@ export class GrpcAuthService {
|
||||
first(),
|
||||
switchMap(() => from(this.GetMyzitadelPermissions())),
|
||||
map(rolesResp => rolesResp.toObject().permissionsList),
|
||||
catchError(_ => {
|
||||
return of([]);
|
||||
}),
|
||||
finalize(() => {
|
||||
this.fetchedZitadelPermissions.next(true);
|
||||
}),
|
||||
).subscribe(roles => {
|
||||
this.zitadelPermissions.next(roles);
|
||||
});
|
||||
@@ -136,9 +144,7 @@ export class GrpcAuthService {
|
||||
*/
|
||||
public isAllowed(roles: string[] | RegExp[]): Observable<boolean> {
|
||||
if (roles && roles.length > 0) {
|
||||
return this.zitadelPermissions.pipe(switchMap(zroles => {
|
||||
return of(this.hasRoles(zroles, roles));
|
||||
}));
|
||||
return this.zitadelPermissions.pipe(switchMap(zroles => of(this.hasRoles(zroles, roles))));
|
||||
} else {
|
||||
return of(false);
|
||||
}
|
||||
@@ -220,6 +226,10 @@ export class GrpcAuthService {
|
||||
return this.grpcService.auth.updateMyUserProfile(req);
|
||||
}
|
||||
|
||||
public get zitadelPermissionsChanged(): Observable<string[]> {
|
||||
return this.zitadelPermissions;
|
||||
}
|
||||
|
||||
public async getMyUserSessions(): Promise<UserSessionViews> {
|
||||
return this.grpcService.auth.getMyUserSessions(
|
||||
new Empty(),
|
||||
@@ -286,15 +296,15 @@ export class GrpcAuthService {
|
||||
}
|
||||
|
||||
public async SearchExternalIdps(
|
||||
userId: string,
|
||||
limit: number,
|
||||
offset: number,
|
||||
asc?: boolean,
|
||||
userId: string,
|
||||
limit: number,
|
||||
offset: number,
|
||||
asc?: boolean,
|
||||
): Promise<ExternalIDPSearchResponse> {
|
||||
const req = new ExternalIDPSearchRequest();
|
||||
req.setLimit(limit);
|
||||
req.setOffset(offset);
|
||||
return this.grpcService.auth.searchMyExternalIDPs(req);
|
||||
const req = new ExternalIDPSearchRequest();
|
||||
req.setLimit(limit);
|
||||
req.setOffset(offset);
|
||||
return this.grpcService.auth.searchMyExternalIDPs(req);
|
||||
}
|
||||
|
||||
public async AddMfaOTP(): Promise<MfaOtpResponse> {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { PlatformLocation } from '@angular/common';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AuthConfig } from 'angular-oauth2-oidc';
|
||||
|
||||
import { AdminServicePromiseClient } from '../proto/generated/admin_grpc_web_pb';
|
||||
@@ -24,6 +25,8 @@ export class GrpcService {
|
||||
private platformLocation: PlatformLocation,
|
||||
private authenticationService: AuthenticationService,
|
||||
private storageService: StorageService,
|
||||
private dialog: MatDialog,
|
||||
// private toast: ToastService,
|
||||
) { }
|
||||
|
||||
public async loadAppEnvironment(): Promise<any> {
|
||||
@@ -31,9 +34,9 @@ export class GrpcService {
|
||||
.toPromise().then((data: any) => {
|
||||
if (data && data.authServiceUrl && data.mgmtServiceUrl && data.issuer) {
|
||||
const interceptors = {
|
||||
'unaryInterceptors': [
|
||||
new AuthInterceptor(this.authenticationService, this.storageService),
|
||||
unaryInterceptors: [
|
||||
new OrgInterceptor(this.storageService),
|
||||
new AuthInterceptor(this.authenticationService, this.storageService, this.dialog),
|
||||
],
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Request, UnaryInterceptor, UnaryResponse } from 'grpc-web';
|
||||
import { filter, first } from 'rxjs/operators';
|
||||
import { filter, first, take } from 'rxjs/operators';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
|
||||
import { AuthenticationService } from '../authentication.service';
|
||||
import { StorageService } from '../storage.service';
|
||||
@@ -10,8 +12,15 @@ const authorizationKey = 'Authorization';
|
||||
const bearerPrefix = 'Bearer';
|
||||
const accessTokenStorageKey = 'access_token';
|
||||
@Injectable({ providedIn: 'root' })
|
||||
/**
|
||||
* Set the authentication token
|
||||
*/
|
||||
export class AuthInterceptor<TReq = unknown, TResp = unknown> implements UnaryInterceptor<TReq, TResp> {
|
||||
constructor(private authenticationService: AuthenticationService, private storageService: StorageService) { }
|
||||
constructor(
|
||||
private authenticationService: AuthenticationService,
|
||||
private storageService: StorageService,
|
||||
private dialog: MatDialog,
|
||||
) { }
|
||||
|
||||
public async intercept(request: Request<TReq, TResp>, invoker: any): Promise<UnaryResponse<TReq, TResp>> {
|
||||
await this.authenticationService.authenticationChanged.pipe(
|
||||
@@ -24,17 +33,25 @@ export class AuthInterceptor<TReq = unknown, TResp = unknown> implements UnaryIn
|
||||
metadata[authorizationKey] = `${bearerPrefix} ${accessToken}`;
|
||||
|
||||
return invoker(request).then((response: any) => {
|
||||
// const message = response.getResponseMessage();
|
||||
const respMetadata = response.getMetadata();
|
||||
|
||||
// TODO: intercept unauthenticated an authenticate
|
||||
|
||||
// const status = respMetadata['grpc-status'];
|
||||
// console.log(respMetadata, status);
|
||||
// if (status?.code === 16) {
|
||||
// this.authenticationService.authenticate();
|
||||
// }
|
||||
return response;
|
||||
}).catch((error: any) => {
|
||||
console.error('error: ', error);
|
||||
if (error.code === 16) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.LOGIN',
|
||||
titleKey: 'ERRORS.TOKENINVALID.TITLE',
|
||||
descriptionKey: 'ERRORS.TOKENINVALID.DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().pipe(take(1)).subscribe(resp => {
|
||||
if (resp) {
|
||||
this.authenticationService.authenticate(undefined, true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -3,9 +3,7 @@ import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
import { WarnDialogComponent } from '../modules/warn-dialog/warn-dialog.component';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
|
||||
@Injectable({
|
||||
@@ -32,24 +30,8 @@ export class ToastService {
|
||||
|
||||
public showError(grpcError: any): void {
|
||||
const { message, code, metadata } = grpcError;
|
||||
// TODO: remove check for code === 7
|
||||
if (code === 16 || (code === 7 && message === 'invalid token')) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.LOGIN',
|
||||
titleKey: 'ERRORS.TOKENINVALID.TITLE',
|
||||
descriptionKey: 'ERRORS.TOKENINVALID.DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().pipe(take(1)).subscribe(resp => {
|
||||
if (resp) {
|
||||
this.authService.authenticate(undefined, true, true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.showMessage(decodeURI(message), 'close', { duration: 3000 });
|
||||
if (code !== 16) {
|
||||
this.showMessage(decodeURI(message), 'close', { duration: 4000 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -409,7 +409,8 @@
|
||||
"TITLE":"Login Richtlinien",
|
||||
"DESCRIPTION":"Definiere die Loginmethoden für Benutzer",
|
||||
"TITLECREATE":"Definiere die Loginmethoden für Benutzer",
|
||||
"DESCRIPTIONCREATE":"Nutzer können Sich mit den verfügbaren Idps authentifizieren."
|
||||
"DESCRIPTIONCREATEADMIN":"Nutzer können Sich mit den verfügbaren Idps authentifizieren.",
|
||||
"DESCRIPTIONCREATEMGMT":"Nutzer können Sich mit den verfügbaren Idps authentifizieren. Achtung: Es kann von System-, sowie von selbsterstellten Providern Ihrer Organisation gewählt werden."
|
||||
},
|
||||
"BTN_INSTALL":"Installieren",
|
||||
"BTN_EDIT":"Modifizieren",
|
||||
|
@@ -409,7 +409,8 @@
|
||||
"TITLE":"Login Policy",
|
||||
"DESCRIPTION":"Define how Users can be authenticated",
|
||||
"TITLECREATE":"Define how Users can be authenticated",
|
||||
"DESCRIPTIONCREATE":"Users can choose from all of the available identity providers."
|
||||
"DESCRIPTIONCREATEADMIN":"Users can choose from the available identity providers below.",
|
||||
"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."
|
||||
},
|
||||
"BTN_INSTALL":"Setup",
|
||||
"BTN_EDIT":"Modify",
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 13 KiB |
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1026.000000pt" height="1026.000000pt" viewBox="0 0 1026.000000 1026.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,1026.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2786 10150 c-8 -24 -67 -243 -72 -265 -2 -11 -17 -69 -34 -130 -17
|
||||
-60 -59 -218 -94 -350 -36 -132 -89 -332 -119 -445 -31 -113 -67 -248 -81
|
||||
-300 -14 -52 -37 -138 -51 -190 -31 -112 -86 -319 -90 -340 -2 -8 -10 -40 -18
|
||||
-70 -9 -30 -47 -172 -86 -316 -38 -144 -95 -355 -126 -470 -50 -186 -156 -581
|
||||
-185 -689 -6 -22 -15 -56 -20 -75 -8 -29 -175 -651 -184 -685 -2 -5 -6 -23
|
||||
-11 -40 -4 -16 -18 -68 -31 -115 -12 -47 -25 -96 -28 -110 -3 -14 -46 -176
|
||||
-96 -360 -93 -343 -168 -621 -175 -653 -2 -9 -17 -65 -34 -125 -17 -59 -41
|
||||
-150 -55 -202 -13 -52 -63 -239 -110 -415 -48 -176 -102 -381 -122 -455 -20
|
||||
-74 -44 -164 -54 -200 -10 -36 -51 -186 -90 -335 -40 -148 -105 -391 -145
|
||||
-540 -40 -148 -101 -376 -135 -505 -35 -129 -71 -266 -82 -305 -35 -131 -69
|
||||
-260 -73 -279 -3 -10 -16 -60 -31 -110 -14 -50 -28 -99 -30 -109 -2 -10 -6
|
||||
-27 -9 -37 -3 -10 -8 -27 -10 -37 -2 -10 -49 -186 -105 -392 -55 -206 -99
|
||||
-375 -97 -377 1 -2 39 6 82 17 44 12 87 23 95 25 12 3 198 52 260 69 8 2 58
|
||||
16 110 30 52 14 138 37 190 51 52 14 102 28 110 30 8 2 33 8 55 14 22 6 47 12
|
||||
56 14 24 6 279 75 334 91 28 7 138 37 245 65 107 29 209 56 225 61 17 5 82 22
|
||||
145 39 63 17 225 60 360 96 135 36 252 68 260 70 8 1 98 25 200 53 102 27 311
|
||||
83 465 125 377 100 561 150 880 236 105 28 197 53 205 55 26 5 812 215 880
|
||||
235 36 10 126 35 200 54 74 20 221 59 325 87 105 28 197 52 205 54 8 2 58 15
|
||||
110 30 91 25 185 50 350 94 189 49 280 74 340 91 36 11 119 33 185 51 66 17
|
||||
167 44 225 59 138 37 807 216 1080 289 118 32 310 84 425 115 116 30 262 70
|
||||
325 87 63 17 165 44 225 60 61 16 144 38 185 50 41 11 82 22 90 24 8 2 119 31
|
||||
245 65 127 34 237 63 246 65 33 7 104 29 111 34 4 4 -544 558 -1218 1231
|
||||
l-1225 1225 83 38 c473 221 834 631 991 1127 40 127 73 278 82 385 7 74 7 309
|
||||
1 360 -59 472 -225 826 -537 1143 -278 283 -651 473 -1044 532 -44 7 -89 14
|
||||
-100 16 -25 6 -320 5 -360 0 -154 -20 -160 -21 -247 -41 -277 -63 -591 -221
|
||||
-795 -402 -216 -191 -375 -401 -479 -631 l-38 -83 -1227 1227 c-798 798 -1230
|
||||
1223 -1233 1214z m2384 -3623 c0 -36 73 -233 125 -342 46 -93 163 -289 184
|
||||
-305 3 -3 19 -23 36 -45 16 -21 36 -47 45 -55 8 -9 36 -39 61 -66 68 -74 151
|
||||
-147 237 -211 42 -32 79 -61 80 -65 2 -5 8 -8 13 -8 5 0 39 -19 76 -41 124
|
||||
-76 385 -185 487 -203 16 -3 30 -7 32 -8 2 -3 -1095 -301 -1226 -333 -26 -7
|
||||
-231 -61 -335 -90 -55 -15 -107 -28 -115 -30 -8 -2 -59 -15 -113 -30 -54 -16
|
||||
-100 -25 -104 -22 -3 4 -1 23 5 44 5 21 35 133 67 248 56 208 119 445 155 580
|
||||
10 39 44 165 75 280 81 300 86 318 90 335 2 8 27 104 57 212 46 172 67 220 68
|
||||
155z"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
console/src/favicon.png
Normal file
After Width: | Height: | Size: 2.0 KiB |