feat: allow global org users to create org and self delete (#2759)

* fix: grant PROJECT_OWNER_VIEWER_GLOBAL org.create permission

* Update authz.yaml

* feat: delete my user

* console things

* lint

* signout after deletion

* stylelint rule

* Update authz.yaml

* Update authz.yaml

* setup step

* role SELF_MANAGEMENT_GLOBAL setup

* fix: change default role on global org

* Apply suggestions from code review

Co-authored-by: Fabi <[email protected]>

* Update console/src/assets/i18n/it.json

Co-authored-by: Fabi <[email protected]>

Co-authored-by: Max Peintner <[email protected]>
Co-authored-by: Fabi <[email protected]>
This commit is contained in:
Livio Amstutz
2021-12-09 08:41:21 +00:00
committed by GitHub
co-authored by Fabi Max Peintner
parent 7ea93bd5b6
commit 43f15953c3
23 changed files with 349 additions and 62 deletions
@@ -1,18 +1,18 @@
<div class="card" [ngClass]="{'nomargin': nomargin}">
<div *ngIf="title || description" class="header" [ngClass]="{'bottom-margin': expanded}">
<div *ngIf="title" class="row">
<h2 class="title">{{title}}</h2>
<span class="fill-space"></span>
<ng-content select="[card-actions]"></ng-content>
<button class="button" type="button" matTooltip="Expand or collapse" mat-icon-button
(click)="expanded = !expanded">
<mat-icon *ngIf="!expanded">keyboard_arrow_down</mat-icon>
<mat-icon *ngIf="expanded">keyboard_arrow_up</mat-icon>
</button>
</div>
<p *ngIf="description" class="desc">{{description}}</p>
</div>
<div class="card-content" *ngIf="expanded" [@openClose]="animate">
<ng-content></ng-content>
<div class="card" [ngClass]="{'nomargin': nomargin, 'warn': warn}">
<div *ngIf="title || description" class="header" [ngClass]="{'bottom-margin': expanded}">
<div *ngIf="title" class="row">
<h2 class="title">{{title}}</h2>
<span class="fill-space"></span>
<ng-content select="[card-actions]"></ng-content>
<button class="button" type="button" matTooltip="Expand or collapse" mat-icon-button
(click)="expanded = !expanded">
<mat-icon *ngIf="!expanded">keyboard_arrow_down</mat-icon>
<mat-icon *ngIf="expanded">keyboard_arrow_up</mat-icon>
</button>
</div>
<p *ngIf="description" class="desc">{{description}}</p>
</div>
<div class="card-content" *ngIf="expanded" [@openClose]="animate">
<ng-content></ng-content>
</div>
</div>
@@ -11,14 +11,13 @@ import { Component, Input } from '@angular/core';
style({ height: '0', opacity: 0 }),
animate('150ms ease-in-out', style({ height: '*', opacity: 1 })),
]),
transition(':leave', [
animate('150ms ease-in-out', style({ height: '0', opacity: 0 })),
]),
transition(':leave', [animate('150ms ease-in-out', style({ height: '0', opacity: 0 }))]),
]),
],
})
export class CardComponent {
@Input() public expanded: boolean = true;
@Input() public warn: boolean = false;
@Input() public title: string = '';
@Input() public description: string = '';
@Input() public animate: boolean = false;
+7 -3
View File
@@ -7,19 +7,23 @@
$background: map-get($theme, background);
$card-background-color: mat.get-color-from-palette($background, card);
$is-dark-theme: map-get($theme, is-dark);
$border-color: if($is-dark-theme, rgba(#8795a1, .2), rgba(#8795a1, .2));
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
$border-selected-color: if($is-dark-theme, #ffffff, #000000);
/* stylelint-enable */
.card {
background-color: $card-background-color;
transition: background-color .3s cubic-bezier(.645, .045, .355, 1);
transition: background-color 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
border: 1px solid $border-color;
box-sizing: border-box;
border-radius: .5rem;
border-radius: 0.5rem;
outline: none;
height: 100%;
&.warn {
border-color: var(--warn);
}
.selection-icon {
opacity: 0;
position: absolute;
@@ -55,6 +55,17 @@
<ng-template cnslHasFeature [hasFeature]="['metadata.user']">
<cnsl-metadata *ngIf="user?.id" [userId]="user.id"></cnsl-metadata>
</ng-template>
<ng-template cnslHasRole [hasRole]="['user.self.delete']">
<cnsl-card title="{{'USER.PAGES.DELETEACCOUNT'| translate}}" [warn]="true">
<p>{{'USER.PAGES.DELETEACCOUNT_DESC'| translate}}</p>
<div class="delete-account-wrapper">
<button color="warn" mat-raised-button (click)="deleteAccount()">{{'USER.PAGES.DELETEACCOUNT_BTN' |
translate}}</button>
</div>
</cnsl-card>
</ng-template>
</div>
<div *ngIf="user" class="side" metainfo>
@@ -60,3 +60,8 @@
.side-padding {
padding-top: 1rem;
}
.delete-account-wrapper {
display: flex;
justify-content: flex-end;
}
@@ -4,7 +4,9 @@ import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { ChangeType } from 'src/app/modules/changes/changes.component';
import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import { Email, Gender, Phone, Profile, User, UserState } from 'src/app/proto/generated/zitadel/user_pb';
import { AuthenticationService } from 'src/app/services/authentication.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ToastService } from 'src/app/services/toast.service';
@@ -36,6 +38,7 @@ export class AuthUserDetailComponent implements OnDestroy {
private toast: ToastService,
public userService: GrpcAuthService,
private dialog: MatDialog,
private auth: AuthenticationService,
) {
this.loading = true;
this.refreshUser();
@@ -252,4 +255,30 @@ export class AuthUserDetailComponent implements OnDestroy {
break;
}
}
public deleteAccount(): void {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'USER.DIALOG.DELETE_BTN',
cancelKey: 'ACTIONS.CANCEL',
titleKey: 'USER.DIALOG.DELETE_TITLE',
descriptionKey: 'USER.DIALOG.DELETE_AUTH_DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().subscribe((resp) => {
if (resp) {
this.userService
.RemoveMyUser()
.then(() => {
this.toast.showInfo('USER.PAGES.DELETEACCOUNT_SUCCESS', true);
this.auth.signout();
})
.catch((error) => {
this.toast.showError(error);
});
}
});
}
}
@@ -56,6 +56,8 @@ import {
RemoveMyPasswordlessResponse,
RemoveMyPhoneRequest,
RemoveMyPhoneResponse,
RemoveMyUserRequest,
RemoveMyUserResponse,
ResendMyEmailVerificationRequest,
ResendMyEmailVerificationResponse,
ResendMyPhoneVerificationRequest,
@@ -400,6 +402,11 @@ export class GrpcAuthService {
return this.grpcService.auth.listMyMemberships(req, null).then((resp) => resp.toObject());
}
public RemoveMyUser(): Promise<RemoveMyUserResponse.AsObject> {
const req = new RemoveMyUserRequest();
return this.grpcService.auth.removeMyUser(req, null).then((resp) => resp.toObject());
}
public getMyEmail(): Promise<GetMyEmailResponse.AsObject> {
const req = new GetMyEmailRequest();
return this.grpcService.auth.getMyEmail(req, null).then((resp) => resp.toObject());