diff --git a/tenants/escolinha/36-kc-theme.yaml b/tenants/escolinha/36-kc-theme.yaml index 1572983..129dd79 100644 --- a/tenants/escolinha/36-kc-theme.yaml +++ b/tenants/escolinha/36-kc-theme.yaml @@ -1,5 +1,5 @@ # GERADO por scripts/tema_login_escolinha.py — nao edite na mao. -# Fonte: keycloak-theme/escolinha/{login,login-update-password,estilo,template}.ftl +# Fonte: keycloak-theme/escolinha/*.ftl (login.ftl, login-update-password.ftl, estilo.ftl, template.ftl, error.ftl, info.ftl, logout-confirm.ftl, login-page-expired.ftl, login-reset-password.ftl, login-config-totp.ftl, login-otp.ftl, webauthn-register.ftl, webauthn-authenticate.ftl, select-authenticator.ftl) apiVersion: v1 kind: ConfigMap metadata: @@ -487,7 +487,9 @@ data: .botao{ display:flex;align-items:center;justify-content:center;gap:10px; width:100%;height:56px;border:0;border-radius:12px; - font-size:16px;font-weight:700;cursor:pointer; + /* `font-family:inherit`: + <#-- `botao`: sem ele o "Tente outra forma" saia sem altura nem + alinhamento — so a borda (achado em 2026-10-08). --> + @@ -702,3 +810,631 @@ data: + error.ftl: |- + <#-- + A tela de ERRO do Keycloak ("Sentimos muito..."): redirect_uri invalido, + client inexistente, link de acao invalido ou ja usado, sessao perdida. + + Ate 2026-10-08 era a `error.ftl` do tema BASE dentro do `template.ftl` deste: + ja tinha a marca, mas o titulo "Sentimos muito..." e o texto tecnico solto + ("Parametro invalido: redirect_uri") sem dizer o que a pessoa faz agora. Quem + chega aqui quase sempre so precisa voltar e tentar de novo. + + Textos: as chaves pt-BR do Keycloak quando existem (`errorTitle`, + `backToApplication`). O `traceIdSupportMessage` NAO tem traducao pt-BR no + 26.7.5 — sairia em ingles —, entao a frase do codigo de suporte e fixa aqui. + + O id `kc-error-message` e o mesmo do base (o validador procura por ele). + --> + <#import "template.ftl" as layout> + <@layout.registrationLayout displayMessage=false; section> + <#if section = "selo"> + + <#elseif section = "header"> + Algo deu errado + <#elseif section = "sub"> + ${kcSanitize(msg("errorTitle"))?no_esc} Não foi possível concluir o seu pedido. + <#elseif section = "form"> +
+ <#if message?? && message.summary?has_content> +
${kcSanitize(message.summary)?no_esc}
+ +

Volte para o aplicativo e tente de novo. Se continuar acontecendo, fale com o suporte.

+ <#if traceId??> +

Se falar com o suporte, informe este código: ${traceId}

+ + <#if !skipLink??> + <#if client?? && client.baseUrl?has_content> + ${layout.semSeta(msg("backToApplication"))} + + +
+ + + + info.ftl: |- + <#-- + As telas de INFORMACAO do Keycloak: "execute estas acoes" (o link do e-mail de + convite/troca de senha), "sua conta foi atualizada", "voce saiu da sessao", + e-mail verificado, acao expirada com sessao, etc. + + Ate 2026-10-08 era a `info.ftl` do tema BASE na moldura deste. Dois defeitos + que motivaram esta: o titulo "Account updated" saia em INGLES (a chave + `accountUpdatedTitle` nao tem traducao pt-BR no 26.7.5), e o titulo repetia + palavra por palavra a frase de baixo. + + TITULO: `messageHeader` quando o Keycloak manda um (traduzido aqui quando o + pt-BR de fabrica nao tem); senao, a propria mensagem — e entao ela NAO se + repete embaixo. + + Os ids `kc-info-message` e os links sao os do base; o validador procura o id. + --> + <#import "template.ftl" as layout> + <#-- Chaves de titulo que o pt-BR do Keycloak 26.7.5 nao traduz. --> + <#assign titulosPtBr = {"accountUpdatedTitle": "Conta atualizada"}> + <#-- Nomes de acao obrigatoria que em pt-BR de fabrica sao tecnicos demais. --> + <#assign acoesPtBr = { + "webauthn-register-passwordless": "Cadastrar uma chave de seguran\xE7a (passkey)", + "webauthn-register": "Cadastrar uma chave de seguran\xE7a para o segundo fator"}> + <#assign sucesso = ((message.type)!'') == 'success' || (messageHeader!'') == 'accountUpdatedTitle'> + <@layout.registrationLayout displayMessage=false; section> + <#if section = "selo"> + <#if requiredActions??> + + <#elseif sucesso> + + <#else> + + + <#elseif section = "header"> + <#if messageHeader??> + ${kcSanitize(titulosPtBr[messageHeader]!msg("${messageHeader}"))?no_esc} + <#elseif requiredActions??> + Antes de continuar + <#else> + ${(message.summary)!''} + + <#elseif section = "sub"> + <#if messageHeader?? || requiredActions??>${(message.summary)!''} + <#elseif section = "form"> +
+ <#if requiredActions??> + + + <#if !skipLink??> + <#if pageRedirectUri?has_content> + ${layout.semSeta(msg("backToApplication"))} + <#elseif actionUri?has_content> + ${msg("doContinue")} + + <#elseif (client.baseUrl)?has_content> + ${layout.semSeta(msg("backToApplication"))} + + +
+ + + + logout-confirm.ftl: |- + <#-- + CONFIRMAR A SAIDA — o que o Keycloak mostra quando o logout chega sem + `id_token_hint` (link antigo, app que perdeu o token, alguem digitando a URL). + + O "Sair" do Painel do dono ja manda o id_token e nao passa por aqui + (2026-10-07); esta tela e para todo o resto. Ate 2026-10-08 era a do tema + BASE na moldura deste: "Saindo" / "Voce realmente deseja sair?" e o botao. + + O botao precisa de `name="confirmLogout"` e o form do `session_code`: e o que + o Keycloak le no POST. O base desabilitava o botao no onsubmit, e um botao + desabilitado nao vai no POST — aqui nao se desabilita nada. + --> + <#import "template.ftl" as layout> + <@layout.registrationLayout; section> + <#if section = "selo"> + + <#elseif section = "header"> + Sair da conta + <#elseif section = "sub"> + ${msg("logoutConfirmHeader")} + <#elseif section = "form"> +
+
+ + +
+
+ <#if !logoutConfirm.skipLink> + <#if (client.baseUrl)?has_content> + ${layout.semSeta(msg("backToApplication"))} + + +
+
+ + + + login-page-expired.ftl: |- + <#-- + PAGINA EXPIRADA — o Keycloak mostra quando chega um formulario de uma etapa + que o login ja passou (voltar do navegador e reenviar, aba antiga). + + O base dizia "Para reiniciar o processo de login [Clique aqui] . Para + continuar o processo de login [Clique aqui] ." — dois links soltos com ponto + depois. Aqui sao dois botoes: o principal recomeca (o que quase todo mundo + quer), o secundario continua de onde parou. + + Os ids `loginRestartLink` e `loginContinueLink` sao os do base. + --> + <#import "template.ftl" as layout> + <@layout.registrationLayout; section> + <#if section = "selo"> + + <#elseif section = "header"> + A página expirou + <#elseif section = "sub"> + Esta etapa do login não vale mais. Escolha como seguir: + <#elseif section = "form"> + Recomeçar o login + Continuar de onde parei + + + + login-reset-password.ftl: |- + <#-- + ESQUECEU SUA SENHA — o link "Esqueceu sua senha?" do login cai aqui. + + Ate 2026-10-08 era a pagina do tema BASE na moldura deste: campo sem o icone e + a altura do login, "« Voltar ao Login" ACIMA do botao e a instrucao no rodape. + Aqui a instrucao vira o subtitulo, o campo e o mesmo do login e o "voltar" + fica embaixo, onde se procura. + + O Keycloak le `username` no POST. O id do form (`kc-reset-password-form`) e o + do base; o validador procura por ele. Depois de enviar, o Keycloak volta ao + LOGIN com o aviso "Voce devera receber um e-mail..." (mesmo para e-mail que + nao existe, para nao revelar quem tem conta) — essa tela e a login.ftl. + --> + <#import "template.ftl" as layout> + <@layout.registrationLayout displayMessage=!messagesPerField.existsError('username'); section> + <#if section = "selo"> + + <#elseif section = "header"> + Esqueceu sua senha? + <#elseif section = "sub"> + <#if realm.duplicateEmailsAllowed>${msg("emailInstructionUsername")}<#else>${msg("emailInstruction")} + <#elseif section = "form"> +
+
+ +
+ + + + +
+ <#if messagesPerField.existsError('username')> + ${kcSanitize(messagesPerField.get('username'))?no_esc} + +
+ + +
+ ${layout.semSeta(msg("backToLogin"))} + + + + login-config-totp.ftl: |- + <#-- + CONFIGURAR O 2FA (TOTP) — o dono (`atm_admin`) cai aqui no primeiro login + depois do 2FA obrigatorio (fluxo `browser-2fa-dono`, 2026-10-07). + + Ate 2026-10-08 era a pagina do tema BASE na moldura deste: funcionava, mas com + o "*" de obrigatorio numa linha sozinha, o passo 3 mandando "clicar em Ok" + num botao que se chama "Enviar", e o QR solto no texto. + + NAO MUDE OS IDS: o robo do e2e (`frontend/e2e/apoio.ts`, passarPeloKeycloak) + acha a tela por `kc-totp-settings-form`, troca para a chave em texto por + `mode-manual`, le `kc-totp-secret-key` e preenche `totp`, `userLabel` e + `saveTOTPBtn`. O Keycloak le no POST: totp, totpSecret, userLabel, mode, + logout-sessions e cancel-aia. + + `totp.policy.algorithmKey` e o getAlgorithmKey() do base, pela propriedade. + --> + <#import "template.ftl" as layout> + <@layout.registrationLayout displayRequiredFields=false displayMessage=!messagesPerField.existsError('totp','userLabel'); section> + <#if section = "selo"> + + <#elseif section = "header"> + Verificação em duas etapas + <#elseif section = "sub"> + Além da senha, cada login vai pedir um código do aplicativo autenticador do seu celular. + <#elseif section = "form"> +
    +
  1. +

    ${msg("loginTotpStep1")}

    + +
  2. + + <#if mode?? && mode = "manual"> +
  3. +

    ${msg("loginTotpManualStep2")}

    + ${totp.totpSecretEncoded} + +

    ${msg("loginTotpScanBarcode")}

    +
  4. + <#else> +
  5. +

    ${msg("loginTotpStep2")}

    + Código QR para o aplicativo autenticador +

    ${msg("loginTotpUnableToScan")}

    +
  6. + + +
  7. +

    Digite o código que o aplicativo mostra e dê um nome a este celular.

    +
  8. +
+ +
+
+ +
+ + + + +
+ <#if messagesPerField.existsError('totp')> + ${kcSanitize(messagesPerField.get('totp'))?no_esc} + + + <#if mode??> +
+ +
+ +
+ + + + +
+ <#if messagesPerField.existsError('userLabel')> + ${kcSanitize(messagesPerField.get('userLabel'))?no_esc} + +
+ + + + + <#if isAppInitiatedAction??> + + +
+ + + + login-otp.ftl: |- + <#-- + DIGITAR O CODIGO DO 2FA — o dono, a cada login com senha (o login por + passkey dispensa; ver `browser-2fa-dono` no molde). + + Ate 2026-10-08 era a pagina do tema BASE na moldura deste: titulo "Entrar", + como se fosse o login de novo, e um campo sem dizer de onde vem o codigo. + + NAO MUDE OS IDS: o e2e (`frontend/e2e/apoio.ts`) acha a tela por + `kc-otp-login-form`, preenche `otp`, clica `kc-login` e detecta codigo + recusado por `input-error-otp-code`. O Keycloak le `otp` e, com mais de um + celular cadastrado, `selectedCredentialId`. + --> + <#import "template.ftl" as layout> + <@layout.registrationLayout displayMessage=!messagesPerField.existsError('totp'); section> + <#if section = "selo"> + + <#elseif section = "header"> + Código de verificação + <#elseif section = "sub"> + Abra o aplicativo autenticador do seu celular e digite o código que ele mostra agora. + <#elseif section = "form"> +
+ <#if otpLogin.userOtpCredentials?size gt 1> +
+ <#list otpLogin.userOtpCredentials as otpCredential> +
+ checked="checked"> + +
+ +
+ + +
+ +
+ + + + +
+ <#if messagesPerField.existsError('totp')> + ${kcSanitize(messagesPerField.get('totp'))?no_esc} + +
+ + +
+ + + + webauthn-register.ftl: |- + <#-- + CADASTRAR PASSKEY / CHAVE DE SEGURANCA — acoes obrigatorias + `webauthn-register-passwordless` (passkey, que dispensa a senha) e + `webauthn-register` (chave como segundo fator). As duas usam esta pagina. + + Ate 2026-10-08 era a pagina do tema BASE na moldura deste: "Registrar Chave de + Seguranca" e um botao "Cadastre-se" — que parece criar CONTA, nao cadastrar a + chave. + + O + + + + <#if !isSetRetry?has_content && isAppInitiatedAction?has_content> +
+ +
+ + + + + webauthn-authenticate.ftl: |- + <#-- + ENTRAR COM PASSKEY / CHAVE DE SEGURANCA — a etapa WebAuthn de um fluxo + (quando o Keycloak pede a chave numa tela propria, e nao pela sugestao no + campo de e-mail do login.ftl). + + Ate 2026-10-08 era a pagina do tema BASE na moldura deste: a lista de chaves + vinha com classes do PatternFly que o tema nao carrega, e saia como texto + corrido. + + O + <#elseif section = "info"> + <#if realm.registrationAllowed && !registrationDisabled??> +
+ ${msg("noAccount")} ${msg("doRegister")} +
+ + + + + select-authenticator.ftl: |- + <#-- + ESCOLHER COMO ENTRAR — o "Tente outra forma" de um fluxo com alternativas + (senha, passkey, codigo do celular...). + + Ate 2026-10-08 era a pagina do tema BASE na moldura deste: cada opcao e um + + + + + + +