Skip to content

Commit d95ccb0

Browse files
authored
Merge pull request #798 from openziti/797-delete-enrollment
Allow deleting of an enrollment from the Identity edit form
2 parents 36e6fcf + 89cf9d9 commit d95ccb0

File tree

9 files changed

+141
-7
lines changed

9 files changed

+141
-7
lines changed

projects/ziti-console-lib/src/lib/features/projectable-forms/identity/identity-form.component.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@
194194
(doRefresh)="refreshIdentity()"
195195
></lib-qr-code>
196196
</div>
197+
</lib-form-field-container>
198+
<lib-form-field-container
199+
*ngIf="isEdit"
200+
[showHeader]="false"
201+
[layout]="'column'"
202+
[contentStyle]="'z-index: 99999999'"
203+
>
197204
<div class="form-field-label-container" style="gap: var(--paddingMedium)">
198205
<div class="form-field-header">
199206
<div class="form-field-title-container">

projects/ziti-console-lib/src/lib/features/qr-code/qr-code.component.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<div class="qr-code-container" [ngClass]="{'modal-view': isModal}">
22
<div *ngIf="!qrOnly" class="qr-code-buttons">
3-
<span class="info-text" *ngIf="hasJWT && !jwtExpired && type !== 'router'">TO REGISTER THIS IDENTITY</span>
4-
<span class="info-text" *ngIf="hasJWT && !jwtExpired && type === 'router'">TO REGISTER THIS ROUTER</span>
5-
<div (click)="identitiesSvc.downloadJWT(jwt, identity.name)" *ngIf="hasJWT && !jwtExpired && type !== 'router'" class="download-button">
3+
<div class="identity-enrollment-container" *ngIf="hasJWT && !jwtExpired && type !== 'router'">
4+
<div (click)="identitiesSvc.downloadJWT(jwt, identity.name)" class="download-button">
65
<div class="download-key"></div>
76
<div>DOWNLOAD ENROLLMENT JWT</div>
87
<div class="tap-to-download icon-ClickIcon"></div>
8+
</div>
9+
<div class="icon-qr qr-code-button qr-code-expandable" (click)="expandQRCode()"></div>
910
</div>
1011
<div (click)="identitiesSvc.copyToken(token)" *ngIf="!jwtExpired && type === 'router'" class="download-button" style="background-color: #232f3e!important;">
1112
<div class="download-key"></div>
@@ -27,15 +28,19 @@
2728
<div>{{mfaReset ? 'MFA RESET SUCCESSFUL' : 'RESET MFA'}}</div>
2829
<div [ngClass]="{spinner: resettingMFA, 'icon-refresh': !resettingMFA, 'tap-to-download': !resettingMFA, 'icon-Icon_Check': mfaReset && !resettingMFA}"></div>
2930
</div>
30-
<span class="info-text" *ngIf="hasJWT && !jwtExpired && type !== 'router'">OR SCAN QR CODE</span>
3131
</div>
3232
<qrcode
33-
*ngIf="!jwtExpired && type !== 'router'"
33+
*ngIf="qrOnly && !jwtExpired && type !== 'router'"
3434
[errorCorrectionLevel]="'M'" [qrdata]="jwt"
3535
[width]="qrCodeSize" (click)="expandQRCode()"
3636
[ngClass]="{'qr-code-expandable': canExpand}"
3737
></qrcode>
3838
<div *ngIf="!qrOnly" class="qr-code-buttons">
39+
<div (click)="identitiesSvc.deleteEnrollment(identity)" *ngIf="hasJWT && type === 'identity'" class="delete-button">
40+
<div class="tap-to-delete icon-Icon_Delete"></div>
41+
<div>DELETE ENROLLMENT</div>
42+
<div class="tap-to-delete icon-Icon_Delete"></div>
43+
</div>
3944
<span class="info-text" *ngIf="!jwtExpired && type === 'router'">OR</span>
4045
<div (click)="identitiesSvc.downloadJWT(jwt, identity.name)" *ngIf="!jwtExpired && type === 'router'" class="download-button">
4146
<div class="download-key"></div>

projects/ziti-console-lib/src/lib/features/qr-code/qr-code.component.scss

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
font-weight: 600;
1010
}
1111

12+
.delete-button,
1213
.download-button {
1314
margin: 0.625rem 0rem;
1415
}
@@ -72,7 +73,7 @@
7273
}
7374

7475
&.modal-view {
75-
width: 31.25rem;
76+
width: 37rem;
7677
background-color: var(--background);
7778
padding: 1.25rem;
7879
border-radius: 0.9375rem;
@@ -92,3 +93,35 @@
9293
}
9394
}
9495
}
96+
97+
.identity-enrollment-container {
98+
display: flex;
99+
flex-direction: row;
100+
align-items: center;
101+
justify-content: space-between;
102+
gap: var(--gapMedium);
103+
104+
.qr-code-button {
105+
width: 3.125rem;
106+
height: 100%;
107+
font-size: 3.125rem;
108+
&:before {
109+
color: var(--tableText);
110+
}
111+
}
112+
}
113+
114+
.delete-button {
115+
filter: grayscale(1);
116+
&:hover {
117+
filter: grayscale(1) brightness(.85);
118+
}
119+
.tap-to-delete {
120+
&.icon-Icon_Delete {
121+
&:before {
122+
font-weight: 600;
123+
color: white;
124+
}
125+
}
126+
}
127+
}

projects/ziti-console-lib/src/lib/features/qr-code/qr-code.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export class QrCodeComponent implements OnChanges {
137137
const data = {
138138
jwt: this.jwt,
139139
expiration: this.expiration,
140-
qrCodeSize: 400,
140+
qrCodeSize: 500,
141141
identity: this.identity,
142142
qrOnly: true
143143
};

projects/ziti-console-lib/src/lib/pages/identities/identities-page.service.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {ExtensionService} from "../../features/extendable/extensions-noop.servic
4141
import {IDENTITY_EXTENSION_SERVICE} from "../../features/projectable-forms/identity/identity-form.service";
4242
import {Router} from "@angular/router";
4343
import {TableCellNameComponent} from "../../features/data-table/cells/table-cell-name/table-cell-name.component";
44+
import {ConfirmComponent} from "../../features/confirm/confirm.component";
4445

4546
@Injectable({
4647
providedIn: 'root'
@@ -570,4 +571,52 @@ export class IdentitiesPageService extends ListPageServiceClass {
570571
this.selectedIdentity = item;
571572
this.sideModalOpen = true;
572573
}
574+
575+
public deleteEnrollment(identity) {
576+
const confirmData = {
577+
appendId: 'DeleteEnrollment',
578+
title: 'Delete Enrollment',
579+
message: `Are you sure you would like to delete the enrollment for this Identity?`,
580+
confirmLabel: 'Yes',
581+
cancelLabel: 'Oops, no get me out of here',
582+
showCancelLink: true,
583+
imageUrl: '../../assets/svgs/Growl_Warning.svg',
584+
};
585+
this.dialogRef = this.dialogForm.open(ConfirmComponent, {
586+
data: confirmData,
587+
autoFocus: false,
588+
});
589+
this.dialogRef.afterClosed().subscribe({
590+
next: (result) => {
591+
if (!result?.confirmed) {
592+
return false;
593+
}
594+
let enrollmentId;
595+
if(!isEmpty(identity?.enrollment?.ott)) {
596+
enrollmentId = identity?.enrollment?.ott.id;
597+
} else if(!isEmpty(identity?.enrollment.ottca)) {
598+
enrollmentId = identity?.enrollment?.ottca.id;
599+
} else if (!isEmpty(identity?.enrollment.updb)) {
600+
enrollmentId = identity?.enrollment?.updb.id;
601+
}
602+
return this.dataService.deleteEnrollment(enrollmentId).then(() => {
603+
const growlerData = new GrowlerModel(
604+
'success',
605+
'Success',
606+
`Enrollment Deleted`,
607+
`Successfully deleted Identity enrollment `,
608+
);
609+
this.growlerService.show(growlerData);
610+
}).catch((error) => {
611+
const growlerData = new GrowlerModel(
612+
'error',
613+
'Error',
614+
`Delete Failed`,
615+
`Failed to delete Identity enrollment token`,
616+
);
617+
this.growlerService.show(growlerData);
618+
});
619+
}
620+
});
621+
}
573622
}

projects/ziti-console-lib/src/lib/services/node-data.service.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,28 @@ export class NodeDataService extends ZitiDataService {
208208
);
209209
}
210210

211+
override deleteEnrollment(enrollmentId: string): Promise<any> {
212+
const nodeServerURL = window.location.origin;
213+
const serviceUrl = nodeServerURL + '/api/deleteEnrollment';
214+
const body = {
215+
id: enrollmentId
216+
}
217+
return firstValueFrom(this.httpClient.post(serviceUrl, body, {}).pipe(
218+
catchError((err: any) => {
219+
const error = "Server Not Accessible";
220+
if (err.code != "ECONNREFUSED") throw({error: err.code});
221+
throw({error: error});
222+
}),
223+
map((results: any) => {
224+
if(!isEmpty(results.error)) {
225+
throw({error: results.error});
226+
}
227+
return results;
228+
})
229+
)
230+
);
231+
}
232+
211233
override reissueEnrollment(id: string, date: string): Promise<any> {
212234
const nodeServerURL = window.location.origin;
213235
const serviceUrl = nodeServerURL + '/api/reissueEnroll';

projects/ziti-console-lib/src/lib/services/ziti-controller-data.service.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,20 @@ export class ZitiControllerDataService extends ZitiDataService {
207207
);
208208
}
209209

210+
override deleteEnrollment(enrollmentId: string): Promise<any> {
211+
const apiVersions = this.settingsService.apiVersions || {};
212+
const prefix = apiVersions["edge-management"]?.v1?.path || '/edge/management/v1';
213+
const url = this.settingsService.settings.selectedEdgeController + `${prefix}/enrollments/${enrollmentId}`;
214+
return firstValueFrom(this.httpClient.delete(url).pipe(
215+
catchError((err: any) => {
216+
const error = "Server Not Accessible";
217+
if (err.code != "ECONNREFUSED") throw({error: err.code});
218+
throw({error: error});
219+
})
220+
)
221+
);
222+
}
223+
210224
override reissueEnrollment(id: string, date): Promise<any> {
211225
const apiVersions = this.settingsService.apiVersions || {};
212226
const prefix = apiVersions["edge-management"]?.v1?.path || '/edge/management/v1';

projects/ziti-console-lib/src/lib/services/ziti-data.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export abstract class ZitiDataService {
6767
abstract delete(type: string, id: string): Promise<any>;
6868
abstract call(url: string): Promise<any>;
6969
abstract resetEnrollment(id: string, date: string): Promise<any>;
70+
abstract deleteEnrollment(enrollmentId: string): Promise<any>
7071
abstract reissueEnrollment(id: string, date: string): Promise<any>;
7172
abstract resetMFA(id: string): Promise<any>;
7273
abstract resetPassword(oldPass, newPass, confirmPass): Promise<any>;

projects/ziti-console-lib/src/lib/shared-assets/styles/global.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,13 +944,15 @@ lib-form-field-container {
944944
}
945945

946946
a {
947+
&.delete-button,
947948
&.download-button {
948949
&:hover {
949950
color: var(--offWhite_ALWAYS)
950951
}
951952
}
952953
}
953954

955+
.delete-button,
954956
.download-button {
955957
display: flex;
956958
flex-direction: row;
@@ -996,6 +998,7 @@ a {
996998
z-index: 10;
997999
}
9981000

1001+
.tap-to-delete,
9991002
.verify-certificate,
10001003
.tap-to-download {
10011004
speak: none;

0 commit comments

Comments
 (0)