mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-13 17:35:12 +00:00
fix(console, e2e): optimize console and activate tests (#4207)
* activate some tests * unskip remove project tests * focus input elements before typing * fix: prune permissions observable * cleanup * remove timeout * remove ngIf * test with chrome * with ngIf * single observable * juhu * maybe better * fix isAllowed response * cleanup Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
co-authored by
Max Peintner
parent
adb5394ae3
commit
f0250a3fdb
@@ -265,7 +265,7 @@ export class AppComponent implements OnDestroy {
|
||||
|
||||
public changedOrg(org: Org.AsObject): void {
|
||||
this.themeService.loadPrivateLabelling();
|
||||
this.authService.zitadelPermissionsChanged.pipe(take(1)).subscribe(() => {
|
||||
this.authService.zitadelPermissions$.pipe(take(1)).subscribe(() => {
|
||||
this.router.navigate(['/org'], { fragment: org.id });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ export class RoleGuard implements CanActivate {
|
||||
constructor(private authService: GrpcAuthService) {}
|
||||
|
||||
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
|
||||
return this.authService.fetchedZitadelPermissions
|
||||
.pipe(filter((permissionsFetched) => !!permissionsFetched))
|
||||
.pipe(switchMap((_) => this.authService.isAllowed(route.data['roles'], route.data['requiresAll'])));
|
||||
return this.authService.isAllowed(route.data['roles'], route.data['requiresAll']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ export class OrgTableComponent {
|
||||
public selectOrg(item: Org.AsObject, event?: any): void {
|
||||
this.authService.setActiveOrg(item);
|
||||
this.themeService.loadPrivateLabelling();
|
||||
this.authService.zitadelPermissionsChanged.pipe(take(1)).subscribe(() => {
|
||||
this.authService.zitadelPermissions$.pipe(take(1)).subscribe(() => {
|
||||
this.router.navigate(['/org'], { fragment: item.id });
|
||||
});
|
||||
}
|
||||
@@ -146,7 +146,7 @@ export class OrgTableComponent {
|
||||
public setAndNavigateToOrg(org: Org.AsObject): void {
|
||||
this.authService.setActiveOrg(org);
|
||||
this.themeService.loadPrivateLabelling();
|
||||
this.authService.zitadelPermissionsChanged.pipe(take(1)).subscribe(() => {
|
||||
this.authService.zitadelPermissions$.pipe(take(1)).subscribe(() => {
|
||||
this.router.navigate(['/org'], { fragment: org.id });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@
|
||||
(filterOpen)="filterOpen = $event"
|
||||
></cnsl-filter-user>
|
||||
<a
|
||||
*ngIf="!selection.hasValue()"
|
||||
[routerLink]="['/users', type === Type.TYPE_HUMAN ? 'create' : 'create-machine']"
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
[disabled]="!canWrite"
|
||||
class="cnsl-action-button"
|
||||
*ngIf="!selection.hasValue()"
|
||||
data-e2e="create-user-button"
|
||||
>
|
||||
<mat-icon class="icon">add</mat-icon>
|
||||
|
||||
@@ -2,91 +2,102 @@ import { Injectable } from '@angular/core';
|
||||
import { SortDirection } from '@angular/material/sort';
|
||||
import { OAuthService } from 'angular-oauth2-oidc';
|
||||
import { BehaviorSubject, from, merge, Observable, of, Subject } from 'rxjs';
|
||||
import { catchError, filter, finalize, map, mergeMap, switchMap, take, timeout } from 'rxjs/operators';
|
||||
import {
|
||||
catchError,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
finalize,
|
||||
map,
|
||||
mergeMap,
|
||||
switchMap,
|
||||
take,
|
||||
timeout,
|
||||
withLatestFrom,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import {
|
||||
AddMyAuthFactorOTPRequest,
|
||||
AddMyAuthFactorOTPResponse,
|
||||
AddMyAuthFactorU2FRequest,
|
||||
AddMyAuthFactorU2FResponse,
|
||||
AddMyPasswordlessLinkRequest,
|
||||
AddMyPasswordlessLinkResponse,
|
||||
AddMyPasswordlessRequest,
|
||||
AddMyPasswordlessResponse,
|
||||
GetMyEmailRequest,
|
||||
GetMyEmailResponse,
|
||||
GetMyLabelPolicyRequest,
|
||||
GetMyLabelPolicyResponse,
|
||||
GetMyPasswordComplexityPolicyRequest,
|
||||
GetMyPasswordComplexityPolicyResponse,
|
||||
GetMyPhoneRequest,
|
||||
GetMyPhoneResponse,
|
||||
GetMyPrivacyPolicyRequest,
|
||||
GetMyPrivacyPolicyResponse,
|
||||
GetMyProfileRequest,
|
||||
GetMyProfileResponse,
|
||||
GetMyUserRequest,
|
||||
GetMyUserResponse,
|
||||
GetSupportedLanguagesRequest,
|
||||
GetSupportedLanguagesResponse,
|
||||
ListMyAuthFactorsRequest,
|
||||
ListMyAuthFactorsResponse,
|
||||
ListMyLinkedIDPsRequest,
|
||||
ListMyLinkedIDPsResponse,
|
||||
ListMyMembershipsRequest,
|
||||
ListMyMembershipsResponse,
|
||||
ListMyMetadataRequest,
|
||||
ListMyMetadataResponse,
|
||||
ListMyPasswordlessRequest,
|
||||
ListMyPasswordlessResponse,
|
||||
ListMyProjectOrgsRequest,
|
||||
ListMyProjectOrgsResponse,
|
||||
ListMyUserChangesRequest,
|
||||
ListMyUserChangesResponse,
|
||||
ListMyUserGrantsRequest,
|
||||
ListMyUserGrantsResponse,
|
||||
ListMyUserSessionsRequest,
|
||||
ListMyUserSessionsResponse,
|
||||
ListMyZitadelPermissionsRequest,
|
||||
ListMyZitadelPermissionsResponse,
|
||||
RemoveMyAuthFactorOTPRequest,
|
||||
RemoveMyAuthFactorOTPResponse,
|
||||
RemoveMyAuthFactorU2FRequest,
|
||||
RemoveMyAuthFactorU2FResponse,
|
||||
RemoveMyAvatarRequest,
|
||||
RemoveMyAvatarResponse,
|
||||
RemoveMyLinkedIDPRequest,
|
||||
RemoveMyLinkedIDPResponse,
|
||||
RemoveMyPasswordlessRequest,
|
||||
RemoveMyPasswordlessResponse,
|
||||
RemoveMyPhoneRequest,
|
||||
RemoveMyPhoneResponse,
|
||||
RemoveMyUserRequest,
|
||||
RemoveMyUserResponse,
|
||||
ResendMyEmailVerificationRequest,
|
||||
ResendMyEmailVerificationResponse,
|
||||
ResendMyPhoneVerificationRequest,
|
||||
ResendMyPhoneVerificationResponse,
|
||||
SendMyPasswordlessLinkRequest,
|
||||
SendMyPasswordlessLinkResponse,
|
||||
SetMyEmailRequest,
|
||||
SetMyEmailResponse,
|
||||
SetMyPhoneRequest,
|
||||
SetMyPhoneResponse,
|
||||
UpdateMyPasswordRequest,
|
||||
UpdateMyPasswordResponse,
|
||||
UpdateMyProfileRequest,
|
||||
UpdateMyProfileResponse,
|
||||
UpdateMyUserNameRequest,
|
||||
UpdateMyUserNameResponse,
|
||||
VerifyMyAuthFactorOTPRequest,
|
||||
VerifyMyAuthFactorOTPResponse,
|
||||
VerifyMyAuthFactorU2FRequest,
|
||||
VerifyMyAuthFactorU2FResponse,
|
||||
VerifyMyPasswordlessRequest,
|
||||
VerifyMyPasswordlessResponse,
|
||||
VerifyMyPhoneRequest,
|
||||
VerifyMyPhoneResponse,
|
||||
AddMyAuthFactorOTPRequest,
|
||||
AddMyAuthFactorOTPResponse,
|
||||
AddMyAuthFactorU2FRequest,
|
||||
AddMyAuthFactorU2FResponse,
|
||||
AddMyPasswordlessLinkRequest,
|
||||
AddMyPasswordlessLinkResponse,
|
||||
AddMyPasswordlessRequest,
|
||||
AddMyPasswordlessResponse,
|
||||
GetMyEmailRequest,
|
||||
GetMyEmailResponse,
|
||||
GetMyLabelPolicyRequest,
|
||||
GetMyLabelPolicyResponse,
|
||||
GetMyPasswordComplexityPolicyRequest,
|
||||
GetMyPasswordComplexityPolicyResponse,
|
||||
GetMyPhoneRequest,
|
||||
GetMyPhoneResponse,
|
||||
GetMyPrivacyPolicyRequest,
|
||||
GetMyPrivacyPolicyResponse,
|
||||
GetMyProfileRequest,
|
||||
GetMyProfileResponse,
|
||||
GetMyUserRequest,
|
||||
GetMyUserResponse,
|
||||
GetSupportedLanguagesRequest,
|
||||
GetSupportedLanguagesResponse,
|
||||
ListMyAuthFactorsRequest,
|
||||
ListMyAuthFactorsResponse,
|
||||
ListMyLinkedIDPsRequest,
|
||||
ListMyLinkedIDPsResponse,
|
||||
ListMyMembershipsRequest,
|
||||
ListMyMembershipsResponse,
|
||||
ListMyMetadataRequest,
|
||||
ListMyMetadataResponse,
|
||||
ListMyPasswordlessRequest,
|
||||
ListMyPasswordlessResponse,
|
||||
ListMyProjectOrgsRequest,
|
||||
ListMyProjectOrgsResponse,
|
||||
ListMyUserChangesRequest,
|
||||
ListMyUserChangesResponse,
|
||||
ListMyUserGrantsRequest,
|
||||
ListMyUserGrantsResponse,
|
||||
ListMyUserSessionsRequest,
|
||||
ListMyUserSessionsResponse,
|
||||
ListMyZitadelPermissionsRequest,
|
||||
ListMyZitadelPermissionsResponse,
|
||||
RemoveMyAuthFactorOTPRequest,
|
||||
RemoveMyAuthFactorOTPResponse,
|
||||
RemoveMyAuthFactorU2FRequest,
|
||||
RemoveMyAuthFactorU2FResponse,
|
||||
RemoveMyAvatarRequest,
|
||||
RemoveMyAvatarResponse,
|
||||
RemoveMyLinkedIDPRequest,
|
||||
RemoveMyLinkedIDPResponse,
|
||||
RemoveMyPasswordlessRequest,
|
||||
RemoveMyPasswordlessResponse,
|
||||
RemoveMyPhoneRequest,
|
||||
RemoveMyPhoneResponse,
|
||||
RemoveMyUserRequest,
|
||||
RemoveMyUserResponse,
|
||||
ResendMyEmailVerificationRequest,
|
||||
ResendMyEmailVerificationResponse,
|
||||
ResendMyPhoneVerificationRequest,
|
||||
ResendMyPhoneVerificationResponse,
|
||||
SendMyPasswordlessLinkRequest,
|
||||
SendMyPasswordlessLinkResponse,
|
||||
SetMyEmailRequest,
|
||||
SetMyEmailResponse,
|
||||
SetMyPhoneRequest,
|
||||
SetMyPhoneResponse,
|
||||
UpdateMyPasswordRequest,
|
||||
UpdateMyPasswordResponse,
|
||||
UpdateMyProfileRequest,
|
||||
UpdateMyProfileResponse,
|
||||
UpdateMyUserNameRequest,
|
||||
UpdateMyUserNameResponse,
|
||||
VerifyMyAuthFactorOTPRequest,
|
||||
VerifyMyAuthFactorOTPResponse,
|
||||
VerifyMyAuthFactorU2FRequest,
|
||||
VerifyMyAuthFactorU2FResponse,
|
||||
VerifyMyPasswordlessRequest,
|
||||
VerifyMyPasswordlessResponse,
|
||||
VerifyMyPhoneRequest,
|
||||
VerifyMyPhoneResponse,
|
||||
} from '../proto/generated/zitadel/auth_pb';
|
||||
import { ChangeQuery } from '../proto/generated/zitadel/change_pb';
|
||||
import { MetadataQuery } from '../proto/generated/zitadel/metadata_pb';
|
||||
@@ -103,9 +114,26 @@ export class GrpcAuthService {
|
||||
private _activeOrgChanged: Subject<Org.AsObject> = new Subject();
|
||||
public user!: Observable<User.AsObject | undefined>;
|
||||
public userSubject: BehaviorSubject<User.AsObject | undefined> = new BehaviorSubject<User.AsObject | undefined>(undefined);
|
||||
private zitadelPermissions: BehaviorSubject<string[]> = new BehaviorSubject(['user.resourceowner']);
|
||||
|
||||
public readonly fetchedZitadelPermissions: BehaviorSubject<boolean> = new BehaviorSubject(false as boolean);
|
||||
private triggerPermissionsRefresh: Subject<void> = new Subject();
|
||||
public zitadelPermissions$: Observable<string[]> = this.triggerPermissionsRefresh.pipe(
|
||||
switchMap(() =>
|
||||
from(this.listMyZitadelPermissions()).pipe(
|
||||
map((rolesResp) => rolesResp.resultList),
|
||||
filter((roles) => !!roles.length),
|
||||
catchError((_) => {
|
||||
return of([]);
|
||||
}),
|
||||
distinctUntilChanged((a, b) => {
|
||||
return JSON.stringify(a.sort()) === JSON.stringify(b.sort());
|
||||
}),
|
||||
finalize(() => {
|
||||
this.fetchedZitadelPermissions.next(true);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
private zitadelPermissions: BehaviorSubject<string[]> = new BehaviorSubject<string[]>([]);
|
||||
public readonly fetchedZitadelPermissions: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
|
||||
private cachedOrgs: Org.AsObject[] = [];
|
||||
|
||||
@@ -114,6 +142,8 @@ export class GrpcAuthService {
|
||||
private oauthService: OAuthService,
|
||||
private storage: StorageService,
|
||||
) {
|
||||
this.zitadelPermissions$.subscribe(this.zitadelPermissions);
|
||||
|
||||
this.user = merge(
|
||||
of(this.oauthService.getAccessToken()).pipe(filter((token) => (token ? true : false))),
|
||||
this.oauthService.events.pipe(
|
||||
@@ -223,19 +253,7 @@ export class GrpcAuthService {
|
||||
}
|
||||
|
||||
private loadPermissions(): void {
|
||||
from(this.listMyZitadelPermissions())
|
||||
.pipe(
|
||||
map((rolesResp) => rolesResp.resultList),
|
||||
catchError((_) => {
|
||||
return of([]);
|
||||
}),
|
||||
finalize(() => {
|
||||
this.fetchedZitadelPermissions.next(true);
|
||||
}),
|
||||
)
|
||||
.subscribe((roles) => {
|
||||
this.zitadelPermissions.next(roles);
|
||||
});
|
||||
this.triggerPermissionsRefresh.next();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,7 +262,17 @@ export class GrpcAuthService {
|
||||
*/
|
||||
public isAllowed(roles: string[] | RegExp[], requiresAll: boolean = false): Observable<boolean> {
|
||||
if (roles && roles.length > 0) {
|
||||
return this.zitadelPermissions.pipe(switchMap((zroles) => of(this.hasRoles(zroles, roles, requiresAll))));
|
||||
return this.fetchedZitadelPermissions.pipe(
|
||||
withLatestFrom(this.zitadelPermissions),
|
||||
filter(([hL, p]) => {
|
||||
return hL === true && !!p.length;
|
||||
}),
|
||||
map(([_, zroles]) => {
|
||||
const what = this.hasRoles(zroles, roles, requiresAll);
|
||||
return what;
|
||||
}),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
} else {
|
||||
return of(false);
|
||||
}
|
||||
@@ -356,10 +384,6 @@ export class GrpcAuthService {
|
||||
return this.grpcService.auth.updateMyProfile(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public get zitadelPermissionsChanged(): Observable<string[]> {
|
||||
return this.zitadelPermissions;
|
||||
}
|
||||
|
||||
public listMyUserSessions(): Promise<ListMyUserSessionsResponse.AsObject> {
|
||||
const req = new ListMyUserSessionsRequest();
|
||||
return this.grpcService.auth.listMyUserSessions(req, null).then((resp) => resp.toObject());
|
||||
|
||||
Reference in New Issue
Block a user