chore!: Introduce ZITADEL v3 (#9645)

This PR summarizes multiple changes specifically only available with
ZITADEL v3:

- feat: Web Keys management
(https://github.com/zitadel/zitadel/pull/9526)
- fix(cmd): ensure proper working of mirror
(https://github.com/zitadel/zitadel/pull/9509)
- feat(Authz): system user support for permission check v2
(https://github.com/zitadel/zitadel/pull/9640)
- chore(license): change from Apache to AGPL
(https://github.com/zitadel/zitadel/pull/9597)
- feat(console): list v2 sessions
(https://github.com/zitadel/zitadel/pull/9539)
- fix(console): add loginV2 feature flag
(https://github.com/zitadel/zitadel/pull/9682)
- fix(feature flags): allow reading "own" flags
(https://github.com/zitadel/zitadel/pull/9649)
- feat(console): add Actions V2 UI
(https://github.com/zitadel/zitadel/pull/9591)

BREAKING CHANGE
- feat(webkey): migrate to v2beta API
(https://github.com/zitadel/zitadel/pull/9445)
- chore!: remove CockroachDB Support
(https://github.com/zitadel/zitadel/pull/9444)
- feat(actions): migrate to v2beta API
(https://github.com/zitadel/zitadel/pull/9489)

---------

Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Stefan Benz <[email protected]>
Co-authored-by: Silvan <[email protected]>
Co-authored-by: Ramon <[email protected]>
Co-authored-by: Elio Bischof <[email protected]>
Co-authored-by: Kenta Yamaguchi <[email protected]>
Co-authored-by: Harsha Reddy <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Max Peintner <[email protected]>
Co-authored-by: Iraq <[email protected]>
Co-authored-by: Florian Forster <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
Fabienne Bühler
2025-04-02 16:53:06 +02:00
committed by GitHub
co-authored by Livio Spring Stefan Benz Silvan Ramon Elio Bischof Kenta Yamaguchi Harsha Reddy Livio Spring Max Peintner Iraq Florian Forster Tim Möhlmann Copilot Max Peintner
parent d14a23ae7e
commit 07ce3b6905
559 changed files with 14578 additions and 7622 deletions
@@ -1,8 +1,8 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, DestroyRef } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { BehaviorSubject, from, Observable, of, Subject } from 'rxjs';
import { catchError, finalize, map, takeUntil } from 'rxjs/operators';
import { BehaviorSubject, defer, from, Observable, of, shareReplay, TimeoutError } from 'rxjs';
import { catchError, finalize, map, timeout } from 'rxjs/operators';
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
import { InstanceDetail, State } from 'src/app/proto/generated/zitadel/instance_pb';
@@ -24,6 +24,7 @@ import {
MESSAGETEXTS,
NOTIFICATIONS,
OIDC,
WEBKEYS,
PRIVACYPOLICY,
SECRETS,
SECURITY,
@@ -34,28 +35,35 @@ import {
EVENTS,
ORGANIZATIONS,
FEATURESETTINGS,
} from '../../modules/settings-list/settings';
ACTIONS,
ACTIONS_TARGETS,
} from 'src/app/modules/settings-list/settings';
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { EnvironmentService } from 'src/app/services/environment.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NewFeatureService } from '../../services/new-feature.service';
import { withLatestFromSynchronousFix } from '../../utils/withLatestFromSynchronousFix';
@Component({
selector: 'cnsl-instance',
templateUrl: './instance.component.html',
styleUrls: ['./instance.component.scss'],
})
export class InstanceComponent implements OnInit, OnDestroy {
public instance?: InstanceDetail.AsObject;
public PolicyComponentServiceType: any = PolicyComponentServiceType;
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
public totalMemberResult: number = 0;
public membersSubject: BehaviorSubject<Member.AsObject[]> = new BehaviorSubject<Member.AsObject[]>([]);
public State: any = State;
export class InstanceComponent {
protected instance?: InstanceDetail.AsObject;
protected readonly PolicyComponentServiceType = PolicyComponentServiceType;
private readonly loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
protected readonly loading$: Observable<boolean> = this.loadingSubject.asObservable();
protected totalMemberResult: number = 0;
protected readonly membersSubject: BehaviorSubject<Member.AsObject[]> = new BehaviorSubject<Member.AsObject[]>([]);
protected readonly State = State;
public id: string = '';
public defaultSettingsList: SidenavSetting[] = [
protected id: string = '';
protected readonly defaultSettingsList: SidenavSetting[] = [
ORGANIZATIONS,
FEATURESETTINGS,
ACTIONS,
ACTIONS_TARGETS,
// notifications
// { showWarn: true, ...NOTIFICATIONS },
NOTIFICATIONS,
@@ -67,7 +75,6 @@ export class InstanceComponent implements OnInit, OnDestroy {
COMPLEXITY,
AGE,
LOCKOUT,
DOMAIN,
// appearance
BRANDING,
@@ -81,23 +88,25 @@ export class InstanceComponent implements OnInit, OnDestroy {
PRIVACYPOLICY,
LANGUAGES,
OIDC,
WEBKEYS,
SECRETS,
SECURITY,
];
public settingsList: Observable<SidenavSetting[]> = of([]);
public customerPortalLink$ = this.envService.env.pipe(map((env) => env.customer_portal));
protected readonly settingsList$: Observable<SidenavSetting[]>;
protected readonly customerPortalLink$ = this.envService.env.pipe(map((env) => env.customer_portal));
private destroy$: Subject<void> = new Subject();
constructor(
public adminService: AdminService,
private dialog: MatDialog,
private toast: ToastService,
protected readonly adminService: AdminService,
private readonly dialog: MatDialog,
private readonly toast: ToastService,
breadcrumbService: BreadcrumbService,
private router: Router,
private authService: GrpcAuthService,
private envService: EnvironmentService,
private readonly router: Router,
private readonly authService: GrpcAuthService,
private readonly envService: EnvironmentService,
activatedRoute: ActivatedRoute,
private readonly destroyRef: DestroyRef,
private readonly featureService: NewFeatureService,
) {
this.loadMembers();
@@ -106,7 +115,6 @@ export class InstanceComponent implements OnInit, OnDestroy {
name: 'Instance',
routerLink: ['/instance'],
});
breadcrumbService.setBreadcrumb([instanceBread]);
this.adminService
@@ -120,12 +128,43 @@ export class InstanceComponent implements OnInit, OnDestroy {
this.toast.showError(error);
});
activatedRoute.queryParams.pipe(takeUntil(this.destroy$)).subscribe((params: Params) => {
const { id } = params;
activatedRoute.queryParamMap.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
const id = params.get('id');
if (id) {
this.id = id;
}
});
this.settingsList$ = this.getSettingsList();
}
private getSettingsList(): Observable<SidenavSetting[]> {
const features$ = this.getFeatures().pipe(shareReplay({ refCount: true, bufferSize: 1 }));
const actionsEnabled$ = features$.pipe(map((features) => features?.actions?.enabled));
return this.authService
.isAllowedMapper(this.defaultSettingsList, (setting) => setting.requiredRoles.admin || [])
.pipe(
withLatestFromSynchronousFix(actionsEnabled$),
map(([settings, actionsEnabled]) =>
settings
.filter((setting) => actionsEnabled || setting.id !== ACTIONS.id)
.filter((setting) => actionsEnabled || setting.id !== ACTIONS_TARGETS.id),
),
);
}
private getFeatures() {
return defer(() => this.featureService.getInstanceFeatures()).pipe(
timeout(1000),
catchError((error) => {
if (!(error instanceof TimeoutError)) {
this.toast.showError(error);
}
return of(undefined);
}),
);
}
public loadMembers(): void {
@@ -185,18 +224,6 @@ export class InstanceComponent implements OnInit, OnDestroy {
}
public showDetail(): void {
this.router.navigate(['/instance', 'members']);
}
ngOnInit(): void {
this.settingsList = this.authService.isAllowedMapper(
this.defaultSettingsList,
(setting) => setting.requiredRoles.admin || [],
);
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
this.router.navigate(['/instance', 'members']).then();
}
}