From b1e58e1add73cc8d46c4db455c09550d4a5c9880 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Wed, 12 Jun 2024 19:41:05 +0200 Subject: [PATCH] Refactor how userFromField is passed down to the client --- src/bin/keycloakify/buildJars/buildJar.ts | 4 +- ..._object_to_js_code_declaring_an_object.ftl | 297 ++++++++---------- .../generateResources/readFieldNameUsage.ts | 2 + 3 files changed, 142 insertions(+), 161 deletions(-) diff --git a/src/bin/keycloakify/buildJars/buildJar.ts b/src/bin/keycloakify/buildJars/buildJar.ts index 79356263..e86cdff0 100644 --- a/src/bin/keycloakify/buildJars/buildJar.ts +++ b/src/bin/keycloakify/buildJars/buildJar.ts @@ -168,8 +168,8 @@ export async function buildJar(params: { })(); const modifiedFtlFileContent = ftlFileContent.replace( - `out["pageId"] = "\${pageId}";`, - `out["pageId"] = "${pageId}"; out["realPageId"] = "${realPageId}";` + `out.pageId = "\${pageId}";`, + `out.pageId = "${pageId}"; out.realPageId = "${realPageId}";` ); assert(modifiedFtlFileContent !== ftlFileContent); diff --git a/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl b/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl index 3b4b4733..751d200c 100644 --- a/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +++ b/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl @@ -2,171 +2,52 @@ (()=>{ <#assign pageId="PAGE_ID_xIgLsPgGId9D8e"> const out = ${ftl_object_to_js_code_declaring_an_object(.data_model, [])?no_esc}; -out["messagesPerField"]= { - <#assign fieldNames = [ FIELD_NAMES_eKsIY4ZsZ4xeM ]> - <#attempt> - <#if profile?? && profile.attributes?? && profile.attributes?is_enumerable> - <#list profile.attributes as attribute> - <#if fieldNames?seq_contains(attribute.name)> - <#continue> - - <#assign fieldNames += [attribute.name]> - - - <#recover> - - "printIfExists": function (fieldName, text) { - <#if !messagesPerField?? || !(messagesPerField?is_hash)> - throw new Error("You're not supposed to use messagesPerField.printIfExists in this page"); - <#else> - <#list fieldNames as fieldName> - if(fieldName === "${fieldName}" ){ - <#-- https://github.com/keycloakify/keycloakify/pull/218 --> - <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'> - <#assign doExistErrorOnUsernameOrPassword = ""> - <#attempt> - <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')> - <#recover> - <#assign doExistErrorOnUsernameOrPassword = true> - - return <#if doExistErrorOnUsernameOrPassword>text<#else>undefined - <#else> - <#assign doExistMessageForField = ""> - <#attempt> - <#assign doExistMessageForField = messagesPerField.exists('${fieldName}')> - <#recover> - <#assign doExistMessageForField = true> - - return <#if doExistMessageForField>text<#else>undefined; - + +if( out.messagesPerField ){ + + { + + var existsError_singleFieldName = out.messagesPerField.existsError; + + out.messagesPerField.existsError = function (){ + for( let i = 0; i < arguments.length; i++ ){ + if( existsError_singleFieldName(arguments[i]) ){ + return true; } - - throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated"); - - }, - "existsError": function (){ - function existsError_singleFieldName(fieldName) { - <#if !messagesPerField?? || !(messagesPerField?is_hash)> - throw new Error("You're not supposed to use messagesPerField.printIfExists in this page"); - <#else> - <#list fieldNames as fieldName> - if(fieldName === "${fieldName}" ){ - <#-- https://github.com/keycloakify/keycloakify/pull/218 --> - <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'> - <#assign doExistErrorOnUsernameOrPassword = ""> - <#attempt> - <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')> - <#recover> - <#assign doExistErrorOnUsernameOrPassword = true> - - return <#if doExistErrorOnUsernameOrPassword>true<#else>false; - <#else> - <#assign doExistErrorMessageForField = ""> - <#attempt> - <#assign doExistErrorMessageForField = messagesPerField.existsError('${fieldName}')> - <#recover> - <#assign doExistErrorMessageForField = true> - - return <#if doExistErrorMessageForField>true<#else>false; - - } - - throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated"); - - } - for( let i = 0; i < arguments.length; i++ ){ - if( existsError_singleFieldName(arguments[i]) ){ - return true; } - } - return false; - }, - "get": function (fieldName) { - <#if !messagesPerField?? || !(messagesPerField?is_hash)> - throw new Error("You're not supposed to use messagesPerField.get in this page"); - <#else> - <#list fieldNames as fieldName> - if(fieldName === "${fieldName}" ){ - <#-- https://github.com/keycloakify/keycloakify/pull/218 --> - <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'> - <#assign doExistErrorOnUsernameOrPassword = ""> - <#attempt> - <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')> - <#recover> - <#assign doExistErrorOnUsernameOrPassword = true> - - <#if doExistErrorOnUsernameOrPassword> - <#attempt> - return decodeHtmlEntities("${msg('invalidUserMessage')?js_string}"); - <#recover> - return "Invalid username or password."; - - <#else> - return ""; - - <#else> - <#attempt> - return decodeHtmlEntities("${messagesPerField.get('${fieldName}')?js_string}"); - <#recover> - return "Invalid field"; - - - } - - throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated"); - - }, - "exists": function (fieldName) { - <#if !messagesPerField?? || !(messagesPerField?is_hash)> - throw new Error("You're not supposed to use messagesPerField.exists in this page"); - <#else> - <#list fieldNames as fieldName> - if(fieldName === "${fieldName}" ){ - <#-- https://github.com/keycloakify/keycloakify/pull/218 --> - <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'> - <#assign doExistErrorOnUsernameOrPassword = ""> - <#attempt> - <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')> - <#recover> - <#assign doExistErrorOnUsernameOrPassword = true> - - return <#if doExistErrorOnUsernameOrPassword>true<#else>false; - <#else> - <#assign doExistErrorMessageForField = ""> - <#attempt> - <#assign doExistErrorMessageForField = messagesPerField.exists('${fieldName}')> - <#recover> - <#assign doExistErrorMessageForField = true> - - return <#if doExistErrorMessageForField>true<#else>false; - - } - - throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated"); - - }, - "getFirstError": function () { + return false; + }; + + } + out.messagesPerField.exists = function (fieldName) { + return out.messagesPerField.get(fieldName) !== ""; + }; + out.messagesPerField.printIfExists = function (fieldName, text) { + return out.messagesPerField.exists(fieldName) ? text : undefined; + }; + out.messagesPerField.getFirstError = function () { for( let i = 0; i < arguments.length; i++ ){ const fieldName = arguments[i]; if( out.messagesPerField.existsError(fieldName) ){ return out.messagesPerField.get(fieldName); } } - } -}; + }; -out["keycloakifyVersion"] = "KEYCLOAKIFY_VERSION_xEdKd3xEdr"; -out["themeVersion"] = "KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx"; -out["themeType"] = "KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr"; -out["themeName"] = "KEYCLOAKIFY_THEME_NAME_cXxKd3xEer"; -out["pageId"] = "${pageId}"; +} -try { - out["url"]["resourcesCommonPath"] = out["url"]["resourcesPath"] + "/" + "RESOURCES_COMMON_cLsLsMrtDkpVv"; -} catch(error) { } +out.keycloakifyVersion = "KEYCLOAKIFY_VERSION_xEdKd3xEdr"; +out.themeVersion = "KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx"; +out.themeType = "KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr"; +out.themeName = "KEYCLOAKIFY_THEME_NAME_cXxKd3xEer"; +out.pageId = "${pageId}"; + +if( out.url && out.url.resourcesPath ){ + out.url.resourcesCommonPath = out.url.resourcesPath + "/" + "RESOURCES_COMMON_cLsLsMrtDkpVv"; +} <#if profile?? && profile.attributes??> - out["lOCALIZATION_REALM_OVERRIDES_USER_PROFILE_PROPERTY_KEY_aaGLsPgGIdeeX"] = { + out.lOCALIZATION_REALM_OVERRIDES_USER_PROFILE_PROPERTY_KEY_aaGLsPgGIdeeX = { <#list profile.attributes as attribute> <#if attribute.annotations?? && attribute.displayName??> "${attribute.displayName}": decodeHtmlEntities("${advancedMsg(attribute.displayName)?js_string}"), @@ -196,22 +77,22 @@ try { attributes_to_attributesByName: { - if( !out["profile"] ){ + if( !out.profile ){ break attributes_to_attributesByName; } - if( !out["profile"]["attributes"] ){ + if( !out.profile.attributes ){ break attributes_to_attributesByName; } - var attributes = out["profile"]["attributes"]; + var attributes = out.profile.attributes; - delete out["profile"]["attributes"]; + delete out.profile.attributes; - out["profile"]["attributesByName"] = {}; + out.profile.attributesByName = {}; attributes.forEach(function(attribute){ - out["profile"]["attributesByName"][attribute.name] = attribute; + out.profile.attributesByName[attribute.name] = attribute; }); } @@ -442,6 +323,104 @@ function decodeHtmlEntities(htmlStr){ <#return 'function(){ return "' + returnValue + '"; }'> + <#assign fieldNames = [ FIELD_NAMES_eKsIY4ZsZ4xeM ]> + <#if profile?? && profile.attributes??> + <#list profile.attributes as attribute> + <#if fieldNames?seq_contains(attribute.name)> + <#continue> + + <#assign fieldNames += [attribute.name]> + + + + <#if are_same_path(path, ["messagesPerField", "get"])> + + <#local jsFunctionCode = "function (fieldName) { "> + + <#list fieldNames as fieldName> + + <#-- See: https://github.com/keycloakify/keycloakify/issues/217 --> + <#if fieldName == "username"> + + <#local jsFunctionCode += "if(fieldName === 'username' || fieldName === 'password' ){ "> + + <#if messagesPerField.exists('username') || messagesPerField.exists('password')> + <#local jsFunctionCode += "return out.message && out.message.summary ? out.message.summary : 'error'; "> + <#else> + <#local jsFunctionCode += "return ''; "> + + + <#local jsFunctionCode += "} "> + + <#continue> + + + <#if fieldName == "password"> + <#continue> + + + <#local jsFunctionCode += "if(fieldName === '" + fieldName + "'){ "> + + <#if messagesPerField.exists('${fieldName}')> + <#local jsFunctionCode += 'return decodeHtmlEntities("' + messagesPerField.get('${fieldName}')?js_string + '"); '> + <#else> + <#local jsFunctionCode += "return ''; "> + + + <#local jsFunctionCode += "} "> + + + + <#local jsFunctionCode += "}"> + + <#return jsFunctionCode> + + + + <#if are_same_path(path, ["messagesPerField", "existsError"])> + + <#local jsFunctionCode = "function (fieldName) { "> + + <#list fieldNames as fieldName> + + <#-- See: https://github.com/keycloakify/keycloakify/issues/217 --> + <#if fieldName == "username"> + + <#local jsFunctionCode += "if(fieldName === 'username' || fieldName === 'password' ){ "> + + <#if messagesPerField.existsError('username') || messagesPerField.existsError('password')> + <#local jsFunctionCode += "return true; "> + <#else> + <#local jsFunctionCode += "return false; "> + + + <#local jsFunctionCode += "} "> + + <#continue> + + + <#if fieldName == "password"> + <#continue> + + + <#local jsFunctionCode += "if(fieldName === '" + fieldName + "' ){ "> + + <#if messagesPerField.existsError('${fieldName}')> + <#local jsFunctionCode += 'return true; '> + <#else> + <#local jsFunctionCode += "return false; "> + + + <#local jsFunctionCode += "}"> + + + + <#local jsFunctionCode += "}"> + + <#return jsFunctionCode> + + + <#return "ABORT: It's a method"> diff --git a/src/bin/keycloakify/generateResources/readFieldNameUsage.ts b/src/bin/keycloakify/generateResources/readFieldNameUsage.ts index 8efac289..65ce152a 100644 --- a/src/bin/keycloakify/generateResources/readFieldNameUsage.ts +++ b/src/bin/keycloakify/generateResources/readFieldNameUsage.ts @@ -29,6 +29,8 @@ export function readFieldNameUsage(params: { continue; } + console.log(filePath); + for (const functionName of [ "printIfExists", "existsError",