From 22bd7fa19541909ea5e9da6800301edbe016f03e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 9 Apr 2024 23:04:45 +0200 Subject: [PATCH] reject bad validations + server validation impl --- .../server-model-validation.context-token.ts | 2 +- .../server-model-validation.context.ts | 32 +++++++++---------- .../validation/context/validation.context.ts | 18 +++++++---- ...tion-message-to-form-control.controller.ts | 4 +-- .../form-control-validator.controller.ts | 4 +-- .../interfaces/validator.interface.ts | 2 +- .../document-validation.server.data-source.ts | 12 ++++--- .../workspace/document-workspace.context.ts | 1 + 8 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context-token.ts index a37d4b48c4..1f8a1932dc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context-token.ts @@ -1,4 +1,4 @@ -import type { UmbServerModelValidationContext } from './server-model-validation.context.js'; +import type { UmbServerModelValidationContext } from './index.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_SERVER_MODEL_VALIDATION_CONTEXT = new UmbContextToken( diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context.ts index d46f58e6a1..ed5879c1e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validation.context.ts @@ -4,7 +4,6 @@ import { UMB_VALIDATION_CONTEXT } from './validation.context-token.js'; import { UMB_SERVER_MODEL_VALIDATION_CONTEXT } from './server-model-validation.context-token.js'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; export class UmbServerModelValidationContext extends UmbContextBase @@ -12,7 +11,6 @@ export class UmbServerModelValidationContext { #validatePromise?: Promise; #validatePromiseResolve?: (valid: boolean) => void; - #validatePromiseReject?: () => void; #context?: typeof UMB_VALIDATION_CONTEXT.TYPE; #isValid = true; @@ -35,24 +33,25 @@ export class UmbServerModelValidationContext }); } - async askServerForValidation(requestPromise: Promise<{ data: string | undefined }>): Promise { + async askServerForValidation(requestPromise: Promise<{ data: string | undefined; error: any }>): Promise { this.#context?.messages.removeMessagesByType('server'); - this.#validatePromiseReject?.(); - this.#validatePromise = new Promise((resolve, reject) => { - this.#validatePromiseResolve = resolve; - this.#validatePromiseReject = reject; - }); this.#serverFeedback = {}; + this.#isValid = false; + //this.#validatePromiseReject?.(); + this.#validatePromise = new Promise((resolve) => { + this.#validatePromiseResolve = resolve; + }); // Ask the server for validation... - const { data } = await tryExecuteAndNotify(this, requestPromise); + const { data, error } = await requestPromise; console.log('VALIDATE — Got server response:'); - console.log(data); + console.log(data, error); - this.#validatePromiseResolve?.(true); + this.#isValid = false; + this.#validatePromiseResolve?.(false); this.#validatePromiseResolve = undefined; - this.#validatePromiseReject = undefined; + //this.#validatePromise = undefined; } addTranslator(translator: UmbValidationMessageTranslator): void { @@ -71,10 +70,11 @@ export class UmbServerModelValidationContext get isValid(): boolean { return this.#isValid; } - validate(): Promise { - // TODO: Return to this decision once we have a bit more implementation to perspectives against: [NL] - // If we dont have a validatePromise, we valid cause then no one has called askServerForValidation(). [NL] (I might change my mind about this one, to then say we are invalid unless we have been validated by the server... ) - return this.#validatePromise ?? Promise.resolve(true); + async validate(): Promise { + if (this.#validatePromise) { + await this.#validatePromise; + } + return this.#isValid ? Promise.resolve() : Promise.reject(); } reset(): void {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts index 0de8caa4bd..1904b3da72 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts @@ -63,23 +63,27 @@ export class UmbValidationContext extends UmbContextBase i * * @returns succeed {Promise} - Returns a promise that resolves to true if the validator succeeded, this depends on the validators and wether forceSucceed is set. */ - async validate(): Promise { + async validate(): Promise { // TODO: clear server messages here?, well maybe only if we know we will get new server messages? Do the server messages hook into the system like another validator? this.#validationMode = true; - const results = await Promise.all(this.#validators.map((v) => v.validate())); + + const resultsStatus = await Promise.all(this.#validators.map((v) => v.validate())).then( + () => Promise.resolve(true), + () => Promise.reject(false), + ); // If we have any messages then we are not valid, otherwise lets check the validation results: [NL] // This enables us to keep client validations though UI is not present anymore — because the client validations got defined as messages. [NL] - const isValid = this.messages.getHasAnyMessages() ? false : results.every((r) => r); + const isValid = this.messages.getHasAnyMessages() ? false : resultsStatus; this.#isValid = isValid; - // Focus first invalid element: - if (!isValid) { + if (isValid === false) { + // Focus first invalid element: this.focusFirstInvalidElement(); + return Promise.reject(); } - //return this.#preventFail ? true : isValid; - return isValid; + return Promise.resolve(); } focusFirstInvalidElement(): void { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-validation-message-to-form-control.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-validation-message-to-form-control.controller.ts index 7708925980..c70b9bc059 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-validation-message-to-form-control.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-validation-message-to-form-control.controller.ts @@ -86,9 +86,9 @@ export class UmbBindValidationMessageToFormControl extends UmbControllerBase { this.#control.checkValidity(); } - validate(): Promise { + validate(): Promise { //this.#isValid = this.#control.checkValidity(); - return Promise.resolve(this.#isValid); + return this.#isValid ? Promise.resolve() : Promise.reject(); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts index c0125067dc..b4d83ab037 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts @@ -56,9 +56,9 @@ export class UmbFormControlValidator extends UmbControllerBase implements UmbVal #setInvalid = this.#setIsValid.bind(this, false); #setValid = this.#setIsValid.bind(this, true); - validate(): Promise { + validate(): Promise { this.#isValid = this.#control.checkValidity(); - return Promise.resolve(this.#isValid); + return this.#isValid ? Promise.resolve() : Promise.reject(); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/interfaces/validator.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/interfaces/validator.interface.ts index b6aef11cf7..43994a5613 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/interfaces/validator.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/interfaces/validator.interface.ts @@ -7,7 +7,7 @@ export interface UmbValidator extends EventTarget { /** * Validate the form, will return a promise that resolves to true if what the Validator represents is valid. */ - validate(): Promise; + validate(): Promise; /** * Reset the validator to its initial state. diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts index 08959f404e..a00bd9821c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts @@ -5,7 +5,7 @@ import { type UpdateDocumentRequestModel, } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A server data source for Document Validation @@ -44,8 +44,9 @@ export class UmbDocumentValidationServerDataSource { variants: model.variants, }; - const { data, error } = await tryExecuteAndNotify( - this.#host, + // Maybe use: tryExecuteAndNotify + const { data, error } = await tryExecute( + //this.#host, DocumentResource.postDocumentValidate({ requestBody, }), @@ -73,8 +74,9 @@ export class UmbDocumentValidationServerDataSource { variants: model.variants, }; - const { data, error } = await tryExecuteAndNotify( - this.#host, + // Maybe use: tryExecuteAndNotify + const { data, error } = await tryExecute( + //this.#host, DocumentResource.putDocumentByIdValidate({ id: model.unique, requestBody, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 9eb1edb6c4..b72ae5d103 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -581,6 +581,7 @@ export class UmbDocumentWorkspaceContext const saveData = this.#buildSaveData(variantIds); + // Create the validation repository if it does not exist. (we first create this here when we need it) [NL] this.#validationRepository ??= new UmbDocumentValidationRepository(this); if (this.getIsNew()) {