├── .browserslistrc ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .prettierrc.json ├── README.md ├── package.json ├── src ├── @types │ └── environment.d.ts ├── components │ └── Layout.vue ├── hooks │ ├── index.ts │ └── login.ts ├── scss │ ├── base │ │ ├── global.scss │ │ └── variables.scss │ ├── index.scss │ └── modules │ │ ├── form.scss │ │ └── layout.scss ├── shims-vue.d.ts ├── static │ ├── messages │ │ ├── messages_en.properties │ │ └── messages_pt_BR.properties │ ├── template.ftl │ └── theme.properties └── views │ ├── login-idp-link-confirm │ ├── index.ftl │ ├── index.ts │ └── index.vue │ ├── login-idp-link-email │ ├── index.ftl │ ├── index.ts │ ├── index.vue │ └── login-idp-link-email.ftl │ ├── login-reset-password │ ├── index.ftl │ ├── index.ts │ └── index.vue │ ├── login-update-profile │ ├── index.ftl │ ├── index.ts │ └── index.vue │ ├── login │ ├── index.ftl │ ├── index.ts │ └── index.vue │ └── register │ ├── index.ftl │ ├── index.ts │ └── index.vue ├── tsconfig.json └── webpack.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = false 12 | insert_final_newline = true -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "plugin:vue/essential", 8 | "standard", 9 | "prettier/@typescript-eslint" 10 | ], 11 | "parserOptions": { 12 | "ecmaVersion": "latest", 13 | "parser": "@typescript-eslint/parser", 14 | "sourceType": "module" 15 | }, 16 | "plugins": [ 17 | "vue", 18 | "@typescript-eslint", 19 | "prettier" 20 | ], 21 | "rules": { 22 | "prettier/prettier": "error", 23 | "max-lines": [ 24 | "error", 25 | { "max": 300, "skipComments": true, "skipBlankLines": true } 26 | ], 27 | "max-lines-per-function": [ 28 | "error", 29 | { "max": 30, "skipComments": true, "skipBlankLines": true } 30 | ], 31 | "max-len": ["error", { "code": 120 }], 32 | "import/extensions": [ 33 | "error", 34 | "ignorePackages", 35 | { 36 | "ts": "never", 37 | "tsx": "never", 38 | "vue": "never", 39 | "json": "never" 40 | } 41 | ] 42 | }, 43 | "settings": { 44 | "import/resolver": { 45 | "typescript": {} 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .env 4 | 5 | yarn.lock 6 | yarn-error.log 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "none", 4 | "arrowParens": "avoid", 5 | "semi": false 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Keycloak Theme with Vue 3 and Typescript 2 | 3 | - You need to have docker installed on your development environment 4 | - Follow the instructions bellow to run this theme 5 | - https://youtu.be/qrjjiG1206E ( tutorial pt-br ) 6 | 7 | 8 | ### 1. Run database for Keycloak (Postgres) 9 | Attention: Configure Volume folder in your environment and replace this (~/database/postgres) 10 | 11 | ``` 12 | docker run -d --name postgres \ 13 | -p 5432:5432 \ 14 | -e POSTGRES_DB=keycloak \ 15 | -e POSTGRES_USER=postgres \ 16 | -e POSTGRES_PASSWORD=postgres \ 17 | -v ~/database/postgres:/var/lib/postgresql/data \ 18 | --restart always postgres:latest 19 | 20 | ``` 21 | 22 | 23 | ### 2. Run Keycloak with correct configuration database 24 | 25 | ``` 26 | docker run -d --name keycloak \ 27 | -p 8080:8080 \ 28 | -e DB_VENDOR=postgres \ 29 | -e DB_ADDR=postgres \ 30 | -e DB_DATABASE=keycloak \ 31 | -e DB_SCHEMA=public \ 32 | -e DB_USER=postgres \ 33 | -e DB_PASSWORD=postgres \ 34 | -e KEYCLOAK_USER=admin \ 35 | -e KEYCLOAK_PASSWORD=admin \ 36 | --link postgres \ 37 | --restart always quay.io/keycloak/keycloak:16.1.0 38 | ``` 39 | 40 | 41 | 42 | ### 3. Create a folder "keycloak" in your environment and copy themes folder from docker container 43 | 44 | ``` 45 | mkdir keycloak 46 | cd keycloak 47 | docker cp keycloak:/opt/jboss/keycloak/themes . 48 | ``` 49 | 50 | 51 | ### 4. Clone this repository inside keycloak folder 52 | 53 | ``` 54 | git clone https://github.com/wrsouza/keycloak-theme-vuejs 55 | ``` 56 | 57 | 58 | ### 5. Create a file "disable-theme-cache.cli" inside keycloak folder and insert script bellow. 59 | 60 | ``` 61 | embed-server --std-out=echo --server-config=standalone-ha.xml 62 | /subsystem=keycloak-server/theme=defaults/:write-attribute(name=cacheThemes,value=false) 63 | /subsystem=keycloak-server/theme=defaults/:write-attribute(name=cacheTemplates,value=false) 64 | /subsystem=keycloak-server/theme=defaults/:write-attribute(name=staticMaxAge,value=-1) 65 | stop-embedded-server 66 | 67 | ``` 68 | 69 | 70 | ### 6. Remove keycloak container 71 | ``` 72 | docker rm -f keycloak 73 | ``` 74 | 75 | 76 | ### 7. Run keycloak container with volumes for disable cache and share themes folder 77 | 78 | ``` 79 | docker run -d --name keycloak \ 80 | -p 8080:8080 \ 81 | -e DB_VENDOR=postgres \ 82 | -e DB_ADDR=postgres \ 83 | -e DB_DATABASE=keycloak \ 84 | -e DB_SCHEMA=public \ 85 | -e DB_USER=postgres \ 86 | -e DB_PASSWORD=postgres \ 87 | -e KEYCLOAK_USER=admin \ 88 | -e KEYCLOAK_PASSWORD=admin \ 89 | --link postgres \ 90 | -v ~/keycloak/themes:/opt/jboss/keycloak/themes \ 91 | -v ~/keycloak/disable-theme-cache.cli:/opt/jboss/startup-scripts/disable-theme-cache.cli \ 92 | --restart always quay.io/keycloak/keycloak:16.1.0 93 | ``` 94 | 95 | ### 8. Open keycloak-theme-vuejs repository folder and install with yarn 96 | ``` 97 | cd keycloak-theme-vuejs 98 | yarn 99 | ``` 100 | 101 | ### 9. Configure theme name inside webpack.config.js (THEME_NAME) and run the command bellow 102 | ``` 103 | yarn build 104 | ``` 105 | 106 | ### 10. Open browser with Keycloak URL and click on Administration Console for login 107 | ``` 108 | keycloakUrl: http://localhost:8080 109 | username: admin 110 | password: admin 111 | ``` 112 | 113 | ### 11. Create your realm and select keycloak theme in realm settings. 114 | 115 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-finance", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "dev": "webpack", 8 | "build": "webpack --mode=production" 9 | }, 10 | "devDependencies": { 11 | "@babel/core": "^7.16.7", 12 | "@babel/plugin-transform-runtime": "^7.16.8", 13 | "@babel/plugin-transform-typescript": "^7.16.8", 14 | "@babel/preset-env": "^7.16.8", 15 | "@babel/preset-typescript": "^7.16.7", 16 | "@typescript-eslint/eslint-plugin": "^5.9.1", 17 | "@typescript-eslint/parser": "^5.9.1", 18 | "@vue/compiler-sfc": "^3.2.26", 19 | "autoprefixer": "^10.4.2", 20 | "babel-loader": "^8.2.3", 21 | "clean-webpack-plugin": "^4.0.0", 22 | "copy-webpack-plugin": "^10.2.4", 23 | "css-loader": "^6.5.1", 24 | "eslint": "^7.32.0", 25 | "eslint-config-prettier": "^8.3.0", 26 | "eslint-config-standard": "^16.0.3", 27 | "eslint-import-resolver-typescript": "^2.5.0", 28 | "eslint-plugin-import": "^2.25.4", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-prettier": "^4.0.0", 31 | "eslint-plugin-promise": "^5.2.0", 32 | "eslint-plugin-vue": "^8.3.0", 33 | "html-webpack-plugin": "^5.5.0", 34 | "node-sass": "^7.0.1", 35 | "postcss-loader": "^6.2.1", 36 | "prettier": "^2.5.1", 37 | "sass-loader": "^12.4.0", 38 | "style-loader": "^3.3.1", 39 | "typescript": "^4.5.4", 40 | "vue-loader": "^17.0.0", 41 | "webpack": "^5.66.0", 42 | "webpack-cli": "^4.9.1" 43 | }, 44 | "dependencies": { 45 | "vue": "^3.2.26" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/@types/environment.d.ts: -------------------------------------------------------------------------------- 1 | interface EnvUrl { 2 | registration: string 3 | loginResetCredentials: string 4 | login: string 5 | loginAction: string 6 | registrationAction: string 7 | } 8 | 9 | interface EnvTitle { 10 | loginProfileTitle: string 11 | loginAccountTitle: string 12 | registerTitle: string 13 | emailForgotTitle: string 14 | confirmLinkIdpTitle: string 15 | emailLinkIdpTitle: string 16 | } 17 | 18 | interface EnvPermission { 19 | usernameEditDisabled: boolean 20 | loginWithEmailAllowed: boolean 21 | registrationEmailAsUsername: boolean 22 | rememberMe: boolean 23 | resetPasswordAllowed: boolean 24 | password: boolean 25 | registrationAllowed: boolean 26 | registrationDisabled: boolean 27 | passwordRequired: boolean 28 | } 29 | 30 | interface EnvLabel { 31 | firstName: string 32 | lastName: string 33 | username: string 34 | usernameOrEmail: string 35 | email: string 36 | password: string 37 | passwordConfirm: string 38 | rememberMe: string 39 | doForgotPassword: string 40 | doLogIn: string 41 | doSubmit: string 42 | noAccount: string 43 | doRegister: string 44 | backToLogin: string 45 | confirmLinkIdpContinue: string 46 | doClickHere: string 47 | } 48 | 49 | interface EnvForm { 50 | loginUsername: string 51 | loginRememberMe: boolean 52 | selectedCredential: string 53 | registerFirstName: string 54 | registerLastName: string 55 | registerEmail: string 56 | registerUsername: string 57 | } 58 | 59 | interface EnvUser { 60 | username: string 61 | email: string 62 | firstName: string 63 | lastName: string 64 | } 65 | 66 | interface EnvValidation { 67 | firstName: string 68 | lastName: string 69 | email: string 70 | usernameOrPassword: string 71 | username: string 72 | password: string 73 | passwordConfirm: string 74 | } 75 | 76 | interface EnvMessage { 77 | type: string 78 | sumary: string 79 | } 80 | 81 | interface EnvInstruction { 82 | emailLinkIdp1: string 83 | emailLinkIdp2: string 84 | emailLinkIdp3: string 85 | emailLinkIdp4: string 86 | emailLinkIdp5: string 87 | } 88 | 89 | interface EnvSocial { 90 | alias: string 91 | displayName: string 92 | loginUrl: string 93 | } 94 | 95 | interface Environment { 96 | urls: EnvUrl 97 | titles: EnvTitle 98 | permissions: EnvPermission 99 | labels: EnvLabel 100 | forms: EnvForm 101 | user: EnvUser 102 | validations: EnvValidation 103 | message: EnvMessage 104 | social: EnvSocial[] 105 | instruction: EnvInstruction 106 | } 107 | -------------------------------------------------------------------------------- /src/components/Layout.vue: -------------------------------------------------------------------------------- 1 | 12 | 22 | -------------------------------------------------------------------------------- /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './login' 2 | -------------------------------------------------------------------------------- /src/hooks/login.ts: -------------------------------------------------------------------------------- 1 | import { inject, computed } from 'vue' 2 | 3 | export const useLogin = () => { 4 | const env = inject('environment') as Environment 5 | 6 | const getUrl = (url: string) => { 7 | return url.replace(/(&)/g, '&') 8 | } 9 | const getUsernameLabel = () => { 10 | if (!env.permissions.loginWithEmailAllowed) { 11 | return env.labels.username 12 | } 13 | if (!env.permissions.registrationEmailAsUsername) { 14 | return env.labels.usernameOrEmail 15 | } 16 | return env.labels.email 17 | } 18 | 19 | const getIcon = (type: string | undefined) => { 20 | if (type === 'info') { 21 | return '' 22 | } 23 | if (type === 'error') { 24 | return '' 25 | } 26 | if (type === 'warning') { 27 | return '' 28 | } 29 | if (type === 'success') { 30 | return '' 31 | } 32 | if (type === 'github') { 33 | return '' 34 | } 35 | return '' 36 | } 37 | 38 | const getSumary = (message: string) => { 39 | return message.replace(/(@)/g, '@') 40 | } 41 | 42 | return { 43 | urls: computed(() => env.urls as EnvUrl), 44 | titles: computed(() => env.titles as EnvTitle), 45 | permissions: computed(() => env.permissions as EnvPermission), 46 | labels: computed(() => env.labels as EnvLabel), 47 | forms: computed(() => env.forms as EnvForm), 48 | user: computed(() => env.user as EnvUser), 49 | validations: computed(() => env.validations as EnvValidation), 50 | message: computed(() => env.message as EnvMessage), 51 | social: computed(() => env.social as EnvSocial[]), 52 | instruction: computed(() => env.instruction as EnvInstruction), 53 | getUrl, 54 | getUsernameLabel, 55 | getIcon, 56 | getSumary 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/scss/base/global.scss: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | html, 8 | body { 9 | height: 100%; 10 | } 11 | 12 | body { 13 | background-color: $bgColor; 14 | font-family: $fontBase; 15 | font-weight: $fontWeight; 16 | font-size: $fontSize; 17 | color: $textColor; 18 | } 19 | 20 | #app { 21 | height: 100%; 22 | } 23 | -------------------------------------------------------------------------------- /src/scss/base/variables.scss: -------------------------------------------------------------------------------- 1 | $bgColor: #f7f9fb; 2 | $borderColor: #ccc; 3 | $textColor: #576271; 4 | $fontBase: 'Roboto', sans-serif; 5 | $fontSize: 13px; 6 | $fontWeight: 400; 7 | $red: #c70000; 8 | $lightRed: #ff0000; 9 | $black: #000; 10 | $lightGray: #aaa; 11 | $blue: #378bee; 12 | $darkBlue: #0855ad; 13 | $green: #00db30; 14 | $orange: #ff6600; 15 | $white: #fff; 16 | -------------------------------------------------------------------------------- /src/scss/index.scss: -------------------------------------------------------------------------------- 1 | @import './base/variables'; 2 | @import './base/global'; 3 | 4 | @import './modules/layout.scss'; 5 | @import './modules/form.scss'; 6 | -------------------------------------------------------------------------------- /src/scss/modules/form.scss: -------------------------------------------------------------------------------- 1 | .title { 2 | margin-bottom: 20px; 3 | font-size: 18px; 4 | color: $black; 5 | text-align: center; 6 | } 7 | 8 | .alert { 9 | &-success, 10 | &-error, 11 | &-warning, 12 | &-info { 13 | display: flex; 14 | flex-direction: row; 15 | align-items: center; 16 | justify-content: center; 17 | gap: 10px; 18 | font-size: 12px; 19 | line-height: 20px; 20 | margin-bottom: 10px; 21 | 22 | i { 23 | font-size: 16px; 24 | line-height: 20px; 25 | } 26 | } 27 | 28 | &-success { 29 | color: $green; 30 | } 31 | 32 | &-error { 33 | color: $red; 34 | } 35 | 36 | &-warning { 37 | color: $orange; 38 | } 39 | 40 | &-info { 41 | color: $blue; 42 | } 43 | } 44 | 45 | .row { 46 | display: flex; 47 | flex-direction: row; 48 | gap: 10px; 49 | } 50 | 51 | .form-group { 52 | position: relative; 53 | display: flex; 54 | flex-direction: column; 55 | width: 100%; 56 | margin-bottom: 15px; 57 | 58 | label { 59 | margin-bottom: 2px; 60 | font-size: 11px; 61 | } 62 | 63 | input[type='text'], 64 | input[type='email'], 65 | input[type='password'] { 66 | padding-left: 10px; 67 | width: 100%; 68 | height: 40px; 69 | font-size: 14px; 70 | color: $blue; 71 | line-height: 40px; 72 | border-radius: 3px; 73 | border: 1px solid $borderColor; 74 | outline: none; 75 | background-color: #fff; 76 | 77 | &:focus { 78 | border: 1px solid $blue; 79 | } 80 | 81 | &:active { 82 | border: 1px solid $blue; 83 | } 84 | } 85 | 86 | &.error { 87 | input[type='text'], 88 | input[type='email'], 89 | input[type='password'] { 90 | color: #c70000; 91 | border: 1px solid #c70000; 92 | 93 | &:focus { 94 | border: 1px solid #c70000; 95 | } 96 | 97 | &:active { 98 | border: 1px solid #c70000; 99 | } 100 | } 101 | } 102 | 103 | i { 104 | position: absolute; 105 | right: 15px; 106 | top: 13px; 107 | font-size: 15px; 108 | color: #dfe2e6; 109 | } 110 | 111 | span { 112 | margin-top: 2px; 113 | font-size: 11px; 114 | color: #c70000; 115 | } 116 | } 117 | 118 | .checkbox { 119 | display: flex; 120 | flex-direction: row; 121 | justify-content: space-between; 122 | margin-bottom: 10px; 123 | 124 | label { 125 | display: flex; 126 | flex-direction: row; 127 | align-items: center; 128 | justify-content: flex-start; 129 | gap: 10px; 130 | font-size: 12px; 131 | line-height: 16px; 132 | cursor: pointer; 133 | } 134 | 135 | input { 136 | width: 16px; 137 | height: 16px; 138 | line-height: 16px; 139 | } 140 | 141 | .forgot-password { 142 | font-size: 12px; 143 | color: $blue; 144 | text-decoration: none; 145 | 146 | &:hover { 147 | color: $darkBlue; 148 | text-decoration: underline; 149 | } 150 | 151 | &:active { 152 | color: $darkBlue; 153 | } 154 | } 155 | } 156 | 157 | button[type='submit'] { 158 | margin-bottom: 15px; 159 | width: 100%; 160 | font-size: 14px; 161 | font-weight: bold; 162 | color: $white; 163 | outline: none; 164 | border-radius: 3px; 165 | border: none; 166 | background-color: $blue; 167 | line-height: 40px; 168 | height: 40px; 169 | cursor: pointer; 170 | 171 | &:hover { 172 | background-color: $darkBlue; 173 | } 174 | } 175 | 176 | .register, 177 | .login, 178 | .social { 179 | display: flex; 180 | flex-direction: row; 181 | align-items: center; 182 | justify-content: center; 183 | gap: 7px; 184 | font-size: 12px; 185 | line-height: 16px; 186 | 187 | a { 188 | font-size: 12px; 189 | color: $blue; 190 | text-decoration: none; 191 | 192 | &:hover { 193 | color: $darkBlue; 194 | text-decoration: underline; 195 | } 196 | 197 | &:active { 198 | color: $darkBlue; 199 | } 200 | } 201 | } 202 | 203 | .social { 204 | text-align: center; 205 | margin-top: 15px; 206 | border-top: 2px solid #eee; 207 | padding-top: 15px; 208 | 209 | i { 210 | display: block; 211 | font-size: 30px; 212 | margin-bottom: 5px; 213 | text-decoration: none; 214 | } 215 | 216 | a:hover { 217 | text-decoration: none; 218 | } 219 | } 220 | 221 | .instruction { 222 | margin: 10px auto; 223 | text-align: center; 224 | } 225 | -------------------------------------------------------------------------------- /src/scss/modules/layout.scss: -------------------------------------------------------------------------------- 1 | .layout { 2 | display: flex; 3 | width: 100%; 4 | height: 100%; 5 | align-items: center; 6 | justify-content: center; 7 | 8 | &-box { 9 | display: flex; 10 | flex-direction: row; 11 | align-items: stretch; 12 | justify-content: stretch; 13 | width: 840px; 14 | min-height: 440px; 15 | background: #fff; 16 | border-radius: 7px; 17 | box-shadow: 0 1px 10px rgba(0, 0, 0, 0.2); 18 | 19 | &-img { 20 | display: flex; 21 | width: 420px; 22 | min-height: 100%; 23 | background: url('https://unsplash.com/photos/hpjSkU2UYSU/download?ixid=MnwxMjA3fDB8MXxzZWFyY2h8MTN8fGVjb21tZXJjZXx8MHx8fHwxNjQzNzkyMzQw&force=true&w=640'); 24 | background-position: center; 25 | background-size: cover; 26 | border-radius: 7px 0 0 7px; 27 | } 28 | 29 | &-form { 30 | display: flex; 31 | flex-direction: column; 32 | justify-content: center; 33 | width: 420px; 34 | min-height: 100%; 35 | padding: 30px; 36 | 37 | .logo { 38 | display: flex; 39 | flex-direction: row; 40 | align-items: center; 41 | justify-content: center; 42 | gap: 10px; 43 | font-size: 20px; 44 | font-weight: bold; 45 | color: $darkBlue; 46 | text-align: center; 47 | margin-bottom: 20px; 48 | 49 | i { 50 | font-size: 30px; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | declare module '*' { 3 | import type { DefineComponent } from 'vue' 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /src/static/messages/messages_en.properties: -------------------------------------------------------------------------------- 1 | doLogIn=Sign In 2 | doRegister=Register 3 | doCancel=Cancel 4 | doSubmit=Send 5 | doBack=Back 6 | doYes=Yes 7 | doNo=No 8 | doContinue=Continue 9 | doIgnore=Ignore 10 | doAccept=Accept 11 | doDecline=Decline 12 | doForgotPassword=Forgot Password? 13 | doClickHere=Click here 14 | doImpersonate=Impersonate 15 | doTryAgain=Try again 16 | doTryAnotherWay=Try Another Way 17 | doConfirmDelete=Confirm deletion 18 | errorDeletingAccount=Error happened while deleting account 19 | deletingAccountForbidden=You do not have enough permissions to delete your own account, contact admin. 20 | kerberosNotConfigured=Kerberos Not Configured 21 | kerberosNotConfiguredTitle=Kerberos Not Configured 22 | bypassKerberosDetail=Either you are not logged in by Kerberos or your browser is not set up for Kerberos login. Please click continue to login in through other means 23 | kerberosNotSetUp=Kerberos is not set up. You cannot login. 24 | registerTitle=Register 25 | loginAccountTitle=Sign in to your account 26 | loginTitle=Sign in to {0} 27 | loginTitleHtml={0} 28 | impersonateTitle={0} Impersonate User 29 | impersonateTitleHtml={0} Impersonate User 30 | realmChoice=Realm 31 | unknownUser=Unknown user 32 | loginTotpTitle=Mobile Authenticator Setup 33 | loginProfileTitle=Update Account Information 34 | loginTimeout=Your login attempt timed out. Login will start from the beginning. 35 | oauthGrantTitle=Grant Access to {0} 36 | oauthGrantTitleHtml={0} 37 | errorTitle=We are sorry... 38 | errorTitleHtml=We are sorry ... 39 | emailVerifyTitle=Email verification 40 | emailForgotTitle=Forgot Your Password? 41 | updatePasswordTitle=Update password 42 | codeSuccessTitle=Success code 43 | codeErrorTitle=Error code\: {0} 44 | displayUnsupported=Requested display type unsupported 45 | browserRequired=Browser required to login 46 | browserContinue=Browser required to complete login 47 | browserContinuePrompt=Open browser and continue login? [y/n]: 48 | browserContinueAnswer=y 49 | 50 | 51 | termsTitle=Terms and Conditions 52 | termsText=

Terms and conditions to be defined

53 | termsPlainText=Terms and conditions to be defined. 54 | 55 | recaptchaFailed=Invalid Recaptcha 56 | recaptchaNotConfigured=Recaptcha is required, but not configured 57 | consentDenied=Consent denied. 58 | 59 | noAccount=New user? 60 | username=Username 61 | usernameOrEmail=Username or email 62 | firstName=First name 63 | givenName=Given name 64 | company=Company 65 | cnpj=CNPJ 66 | phone=Phone 67 | mobile=Mobile 68 | fullName=Full name 69 | lastName=Last name 70 | familyName=Family name 71 | email=Email 72 | password=Password 73 | passwordConfirm=Confirm password 74 | passwordNew=New Password 75 | passwordNewConfirm=New Password confirmation 76 | rememberMe=Remember me 77 | authenticatorCode=One-time code 78 | address=Address 79 | street=Street 80 | locality=City or Locality 81 | region=State, Province, or Region 82 | postal_code=Zip or Postal code 83 | country=Country 84 | emailVerified=Email verified 85 | website=Web page 86 | phoneNumber=Phone number 87 | phoneNumberVerified=Phone number verified 88 | gender=Gender 89 | birthday=Birthdate 90 | zoneinfo=Time zone 91 | gssDelegationCredential=GSS Delegation Credential 92 | logoutOtherSessions=Sign out from other devices 93 | 94 | profileScopeConsentText=User profile 95 | emailScopeConsentText=Email address 96 | addressScopeConsentText=Address 97 | phoneScopeConsentText=Phone number 98 | offlineAccessScopeConsentText=Offline Access 99 | samlRoleListScopeConsentText=My Roles 100 | rolesScopeConsentText=User roles 101 | 102 | restartLoginTooltip=Restart login 103 | 104 | loginTotpIntro=You need to set up a One Time Password generator to access this account 105 | loginTotpStep1=Install one of the following applications on your mobile: 106 | loginTotpStep2=Open the application and scan the barcode: 107 | loginTotpStep3=Enter the one-time code provided by the application and click Submit to finish the setup. 108 | loginTotpStep3DeviceName=Provide a Device Name to help you manage your OTP devices. 109 | loginTotpManualStep2=Open the application and enter the key: 110 | loginTotpManualStep3=Use the following configuration values if the application allows setting them: 111 | loginTotpUnableToScan=Unable to scan? 112 | loginTotpScanBarcode=Scan barcode? 113 | loginCredential=Credential 114 | loginOtpOneTime=One-time code 115 | loginTotpType=Type 116 | loginTotpAlgorithm=Algorithm 117 | loginTotpDigits=Digits 118 | loginTotpInterval=Interval 119 | loginTotpCounter=Counter 120 | loginTotpDeviceName=Device Name 121 | 122 | loginTotp.totp=Time-based 123 | loginTotp.hotp=Counter-based 124 | 125 | loginChooseAuthenticator=Select login method 126 | 127 | oauthGrantRequest=Do you grant these access privileges? 128 | inResource=in 129 | 130 | emailVerifyInstruction1=An email with instructions to verify your email address has been sent to you. 131 | emailVerifyInstruction2=Haven''t received a verification code in your email? 132 | emailVerifyInstruction3=to re-send the email. 133 | 134 | emailLinkIdpTitle=Link {0} 135 | emailLinkIdp1=An email with instructions to link {0} account {1} with your {2} account has been sent to you. 136 | emailLinkIdp2=Haven''t received a verification code in your email? 137 | emailLinkIdp3=to re-send the email. 138 | emailLinkIdp4=If you already verified the email in different browser 139 | emailLinkIdp5=to continue. 140 | 141 | backToLogin=« Back to Login 142 | 143 | emailInstruction=Enter your username or email address and we will send you instructions on how to create a new password. 144 | 145 | copyCodeInstruction=Please copy this code and paste it into your application: 146 | 147 | pageExpiredTitle=Page has expired 148 | pageExpiredMsg1=To restart the login process 149 | pageExpiredMsg2=To continue the login process 150 | 151 | personalInfo=Personal Info: 152 | role_admin=Admin 153 | role_realm-admin=Realm Admin 154 | role_create-realm=Create realm 155 | role_create-client=Create client 156 | role_view-realm=View realm 157 | role_view-users=View users 158 | role_view-applications=View applications 159 | role_view-clients=View clients 160 | role_view-events=View events 161 | role_view-identity-providers=View identity providers 162 | role_manage-realm=Manage realm 163 | role_manage-users=Manage users 164 | role_manage-applications=Manage applications 165 | role_manage-identity-providers=Manage identity providers 166 | role_manage-clients=Manage clients 167 | role_manage-events=Manage events 168 | role_view-profile=View profile 169 | role_manage-account=Manage account 170 | role_manage-account-links=Manage account links 171 | role_read-token=Read token 172 | role_offline-access=Offline access 173 | client_account=Account 174 | client_account-console=Account Console 175 | client_security-admin-console=Security Admin Console 176 | client_admin-cli=Admin CLI 177 | client_realm-management=Realm Management 178 | client_broker=Broker 179 | 180 | requiredFields=Required fields 181 | 182 | invalidUserMessage=Invalid username or password. 183 | invalidUsernameMessage=Invalid username. 184 | invalidUsernameOrEmailMessage=Invalid username or email. 185 | invalidPasswordMessage=Invalid password. 186 | invalidEmailMessage=Invalid email address. 187 | accountDisabledMessage=Account is disabled, contact your administrator. 188 | accountTemporarilyDisabledMessage=Account is temporarily disabled; contact your administrator or retry later. 189 | expiredCodeMessage=Login timeout. Please sign in again. 190 | expiredActionMessage=Action expired. Please continue with login now. 191 | expiredActionTokenNoSessionMessage=Action expired. 192 | expiredActionTokenSessionExistsMessage=Action expired. Please start again. 193 | 194 | missingFirstNameMessage=Please specify first name. 195 | missingLastNameMessage=Please specify last name. 196 | missingEmailMessage=Please specify email. 197 | missingUsernameMessage=Please specify username. 198 | missingPasswordMessage=Please specify password. 199 | missingTotpMessage=Please specify authenticator code. 200 | missingTotpDeviceNameMessage=Please specify device name. 201 | notMatchPasswordMessage=Passwords don''t match. 202 | 203 | invalidPasswordExistingMessage=Invalid existing password. 204 | invalidPasswordBlacklistedMessage=Invalid password: password is blacklisted. 205 | invalidPasswordConfirmMessage=Password confirmation doesn''t match. 206 | invalidTotpMessage=Invalid authenticator code. 207 | 208 | usernameExistsMessage=Username already exists. 209 | emailExistsMessage=Email already exists. 210 | 211 | federatedIdentityExistsMessage=User with {0} {1} already exists. Please login to account management to link the account. 212 | 213 | confirmLinkIdpTitle=Account already exists 214 | federatedIdentityConfirmLinkMessage=User with {0} {1} already exists. How do you want to continue? 215 | federatedIdentityConfirmReauthenticateMessage=Authenticate to link your account with {0} 216 | nestedFirstBrokerFlowMessage=The {0} user {1} is not linked to any known user. 217 | confirmLinkIdpReviewProfile=Review profile 218 | confirmLinkIdpContinue=Add to existing account 219 | 220 | configureTotpMessage=You need to set up Mobile Authenticator to activate your account. 221 | updateProfileMessage=You need to update your user profile to activate your account. 222 | updatePasswordMessage=You need to change your password to activate your account. 223 | resetPasswordMessage=You need to change your password. 224 | verifyEmailMessage=You need to verify your email address to activate your account. 225 | linkIdpMessage=You need to verify your email address to link your account with {0}. 226 | 227 | emailSentMessage=You should receive an email shortly with further instructions. 228 | emailSendErrorMessage=Failed to send email, please try again later. 229 | 230 | accountUpdatedMessage=Your account has been updated. 231 | accountPasswordUpdatedMessage=Your password has been updated. 232 | 233 | delegationCompleteHeader=Login Successful 234 | delegationCompleteMessage=You may close this browser window and go back to your console application. 235 | delegationFailedHeader=Login Failed 236 | delegationFailedMessage=You may close this browser window and go back to your console application and try logging in again. 237 | 238 | noAccessMessage=No access 239 | 240 | invalidPasswordMinLengthMessage=Invalid password: minimum length {0}. 241 | invalidPasswordMinDigitsMessage=Invalid password: must contain at least {0} numerical digits. 242 | invalidPasswordMinLowerCaseCharsMessage=Invalid password: must contain at least {0} lower case characters. 243 | invalidPasswordMinUpperCaseCharsMessage=Invalid password: must contain at least {0} upper case characters. 244 | invalidPasswordMinSpecialCharsMessage=Invalid password: must contain at least {0} special characters. 245 | invalidPasswordNotUsernameMessage=Invalid password: must not be equal to the username. 246 | invalidPasswordNotEmailMessage=Invalid password: must not be equal to the email. 247 | invalidPasswordRegexPatternMessage=Invalid password: fails to match regex pattern(s). 248 | invalidPasswordHistoryMessage=Invalid password: must not be equal to any of last {0} passwords. 249 | invalidPasswordGenericMessage=Invalid password: new password doesn''t match password policies. 250 | 251 | failedToProcessResponseMessage=Failed to process response 252 | httpsRequiredMessage=HTTPS required 253 | realmNotEnabledMessage=Realm not enabled 254 | invalidRequestMessage=Invalid Request 255 | failedLogout=Logout failed 256 | unknownLoginRequesterMessage=Unknown login requester 257 | loginRequesterNotEnabledMessage=Login requester not enabled 258 | bearerOnlyMessage=Bearer-only applications are not allowed to initiate browser login 259 | standardFlowDisabledMessage=Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client. 260 | implicitFlowDisabledMessage=Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client. 261 | invalidRedirectUriMessage=Invalid redirect uri 262 | unsupportedNameIdFormatMessage=Unsupported NameIDFormat 263 | invalidRequesterMessage=Invalid requester 264 | registrationNotAllowedMessage=Registration not allowed 265 | resetCredentialNotAllowedMessage=Reset Credential not allowed 266 | 267 | permissionNotApprovedMessage=Permission not approved. 268 | noRelayStateInResponseMessage=No relay state in response from identity provider. 269 | insufficientPermissionMessage=Insufficient permissions to link identities. 270 | couldNotProceedWithAuthenticationRequestMessage=Could not proceed with authentication request to identity provider. 271 | couldNotObtainTokenMessage=Could not obtain token from identity provider. 272 | unexpectedErrorRetrievingTokenMessage=Unexpected error when retrieving token from identity provider. 273 | unexpectedErrorHandlingResponseMessage=Unexpected error when handling response from identity provider. 274 | identityProviderAuthenticationFailedMessage=Authentication failed. Could not authenticate with identity provider. 275 | couldNotSendAuthenticationRequestMessage=Could not send authentication request to identity provider. 276 | unexpectedErrorHandlingRequestMessage=Unexpected error when handling authentication request to identity provider. 277 | invalidAccessCodeMessage=Invalid access code. 278 | sessionNotActiveMessage=Session not active. 279 | invalidCodeMessage=An error occurred, please login again through your application. 280 | identityProviderUnexpectedErrorMessage=Unexpected error when authenticating with identity provider 281 | identityProviderMissingStateMessage=Missing state parameter in response from identity provider. 282 | identityProviderNotFoundMessage=Could not find an identity provider with the identifier. 283 | identityProviderLinkSuccess=You successfully verified your email. Please go back to your original browser and continue there with the login. 284 | staleCodeMessage=This page is no longer valid, please go back to your application and sign in again 285 | realmSupportsNoCredentialsMessage=Realm does not support any credential type. 286 | credentialSetupRequired=Cannot login, credential setup required. 287 | identityProviderNotUniqueMessage=Realm supports multiple identity providers. Could not determine which identity provider should be used to authenticate with. 288 | emailVerifiedMessage=Your email address has been verified. 289 | staleEmailVerificationLink=The link you clicked is an old stale link and is no longer valid. Maybe you have already verified your email. 290 | identityProviderAlreadyLinkedMessage=Federated identity returned by {0} is already linked to another user. 291 | confirmAccountLinking=Confirm linking the account {0} of identity provider {1} with your account. 292 | confirmEmailAddressVerification=Confirm validity of e-mail address {0}. 293 | confirmExecutionOfActions=Perform the following action(s) 294 | 295 | locale_ca=Catal\u00E0 296 | locale_cs=\u010Ce\u0161tina 297 | locale_da=Dansk 298 | locale_de=Deutsch 299 | locale_en=English 300 | locale_es=Espa\u00F1ol 301 | locale_fr=Fran\u00E7ais 302 | locale_hu=Magyar 303 | locale_it=Italiano 304 | locale_ja=\u65E5\u672C\u8A9E 305 | locale_lt=Lietuvi\u0173 306 | locale_nl=Nederlands 307 | locale_no=Norsk 308 | locale_pl=Polski 309 | locale_pt_BR=Portugu\u00EAs (Brasil) 310 | locale_pt-BR=Portugu\u00EAs (Brasil) 311 | locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439 312 | locale_sk=Sloven\u010Dina 313 | locale_sv=Svenska 314 | locale_tr=T\u00FCrk\u00E7e 315 | locale_zh-CN=\u4E2D\u6587\u7B80\u4F53 316 | 317 | backToApplication=« Back to Application 318 | missingParameterMessage=Missing parameters\: {0} 319 | clientNotFoundMessage=Client not found. 320 | clientDisabledMessage=Client disabled. 321 | invalidParameterMessage=Invalid parameter\: {0} 322 | alreadyLoggedIn=You are already logged in. 323 | differentUserAuthenticated=You are already authenticated as different user ''{0}'' in this session. Please sign out first. 324 | brokerLinkingSessionExpired=Requested broker account linking, but current session is no longer valid. 325 | proceedWithAction=» Click here to proceed 326 | 327 | requiredAction.CONFIGURE_TOTP=Configure OTP 328 | requiredAction.terms_and_conditions=Terms and Conditions 329 | requiredAction.UPDATE_PASSWORD=Update Password 330 | requiredAction.UPDATE_PROFILE=Update Profile 331 | requiredAction.VERIFY_EMAIL=Verify Email 332 | 333 | doX509Login=You will be logged in as\: 334 | clientCertificate=X509 client certificate\: 335 | noCertificate=[No Certificate] 336 | 337 | 338 | pageNotFound=Page not found 339 | internalServerError=An internal server error has occurred 340 | 341 | console-username=Username: 342 | console-password=Password: 343 | console-otp=One Time Password: 344 | console-new-password=New Password: 345 | console-confirm-password=Confirm Password: 346 | console-update-password=Update of your password is required. 347 | console-verify-email=You need to verify your email address. We sent an email to {0} that contains a verification code. Please enter this code into the input below. 348 | console-email-code=Email Code: 349 | console-accept-terms=Accept Terms? [y/n]: 350 | console-accept=y 351 | 352 | # Openshift messages 353 | openshift.scope.user_info=User information 354 | openshift.scope.user_check-access=User access information 355 | openshift.scope.user_full=Full Access 356 | openshift.scope.list-projects=List projects 357 | 358 | # SAML authentication 359 | saml.post-form.title=Authentication Redirect 360 | saml.post-form.message=Redirecting, please wait. 361 | saml.post-form.js-disabled=JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue. 362 | 363 | #authenticators 364 | otp-display-name=Authenticator Application 365 | otp-help-text=Enter a verification code from authenticator application. 366 | password-display-name=Password 367 | password-help-text=Sign in by entering your password. 368 | auth-username-form-display-name=Username 369 | auth-username-form-help-text=Start sign in by entering your username 370 | auth-username-password-form-display-name=Username and password 371 | auth-username-password-form-help-text=Sign in by entering your username and password. 372 | 373 | # WebAuthn 374 | webauthn-display-name=Security Key 375 | webauthn-help-text=Use your security key to sign in. 376 | webauthn-passwordless-display-name=Security Key 377 | webauthn-passwordless-help-text=Use your security key for passwordless sign in. 378 | webauthn-login-title=Security Key login 379 | webauthn-registration-title=Security Key Registration 380 | webauthn-available-authenticators=Available authenticators 381 | webauthn-unsupported-browser-text=WebAuthn is not supported by this browser. Try another one or contact your administrator. 382 | 383 | # WebAuthn Error 384 | webauthn-error-title=Security Key Error 385 | webauthn-error-registration=Failed to register your Security key.
{0} 386 | webauthn-error-api-get=Failed to authenticate by the Security key.
{0} 387 | webauthn-error-different-user=First authenticated user is not the one authenticated by the Security key. 388 | webauthn-error-auth-verification=Security key authentication result is invalid.
{0} 389 | webauthn-error-register-verification=Security key registration result is invalid.
{0} 390 | webauthn-error-user-not-found=Unknown user authenticated by the Security key. 391 | 392 | # Identity provider 393 | identity-provider-redirector=Connect with another Identity Provider 394 | identity-provider-login-label=Or sign in with 395 | 396 | finalDeletionConfirmation=If you delete your account, it cannot be restored. To keep your account, click Cancel. 397 | irreversibleAction=This action is irreversible 398 | deleteAccountConfirm=Delete account confirmation 399 | 400 | deletingImplies=Deleting your account implies: 401 | errasingData=Erasing all your data 402 | loggingOutImmediately=Logging you out immediately 403 | accountUnusable=Any subsequent use of the application will not be possible with this account 404 | userDeletedSuccessfully=User deleted successfully 405 | 406 | -------------------------------------------------------------------------------- /src/static/messages/messages_pt_BR.properties: -------------------------------------------------------------------------------- 1 | doLogIn=Entrar 2 | doRegister=Cadastre-se 3 | doCancel=Cancelar 4 | doSubmit=Enviar 5 | doBack=Voltar 6 | doYes=Sim 7 | doNo=N\u00E3o 8 | doContinue=Continuar 9 | doIgnore=Ignorar 10 | doAccept=Aceitar 11 | doDecline=Rejeitar 12 | doForgotPassword=Esqueceu sua senha? 13 | doClickHere=Clique aqui 14 | doImpersonate=Personificar 15 | doTryAgain=Tente novamente 16 | doTryAnotherWay=Tente outra forma 17 | kerberosNotConfigured=Kerberos N\u00E3o Configurado 18 | kerberosNotConfiguredTitle=Kerberos N\u00E3o Configurado 19 | bypassKerberosDetail=Ou voc\u00EA n\u00E3o est\u00E1 logado via Kerberos ou o seu navegador n\u00E3o est\u00E1 configurado para login Kerberos. Por favor, clique em continuar para fazer o login no atrav\u00E9s de outros meios 20 | kerberosNotSetUp=Kerberos n\u00E3o est\u00E1 configurado. Voc\u00EA n\u00E3o pode acessar. 21 | registerTitle=Crie sua Conta 22 | loginAccountTitle=Fa\u00E7a Login em sua conta 23 | loginTitle=Entrar em {0} 24 | loginTitleHtml={0} 25 | impersonateTitle={0} Personificar Usu\u00E1rio 26 | impersonateTitleHtml={0} Personificar Usu\u00E1rio 27 | realmChoice=Dom\u00EDnio 28 | unknownUser=Usu\u00E1rio desconhecido 29 | loginTotpTitle=Configura\u00E7\u00E3o do autenticador mobile 30 | loginProfileTitle=Atualiza\u00E7\u00E3o das Informa\u00E7\u00F5es da Conta 31 | loginTimeout=Voc\u00EA demorou muito para entrar. Por favor, refa\u00E7a o processo de login a partir do in\u00EDcio. 32 | oauthGrantTitle=Concess\u00E3o OAuth 33 | oauthGrantTitleHtml={0} 34 | errorTitle=N\u00F3s lamentamos... 35 | errorTitleHtml=N\u00F3s lamentamos ... 36 | emailVerifyTitle=Verifica\u00E7\u00E3o de e-mail 37 | emailForgotTitle=Esqueceu sua senha? 38 | updatePasswordTitle=Atualiza\u00E7\u00E3o de senha 39 | codeSuccessTitle=C\u00F3digo de sucesso 40 | codeErrorTitle=C\u00F3digo de erro\: {0} 41 | displayUnsupported=Tipo de exibi\u00E7\u00E3o solicitado n\u00E3o suportado 42 | browserRequired=Navegador necess\u00E1rio para efetuar login 43 | browserContinue=Navegador necess\u00E1rio para concluir o login 44 | browserContinuePrompt=Abrir navegador e continuar o login? [s/n]: 45 | browserContinueAnswer=s 46 | 47 | 48 | termsTitle=Termos e Condi\u00E7\u00F5es 49 | termsText=

Termos e condi\u00E7\u00F5es a serem definidos

50 | termsPlainText=Termos e condi\u00E7\u00F5es a serem definidos. 51 | 52 | recaptchaFailed=Recaptcha inv\u00E1lido 53 | recaptchaNotConfigured=Recaptcha \u00E9 requerido, mas n\u00E3o foi configurado 54 | consentDenied=Consentimento negado. 55 | 56 | noAccount=Novo usu\u00E1rio? 57 | username=Nome de usu\u00E1rio 58 | usernameOrEmail=Nome de usu\u00E1rio ou e-mail 59 | firstName=Primeiro nome 60 | givenName=Primeiro nome 61 | company=Empresa 62 | cnpj=CNPJ 63 | phone=Telefone 64 | mobile=Celular 65 | fullName=Nome completo 66 | lastName=Sobrenome 67 | familyName=Sobrenome 68 | email=E-mail 69 | password=Senha 70 | passwordConfirm=Confirme a senha 71 | passwordNew=Nova senha 72 | passwordNewConfirm=Confirma\u00E7\u00E3o da nova senha 73 | rememberMe=Mantenha-me conectado 74 | authenticatorCode=C\u00F3digo autenticador 75 | address=Endere\u00E7o 76 | street=Logradouro 77 | locality=Cidade ou localidade 78 | region=Estado 79 | postal_code=CEP 80 | country=Pa\u00EDs 81 | emailVerified=E-mail verificado 82 | gssDelegationCredential=Delega\u00E7\u00E3o de Credenciais GSS 83 | 84 | profileScopeConsentText=Perfil de usu\u00E1rio 85 | emailScopeConsentText=Endere\u00E7o de e-mail 86 | addressScopeConsentText=Endere\u00E7o 87 | phoneScopeConsentText=N\u00FAmero de telefone 88 | offlineAccessScopeConsentText=Acesso Offline 89 | samlRoleListScopeConsentText=Meus Perfis de Acesso 90 | rolesScopeConsentText=Perfis de Acesso do Usu\u00E1rio 91 | 92 | restartLoginTooltip=Reiniciar o login 93 | 94 | loginTotpIntro=Voc\u00EA precisa configurar um gerador de c\u00F3digo de uso \u00FAnico para acessar esta conta 95 | loginTotpStep1=Instale um dos seguintes aplicativos no seu celular: 96 | loginTotpStep2=Abra o aplicativo e leia o QRCode: 97 | loginTotpStep3=Digite o c\u00F3digo \u00FAnico fornecido pelo aplicativo e clique em Ok para concluir a configura\u00E7\u00E3o. 98 | loginTotpStep3DeviceName=Forne\u00E7a um nome de dispositivo para ajud\u00E1-lo a gerenciar seus dispositivos OTP. 99 | loginTotpManualStep2=Abra o aplicativo e digite a chave: 100 | loginTotpManualStep3=Use os seguintes valores de configura\u00E7\u00E3o se o aplicativo permitir defini-los: 101 | loginTotpUnableToScan=N\u00E3o foi poss\u00EDvel ler o QRCode? 102 | loginTotpScanBarcode=Ler QRCode? 103 | loginCredential=Credencial 104 | loginOtpOneTime=C\u00F3digo \u00FAnico 105 | loginTotpType=Tipo 106 | loginTotpAlgorithm=Algoritmo 107 | loginTotpDigits=D\u00EDgitos 108 | loginTotpInterval=Intervalo 109 | loginTotpCounter=Contador 110 | loginTotpDeviceName=Nome do dispositivo 111 | 112 | loginTotp.totp=Baseado em tempo 113 | loginTotp.hotp=Baseado em contador 114 | 115 | loginChooseAuthenticator=Selecione o m\u00E9todo de login 116 | 117 | oauthGrantRequest=Voc\u00EA concede esses privil\u00E9gios de acesso? 118 | inResource=em 119 | 120 | emailVerifyInstruction1=Um e-mail com instru\u00E7\u00F5es para verificar o seu endere\u00E7o de e-mail foi enviado para voc\u00EA. 121 | emailVerifyInstruction2=N\u00E3o recebeu um c\u00F3digo de verifica\u00E7\u00E3o em seu e-mail? 122 | emailVerifyInstruction3=para reenviar o e-mail. 123 | 124 | emailLinkIdpTitle=Vincular {0} 125 | emailLinkIdp1=Um e-mail com instru\u00E7\u00F5es para vincular a conta {0} {1} com sua conta {2} foi enviado para voc\u00EA. 126 | emailLinkIdp2=N\u00E3o recebeu um c\u00F3digo de verifica\u00E7\u00E3o no e-mail? 127 | emailLinkIdp3=para reenviar o e-mail. 128 | emailLinkIdp4=Se voc\u00EA j\u00E1 verificou o email em outro navegador 129 | emailLinkIdp5=para continuar. 130 | 131 | backToLogin=« Voltar ao Login 132 | 133 | emailInstruction=Digite seu nome de usu\u00E1rio ou endere\u00E7o de e-mail e n\u00F3s lhe enviaremos instru\u00E7\u00F5es sobre como criar uma nova senha. 134 | 135 | copyCodeInstruction=Por favor, copie o c\u00F3digo e cole-o em seu aplicativo: 136 | 137 | pageExpiredTitle=A p\u00E1gina expirou 138 | pageExpiredMsg1=Para reiniciar o processo de login 139 | pageExpiredMsg2=Para continuar o processo de login 140 | 141 | personalInfo=Informa\u00E7\u00F5es Pessoais: 142 | role_admin=Admininstrador 143 | role_realm-admin=Admininstrador do Dom\u00EDnio 144 | role_create-realm=Criar dom\u00EDnio 145 | role_create-client=Criar cliente 146 | role_view-realm=Visualizar dom\u00EDnio 147 | role_view-users=Visualizar usu\u00E1rios 148 | role_view-applications=Visualizar aplicativos 149 | role_view-clients=Visualizar clientes 150 | role_view-events=Visualizar eventos 151 | role_view-identity-providers=Visualizar provedores de identidade 152 | role_manage-realm=Gerenciar dom\u00EDnio 153 | role_manage-users=Gerenciar usu\u00E1rios 154 | role_manage-applications=Gerenciar aplicativos 155 | role_manage-identity-providers=Gerenciar provedores de identidade 156 | role_manage-clients=Gerenciar clientes 157 | role_manage-events=Gerenciar eventos 158 | role_view-profile=Visualizar perfil 159 | role_manage-account=Gerenciar contas 160 | role_manage-account-links=Gerenciar v\00ED nculos de conta 161 | role_read-token=Ler token 162 | role_offline-access=Acesso offline 163 | client_account=Conta 164 | client_account-console=Console da Conta 165 | client_security-admin-console=Console de Administra\u00E7\u00E3o de Seguran\u00E7a 166 | client_admin-cli=Admin CLI 167 | client_realm-management=Gerenciamento de Dom\u00EDnio 168 | client_broker=Provedor de Identidade 169 | 170 | requiredFields=Campos obrigat\u00F3rios 171 | 172 | invalidUserMessage=Nome de usu\u00E1rio ou senha inv\u00E1lida. 173 | invalidUsernameMessage=Nome de usu\u00E1rio inv\u00E1lido. 174 | invalidUsernameOrEmailMessage=Nome de usu\u00E1rio ou e-mail inv\u00E1lido. 175 | invalidPasswordMessage=Senha inv\u00E1lida. 176 | invalidEmailMessage=E-mail inv\u00E1lido. 177 | accountDisabledMessage=Conta desativada, contate o administrador. 178 | accountTemporarilyDisabledMessage=Conta temporariamente indispon\u00EDvel, contate o administrador ou tente novamente mais tarde. 179 | expiredCodeMessage=Tempo de login expirado. Por favor, fa\u00E7a login novamente. 180 | expiredActionMessage=A\u00E7\u00E3o expirada. Por favor, continue com o login agora. 181 | expiredActionTokenNoSessionMessage=A\u00E7\u00E3o expirada. 182 | expiredActionTokenSessionExistsMessage=A\u00E7\u00E3o expirada. Por favor, comece novamente. 183 | 184 | missingFirstNameMessage=Por favor, informe o primeiro nome. 185 | missingLastNameMessage=Por favor, informe o sobrenome. 186 | missingEmailMessage=Por favor, informe o e-mail. 187 | missingUsernameMessage=Por favor, informe o nome de usu\u00E1rio. 188 | missingPasswordMessage=Por favor, informe a senha. 189 | missingTotpMessage=Por favor, informe o c\u00F3digo autenticador. 190 | missingTotpDeviceNameMessage=Por favor, informe o nome do dispositivo. 191 | notMatchPasswordMessage=As senhas n\u00E3o coincidem. 192 | 193 | invalidPasswordExistingMessage=Senha atual inv\u00E1lida. 194 | invalidPasswordBlacklistedMessage=Senha inv\u00E1lida de acordo com as pol\u00EDticas estabelecidas para o dom\u00EDnio. 195 | invalidPasswordConfirmMessage=Senha de confirma\u00E7\u00E3o n\u00E3o coincide. 196 | invalidTotpMessage=C\u00F3digo autenticador inv\u00E1lido. 197 | 198 | usernameExistsMessage=Nome de usu\u00E1rio j\u00E1 existe. 199 | emailExistsMessage=E-mail j\u00E1 existe. 200 | 201 | federatedIdentityExistsMessage=Usu\u00E1rio com {0} {1} j\u00E1 existe. Por favor, entre em gerenciamento de contas para vincular a conta. 202 | 203 | confirmLinkIdpTitle=Conta j\u00E1 existente 204 | federatedIdentityConfirmLinkMessage=Usu\u00E1rio com {0} {1} j\u00E1 existe. Como voc\u00EA quer continuar? 205 | federatedIdentityConfirmReauthenticateMessage=Autenticar para vincular sua conta com {0} 206 | confirmLinkIdpReviewProfile=Revisar informa\u00E7\u00F5es do perfil 207 | confirmLinkIdpContinue=Vincular \u00E0 conta existente 208 | 209 | configureTotpMessage=Voc\u00EA precisa configurar seu celular com o autenticador Mobile para ativar sua conta. 210 | updateProfileMessage=Voc\u00EA precisa atualizar o seu perfil de usu\u00E1rio para ativar sua conta. 211 | updatePasswordMessage=Voc\u00EA precisa mudar sua senha para ativar sua conta. 212 | resetPasswordMessage=Voc\u00EA precisa mudar sua senha. 213 | verifyEmailMessage=Voc\u00EA precisa verificar o seu endere\u00E7o de e-mail para ativar sua conta. 214 | linkIdpMessage=Voc\u00EA precisa confirmar o seu endere\u00E7o de e-mail para vincular sua conta com {0}. 215 | 216 | emailSentMessage=Voc\u00EA dever\u00E1 receber um e-mail em breve com mais instru\u00E7\u00F5es. 217 | emailSendErrorMessage=Falha ao enviar e-mail, por favor, tente novamente mais tarde. 218 | 219 | accountUpdatedMessage=Sua conta foi atualizada. 220 | accountPasswordUpdatedMessage=Sua senha foi atualizada. 221 | 222 | delegationCompleteHeader=Autentica\u00E7\u00E3o Bem Sucedida 223 | delegationCompleteMessage=YVoc\00EA pode fechar esta janela do navegador e voltar ao seu aplicativo. 224 | delegationFailedHeader=Falha na Autentica\u00E7\u00E3o 225 | delegationFailedMessage=Voc\u00EA pode fechar esta janela do navegador e voltar ao aplicativo e tentar fazer login novamente. 226 | 227 | noAccessMessage=Sem acesso 228 | 229 | invalidPasswordMinLengthMessage=Senha inv\u00E1lida\: comprimento m\u00EDnimo {0} 230 | invalidPasswordMinDigitsMessage=Senha inv\u00E1lida\: deve conter pelo menos {0} n\u00FAmero(s) 231 | invalidPasswordMinLowerCaseCharsMessage=Senha inv\u00E1lida\: deve conter pelo menos {0} caractere(s) min\u00FAsculo 232 | invalidPasswordMinUpperCaseCharsMessage=Senha inv\u00E1lida\: deve conter pelo menos {0} caractere(s) mai\u00FAsculo 233 | invalidPasswordMinSpecialCharsMessage=Senha inv\u00E1lida\: deve conter pelo menos {0} caractere(s) especial 234 | invalidPasswordNotUsernameMessage=Senha inv\u00E1lida\: n\u00E3o deve ser igual ao nome de usu\u00E1rio 235 | invalidPasswordRegexPatternMessage=Senha inv\u00E1lida\: n\u00E3o corresponde ao padr\u00E3o da express\u00E3o regular. 236 | invalidPasswordHistoryMessage=Senha inv\u00E1lida\: n\u00E3o pode ser igual a qualquer uma das {0} \u00FAltimas senhas. 237 | invalidPasswordGenericMessage=Senha inv\u00E1lida: a nova senha n\u00E3o corresponde \u00E0s pol\u00EDticas de senha. 238 | 239 | failedToProcessResponseMessage=Falha ao processar a resposta 240 | httpsRequiredMessage=HTTPS requerido 241 | realmNotEnabledMessage=Dom\u00EDnio desativado 242 | invalidRequestMessage=Pedido inv\u00E1lido 243 | failedLogout=Falha ao sair 244 | unknownLoginRequesterMessage=Solicitante de login desconhecido 245 | loginRequesterNotEnabledMessage=Solicitante de login desativado 246 | bearerOnlyMessage=Aplicativos somente ao portador n\u00E3o tem permiss\u00E3o para iniciar o login pelo navegador 247 | standardFlowDisabledMessage=Cliente n\u00E3o tem permiss\u00E3o para iniciar o login com response_type informado. O fluxo padr\u00E3o est\u00E1 desabilitado para o cliente. 248 | implicitFlowDisabledMessage=Cliente n\u00E3o tem permiss\u00E3o para iniciar o login com response_type informado. O fluxo impl\u00EDcito est\u00E1 desabilitado para o cliente. 249 | invalidRedirectUriMessage=URI de redirecionamento inv\u00E1lido 250 | unsupportedNameIdFormatMessage=NameIDFormat n\u00E3o suportado 251 | invalidRequesterMessage=Solicitante inv\u00E1lido 252 | registrationNotAllowedMessage=Registro n\u00E3o permitido. 253 | resetCredentialNotAllowedMessage=N\u00E3o \u00E9 permitido redefinir credencial. 254 | 255 | permissionNotApprovedMessage=Permiss\u00E3o n\u00E3o aprovada. 256 | noRelayStateInResponseMessage=Sem estado de retransmiss\u00E3o na resposta do provedor de identidade. 257 | insufficientPermissionMessage=Permiss\u00F5es insuficientes para vincular identidades. 258 | couldNotProceedWithAuthenticationRequestMessage=N\u00E3o foi poss\u00EDvel proceder \u00E0 solicita\u00E7\u00E3o de autentica\u00E7\u00E3o para provedor de identidade. 259 | couldNotObtainTokenMessage=N\u00E3o foi poss\u00EDvel obter token do provedor de identidade. 260 | unexpectedErrorRetrievingTokenMessage=Erro inesperado ao recuperar token do provedor de identidade. 261 | unexpectedErrorHandlingResponseMessage=Erro inesperado ao manusear resposta do provedor de identidade. 262 | identityProviderAuthenticationFailedMessage=Falha na autentica\u00E7\u00E3o. N\u00E3o foi poss\u00EDvel autenticar com o provedor de identidade. 263 | couldNotSendAuthenticationRequestMessage=N\u00E3o foi poss\u00EDvel enviar solicita\u00E7\u00E3o de autentica\u00E7\u00E3o para o provedor de identidade. 264 | unexpectedErrorHandlingRequestMessage=Erro inesperado ao manusear pedido de autentica\u00E7\u00E3o para provedor de identidade. 265 | invalidAccessCodeMessage=C\u00F3digo de acesso inv\u00E1lido. 266 | sessionNotActiveMessage=Sess\u00E3o inativa. 267 | invalidCodeMessage=C\u00F3digo inv\u00E1lido, por favor fa\u00E7a login novamente atrav\u00E9s de sua aplica\u00E7\u00E3o. 268 | identityProviderUnexpectedErrorMessage=Erro inesperado durante a autentica\u00E7\u00E3o com o provedor de identidade 269 | identityProviderNotFoundMessage=N\u00E3o foi poss\u00EDvel encontrar um provedor de identidade com o identificador. 270 | identityProviderLinkSuccess=Sua conta foi vinculada com sucesso com {0} conta {1} . 271 | staleCodeMessage=Esta p\u00E1gina n\u00E3o \u00E9 mais v\u00E1lida. Volte ao seu aplicativo e fa\u00E7a login novamente 272 | realmSupportsNoCredentialsMessage=O dom\u00EDnio n\u00E3o suporta qualquer tipo de credencial. 273 | credentialSetupRequired=N\u00E3o \u00E9 poss\u00EDvel fazer o login, \u00E9 necess\u00E1ria configura\u00E7\u00E3o de credencial. 274 | identityProviderNotUniqueMessage=O dom\u00EDnio suporta m\u00FAltiplos provedores de identidade. N\u00E3o foi poss\u00EDvel determinar qual o provedor de identidade deve ser usado para se autenticar. 275 | emailVerifiedMessage=O seu endere\u00E7o de e-mail foi confirmado. 276 | staleEmailVerificationLink=O link em que voc\u00EA clicou \u00E9 um link antigo e n\u00E3o \u00E9 mais v\u00E1lido. Talvez voc\u00EA j\u00E1 tenha verificado seu e-mail. 277 | identityProviderAlreadyLinkedMessage=A conta retornada do {0} j\u00E1 est\u00E1 vinculada a outro usu\u00E1rio. 278 | confirmAccountLinking=Confirme a vincula\u00E7\u00E3o da conta {0} do provedor de identidade {1} \u00E0 sua conta. 279 | confirmEmailAddressVerification=Confirme a validade do endere\u00E7o de e-mail {0}. 280 | confirmExecutionOfActions=Execute a(s) seguinte(s) a\u00E7\u00E3o(\u00F5es) 281 | 282 | backToApplication=« Voltar para o aplicativo 283 | missingParameterMessage=Par\u00E2metros ausentes\: {0} 284 | clientNotFoundMessage=Cliente n\u00E3o encontrado. 285 | clientDisabledMessage=Cliente desativado. 286 | invalidParameterMessage=Par\u00E2mentro inv\u00E1lido\: {0} 287 | alreadyLoggedIn=Voc\u00EA j\u00E1 est\u00E1 logado. 288 | differentUserAuthenticated=Voc\u00EA j\u00E1 est\u00E1 autenticado como usu\u00E1rio diferente ''{0}'' nesta sess\u00E3o. Por favor, saia primeiro. 289 | brokerLinkingSessionExpired=Vincula\u00E7\u00E3o de conta do provedor de identidade solicitada, mas a sess\u00E3o atual n\u00E3o \u00E9 mais v\u00E1lida. 290 | proceedWithAction=» Clique aqui para continuar 291 | 292 | requiredAction.CONFIGURE_TOTP=Configurar OTP 293 | requiredAction.terms_and_conditions=Termos e Condi\u00E7\u00F5es 294 | requiredAction.UPDATE_PASSWORD=Atualizar Senha 295 | requiredAction.UPDATE_PROFILE=Atualizar Perfil 296 | requiredAction.VERIFY_EMAIL=Verificar E-mail 297 | 298 | doX509Login=Voc\u00EA ser\u00E1 logado como\: 299 | clientCertificate=Certificado X509 do cliente\: 300 | noCertificate=[Sem Certificado] 301 | 302 | 303 | pageNotFound=P\u00E1gina n\u00E3o encontrada 304 | internalServerError=Ocorreu um erro interno no servidor 305 | 306 | console-username=Nome do usu\u00E1rio: 307 | console-password=Senha: 308 | console-otp=C\u00F3digo \u00FAnico: 309 | console-new-password=Nova Senha: 310 | console-confirm-password=Confirma\u00E7\u00E3o de senha: 311 | console-update-password=\u00C9 necess\u00E1rio atualizar sua senha. 312 | console-verify-email=Voc\u00EA precisa verificar seu endere\u00E7o de e-mail. Enviamos um email para {0} que cont\u00E9m um c\u00F3digo de verifica\u00E7\u00E3o. Digite este c\u00F3digo no campo abaixo. 313 | console-email-code=C\u00F3digo do email: 314 | console-accept-terms=Aceita os termos? [s/n]: 315 | console-accept=s 316 | 317 | # Openshift messages 318 | openshift.scope.user_info=Informa\u00E7\u00E3o do usu\u00E1rio 319 | openshift.scope.user_check-access=Informa\u00E7\u00E3o de acesso do usu\u00E1rio 320 | openshift.scope.user_full=Acesso Completo 321 | openshift.scope.list-projects=Listar projetos 322 | 323 | # SAML authentication 324 | saml.post-form.title=Redirecionamento de autentica\u00E7\u00E3o 325 | saml.post-form.message=Redirecionando. Por favor, aguarde. 326 | saml.post-form.js-disabled=O JavaScript est\u00E1 desabilitado. \u00C9 altamente recomend\u00E1vel habilit\u00E1-lo. Clique no bot\u00E3o abaixo para continuar. 327 | 328 | #authenticators 329 | otp-display-name=Aplicativo Autenticador 330 | otp-help-text=Digite um c\u00F3digo de verifica\u00E7\u00E3o do aplicativo autenticador. 331 | password-display-name=Senha 332 | password-help-text=Fa\u00E7a o login digitando sua senha. 333 | auth-username-form-display-name=Nome de usu\u00E1rio 334 | auth-username-form-help-text=Fa\u00E7a o login digitando seu nome de usu\u00E1rio. 335 | auth-username-password-form-display-name=Nome de usu\u00E1rio e senha 336 | auth-username-password-form-help-text=Fa\u00E7a o login digitando seu nome de usu\u00E1rio e senha. 337 | 338 | # WebAuthn 339 | webauthn-display-name=Chave de Seguran\u00E7a 340 | webauthn-help-text=Use sua chave de seguran\u00E7a para fazer login. 341 | webauthn-passwordless-display-name=Chave de Seguran\u00E7a 342 | webauthn-passwordless-help-text=Use sua chave de seguran\u00E7a para fazer login sem senha. 343 | webauthn-login-title=Login com Chave de Seguran\u00E7a 344 | webauthn-registration-title=Registro com Chave de Seguran\u00E7a 345 | webauthn-available-authenticators=Autenticadores dispon\u00EDveis 346 | 347 | # WebAuthn Error 348 | webauthn-error-title=Erro de Chave de Seguran\u00E7a 349 | webauthn-error-registration=Falha ao registrar sua Chave de Seguran\u00E7a. 350 | webauthn-error-api-get=Falha ao autenticar usando Chave de Seguran\u00E7a. 351 | webauthn-error-different-user=O primeiro usu\u00E1rio autenticado n\u00E3o \u00E9 aquele autenticado pela Chave de Seguran\u00E7a. 352 | webauthn-error-auth-verification=O resultado da autentica\u00E7\u00E3o da Chave de Seguran\u00E7a \u00E9 inv\u00E1lido. 353 | webauthn-error-register-verification=O resultado do registro da Chave de Seguran\u00E7a \u00E9 inv\u00E1lido. 354 | webauthn-error-user-not-found=Usu\u00E1rio desconhecido autenticado pela Chave de Seguran\u00E7a. 355 | 356 | identity-provider-redirector=Conecte-se com outro Provedor de Identidade 357 | 358 | -------------------------------------------------------------------------------- /src/static/template.ftl: -------------------------------------------------------------------------------- 1 | <#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false showAnotherWayIfPresent=true> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ${msg("loginTitle",(realm.displayName!''))} 10 | 11 | 12 | 13 | 14 | <#nested "head"> 15 | 16 | 17 |
18 | 112 | <#nested "scripts"> 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/static/theme.properties: -------------------------------------------------------------------------------- 1 | locales=ca,cs,da,de,en,es,fr,hu,it,ja,lt,nl,no,pl,pt-BR,ru,sk,sv,tr,zh-CN 2 | -------------------------------------------------------------------------------- /src/views/login-idp-link-confirm/index.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout; section> 3 | <#if section = "scripts"> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/views/login-idp-link-confirm/index.ts: -------------------------------------------------------------------------------- 1 | import '~/scss/index.scss' 2 | import { createApp } from 'vue' 3 | import index from './index.vue' 4 | 5 | const environment = document.querySelector('#environment') 6 | if (environment) { 7 | const app = createApp(index) 8 | app.provide( 9 | 'environment', 10 | JSON.parse(String(environment.textContent)) 11 | ) 12 | app.mount('#app') 13 | } 14 | -------------------------------------------------------------------------------- /src/views/login-idp-link-confirm/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 41 | -------------------------------------------------------------------------------- /src/views/login-idp-link-email/index.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout; section> 3 | <#if section = "scripts"> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/views/login-idp-link-email/index.ts: -------------------------------------------------------------------------------- 1 | import '~/scss/index.scss' 2 | import { createApp } from 'vue' 3 | import index from './index.vue' 4 | 5 | const environment = document.querySelector('#environment') 6 | if (environment) { 7 | const app = createApp(index) 8 | app.provide( 9 | 'environment', 10 | JSON.parse(String(environment.textContent)) 11 | ) 12 | app.mount('#app') 13 | } 14 | -------------------------------------------------------------------------------- /src/views/login-idp-link-email/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 41 | -------------------------------------------------------------------------------- /src/views/login-idp-link-email/login-idp-link-email.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout; section> 3 | <#if section = "header"> 4 | ${msg("emailLinkIdpTitle", idpDisplayName)} 5 | <#elseif section = "form"> 6 |

Login-Idp-Link-Email

7 |

8 | ${msg("emailLinkIdp1", idpDisplayName, brokerContext.username, realm.displayName)} 9 |

10 |

11 | ${msg("emailLinkIdp2")} ${msg("doClickHere")} ${msg("emailLinkIdp3")} 12 |

13 |

14 | ${msg("emailLinkIdp4")} ${msg("doClickHere")} ${msg("emailLinkIdp5")} 15 |

16 | 17 | -------------------------------------------------------------------------------- /src/views/login-reset-password/index.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout displayInfo=true displayMessage=!messagesPerField.existsError('username'); section> 3 | <#if section = "scripts"> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/views/login-reset-password/index.ts: -------------------------------------------------------------------------------- 1 | import '~/scss/index.scss' 2 | import { createApp } from 'vue' 3 | import index from './index.vue' 4 | 5 | const environment = document.querySelector('#environment') 6 | if (environment) { 7 | const app = createApp(index) 8 | app.provide('environment', JSON.parse(String(environment.textContent))) 9 | app.mount('#app') 10 | } 11 | -------------------------------------------------------------------------------- /src/views/login-reset-password/index.vue: -------------------------------------------------------------------------------- 1 | 30 | 48 | -------------------------------------------------------------------------------- /src/views/login-update-profile/index.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout displayMessage=!messagesPerField.existsError('firstName','lastName','email','username','password','password-confirm'); section> 3 | <#if section = "scripts"> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/views/login-update-profile/index.ts: -------------------------------------------------------------------------------- 1 | import '~/scss/index.scss' 2 | import { createApp } from 'vue' 3 | import index from './index.vue' 4 | 5 | const environment = document.querySelector('#environment') 6 | if (environment) { 7 | const app = createApp(index) 8 | app.provide( 9 | 'environment', 10 | JSON.parse(String(environment.textContent)) 11 | ) 12 | app.mount('#app') 13 | } 14 | -------------------------------------------------------------------------------- /src/views/login-update-profile/index.vue: -------------------------------------------------------------------------------- 1 | 64 | 82 | -------------------------------------------------------------------------------- /src/views/login/index.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','password') displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled??; section> 3 | <#if section = "scripts"> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/views/login/index.ts: -------------------------------------------------------------------------------- 1 | import '~/scss/index.scss' 2 | import { createApp } from 'vue' 3 | import index from './index.vue' 4 | 5 | const environment = document.querySelector('#environment') 6 | if (environment) { 7 | const app = createApp(index) 8 | app.provide('environment', JSON.parse(String(environment.textContent))) 9 | app.mount('#app') 10 | } 11 | -------------------------------------------------------------------------------- /src/views/login/index.vue: -------------------------------------------------------------------------------- 1 | 85 | 103 | -------------------------------------------------------------------------------- /src/views/register/index.ftl: -------------------------------------------------------------------------------- 1 | <#import "template.ftl" as layout> 2 | <@layout.registrationLayout displayMessage=!messagesPerField.existsError('firstName','lastName','email','username','password','password-confirm'); section> 3 | <#if section = "scripts"> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/views/register/index.ts: -------------------------------------------------------------------------------- 1 | import '~/scss/index.scss' 2 | import { createApp } from 'vue' 3 | import index from './index.vue' 4 | 5 | const environment = document.querySelector('#environment') 6 | if (environment) { 7 | const app = createApp(index) 8 | app.provide('environment', JSON.parse(String(environment.textContent))) 9 | app.mount('#app') 10 | } 11 | -------------------------------------------------------------------------------- /src/views/register/index.vue: -------------------------------------------------------------------------------- 1 | 98 | 116 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | "lib": ["esnext", "dom", "dom.iterable", "scripthost"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "commonjs", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | "baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */ 31 | "paths": { 32 | "~/*": ["./*"] 33 | }, /* Specify a set of entries that re-map imports to additional lookup locations. */ 34 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 35 | "typeRoots": ["./node_modules/@types", "./src/@types"], /* Specify multiple folders that act like `./node_modules/@types`. */ 36 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 37 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files */ 39 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 52 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 81 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 86 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | }, 103 | "include": [ 104 | "src/**/*.ts", 105 | "src/**/*.tsx", 106 | "src/**/*.vue", 107 | "tests/**/*.ts", 108 | "tests/**/*.tsx" 109 | ], 110 | "exclude": ["node_modules"] 111 | } 112 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { VueLoaderPlugin } = require('vue-loader') 3 | const { EnvironmentPlugin } = require('webpack') 4 | const HtmlWebpackPlugin = require('html-webpack-plugin') 5 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 6 | const CopyWebpackPlugin = require('copy-webpack-plugin') 7 | 8 | const THEME_NAME = 'openfinance' 9 | const entries = [ 10 | 'login', 11 | 'register', 12 | 'login-reset-password', 13 | 'login-update-profile', 14 | 'login-idp-link-confirm', 15 | 'login-idp-link-email' 16 | ] 17 | 18 | module.exports = (env, argv) => { 19 | const isDevelopment = argv.mode !== 'production' ? true : false 20 | return { 21 | entry: () => { 22 | let entryList = {} 23 | for (let entry of entries) { 24 | entryList[entry] = path.resolve( 25 | __dirname, 26 | 'src', 27 | 'views', 28 | entry, 29 | 'index.ts' 30 | ) 31 | } 32 | return entryList 33 | }, 34 | output: { 35 | path: path.resolve(__dirname, '..', 'themes', THEME_NAME, 'login'), 36 | filename: 'resources/js/[name].js', 37 | publicPath: '/' 38 | }, 39 | devtool: 'inline-cheap-module-source-map', 40 | resolve: { 41 | extensions: ['.ts', '.tsx', '.js', '.vue', '.json', '.scss'], 42 | alias: { 43 | '~': path.resolve(__dirname, 'src') 44 | } 45 | }, 46 | mode: isDevelopment ? 'development' : 'production', 47 | watch: isDevelopment ? true : false, 48 | module: { 49 | rules: [ 50 | { 51 | test: /\.vue$/, 52 | loader: 'vue-loader', 53 | options: { 54 | sourceMap: isDevelopment, 55 | extract: false 56 | } 57 | }, 58 | { 59 | test: /\.(ts|tsx)$/, 60 | exclude: /node_modules/, 61 | use: { 62 | loader: 'babel-loader', 63 | options: { 64 | presets: ['@babel/preset-env', '@babel/preset-typescript'], 65 | plugins: [ 66 | '@babel/plugin-transform-runtime', 67 | '@babel/plugin-transform-typescript' 68 | ] 69 | } 70 | } 71 | }, 72 | { 73 | test: /\.(scss|css)$/, 74 | use: [ 75 | 'style-loader', 76 | 'css-loader', 77 | { 78 | loader: 'postcss-loader', 79 | options: { 80 | postcssOptions: { 81 | plugins: { autoprefixer: {} } 82 | } 83 | } 84 | }, 85 | 'sass-loader' 86 | ] 87 | } 88 | ] 89 | }, 90 | plugins: [ 91 | new CleanWebpackPlugin(), 92 | new VueLoaderPlugin(), 93 | ...entries.map( 94 | entry => 95 | new HtmlWebpackPlugin({ 96 | inject: false, 97 | template: path.resolve( 98 | __dirname, 99 | 'src', 100 | 'views', 101 | entry, 102 | 'index.ftl' 103 | ), 104 | filename: `${entry}.ftl`, 105 | minify: false 106 | }) 107 | ), 108 | new CopyWebpackPlugin({ 109 | patterns: [ 110 | { 111 | from: path.resolve(__dirname, 'src', 'static'), 112 | to: path.resolve(__dirname, '..', 'themes', THEME_NAME, 'login') 113 | } 114 | ] 115 | }) 116 | ], 117 | ...(isDevelopment 118 | ? {} 119 | : { 120 | optimization: { 121 | removeAvailableModules: false, 122 | removeEmptyChunks: false, 123 | splitChunks: false 124 | } 125 | }) 126 | } 127 | } 128 | --------------------------------------------------------------------------------