Skip to content

Commit

Permalink
feat: login asset acl checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron3S committed Dec 6, 2024
1 parent fdac060 commit 3ee96d6
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 5 deletions.
6 changes: 6 additions & 0 deletions proxy.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
"ws": true,
"changeOrigin": true
},
"/facelive": {
"target": "http://localhost:9999",
"secure": false,
"ws": true,
"changeOrigin": true
},
"/kael": {
"target": "http://localhost:5173",
"secure": false,
Expand Down
1 change: 1 addition & 0 deletions src/app/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ export class ConnectionToken {
is_active: boolean;
date_expired: Date;
is_reusable: boolean;
face_token: string;
from_ticket: {
id: string;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
</mat-dialog-actions>
</div>

<div *ngSwitchCase="'acl_face_verify'">
<mat-dialog-content>
<div>{{ 'Facial recognition is required. Do you want to proceed?' | translate }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button (click)="onCancelFaceVerify()" mat-raised-button>{{ "Cancel" | translate }}</button>
<button (click)="onConfirmFaceVerify()" color="primary" mat-raised-button>{{ "Confirm" | translate }}</button>
</mat-dialog-actions>
</div>

<div *ngSwitchCase="'no_face_feature'">
<mat-dialog-content>
<div class="error-message">No available facial features,go to <a href="/ui/#/profile/index">profile</a>page to bind your facial data</div>
</mat-dialog-content>
<mat-dialog-actions>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>

<div *ngSwitchCase="'face_verify_capture'">
<iframe
*ngIf="faceVerifyUrl"
[src]="faceVerifyUrl"
allow="camera"
sandbox="allow-scripts allow-same-origin"
style="width: 100%; height: 540px;border: none;"></iframe>
</div>

<div *ngSwitchCase="'ticket_review_pending'">
<mat-dialog-content>
<div>
Expand All @@ -41,7 +69,8 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
color="primary"
mat-raised-button
ngxClipboard
>{{ "Copy link" | translate }}</button>
>{{ "Copy link" | translate }}
</button>
</mat-dialog-actions>
</div>

Expand Down Expand Up @@ -74,8 +103,7 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>

<div *ngSwitchCase="'other'">
<mat-dialog-content>
<div class="error-message">{{ otherError }} </div>
>
<div class="error-message">{{ otherError }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
Expand Down
45 changes: 45 additions & 0 deletions src/app/services/connect-token/acl-dialog/acl-dialog.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {I18nService} from '@app/services/i18n';
import {HttpService} from '@app/services/http';
import {ToastrService} from 'ngx-toastr';
import {HttpErrorResponse} from '@angular/common/http';
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';


@Component({
selector: 'elements-acl-dialog',
Expand All @@ -24,10 +26,14 @@ export class ElementACLDialogComponent implements OnInit {
public tokenID: string;
private timerCheckTicket: number;

public faceVerifyUrl: SafeResourceUrl;


constructor(public dialogRef: MatDialogRef<ElementACLDialogComponent>,
private _i18n: I18nService,
private _toastr: ToastrService,
private _http: HttpService,
private sanitizer: DomSanitizer,
@Inject(MAT_DIALOG_DATA) public data: any
) {
}
Expand Down Expand Up @@ -66,6 +72,45 @@ export class ElementACLDialogComponent implements OnInit {
this.closeDialog();
}

onConfirmFaceVerify() {
const successCallback = (connToken: ConnectionToken) => {
if (connToken && connToken.face_token) {
this.faceVerifyUrl = this.sanitizer.bypassSecurityTrustResourceUrl('/facelive/capture?token=' + connToken.face_token);
this.code = 'face_verify_capture';

const timer = setInterval(() => {
this._http.getFaceVerifyState(connToken.face_token).subscribe(async (data) => {
if (data.is_finished) {
clearInterval(timer);
if (!data.success) {
this.code = 'other';
this.otherError = data.error_message;
} else {
const msg = await this._i18n.t('Face verify success');
this._toastr.success(msg);
this.dialogRef.close(connToken);
}
}
});
}, 1000);
}
};
const errorCallback = (error) => {
if (error.error.code === 'no_face_feature') {
this.code = error.error.code;
} else {
this.code = 'other';
this.otherError = error.error.detail;
}
};
this._http.createConnectToken(this.asset, this.connectInfo, false, true).subscribe(successCallback, errorCallback);
}

onCancelFaceVerify() {
this.closeDialog();
}


onConfirmReview() {
const successCallback = (connToken: ConnectionToken) => {
if (connToken && connToken.from_ticket) {
Expand Down
10 changes: 8 additions & 2 deletions src/app/services/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,14 @@ export class HttpService {
return cleanedParams;
}

createConnectToken(asset: Asset, connectData: ConnectData, createTicket = false) {
const params = createTicket ? '?create_ticket=1' : '';
getFaceVerifyState(token: string) {
const url = `/api/v1/authentication/mfa/face/context/?token=${token}`;
return this.get(url);
}

createConnectToken(asset: Asset, connectData: ConnectData, createTicket = false, face_verify = false) {
let params = createTicket ? '?create_ticket=1' : '';
params += face_verify ? '?face_verify=1' : '';
const url = '/api/v1/authentication/connection-token/' + params;
const {account, protocol, manualAuthInfo, connectMethod} = connectData;
const username = account.username.startsWith('@') ? manualAuthInfo.username : account.username;
Expand Down

0 comments on commit 3ee96d6

Please sign in to comment.