diff --git a/rest/index.php b/rest/index.php index f07ccefd41928ac3fe943c60015979273cbd93ad..45adcf2884cc474529e80ef5869b6992d121348f 100755 --- a/rest/index.php +++ b/rest/index.php @@ -80,7 +80,6 @@ $app->get('/commitInformation', \SrcCore\controllers\AuthenticationController::c $app->put('/customization', \Configuration\controllers\ConfigurationController::class . ':updateCustomization'); $app->get('/customization/watermark', \Configuration\controllers\ConfigurationController::class . ':getWatermarkConfiguration'); - //Documents $app->post('/documents', \Document\controllers\DocumentController::class . ':create'); $app->get('/documents', \Document\controllers\DocumentController::class . ':get'); diff --git a/src/app/document/controllers/DocumentController.php b/src/app/document/controllers/DocumentController.php index a30411e32f645462f04b7d2af6704717e200768a..994724ad32a62c5dd8517eb67491f5a5e5bf6382 100755 --- a/src/app/document/controllers/DocumentController.php +++ b/src/app/document/controllers/DocumentController.php @@ -586,7 +586,13 @@ class DocumentController return $response->withStatus(400)->withJson(['errors' => 'Action does not exist']); } - $workflow = WorkflowModel::getCurrentStep(['select' => ['id', 'mode', 'user_id', 'signature_mode', 'digital_signature_id'], 'documentId' => $args['id']]); + $workflow = WorkflowModel::getCurrentStep(['select' => ['id', 'mode', 'user_id', 'signature_mode', 'digital_signature_id'], 'documentId' => $args['id']]); + $substitute = UserModel::getById(['id' => $workflow['user_id'], 'select' => ['substitute']]); + + if ($GLOBALS['id'] != ($substitute['substitute'] ?? $workflow['user_id'])) { + return $response->withStatus(403)->withJson(['errors' => 'Current user unauthorized for this step']); + } + $libDir = CoreConfigModel::getLibrariesDirectory(); $loadedXml = CoreConfigModel::getConfig(); $tmpPath = CoreConfigModel::getTmpPath(); diff --git a/src/app/user/controllers/UserController.php b/src/app/user/controllers/UserController.php index 9094d738dc2a940fcae9afe3e48d9581d0ff4dd6..c55f1cd812efdab572f9e8f52eb44201969079d1 100755 --- a/src/app/user/controllers/UserController.php +++ b/src/app/user/controllers/UserController.php @@ -80,15 +80,16 @@ class UserController public function getById(Request $request, Response $response, array $args) { - if ($GLOBALS['id'] != $args['id'] && !PrivilegeController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) { - return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']); - } - if (!Validator::intVal()->notEmpty()->validate($args['id'])) { return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']); } - $user = UserController::getUserInformationsById(['id' => $args['id']]); + if ($GLOBALS['id'] == $args['id'] || PrivilegeController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) { + $user = UserController::getUserInformationsById(['id' => $args['id']]); + } else { + $user = UserModel::getById(['select' => ['id', 'firstname', 'lastname', 'email', 'substitute'], 'id' => $args['id']]); + } + if (empty($user)) { return $response->withStatus(400)->withJson(['errors' => 'User does not exist']); } diff --git a/src/frontend/app/document/document.component.html b/src/frontend/app/document/document.component.html index afb505b3d31d68e4466b7863f8b2860ee938ef8c..99d342f1fee1921f1d529a42b3118c2606cef277 100755 --- a/src/frontend/app/document/document.component.html +++ b/src/frontend/app/document/document.component.html @@ -141,7 +141,7 @@ </ion-footer> <ng-template #rightContent> - <app-visa-workflow [visaWorkflow]="mainDocument.workflow" + <app-visa-workflow [visaWorkflow]="mainDocument.workflow" [userDelegated]="userDelegated" *ngIf="signaturesService.currentToobal == 'visaWorkflow'" style="display: contents;"> </app-visa-workflow> <app-document-list #appDocumentList [currentDocId]="currentDoc" diff --git a/src/frontend/app/document/document.component.ts b/src/frontend/app/document/document.component.ts index 09f62f2fc8eca140c65824b4c7f9d4f554014918..570e678cf031ed6c4d6b00b01293c1ab492520c3 100755 --- a/src/frontend/app/document/document.component.ts +++ b/src/frontend/app/document/document.component.ts @@ -104,6 +104,8 @@ export class DocumentComponent implements OnInit { fileContent: string = ''; + userDelegated: boolean = false; + constructor(private translate: TranslateService, private router: Router, private route: ActivatedRoute, @@ -202,14 +204,14 @@ export class DocumentComponent implements OnInit { this.openSignatures(); } }); + buttons.push({ + text: this.translate.instant('lang.annotateDocument'), + icon: 'receipt-outline', + handler: () => { + this.openNoteEditor(); + } + }); } - buttons.push({ - text: this.translate.instant('lang.annotateDocument'), - icon: 'receipt-outline', - handler: () => { - this.openNoteEditor(); - } - }); /* if (this.originalSize) { buttons.push({ text: 'Zoom taille écran', @@ -296,10 +298,9 @@ export class DocumentComponent implements OnInit { this.signaturesService.initTemplate(this.rightContent, this.viewContainerRef, 'rightContent'); } - ngOnInit(): void { + async ngOnInit(): Promise<void> { this.menu.enable(false, 'right-menu'); this.menu.enable(true, 'left-menu'); - this.route.params.subscribe(params => { if (typeof params['id'] !== 'undefined') { this.loadingController.create({ @@ -309,7 +310,8 @@ export class DocumentComponent implements OnInit { this.load = load; this.load.present(); this.http.get('../rest/documents/' + params['id']).pipe( - tap((data: any) => { + tap(async (data: any) => { + const userDelegated: any = await this.checkSubstitute(data.document.workflow.find((user: any) => user.current)); this.mainDocument = data.document; this.mainDocument.workflow = this.mainDocument.workflow.map((item: any) => { if (item.note) { @@ -330,33 +332,39 @@ export class DocumentComponent implements OnInit { this.menu.enable(true, 'right-menu'); this.initDoc(); - const realUserWorkflow = this.mainDocument.workflow.filter((line: { current: boolean }) => line.current === true); - + const realUserWorkflow = this.mainDocument.workflow.find((line: { current: boolean }) => line.current === true); this.mainDocument.isCertified = this.mainDocument.workflow.filter((line: any) => line.status !== 'REF' && line.status !== 'STOP' && line.mode === 'sign' && line.signatureMode !== 'stamp' && line.processDate !== null).length > 0; - - if (realUserWorkflow.length === 0 || this.mainDocument.readOnly) { - this.actionsList = [ - { - id: 4, - label: 'lang.back', - color: 'medium', - logo: 'chevron-back-outline', - event: 'back' - }, - ]; + this.userDelegated = userDelegated; + const backAction: any[] = [ + { + id: 4, + label: 'lang.back', + color: 'medium', + logo: 'chevron-back-outline', + event: 'back' + }, + ]; + + if (this.mainDocument.readOnly) { + this.actionsList = backAction; this.detailMode = true; - } else { - this.signaturesService.stampLock = this.mainDocument.isCertified && ((realUserWorkflow[0].signatureMode === 'stamp' && realUserWorkflow[0].mode === 'sign') || (realUserWorkflow[0].mode === 'visa')); - if (realUserWorkflow[0].userId !== this.authService.user.id) { - this.http.get('../rest/users/' + realUserWorkflow[0].userId + '/signatures') + } else if (realUserWorkflow?.userId !== this.authService.user.id) { + if (!userDelegated) { + this.actionsList = backAction; + this.detailMode = true; + } + } else if (!this.functionsService.empty(realUserWorkflow)) { + this.signaturesService.stampLock = this.mainDocument.isCertified && ((realUserWorkflow.signatureMode === 'stamp' && realUserWorkflow[0].mode === 'sign') || (realUserWorkflow.mode === 'visa')); + if (realUserWorkflow.userId !== this.authService.user.id) { + this.http.get('../rest/users/' + realUserWorkflow.userId + '/signatures') .subscribe((dataSign: any) => { this.signaturesService.signaturesListSubstituted = dataSign.signatures; }); } else { this.signaturesService.signaturesListSubstituted = []; } - if (realUserWorkflow[0].datePositions.length > 0 && this.functionsService.empty(this.signaturesService.datesContent)) { - realUserWorkflow[0].datePositions.forEach((date: any) => { + if (realUserWorkflow.datePositions.length > 0 && this.functionsService.empty(this.signaturesService.datesContent)) { + realUserWorkflow.datePositions.forEach((date: any) => { if (!this.signaturesService.datesContent[date.page]) { this.signaturesService.datesContent[date.page] = []; } @@ -398,6 +406,24 @@ export class DocumentComponent implements OnInit { }); } + checkSubstitute(currentUser: any) { + if (!this.functionsService.empty(currentUser)) { + return new Promise((resolve) => { + this.http.get('../rest/users/' + currentUser.userId).pipe( + tap((data: any) => { + resolve(data.user.substitute === this.authService.user.id); + }), + catchError((err: any) => { + this.notificationService.handleErrors(err); + return of(false); + }) + ).subscribe(); + }); + } else { + return false; + } + } + renderPdf() { this.http.get('../rest/documents/' + this.docList[this.currentDoc].id + '/content') .subscribe((data: any) => { @@ -824,4 +850,5 @@ export class DocumentComponent implements OnInit { } return res.buffer; } + } diff --git a/src/frontend/app/document/visa-workflow/visa-workflow.component.html b/src/frontend/app/document/visa-workflow/visa-workflow.component.html index 7865a96ae57ea65c58177da8e0b543da78efe20b..d2a2af2ef09a1a8b28555c9e92e0c5ed7e5a3ffa 100644 --- a/src/frontend/app/document/visa-workflow/visa-workflow.component.html +++ b/src/frontend/app/document/visa-workflow/visa-workflow.component.html @@ -46,7 +46,7 @@ <img [src]="diffusion.userPicture"> </ion-avatar> <ion-label> - <p class="secondary" *ngIf="diffusion.current && diffusion.userId !== authService.user.id"> + <p class="secondary" *ngIf="userDelegated && diffusion.current"> {{'lang.substituteMsg' | translate}}</p> <h2 [title]="diffusion.userDisplay" *ngIf="diffusion.userDisplay !== ''">{{diffusion.userDisplay}}</h2> <h2 [title]="diffusion.userDisplay" class="danger" *ngIf="diffusion.userDisplay === ''"> diff --git a/src/frontend/app/document/visa-workflow/visa-workflow.component.ts b/src/frontend/app/document/visa-workflow/visa-workflow.component.ts index e8641779de37155bb84b87278e91cfdeef3714e6..e402789240b1eeb7236de823847f194d5f47f4bd 100644 --- a/src/frontend/app/document/visa-workflow/visa-workflow.component.ts +++ b/src/frontend/app/document/visa-workflow/visa-workflow.component.ts @@ -18,6 +18,7 @@ export class VisaWorkflowComponent implements OnInit { @Input() editMode: boolean = false; @Input() visaWorkflow: any = []; + @Input() userDelegated: boolean = false; @ViewChild(IonReorderGroup) reorderGroup: IonReorderGroup; loading: boolean = false;