Merge pull request #4933 from LibreSign/chore/improve-internal-server-error

chore: improve error message
This commit is contained in:
Samuelson Brito 2025-05-13 11:16:45 -04:00 committed by GitHub
commit 0c44a2b1d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 820 additions and 301 deletions

View file

@ -80,7 +80,7 @@ class FileController extends AEnvironmentAwareController {
* Validate a file returning file data.
*
* @param string $uuid The UUID of the LibreSign file
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{action: int, errors: string[], messages?: array{type: string, message: string}[]}, array{}>
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{action: int, errors: list<array{message: string, title?: string}>, messages?: array{type: string, message: string}[]}, array{}>
*
* 200: OK
* 404: Request failed
@ -101,7 +101,7 @@ class FileController extends AEnvironmentAwareController {
* Validate a file returning file data.
*
* @param int $fileId The identifier value of the LibreSign file
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{action: int, errors: string[], messages?: array{type: string, message: string}[]}, array{}>
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{action: int, errors: list<array{message: string, title?: string}>, messages?: array{type: string, message: string}[]}, array{}>
*
* 200: OK
* 404: Request failed
@ -122,7 +122,7 @@ class FileController extends AEnvironmentAwareController {
* Validate a binary file returning file data.
* Use field 'file' for the file upload
*
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_BAD_REQUEST, array{action: int, errors: string[], messages?: array{type: string, message: string}[]}, array{}>
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_BAD_REQUEST, array{action: int, errors: list<array{message: string, title?: string}>, messages?: array{type: string, message: string}[], message?: string}, array{}>
*
* 200: OK
* 404: Request failed
@ -151,7 +151,7 @@ class FileController extends AEnvironmentAwareController {
$message = $this->l10n->t($e->getMessage());
$return = [
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$message]
'errors' => [['message' => $message]]
];
$statusCode = Http::STATUS_NOT_FOUND;
} catch (\Exception $e) {
@ -170,7 +170,7 @@ class FileController extends AEnvironmentAwareController {
*
* @param string|null $type The type of identifier could be Uuid or FileId
* @param string|int $identifier The identifier value, could be string or integer, if UUID will be a string, if FileId will be an integer
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{action: int, errors: string[], messages?: array{type: string, message: string}[]}, array{}>
* @return DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{action: int, errors: list<array{message: string, title?: string}>, messages?: array{type: string, message: string}[]}, array{}>
*/
private function validate(?string $type = null, $identifier = null): DataResponse {
try {
@ -216,7 +216,7 @@ class FileController extends AEnvironmentAwareController {
$message = $this->l10n->t($e->getMessage());
$return = [
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$message]
'errors' => [['message' => $message]]
];
$statusCode = Http::STATUS_NOT_FOUND;
} catch (\Throwable $th) {
@ -224,7 +224,7 @@ class FileController extends AEnvironmentAwareController {
$this->logger->error($message);
$return = [
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$message]
'errors' => [['message' => $message]]
];
$statusCode = Http::STATUS_NOT_FOUND;
}
@ -452,7 +452,7 @@ class FileController extends AEnvironmentAwareController {
* This will delete the file and all data
*
* @param integer $fileId Node id of a Nextcloud file
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 401: Failed

View file

@ -46,7 +46,7 @@ class FileElementController extends AEnvironmentAwareController {
* @param string $type The type of element to create, sginature, sinitial, date, datetime, text
* @param array{} $metadata Metadata of visible elements to associate with the document
* @param LibresignCoordinate $coordinates Coortinates of a visible element on PDF
* @return DataResponse<Http::STATUS_OK, array{fileElementId: integer}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{errors: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{fileElementId: integer}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{errors: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 404: Failure when create visible element
@ -78,7 +78,7 @@ class FileElementController extends AEnvironmentAwareController {
$this->logger->error($th->getMessage());
return new DataResponse(
[
'errors' => [$th->getMessage()]
'errors' => [['message' => $th->getMessage()]],
],
Http::STATUS_NOT_FOUND
);
@ -96,7 +96,7 @@ class FileElementController extends AEnvironmentAwareController {
* @param string $type The type of element to create, sginature, sinitial, date, datetime, text
* @param array{} $metadata Metadata of visible elements to associate with the document
* @param LibresignCoordinate $coordinates Coortinates of a visible element on PDF
* @return DataResponse<Http::STATUS_OK, array{fileElementId: integer}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{errors: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{fileElementId: integer}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{errors: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 404: Failure when patch visible element
@ -115,7 +115,7 @@ class FileElementController extends AEnvironmentAwareController {
*
* @param string $uuid UUID of sign request. The signer UUID is what the person receives via email when asked to sign. This is not the file UUID.
* @param integer $elementId ID of visible element. Each element has an ID that is returned on validation endpoints.
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{errors: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{errors: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 404: Failure when delete visible element or file not found
@ -136,7 +136,7 @@ class FileElementController extends AEnvironmentAwareController {
$this->logger->error($th->getMessage());
return new DataResponse(
[
'errors' => [$th->getMessage()]
'errors' => [['message' => $th->getMessage()]],
],
Http::STATUS_NOT_FOUND
);

View file

@ -43,7 +43,7 @@ trait LibresignTrait {
} catch (DoesNotExistException|LibresignException $e) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('Invalid UUID')],
'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
]), AppFrameworkHttp::STATUS_NOT_FOUND);
}
}

View file

@ -196,7 +196,7 @@ class PageController extends AEnvironmentPageAwareController {
} catch (LibresignException $e) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('Invalid UUID')],
'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
]), Http::STATUS_NOT_FOUND);
}
}
@ -349,7 +349,7 @@ class PageController extends AEnvironmentPageAwareController {
} catch (DoesNotExistException $e) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('Invalid UUID')],
'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
]), Http::STATUS_NOT_FOUND);
}
$this->initialState->provideInitialState('action', JSActions::ACTION_SIGN_ACCOUNT_FILE);
@ -564,7 +564,7 @@ class PageController extends AEnvironmentPageAwareController {
$this->fileService->setFile($libresignFile);
} catch (DoesNotExistException $e) {
$this->initialState->provideInitialState('action', JSActions::ACTION_DO_NOTHING);
$this->initialState->provideInitialState('errors', [$this->l10n->t('Invalid UUID')]);
$this->initialState->provideInitialState('errors', [['message' => $this->l10n->t('Invalid UUID')]]);
}
}
if ($this->userSession->isLoggedIn()) {

View file

@ -53,7 +53,7 @@ class RequestSignatureController extends AEnvironmentAwareController {
* @param string $name The name of file to sign
* @param string|null $callback URL that will receive a POST after the document is signed
* @param integer|null $status Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
* @return DataResponse<Http::STATUS_OK, array{data: LibresignValidateFile, message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{message?: string, action?: integer, errors?: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{data: LibresignValidateFile, message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{message?: string, action?: integer, errors?: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 422: Unauthorized
@ -111,7 +111,7 @@ class RequestSignatureController extends AEnvironmentAwareController {
* @param LibresignVisibleElement[]|null $visibleElements Visible elements on document
* @param LibresignNewFile|array<empty>|null $file File object.
* @param integer|null $status Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
* @return DataResponse<Http::STATUS_OK, array{message: string, data: LibresignValidateFile}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{message?: string, action?: integer, errors?: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{message: string, data: LibresignValidateFile}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{message?: string, action?: integer, errors?: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 422: Unauthorized
@ -170,7 +170,7 @@ class RequestSignatureController extends AEnvironmentAwareController {
*
* @param integer $fileId Node id of a Nextcloud file
* @param integer $signRequestId The sign request id
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 401: Failed
@ -213,7 +213,7 @@ class RequestSignatureController extends AEnvironmentAwareController {
* You can only request exclusion as any sign
*
* @param integer $fileId Node id of a Nextcloud file
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: string[]}, array{}>
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
* 401: Failed

View file

@ -57,7 +57,7 @@ class SignFileController extends AEnvironmentAwareController implements ISignatu
* @param array<string, mixed> $elements List of visible elements
* @param string $identifyValue Identify value
* @param string $token Token, commonly send by email
* @return DataResponse<Http::STATUS_OK, array{action: integer, message: string, file: array{uuid: string}}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: string[], redirect?: string}, array{}>
* @return DataResponse<Http::STATUS_OK, array{action: integer, message: string, file: array{uuid: string}}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: list<array{message: string, title?: string}>, redirect?: string}, array{}>
*
* 200: OK
* 404: Invalid data
@ -80,7 +80,7 @@ class SignFileController extends AEnvironmentAwareController implements ISignatu
* @param array<string, mixed> $elements List of visible elements
* @param string $identifyValue Identify value
* @param string $token Token, commonly send by email
* @return DataResponse<Http::STATUS_OK, array{action: integer, message: string, file: array{uuid: string}}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: string[], redirect?: string}, array{}>
* @return DataResponse<Http::STATUS_OK, array{action: integer, message: string, file: array{uuid: string}}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: list<array{message: string, title?: string}>, redirect?: string}, array{}>
*
* 200: OK
* 404: Invalid data
@ -96,7 +96,7 @@ class SignFileController extends AEnvironmentAwareController implements ISignatu
}
/**
* @return DataResponse<Http::STATUS_OK, array{action: integer, message: string, file: array{uuid: string}}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: string[], redirect?: string}, array{}>
* @return DataResponse<Http::STATUS_OK, array{action: integer, message: string, file: array{uuid: string}}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{action: integer, errors: list<array{message: string, title?: string}>, redirect?: string}, array{}>
*/
public function sign(string $method, array $elements = [], string $identifyValue = '', string $token = '', ?int $fileId = null, ?string $signRequestUuid = null): DataResponse {
try {
@ -143,36 +143,49 @@ class SignFileController extends AEnvironmentAwareController implements ISignatu
Http::STATUS_OK
);
} catch (LibresignException $e) {
return new DataResponse(
[
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$e->getMessage()]
],
Http::STATUS_UNPROCESSABLE_ENTITY
);
$message = $e->getMessage();
if ($message === 'Password to sign not defined. Create a password to sign') {
$action = JSActions::ACTION_CREATE_SIGNATURE_PASSWORD;
} else {
$action = JSActions::ACTION_DO_NOTHING;
}
$data = [
'action' => $action,
'errors' => [['message' => $e->getMessage()]],
];
} catch (\Throwable $th) {
$message = $th->getMessage();
$action = JSActions::ACTION_DO_NOTHING;
$data = [
'action' => JSActions::ACTION_DO_NOTHING,
];
switch ($message) {
case 'Password to sign not defined. Create a password to sign':
$action = JSActions::ACTION_CREATE_SIGNATURE_PASSWORD;
// no break
case 'Host violates local access rules.':
case 'Certificate Password Invalid.':
case 'Certificate Password is Empty.':
$message = $this->l10n->t($message);
$data['errors'] = [['message' => $this->l10n->t($message)]];
break;
default:
$this->logger->error($message);
$this->logger->error(json_encode($th->getTrace()));
$message = $this->l10n->t('Internal error. Contact admin.');
$this->logger->error($message, ['exception' => $th]);
$data['errors'] = [[
'message' =>
sprintf(<<<MESSAGE
The server was unable to complete your request.
If this happens again, please send the technical details below to the server administrator.
## Technical details:
**Remote Address**: %s
**Request ID**: %s
**Message**: %s
MESSAGE,
$this->request->getRemoteAddress(),
$this->request->getId(),
$message,
),
'title' => $this->l10n->t('Internal Server Error'),
]];
}
}
return new DataResponse(
[
'action' => $action,
'errors' => [$message]
],
$data,
Http::STATUS_UNPROCESSABLE_ENTITY
);
}

View file

@ -449,7 +449,7 @@ class ValidateHelper {
throw new LibresignException(
json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('You are not allowed to request signing')],
'errors' => [['message' => $this->l10n->t('You are not allowed to request signing')]],
]),
Http::STATUS_UNPROCESSABLE_ENTITY,
);
@ -459,7 +459,7 @@ class ValidateHelper {
throw new LibresignException(
json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('You are not allowed to request signing')],
'errors' => [['message' => $this->l10n->t('You are not allowed to request signing')]],
]),
Http::STATUS_UNPROCESSABLE_ENTITY,
);
@ -642,7 +642,7 @@ class ValidateHelper {
} catch (DoesNotExistException $e) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('Invalid UUID')],
'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
]));
}
}
@ -654,7 +654,7 @@ class ValidateHelper {
if (!$uuid || !preg_match('/^[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}$/i', $uuid)) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('Invalid UUID')],
'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
]), Http::STATUS_NOT_FOUND);
}
}

View file

@ -153,7 +153,7 @@ abstract class AbstractIdentifyMethod implements IIdentifyMethod {
if (count($fileToSign) < 1) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->identifyService->getL10n()->t('File not found')],
'errors' => [['message' => $this->identifyService->getL10n()->t('File not found')]],
]));
}
}
@ -170,7 +170,7 @@ abstract class AbstractIdentifyMethod implements IIdentifyMethod {
if ($expirationDate < $now) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->identifyService->getL10n()->t('Link expired.')],
'errors' => [['message' => $this->identifyService->getL10n()->t('Link expired.')]],
]));
}
}
@ -271,7 +271,7 @@ abstract class AbstractIdentifyMethod implements IIdentifyMethod {
) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_REDIRECT,
'errors' => [$this->identifyService->getL10n()->t('File already signed.')],
'errors' => [['message' => $this->identifyService->getL10n()->t('File already signed.')]],
'redirect' => $this->identifyService->getUrlGenerator()->linkToRoute(
'libresign.page.validationFilePublic',
['uuid' => $signRequest->getUuid()]

View file

@ -93,7 +93,7 @@ class Account extends AbstractIdentifyMethod {
if (empty($signer) || count($signer) > 1) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->identifyService->getL10n()->t('Invalid user')],
'errors' => [['message' => $this->identifyService->getL10n()->t('Invalid user')]],
]));
}
$signer = current($signer);
@ -105,7 +105,7 @@ class Account extends AbstractIdentifyMethod {
if ($this->userSession->getUser() !== $signer) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->identifyService->getL10n()->t('Invalid user')],
'errors' => [['message' => $this->identifyService->getL10n()->t('Invalid user')]],
]));
}
}

View file

@ -122,7 +122,7 @@ class Email extends AbstractIdentifyMethod {
}
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->identifyService->getL10n()->t('Invalid user')],
'errors' => [['message' => $this->identifyService->getL10n()->t('Invalid user')]],
]));
}
}
@ -176,7 +176,7 @@ class Email extends AbstractIdentifyMethod {
if (!$settings['can_create_account']) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_SHOW_ERROR,
'errors' => [$this->identifyService->getL10n()->t('It is not possible to create new accounts.')],
'errors' => [['message' => $this->identifyService->getL10n()->t('It is not possible to create new accounts.')]],
]));
}
}

View file

@ -41,7 +41,7 @@ class EmailToken extends AbstractSignatureMethod implements IToken {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->identifyService->getL10n()->t('Invalid email')],
'errors' => [['message' => $this->identifyService->getL10n()->t('Invalid email')]],
]));
}
$return = parent::toArray();

View file

@ -677,7 +677,7 @@ class SignFileService {
if (count($fileToSign) < 1) {
throw new LibresignException(json_encode([
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$this->l10n->t('File not found')],
'errors' => [['message' => $this->l10n->t('File not found')]],
]), AppFrameworkHttp::STATUS_NOT_FOUND);
}
/** @var File */

View file

@ -3554,7 +3554,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3703,7 +3714,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3842,7 +3864,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3862,6 +3895,9 @@
}
}
}
},
"message": {
"type": "string"
}
}
}
@ -3906,7 +3942,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3926,6 +3973,9 @@
}
}
}
},
"message": {
"type": "string"
}
}
}
@ -4646,7 +4696,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -4820,7 +4881,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -4999,7 +5071,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -5129,7 +5212,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -5839,7 +5933,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6022,7 +6127,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6208,7 +6324,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6384,7 +6511,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6574,7 +6712,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"redirect": {
@ -6768,7 +6917,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"redirect": {

View file

@ -3458,7 +3458,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3607,7 +3618,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3746,7 +3768,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3766,6 +3799,9 @@
}
}
}
},
"message": {
"type": "string"
}
}
}
@ -3810,7 +3846,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"messages": {
@ -3830,6 +3877,9 @@
}
}
}
},
"message": {
"type": "string"
}
}
}
@ -4550,7 +4600,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -4724,7 +4785,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -4903,7 +4975,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -5033,7 +5116,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -5743,7 +5837,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -5926,7 +6031,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6112,7 +6228,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6288,7 +6415,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
@ -6478,7 +6616,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"redirect": {
@ -6672,7 +6821,18 @@
"errors": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
},
"redirect": {

212
package-lock.json generated
View file

@ -10,7 +10,7 @@
"license": "agpl",
"dependencies": {
"@fontsource/dancing-script": "^5.2.5",
"@libresign/vue-pdf-editor": "^1.4.5",
"@libresign/vue-pdf-editor": "^1.4.6",
"@marionebl/option": "^1.0.8",
"@mdi/js": "^7.4.47",
"@mdi/svg": "^7.4.47",
@ -1680,9 +1680,9 @@
}
},
"node_modules/@cantoo/pdf-lib": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@cantoo/pdf-lib/-/pdf-lib-2.3.2.tgz",
"integrity": "sha512-mTDE/pRsg+dj1+arXD07HQS4Rkjtw5rN9Rn7ZdNo5Fjz2703SC8ea5SV5PMncWd6aNM5yrDm0P177YvEsjd8TQ==",
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@cantoo/pdf-lib/-/pdf-lib-2.4.1.tgz",
"integrity": "sha512-YAheO4lZK5HqOH6pi9TlO2jNys2Sfp8/5bAoIO0jctErBCRxu3x58uMsv/C4dc0raKZB3pb1jobRMhFuFy/eCA==",
"license": "MIT",
"dependencies": {
"@pdf-lib/standard-fonts": "^1.0.0",
@ -1690,7 +1690,8 @@
"color": "^4.2.3",
"crypto-js": "^4.2.0",
"node-html-better-parser": "^1.4.0",
"pako": "^1.0.11"
"pako": "^1.0.11",
"tslib": ">=2"
}
},
"node_modules/@csstools/css-parser-algorithms": {
@ -2642,9 +2643,9 @@
"peer": true
},
"node_modules/@libresign/vue-pdf-editor": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@libresign/vue-pdf-editor/-/vue-pdf-editor-1.4.5.tgz",
"integrity": "sha512-ntt3JWlXSXuaQzH7wzdLlgD13fKEReTaQbEMw0WkFyNFzCHfQs2PmMHrz4vLyX1qGFcu4k7gHcJmnbForJ6eog==",
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/@libresign/vue-pdf-editor/-/vue-pdf-editor-1.4.6.tgz",
"integrity": "sha512-Eg7UvjQQS3yGZ6YPIBgZo/PsP3oY8WZcp28O8VnMPRf/CESAZvg9CJy33f5W94l6XcwQRUUakIOVR0daBsP1UQ==",
"license": "MIT",
"dependencies": {
"@cantoo/pdf-lib": "^2.2.3",
@ -2652,7 +2653,7 @@
"core-js": "^3.38.1",
"downloadjs": "^1.4.7",
"pdfjs-dist": "^4.7.76",
"pdfkit": "^0.15.0",
"pdfkit": "^0.16.0",
"vue-material-design-icons": "^5.3.1"
}
},
@ -3929,12 +3930,12 @@
"peer": true
},
"node_modules/@swc/helpers": {
"version": "0.3.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz",
"integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==",
"license": "MIT",
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
"integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.4.0"
"tslib": "^2.8.0"
}
},
"node_modules/@tybys/wasm-util": {
@ -5425,7 +5426,9 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
"integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3",
"is-array-buffer": "^3.0.5"
@ -5628,7 +5631,9 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
@ -6223,7 +6228,9 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
@ -6254,7 +6261,9 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
@ -7102,38 +7111,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/deep-equal": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
"integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
"license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.0",
"call-bind": "^1.0.5",
"es-get-iterator": "^1.1.3",
"get-intrinsic": "^1.2.2",
"is-arguments": "^1.1.1",
"is-array-buffer": "^3.0.2",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.2",
"isarray": "^2.0.5",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"object.assign": "^4.1.4",
"regexp.prototype.flags": "^1.5.1",
"side-channel": "^1.0.4",
"which-boxed-primitive": "^1.0.2",
"which-collection": "^1.0.1",
"which-typed-array": "^1.1.13"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@ -7178,7 +7155,9 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -7209,7 +7188,9 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
@ -7720,26 +7701,6 @@
"node": ">= 0.4"
}
},
"node_modules/es-get-iterator": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
"integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.3",
"has-symbols": "^1.0.3",
"is-arguments": "^1.1.1",
"is-map": "^2.0.2",
"is-set": "^2.0.2",
"is-string": "^1.0.7",
"isarray": "^2.0.5",
"stop-iteration-iterator": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es-module-lexer": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
@ -9170,19 +9131,19 @@
}
},
"node_modules/fontkit": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz",
"integrity": "sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
"integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
"license": "MIT",
"dependencies": {
"@swc/helpers": "^0.3.13",
"@swc/helpers": "^0.5.12",
"brotli": "^1.3.2",
"clone": "^2.1.2",
"deep-equal": "^2.0.5",
"dfa": "^1.2.0",
"restructure": "^2.0.1",
"fast-deep-equal": "^3.1.3",
"restructure": "^3.0.0",
"tiny-inflate": "^1.0.3",
"unicode-properties": "^1.3.1",
"unicode-properties": "^1.4.0",
"unicode-trie": "^2.0.0"
}
},
@ -9190,7 +9151,9 @@
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"is-callable": "^1.2.7"
},
@ -9309,7 +9272,9 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true,
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -9602,7 +9567,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
"integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -9624,7 +9591,9 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
@ -10197,7 +10166,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
"integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"es-errors": "^1.3.0",
"hasown": "^2.0.2",
@ -10245,7 +10216,9 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
@ -10261,7 +10234,9 @@
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
"integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@ -10305,7 +10280,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
"integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"has-bigints": "^1.0.2"
},
@ -10334,7 +10311,9 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
"integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
@ -10398,7 +10377,9 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -10446,7 +10427,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
@ -10568,7 +10551,9 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
"integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -10623,7 +10608,9 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
"integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
@ -10673,7 +10660,9 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
@ -10703,7 +10692,9 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
"integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -10715,7 +10706,9 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
"integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3"
},
@ -10730,7 +10723,9 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
"integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
@ -10761,7 +10756,9 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
"integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"has-symbols": "^1.1.0",
@ -10795,7 +10792,9 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
"integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -10824,7 +10823,9 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
"integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3",
"get-intrinsic": "^1.2.6"
@ -10857,7 +10858,9 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"license": "MIT"
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/isexe": {
"version": "2.0.0",
@ -12277,7 +12280,9 @@
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -12289,7 +12294,9 @@
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
@ -12305,7 +12312,9 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
}
@ -12314,7 +12323,9 @@
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@ -12800,15 +12811,15 @@
}
},
"node_modules/pdfkit": {
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.15.2.tgz",
"integrity": "sha512-s3GjpdBFSCaeDSX/v73MI5UsPqH1kjKut2AXCgxQ5OH10lPVOu5q5vLAG0OCpz/EYqKsTSw1WHpENqMvp43RKg==",
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.16.0.tgz",
"integrity": "sha512-oXMxkIqXH4uTAtohWdYA41i/f6i2ReB78uhgizN8H4hJEpgR3/Xjy3iu2InNAuwCIabN3PVs8P1D6G4+W2NH0A==",
"license": "MIT",
"dependencies": {
"crypto-js": "^4.2.0",
"fontkit": "^1.8.1",
"fontkit": "^2.0.4",
"jpeg-exif": "^1.1.4",
"linebreak": "^1.0.2",
"linebreak": "^1.1.0",
"png-js": "^1.0.0"
}
},
@ -12973,7 +12984,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 0.4"
}
@ -13547,7 +13560,9 @@
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
@ -13927,9 +13942,9 @@
}
},
"node_modules/restructure": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz",
"integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
"integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
"license": "MIT"
},
"node_modules/retry": {
@ -14085,7 +14100,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@ -14436,7 +14453,9 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@ -14453,7 +14472,9 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@ -14566,7 +14587,9 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
@ -14585,7 +14608,9 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
@ -14601,7 +14626,9 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@ -14619,7 +14646,9 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@ -14867,19 +14896,6 @@
"node": ">= 0.8"
}
},
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
"integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"internal-slot": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/stream-browserify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
@ -17190,7 +17206,9 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
"integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"is-bigint": "^1.1.0",
"is-boolean-object": "^1.2.1",
@ -17238,7 +17256,9 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
"integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"is-map": "^2.0.3",
"is-set": "^2.0.3",
@ -17256,7 +17276,9 @@
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",

View file

@ -21,7 +21,7 @@
},
"dependencies": {
"@fontsource/dancing-script": "^5.2.5",
"@libresign/vue-pdf-editor": "^1.4.5",
"@libresign/vue-pdf-editor": "^1.4.6",
"@marionebl/option": "^1.0.8",
"@mdi/js": "^7.4.47",
"@mdi/svg": "^7.4.47",

View file

@ -15,7 +15,7 @@
:show-rename="false"
:show-save-btn="false"
:save-to-upload="false"
:init-file-src="fileSrc"
:init-file="file"
:init-image-scale="1"
:seal-image-show="false"
@pdf-editor:end-init="endInit">
@ -49,10 +49,9 @@ export default {
Signature,
},
props: {
fileSrc: {
type: String,
default: '',
require: true,
file: {
type: File,
required: true,
},
readOnly: {
type: Boolean,

View file

@ -255,7 +255,7 @@ export default {
if (response?.data?.ocs?.data?.message) {
showError(response.data.ocs.data.message)
} else if (response?.data?.ocs?.data?.errors) {
response.data.ocs.data.errors.forEach(error => showError(error))
response.data.ocs.data.errors.forEach(error => showError(error.message))
}
})
this.hasLoading = false

View file

@ -97,7 +97,7 @@ export const useFilesStore = function(...args) {
return false
}
return file.signers
.filter(signer => signer.signed > 0).length > 0
.filter(signer => signer.signed?.length > 0).length > 0
},
isFullSigned(file) {
file = this.getFile(file)
@ -106,7 +106,7 @@ export const useFilesStore = function(...args) {
}
return file.signers.length > 0
&& file.signers
.filter(signer => signer.signed > 0).length === file.signers.length
.filter(signer => signer.signed?.length > 0).length === file.signers.length
},
canSign(file) {
file = this.getFile(file)
@ -114,7 +114,7 @@ export const useFilesStore = function(...args) {
&& file.status > 0
&& file?.signers?.filter(signer => signer.me).length > 0
&& file?.signers?.filter(signer => signer.me)
.filter(signer => signer.signed > 0).length === 0
.filter(signer => signer.signed?.length > 0).length === 0
},
canValidate(file) {
file = this.getFile(file)
@ -126,7 +126,7 @@ export const useFilesStore = function(...args) {
return this.canRequestSign
&& (
!Object.hasOwn(file, 'requested_by')
|| file.requested_by.userId === getCurrentUser().uid
|| file.requested_by.userId === getCurrentUser()?.uid
)
},
canAddSigner(file) {
@ -134,7 +134,7 @@ export const useFilesStore = function(...args) {
return this.canRequestSign
&& (
!Object.hasOwn(file, 'requested_by')
|| file.requested_by.userId === getCurrentUser().uid
|| file.requested_by.userId === getCurrentUser()?.uid
)
&& !this.isPartialSigned(file)
&& !this.isFullSigned(file)
@ -144,7 +144,7 @@ export const useFilesStore = function(...args) {
return this.canRequestSign
&& (
!Object.hasOwn(file, 'requested_by')
|| file.requested_by.userId === getCurrentUser().uid
|| file.requested_by.userId === getCurrentUser()?.uid
)
&& !this.isPartialSigned(file)
&& !this.isFullSigned(file)

View file

@ -51,6 +51,7 @@ export const useSignStore = defineStore('sign', {
},
setDocumentToSign(document) {
if (document) {
this.errors = []
set(this, 'document', document)
const sidebarStore = useSidebarStore()

View file

@ -64,7 +64,7 @@ export const useSignatureElementsStore = function(...args) {
})
})
.catch(({ data }) => {
this.error = data.ocs.data.message
this.error = { message: data.ocs.data.message }
})
this._initialized = true
},
@ -115,7 +115,7 @@ export const useSignatureElementsStore = function(...args) {
if (Object.hasOwn(response.data.ocs.data, 'errors')) {
this.error = response.data.ocs.data.errors[0]
} else {
this.error = response.data.ocs.data.message
this.error = { message: response.data.ocs.data.message }
}
})
},
@ -137,7 +137,7 @@ export const useSignatureElementsStore = function(...args) {
this.success = data.ocs.data.message
})
.catch(({ data }) => {
this.error = data.ocs.data.message
this.error = { message: data.ocs.data.message }
})
},
},

View file

@ -2547,7 +2547,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
@ -2601,7 +2604,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
@ -2653,11 +2659,15 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
}[];
message?: string;
};
};
};
@ -2675,11 +2685,15 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
}[];
message?: string;
};
};
};
@ -2952,7 +2966,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3033,7 +3050,10 @@ export interface operations {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3083,7 +3103,10 @@ export interface operations {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3161,7 +3184,10 @@ export interface operations {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3402,7 +3428,7 @@ export interface operations {
* @description Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
* @default 1
*/
status?: number;
status?: number | null;
};
};
};
@ -3437,7 +3463,10 @@ export interface operations {
message?: string;
/** Format: int64 */
action?: number;
errors?: string[];
errors?: {
message: string;
title?: string;
}[];
};
};
};
@ -3464,7 +3493,7 @@ export interface operations {
* @description Collection of users who must sign the document
* @default []
*/
users?: components["schemas"]["NewSigner"][];
users?: components["schemas"]["NewSigner"][] | null;
/** @description UUID of sign request. The signer UUID is what the person receives via email when asked to sign. This is not the file UUID. */
uuid?: string | null;
/** @description Visible elements on document */
@ -3473,7 +3502,7 @@ export interface operations {
* @description File object.
* @default []
*/
file?: components["schemas"]["NewFile"] | unknown[];
file?: (components["schemas"]["NewFile"] | unknown[]) | null;
/**
* Format: int64
* @description Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
@ -3513,7 +3542,10 @@ export interface operations {
message?: string;
/** Format: int64 */
action?: number;
errors?: string[];
errors?: {
message: string;
title?: string;
}[];
};
};
};
@ -3583,7 +3615,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3664,7 +3699,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
redirect?: string;
};
};
@ -3733,7 +3771,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3814,7 +3855,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
redirect?: string;
};
};

View file

@ -2305,7 +2305,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
@ -2359,7 +2362,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
@ -2411,11 +2417,15 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
}[];
message?: string;
};
};
};
@ -2433,11 +2443,15 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
messages?: {
type: string;
message: string;
}[];
message?: string;
};
};
};
@ -2710,7 +2724,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -2791,7 +2808,10 @@ export interface operations {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -2841,7 +2861,10 @@ export interface operations {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -2919,7 +2942,10 @@ export interface operations {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3160,7 +3186,7 @@ export interface operations {
* @description Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
* @default 1
*/
status?: number;
status?: number | null;
};
};
};
@ -3195,7 +3221,10 @@ export interface operations {
message?: string;
/** Format: int64 */
action?: number;
errors?: string[];
errors?: {
message: string;
title?: string;
}[];
};
};
};
@ -3222,7 +3251,7 @@ export interface operations {
* @description Collection of users who must sign the document
* @default []
*/
users?: components["schemas"]["NewSigner"][];
users?: components["schemas"]["NewSigner"][] | null;
/** @description UUID of sign request. The signer UUID is what the person receives via email when asked to sign. This is not the file UUID. */
uuid?: string | null;
/** @description Visible elements on document */
@ -3231,7 +3260,7 @@ export interface operations {
* @description File object.
* @default []
*/
file?: components["schemas"]["NewFile"] | unknown[];
file?: (components["schemas"]["NewFile"] | unknown[]) | null;
/**
* Format: int64
* @description Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
@ -3271,7 +3300,10 @@ export interface operations {
message?: string;
/** Format: int64 */
action?: number;
errors?: string[];
errors?: {
message: string;
title?: string;
}[];
};
};
};
@ -3341,7 +3373,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3422,7 +3457,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
redirect?: string;
};
};
@ -3491,7 +3529,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
};
};
};
@ -3572,7 +3613,10 @@ export interface operations {
data: {
/** Format: int64 */
action: number;
errors: string[];
errors: {
message: string;
title?: string;
}[];
redirect?: string;
};
};

View file

@ -103,8 +103,8 @@ export default {
await this.signatureElementsStore.delete(this.type)
if (this.signatureElementsStore.success.length) {
showSuccess(this.signatureElementsStore.success)
} else if (this.signatureElementsStore.error.length) {
showError(this.signatureElementsStore.error)
} else if (this.signatureElementsStore.error?.message) {
showError(this.signatureElementsStore.error.message)
}
},
close() {
@ -113,8 +113,8 @@ export default {
save() {
if (this.signatureElementsStore.success.length) {
showSuccess(this.signatureElementsStore.success)
} else if (this.signatureElementsStore.error.length) {
showError(this.signatureElementsStore.error)
} else if (this.signatureElementsStore.error?.message) {
showError(this.signatureElementsStore.error.message)
}
this.close()
},

View file

@ -5,59 +5,67 @@
<template>
<div class="main-view">
<TopBar :sidebar-toggle="true" />
<PdfEditor v-if="mounted"
<PdfEditor v-if="mounted && !signStore.errors.length && pdfBlob"
ref="pdfEditor"
width="100%"
height="100%"
:file-src="signStore.document.url"
:file="pdfBlob"
:read-only="true"
@pdf-editor:end-init="updateSigners" />
<NcNoteCard v-for="(error, index) in signStore.errors"
:key="index"
:heading="error.title || ''"
type="error">
{{ error.message }}
</NcNoteCard>
</div>
</template>
<script>
import { showError } from '@nextcloud/dialogs'
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
import PdfEditor from '../../Components/PdfEditor/PdfEditor.vue'
import TopBar from '../../Components/TopBar/TopBar.vue'
import { useFilesStore } from '../../store/files.js'
import { useSidebarStore } from '../../store/sidebar.js'
import { useSignStore } from '../../store/sign.js'
import { useSignMethodsStore } from '../../store/signMethods.js'
export default {
name: 'SignPDF',
components: {
NcNoteCard,
TopBar,
PdfEditor,
},
setup() {
const signStore = useSignStore()
const fileStore = useFilesStore()
const sidebarStore = useSidebarStore()
const signMethodsStore = useSignMethodsStore()
return { signStore, fileStore, signMethodsStore }
return { signStore, fileStore, sidebarStore, signMethodsStore }
},
data() {
return {
mounted: false,
pdfBlob: null,
}
},
mounted() {
async created() {
if (this.$route.name === 'SignPDFExternal') {
this.initSignExternal()
await this.initSignExternal()
} else if (this.$route.name === 'SignPDF') {
this.initSignInternal()
await this.initSignInternal()
}
this.signStore.errors.forEach(error => {
showError(error)
})
},
methods: {
initSignExternal() {
async initSignExternal() {
this.signStore.initFromState()
if (!this.signStore.document.uuid) {
this.signStore.document.uuid = this.$route.params.uuid
}
await this.fetchPdfAsBlob(this.signStore.document.url)
this.mounted = true
},
async initSignInternal() {
@ -69,11 +77,29 @@ export default {
if (Object.keys(signer).length > 0) {
this.signStore.setDocumentToSign(files[nodeId])
this.fileStore.selectedNodeId = nodeId
await this.fetchPdfAsBlob(this.signStore.document.url)
this.mounted = true
return true
return
}
}
},
async fetchPdfAsBlob(url) {
const response = await fetch(url)
const contentType = response.headers.get('Content-Type') || ''
if (contentType.includes('application/json')) {
const data = await response.json()
this.sidebarStore.hideSidebar()
if (data?.errors?.[0]?.message.length > 0) {
this.signStore.errors = data.errors
return
}
this.signStore.errors = [{ message: t('libresign', 'File not found') }]
return
}
const blob = await response.blob()
this.pdfBlob = new File([blob], 'arquivo.pdf', { type: 'application/pdf' })
},
updateSigners(data) {
this.signStore.document.signers.forEach(signer => {
if (signer.visibleElements.length > 0) {
@ -106,5 +132,10 @@ export default {
flex-direction: column;
align-content: space-between;
position: relative;
:deep(.notecard) {
max-width: 600px;
margin: 0 auto;
}
}
</style>

View file

@ -50,6 +50,13 @@
:no-close="loading"
:name="t('libresign', 'Confirm')"
@closing="signMethodsStore.closeModal('clickToSign')">
<NcNoteCard v-for="(error, index) in errors"
:key="index"
:heading="error.title || ''"
type="error">
<NcRichText :text="error.message"
:use-markdown="true" />
</NcNoteCard>
{{ t('libresign', 'Confirm your signature') }}
<template #actions>
<NcButton :disabled="loading"
@ -70,6 +77,13 @@
:no-close="loading"
:name="t('libresign', 'Confirm your signature')"
@closing="onCloseConfirmPassword">
<NcNoteCard v-for="(error, index) in errors"
:key="index"
:heading="error.title || ''"
type="error">
<NcRichText :text="error.message"
:use-markdown="true" />
</NcNoteCard>
{{ t('libresign', 'Subscription password.') }}
<form @submit.prevent="signWithPassword()">
<NcPasswordField v-model="signPassword" type="password" />
@ -119,7 +133,9 @@ import { generateOcsUrl } from '@nextcloud/router'
import NcButton from '@nextcloud/vue/components/NcButton'
import NcDialog from '@nextcloud/vue/components/NcDialog'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
import NcPasswordField from '@nextcloud/vue/components/NcPasswordField'
import NcRichText from '@nextcloud/vue/components/NcRichText'
import EmailManager from './ModalEmailManager.vue'
import SMSManager from './ModalSMSManager.vue'
@ -139,7 +155,9 @@ export default {
NcDialog,
NcButton,
NcLoadingIcon,
NcNoteCard,
NcPasswordField,
NcRichText,
CreatePassword,
SMSManager,
EmailManager,
@ -200,6 +218,9 @@ export default {
if (this.needCreateSignature) {
return false
}
if (this.signStore.errors.length > 0) {
return false
}
return true
},
signRequestUuid() {
@ -270,6 +291,7 @@ export default {
},
async signDocument(payload = {}) {
this.loading = true
this.errors = []
if (this.elements.length > 0) {
if (this.canCreateSignature) {
payload.elements = this.elements
@ -300,21 +322,12 @@ export default {
}
})
.catch((err) => {
const message = err.response?.data?.ocs?.data?.message
if (message) {
showError(message)
return
}
const errors = err.response?.data?.ocs?.data?.errors
if (errors) {
errors.forEach(error => {
showError(error)
})
}
this.errors = err.response?.data?.ocs?.data?.errors
})
this.loading = false
},
confirmSignDocument() {
this.errors = []
if (this.signMethodsStore.needEmailCode()) {
this.signMethodsStore.showModal('emailToken')
return

View file

@ -433,7 +433,7 @@ export default {
}
})
.catch(({ response }) => {
showError(response.data.ocs.data.errors[0])
showError(response.data.ocs.data.errors[0].message)
})
},
async uploadFile() {
@ -488,7 +488,7 @@ export default {
}
})
.catch(({ response }) => {
showError(response.data.ocs.data.errors[0])
showError(response.data.ocs.data.errors[0].message)
})
this.loading = false
},
@ -509,7 +509,7 @@ export default {
})
.catch(({ response }) => {
if (response?.data?.ocs?.data?.errors?.length > 0) {
showError(response.data.ocs.data.errors[0])
showError(response.data.ocs.data.errors[0].message)
}
})
this.loading = false

View file

@ -27,7 +27,9 @@ final class FileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('Invalid data to validate file', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('Invalid data to validate file', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -40,7 +42,9 @@ final class FileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('Invalid data to validate file', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('Invalid data to validate file', $body['ocs']['data']['errors'][0]['message']);
}
/**

View file

@ -36,7 +36,9 @@ final class RequestSignatureControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('You are not allowed to request signing', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('You are not allowed to request signing', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -95,7 +97,9 @@ final class RequestSignatureControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('You are not allowed to request signing', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('You are not allowed to request signing', $body['ocs']['data']['errors'][0]['message']);
}
/**

View file

@ -42,7 +42,9 @@ final class SignFileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('File not found', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('File not found', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -65,7 +67,9 @@ final class SignFileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('Invalid UUID', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('Invalid UUID', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -107,7 +111,9 @@ final class SignFileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('File already signed.', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('File already signed.', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -150,7 +156,9 @@ final class SignFileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('File not found', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('File not found', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -190,7 +198,9 @@ final class SignFileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals(200, $body['ocs']['data']['action']);
$this->assertEquals('Empty identify data.', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('Empty identify data.', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -250,7 +260,9 @@ final class SignFileControllerTest extends ApiTestCase {
$response = $this->assertRequest();
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals('Empty identify data.', $body['ocs']['data']['errors'][0]);
$this->assertCount(1, $body['ocs']['data']['errors']);
$this->assertArrayHasKey(0, $body['ocs']['data']['errors']);
$this->assertEquals('Empty identify data.', $body['ocs']['data']['errors'][0]['message']);
}
/**
@ -465,7 +477,7 @@ final class SignFileControllerTest extends ApiTestCase {
/**
* @runInSeparateProcess
*/
public function testDeleteUsingSignFileIdWithError():void {
public function testDeleteUsingSignFileIdWithInvalidSignRequestGroup():void {
$user = $this->createAccount('username', 'password');
$this->request
@ -478,4 +490,22 @@ final class SignFileControllerTest extends ApiTestCase {
$this->assertRequest();
}
/**
* @runInSeparateProcess
*/
public function testDeleteUsingSignFileIdWithInvalidFile():void {
$user = $this->createAccount('username', 'password');
$this->getMockAppConfig()->setValueArray(Application::APP_ID, 'groups_request_sign', ['admin','testGroup']);
$this->request
->withMethod('DELETE')
->withRequestHeader([
'Authorization' => 'Basic ' . base64_encode('username:password')
])
->withPath('/api/v1/sign/file_id/171')
->assertResponseCode(401);
$this->assertRequest();
}
}

View file

@ -59,7 +59,7 @@ final class AEnvironmentPageAwareControllerTest extends TestCase {
$this->expectExceptionCode(404);
$this->expectExceptionMessage(json_encode([
'action' => 2000,
'errors' => ['Invalid UUID'],
'errors' => [['message' => 'Invalid UUID']],
]));
$this->controller->loadNextcloudFileFromSignRequestUuid('');
}
@ -95,7 +95,7 @@ final class AEnvironmentPageAwareControllerTest extends TestCase {
$this->expectExceptionCode(404);
$this->expectExceptionMessage(json_encode([
'action' => 2000,
'errors' => ['Invalid UUID'],
'errors' => [['message' => 'Invalid UUID']],
]));
$this->controller->validateSignRequestUuid($file->getUuid());

View file

@ -38,7 +38,7 @@ Feature: page/sign_identify_account
And the response should be a JSON array with the following mandatory values
| key | value |
| action | 2000 |
| errors | ["Invalid UUID"] |
| errors | [{"message":"Invalid UUID"}] |
# invalid user
When as user "admin"
And sending "get" to "/apps/libresign/p/sign/<SIGN_UUID>"
@ -46,7 +46,7 @@ Feature: page/sign_identify_account
And the response should be a JSON array with the following mandatory values
| key | value |
| action | 2000 |
| errors | ["Invalid user"] |
| errors | [{"message":"Invalid user"}] |
# unauthenticated user
When as user ""
And sending "get" to "/apps/libresign/p/sign/<SIGN_UUID>"

View file

@ -9,9 +9,9 @@ Feature: request-signature
| name | document |
Then the response should have a status code 422
And the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors | ["You are not allowed to request signing"] |
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0].message | You are not allowed to request signing |
Scenario: Get error when try to request to sign without file name
Given as user "admin"
@ -45,7 +45,7 @@ Feature: request-signature
And the response should be a JSON array with the following mandatory values
| key | value |
| action | 2000 |
| errors | ["Invalid user"] |
| errors | [{"message":"Invalid user"}] |
Scenario: Request to sign with error when the user is not authenticated
Given as user "admin"
@ -113,7 +113,7 @@ Feature: request-signature
And the response should be a JSON array with the following mandatory values
| key | value |
| action | 2000 |
| errors | ["Link expired."] |
| errors | [{"message":"Link expired."}] |
Scenario: Request to sign with success when is necessary to renew the link
Given as user "admin"
@ -441,17 +441,17 @@ Feature: request-signature
| token | |
And the response should have a status code 422
Then the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0] | Invalid code. |
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0].message | Invalid code. |
And sending "post" to ocs "/apps/libresign/api/v1/sign/uuid/<SIGN_UUID>"
| method | account |
| token | |
And the response should have a status code 422
Then the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0] | Invalid code. |
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0].message | Invalid code. |
And sending "post" to ocs "/apps/provisioning_api/api/v1/config/apps/libresign/identify_methods"
| value | (string)[{"name":"email","enabled":true,"mandatory":true,"signatureMethods":{"clickToSign":{"enabled":true}},"can_create_account":false}] |
And sending "post" to ocs "/apps/libresign/api/v1/sign/uuid/<SIGN_UUID>"
@ -459,17 +459,17 @@ Feature: request-signature
| token | |
And the response should have a status code 422
Then the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0] | Invalid code. |
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0].message | Invalid code. |
And sending "post" to ocs "/apps/libresign/api/v1/sign/uuid/<SIGN_UUID>"
| method | account |
| token | |
And the response should have a status code 422
Then the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0] | Invalid code. |
| key | value |
| (jq).ocs.data.action | 2000 |
| (jq).ocs.data.errors[0].message | Invalid code. |
Scenario: Failed to sign with invalid code
Given run the command "libresign:configure:openssl --cn test" with result code 0
@ -500,15 +500,15 @@ Feature: request-signature
| token | |
And the response should have a status code 422
Then the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.errors[0] | Invalid code. |
| key | value |
| (jq).ocs.data.errors[0].message | Invalid code. |
And sending "post" to ocs "/apps/libresign/api/v1/sign/uuid/<SIGN_UUID>"
| method | email |
| token | 123456789132456789 |
And the response should have a status code 422
Then the response should be a JSON array with the following mandatory values
| key | value |
| (jq).ocs.data.errors[0] | Invalid code. |
| key | value |
| (jq).ocs.data.errors[0].message | Invalid code. |
Scenario: CRUD of identify methods
Given run the command "libresign:configure:openssl --cn test" with result code 0

View file

@ -39,12 +39,6 @@
</InvalidReturnType>
</file>
<file src="lib/Controller/FileController.php">
<InvalidReturnStatement>
<code><![CDATA[new DataResponse($return, $statusCode)]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[DataResponse<Http::STATUS_OK, LibresignValidateFile, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_BAD_REQUEST, array{action: int, errors: string[], messages?: array{type: string, message: string}[]}, array{}>]]></code>
</InvalidReturnType>
<UndefinedClass>
<code><![CDATA[SharedStorage]]></code>
</UndefinedClass>