masks-server 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/masks/server/scim_endpoint.rb +2 -2
  3. data/app/controllers/masks/server/account_exports_controller.rb +2 -2
  4. data/app/controllers/masks/server/addresses_controller.rb +2 -3
  5. data/app/controllers/masks/server/authenticator_apps_controller.rb +2 -3
  6. data/app/controllers/masks/server/authorize_controller.rb +2 -2
  7. data/app/controllers/masks/server/device_authorizations_controller.rb +2 -2
  8. data/app/controllers/masks/server/device_verifications_controller.rb +2 -2
  9. data/app/controllers/masks/server/enrollments_controller.rb +4 -4
  10. data/app/controllers/masks/server/forward_auth_controller.rb +2 -2
  11. data/app/controllers/masks/server/introspections_controller.rb +2 -2
  12. data/app/controllers/masks/server/logins_controller.rb +10 -12
  13. data/app/controllers/masks/server/manage_controller.rb +1 -0
  14. data/app/controllers/masks/server/organization_members_controller.rb +2 -2
  15. data/app/controllers/masks/server/passwords_controller.rb +2 -3
  16. data/app/controllers/masks/server/pushed_authorizations_controller.rb +2 -2
  17. data/app/controllers/masks/server/received_signals_controller.rb +2 -2
  18. data/app/controllers/masks/server/registrations_controller.rb +2 -2
  19. data/app/controllers/masks/server/revocations_controller.rb +2 -2
  20. data/app/controllers/masks/server/saml_controller.rb +2 -2
  21. data/app/controllers/masks/server/scim/metadata_controller.rb +1 -1
  22. data/app/controllers/masks/server/sign_in_approvals_controller.rb +2 -3
  23. data/app/controllers/masks/server/tokens_controller.rb +2 -2
  24. data/app/controllers/masks/server/verifications_controller.rb +2 -3
  25. data/app/graphql/masks/server/manage/types/health_check_type.rb +1 -1
  26. data/app/ldap/masks/server/ldap/gate.rb +14 -16
  27. data/app/models/masks/server/app_passwords.rb +7 -13
  28. data/app/models/masks/server/app_preset.rb +1 -1
  29. data/app/models/masks/server/client.rb +24 -0
  30. data/app/models/masks/server/client_metadata_document.rb +4 -8
  31. data/app/models/masks/server/confirmation_code.rb +2 -2
  32. data/app/models/masks/server/declared.rb +3 -1
  33. data/app/models/masks/server/event.rb +2 -2
  34. data/app/models/masks/server/health.rb +70 -3
  35. data/app/models/masks/server/saml_identity/farewells.rb +1 -0
  36. data/app/models/masks/server/tenant.rb +48 -4
  37. data/app/models/masks/server/throttle.rb +165 -0
  38. data/app/views/masks/server/handshakes/show.html.erb +2 -8
  39. data/app/views/masks/server/logins/_consent.html.erb +43 -44
  40. data/app/views/masks/server/logins/_enrol.html.erb +1 -1
  41. data/app/views/masks/server/logins/_setup_configure.html.erb +2 -6
  42. data/app/views/masks/server/logins/_signup.html.erb +2 -9
  43. data/app/views/masks/server/logins/_signup_credentials.html.erb +1 -2
  44. data/app/views/masks/server/logins/_signup_head.html.erb +1 -11
  45. data/config/locales/de/account.yml +4 -4
  46. data/config/locales/de/handshakes.yml +6 -6
  47. data/config/locales/de/logins.yml +44 -30
  48. data/config/locales/de/manage/health.yml +9 -2
  49. data/config/locales/en/account.yml +4 -4
  50. data/config/locales/en/handshakes.yml +6 -6
  51. data/config/locales/en/logins.yml +44 -30
  52. data/config/locales/en/manage/health.yml +9 -2
  53. data/config/locales/es/account.yml +4 -4
  54. data/config/locales/es/handshakes.yml +6 -6
  55. data/config/locales/es/logins.yml +42 -28
  56. data/config/locales/es/manage/health.yml +9 -2
  57. data/config/locales/fr/account.yml +4 -4
  58. data/config/locales/fr/handshakes.yml +6 -6
  59. data/config/locales/fr/logins.yml +43 -29
  60. data/config/locales/fr/manage/health.yml +9 -2
  61. data/db/migrate/20261031100000_default_key_rotation_to_ninety_days.rb +5 -0
  62. data/lib/generators/masks/server/install/install_generator.rb +19 -0
  63. data/lib/masks/server/configuration.rb +14 -8
  64. data/lib/masks/server/engine.rb +2 -1
  65. data/lib/masks/server/forwarding.rb +26 -3
  66. data/lib/masks/server/schema_reference.rb +1 -1
  67. data/lib/masks/server/tenancy/middleware.rb +4 -7
  68. data/lib/masks/server/tenant_isolation.rb +12 -0
  69. data/public/masks-assets/.vite/manifest.json +3 -3
  70. data/public/masks-assets/assets/app-Cfbt-A5V.css +2 -0
  71. data/public/masks-assets/assets/login-BDggujiZ.js +6 -0
  72. data/public/masks-assets/assets/login-BDggujiZ.js.map +1 -0
  73. data/public/masks-assets/assets/{manage-DpVxe5sv.js → manage-VgOqKj7N.js} +2 -2
  74. data/public/masks-assets/assets/manage-VgOqKj7N.js.map +1 -0
  75. data/version.txt +1 -1
  76. metadata +8 -6
  77. data/public/masks-assets/assets/app-BXOScMjL.css +0 -2
  78. data/public/masks-assets/assets/login-C21_jb6L.js +0 -4
  79. data/public/masks-assets/assets/login-C21_jb6L.js.map +0 -1
  80. data/public/masks-assets/assets/manage-DpVxe5sv.js.map +0 -1
@@ -16,7 +16,7 @@ es:
16
16
  name: "Nombre"
17
17
  phone: "Teléfono"
18
18
  password: "Contraseña"
19
- not_you: "¿No eres tú?"
19
+ not_you: "Usar otra cuenta"
20
20
  sign_out: "Cerrar sesión"
21
21
  use_passkey: "Usar una llave de acceso"
22
22
  or: "o"
@@ -40,10 +40,12 @@ es:
40
40
  tab_confirmation: "Confirmación"
41
41
  setup_cap: "¡Te damos la bienvenida!"
42
42
  setup_title: "Configurar"
43
- signup_title: "Crear una cuenta en"
43
+ signup_title: "Crea tu cuenta"
44
44
  token: "Token de configuración"
45
- token_hint: "Aparece en los registros del servidor, donde solo puede leerlo quien ejecuta masks."
46
- origin: "Configurar en"
45
+ token_hint: "Está impreso en el registro del servidor."
46
+ origin: "Este masks responde en %{origin}."
47
+ pick_nickname: "Elegir un apodo"
48
+ nickname_hint: "Otras personas lo ven. Déjalo como está para usar %{suggested}."
47
49
  once: "Esta pantalla no volverá a aparecer."
48
50
  docs: "Lee la documentación."
49
51
  confirm: "Confirmar contraseña"
@@ -57,15 +59,15 @@ es:
57
59
  proving: "Comprobando este navegador"
58
60
 
59
61
  identify:
60
- heading: "Inicia sesión para continuar"
62
+ heading: "Iniciar sesión"
61
63
  heading_to: "Iniciar sesión en %{client}"
62
- identifier: "Apodo o correo"
63
- signup_hint: "¿Eres nuevo? Escribe la dirección que quieres usar y se creará una cuenta para ella."
64
+ identifier: "Correo o apodo"
65
+ signup_hint: "¿Nuevo aquí? Escribe tu correo y masks te crea una cuenta."
64
66
 
65
67
  first_factor:
66
68
  title: "Escribe tu contraseña"
67
69
  title_code: "Iniciar sesión con un código"
68
- forgot: "¿La olvidaste?"
70
+ forgot: "¿Olvidaste tu contraseña?"
69
71
  email_me: "Enviarme un código por correo"
70
72
  email_only: "Enviarme un código por correo"
71
73
 
@@ -76,9 +78,9 @@ es:
76
78
  sent_again: "Enviado"
77
79
 
78
80
  second_factor:
79
- title: "Escribe tu código"
80
- title_passkey: "Usa tu segundo factor"
81
- trust: "Confiar en este dispositivo durante %{duration}"
81
+ title: "Confirma que eres tú"
82
+ title_passkey: "Confirma que eres tú con tu llave de acceso"
83
+ trust: "Saltar esto en este dispositivo durante %{duration}"
82
84
  use_backup_code: "Usar un código de respaldo"
83
85
  stuck_insecure: "El segundo factor de esta cuenta es una llave de acceso, y el navegador solo ofrece llaves de acceso a páginas servidas por HTTPS. Abre esta página por HTTPS para continuar."
84
86
  stuck_unsupported: "El segundo factor de esta cuenta es una llave de acceso, y este navegador no admite llaves de acceso. Abre esta página en un navegador que las admita para continuar."
@@ -102,15 +104,25 @@ es:
102
104
 
103
105
  enrol:
104
106
  title: "Protege tu cuenta"
105
- lede: "Añade tantos segundos factores como quieras. Esta cuenta necesita al menos uno."
106
- lede_optional: "Añade tantos segundos factores como quieras."
107
+ lede: "Elige una forma de confirmar que eres tú al iniciar sesión. Puedes añadir más después."
108
+ lede_optional: "Elige una forma de confirmar que eres tú al iniciar sesión, o sáltalo por ahora."
109
+ on_title: "Tu cuenta está protegida"
110
+ on_lede: "Así confirmas que eres tú al iniciar sesión."
111
+ on_label: "Activado"
112
+ passkey: "Llave de acceso"
107
113
  otp: "Aplicación de autenticación"
114
+ otp_about: "Una app como Google Authenticator o 1Password muestra un código de seis dígitos."
108
115
  otp_on: "Activada"
109
- scan_hint: "Escanéalo o escribe esta clave a mano:"
116
+ scan_hint: "Escanea esto con tu app de autenticación, o escribe la clave en ella:"
117
+ passkey_about: "Tu teléfono o computadora comprueba que eres tú con tu cara, tu huella o tu PIN."
118
+ codes_email_about: "Un código llega a %{to} cada vez que inicias sesión."
119
+ codes_sms_about: "Un código llega a %{to} por mensaje de texto cada vez que inicias sesión."
120
+ another_way: "Elegir otra forma"
121
+ add_way: "Añadir otra forma"
110
122
  open: "Abrir en tu aplicación de autenticación"
111
123
  turn_on: "Activarla"
112
124
  passkeys: "Llaves de acceso"
113
- passkeys_none: "Ninguna todavía. Sirve una que compruebe un PIN o una huella."
125
+ passkeys_none: "Ninguna todavía."
114
126
  passkeys_some: "%{count} añadidas"
115
127
  add_passkey: "Añadir una llave de acceso"
116
128
  add_another_passkey: "Añadir otra"
@@ -118,17 +130,17 @@ es:
118
130
  codes_email_hint: "Un código enviado a %{to} confirma cada inicio de sesión."
119
131
  codes_sms: "Códigos por SMS"
120
132
  codes_sms_hint: "Un código enviado por SMS a %{to} confirma cada inicio de sesión."
121
- send_code: "Enviar un código para activarlo"
133
+ send_code: "Enviarme un código"
122
134
  sent_to: "Enviado a %{to}."
123
135
  backup_codes: "Códigos de respaldo"
124
- backup_codes_waiting: "Se generan cuando actives uno de los factores de arriba."
125
- backup_codes_hint: "Cada uno sirve para iniciar sesión una vez, cuando no tienes nada más a mano. No se vuelven a mostrar."
136
+ backup_codes_waiting: "Se crean cuando una forma de arriba esté activada."
137
+ backup_codes_hint: "Cada código te deja entrar una vez si pierdes tu otra forma de entrar. Guárdalos ahora. No se muestran otra vez."
126
138
  backup_codes_left: "Quedan %{count}"
127
139
  backup_codes_file: "Códigos de respaldo de %{account} en %{origin}"
128
140
  copy: "Copiarlos"
129
141
  copied: "Copiados"
130
142
  download: "Descargarlos"
131
- kept: "Guardé mis códigos de respaldo en un lugar seguro"
143
+ kept: "Guardé mis códigos de respaldo"
132
144
  done: "Continuar"
133
145
  skip: "Omitir por ahora"
134
146
 
@@ -163,7 +175,7 @@ es:
163
175
  prove_email:
164
176
  title: "Revisa tu correo"
165
177
  lede: "Te enviamos un código de seis dígitos a %{email}. Escríbelo para continuar."
166
- no_mailer: "Este servidor todavía no puede enviar correo, así que no se puede usar una dirección para iniciar sesión. Usa tu apodo o pregunta a un gestor."
178
+ no_mailer: "Este servidor aún no puede enviar correo, así que no puede comprobar tu dirección. Inicia sesión con tu apodo, o pide a quien lo administra que confirme la dirección por ti."
167
179
 
168
180
  setup_configure:
169
181
  called: "Este servidor se llama"
@@ -202,17 +214,19 @@ es:
202
214
  as: "%{organization}, como %{role}"
203
215
 
204
216
  consent:
205
- title: "¿Permitir %{client}?"
206
- access: "Acceso"
207
- no_access: "Nada más allá de confirmar quién eres."
208
- audience: "En tu nombre en"
217
+ title: "%{client} quiere iniciar tu sesión"
218
+ access: "Sabrá"
219
+ no_access: "Solo que tienes una cuenta aquí."
220
+ audience: "Puede actuar por ti en %{resources}."
209
221
  details: "Exactamente esto"
210
222
  returns_to: "Después vuelve a"
223
+ more: "Detalles"
224
+ scopes: "Permisos"
211
225
  site: "Acerca de %{client}"
212
226
  terms: "Sus condiciones"
213
227
  privacy: "Su política de privacidad"
214
228
  allow: "Permitir"
215
- deny: "Denegar"
229
+ deny: "Ahora no"
216
230
  working: "Permitiendo"
217
231
 
218
232
  settled:
@@ -221,7 +235,7 @@ es:
221
235
  waiting: "Te llevamos de vuelta"
222
236
 
223
237
  warnings:
224
- invalid-credentials: "Ese apodo y esa contraseña no coinciden."
238
+ invalid-credentials: "Ese correo o apodo y la contraseña no coinciden."
225
239
  invalid-code: "Ese código no es válido."
226
240
  invalid-backup-code: "Ese código de respaldo no es válido."
227
241
  invalid-passkey: "No se pudo usar esa llave de acceso."
@@ -233,7 +247,7 @@ es:
233
247
  passkey-crowded: "Esta cuenta ya tiene tantas llaves de acceso como admite este servidor."
234
248
  second-factor-required: "Activa al menos un segundo factor para continuar."
235
249
  backup-codes-unkept: "Guarda tus códigos de respaldo antes de continuar."
236
- missing-identifier: "Escribe tu apodo o tu correo."
250
+ missing-identifier: "Escribe tu correo o tu apodo."
237
251
  missing-first-factor: "Ese paso caducó. Empieza de nuevo."
238
252
  too-many-attempts: "Demasiados intentos. Espera unos minutos."
239
253
  too-many-attempts-for-account: "Demasiados intentos para esa cuenta."
@@ -258,7 +272,7 @@ es:
258
272
  work-unsolved: "Este navegador no terminó la comprobación que frena los registros automáticos. Inténtalo de nuevo."
259
273
  invitation-expired: "Esa invitación ya no es válida. Pide otra."
260
274
  reset-expired: "Ese enlace de restablecimiento ya no es válido. Pide otro."
261
- no-mailer: "Este servidor no puede enviar correo. Pregunta a un gestor."
275
+ no-mailer: "Este servidor aún no puede enviar correo, así que no puede restablecer tu contraseña. Pide a quien lo administra un enlace para restablecerla."
262
276
  sso-failed: "Ese inicio de sesión no se completó. Vuelve a intentarlo."
263
277
  sso-expired: "Ese inicio de sesión tardó demasiado. Vuelve a intentarlo."
264
278
  sso-unavailable: "Esa forma de iniciar sesión no está disponible."
@@ -65,13 +65,20 @@ es:
65
65
  proven: "Cada dominio reclamado conserva su registro TXT."
66
66
  missing: "Falta el registro TXT de %{domains}. Una reclamación se libera una semana después de que desaparezca su registro."
67
67
  advice: "Vuelve a poner el registro TXT en el nombre que muestra la página Dominios."
68
+ proxy:
69
+ title: "Proxy inverso"
70
+ quiet: "Las cabeceras reenviadas llegan solo desde proxies de confianza, por HTTPS."
71
+ untrusted: "Llegaron cabeceras reenviadas desde %{addresses}, que no figura en MASKS_TRUSTED_PROXIES, así que se ignoraron. Todos los visitantes detrás de ese proxy comparten una dirección y un mismo límite."
72
+ plain: "El proxy en %{addresses} reenvía las peticiones como HTTP sin cifrar. masks marca sus cookies solo para HTTPS, así que los navegadores las descartan y el inicio de sesión se repite en bucle."
73
+ one: "Los %{count} eventos de la última hora llegaron todos desde %{address}, una dirección privada, que casi seguro es el propio proxy."
74
+ advice: "Añade el proxy a MASKS_TRUSTED_PROXIES y haz que envíe X-Forwarded-For y X-Forwarded-Proto. Busca en el registro del servidor las líneas que empiezan por proxy:."
68
75
  keys:
69
76
  title: "Claves de firma"
70
77
  missing: "Este inquilino no tiene ninguna clave de firma activa, así que no se puede firmar nada."
71
- manual: "Las claves se rotan a mano. La clave activa tiene %{days} días."
78
+ manual: "Las claves se rotan a mano, así que nada sustituye la clave activa por sí solo. Tiene %{days} días."
72
79
  fresh: "La clave activa tiene %{days} días y rota cada %{period} días."
73
80
  stale: "La clave activa tiene %{days} días, más que su rotación de %{period} días."
74
- advice: "Rota la clave en la página Configuración, o lee la tarea signing_keys en el registro del servidor."
81
+ advice: "Elige un calendario de rotación en la página Configuración, rota la clave allí, o lee la tarea signing_keys en el registro del servidor."
75
82
  release:
76
83
  available: "La versión %{version} está disponible."
77
84
  operator: "Esta versión necesita un paso de un operador. Lee sus notas antes de actualizar."
@@ -62,7 +62,7 @@ fr:
62
62
  set:
63
63
  one: "1 configurée"
64
64
  other: "%{count} configurées"
65
- explained: "Au lieu de saisir un mot de passe, votre appareil vérifie que c’est bien vous, de la même façon qu’il se déverrouille déjà. Une clé d’accès compte pour les deux facteurs à la fois, donc il n’y a aucun code à attendre."
65
+ explained: "Au lieu de saisir un mot de passe, votre appareil vérifie que c'est vous comme il se déverrouille déjà. Il compte aussi comme votre deuxième étape, donc aucun code à attendre."
66
66
  used: "utilisée il y a %{age}"
67
67
  never_used: "jamais utilisée"
68
68
  remove: "Supprimer"
@@ -209,11 +209,11 @@ fr:
209
209
  remembered: "%{label}, sans demander jusqu’au %{date}"
210
210
  heading: "Applications que vous avez autorisées"
211
211
  none_yet: "Aucune demande pour l’instant. Une application apparaît ici dès que vous vous y connectez, avec ce que vous avez accepté qu’elle voie."
212
- revoke: "Révoquer l’accès"
212
+ revoke: "Retirer l'accès"
213
213
  more:
214
214
  one: "et une autre"
215
215
  other: "et %{count} autres"
216
- confirm_revoke: "Révoquer %{client} ? Tout ce qu’elle détient cesse de fonctionner, et elle devra redemander l’accès lors de votre prochaine connexion."
216
+ confirm_revoke: "Retirer l'accès de %{client} ? Tout ce qu'il détient cesse de fonctionner, et il devra redemander à votre prochaine connexion."
217
217
 
218
218
  connections:
219
219
  heading: "Comptes associés"
@@ -258,7 +258,7 @@ fr:
258
258
 
259
259
  export:
260
260
  heading: "Télécharger votre compte"
261
- state: "JSON"
261
+ state: "Un fichier"
262
262
  lede: "Un fichier contenant votre profil, vos modes de connexion, vos organisations, applications, comptes associés et appareils, ainsi que l’activité conservée par masks. Il ne contient aucun mot de passe, code ni clé."
263
263
  again: "Votre connexion date d’un moment, il vous sera donc d’abord demandé de vous reconnecter."
264
264
  submit: "Télécharger"
@@ -3,29 +3,29 @@ fr:
3
3
  show:
4
4
  page_title: "Connecter %{name}"
5
5
  page_title_again: "Reconnecter %{name}"
6
- title: "Connecter %{name} à %{tenant} ?"
6
+ title: "Connecter %{name} ?"
7
7
  title_again: "Reconnecter %{name} ?"
8
- runs_at: "Fonctionne à"
8
+ runs_at: "%{name} fonctionne à %{origin}."
9
9
  lede_html: "Les gens pourront se connecter à <strong>%{name}</strong> avec leur compte %{tenant}. Pour l’instant, vous seul y avez accès, et vous choisissez plus tard qui d’autre peut entrer."
10
10
  lede_again_html: "<strong>%{name}</strong> est déjà connectée à %{tenant}. La reconnecter la configure à nouveau. Pour l’instant, vous seul y avez accès, et vous choisissez plus tard qui d’autre peut entrer."
11
11
  stops_working: "La connexion actuelle de %{name} cesse de fonctionner."
12
12
  connected_by_you: "Vous avez connecté %{name} le %{date}."
13
13
  connected_by: "%{who} a connecté %{name} le %{date}."
14
- signed_in_as: "Vous approuvez en tant que"
14
+ signed_in_as: "Vous connectez en tant que"
15
15
  unconfirmed: "(adresse e-mail pas encore confirmée)"
16
- check: "Regardez d’abord ceci"
16
+ check: "Avant de connecter"
17
17
  heed:
18
18
  offline_access: "%{name} peut garder les gens connectés sans redemander, jusqu’à ce qu’ils se déconnectent."
19
19
  delegates_title: "Demander aux gens d’associer leurs autres comptes"
20
20
  delegates: "Chaque personne choisit elle-même. %{name} peut ensuite utiliser ces comptes en leur absence."
21
21
  delegate: "%{name} peut utiliser ce compte en votre absence, jusqu’à ce que vous l’arrêtiez."
22
22
  manage: "Toute personne qui se connecte via %{name} peut modifier tous les paramètres de ce serveur."
23
- sees: "%{name} peut voir"
23
+ sees: "%{name} saura"
24
24
  area: "Les autorisations propres à %{name}"
25
25
  area_says_html: "%{name} reçoit son propre ensemble d’autorisations, nommé %{namespaces}. Vous décidez qui les reçoit."
26
26
  area_yours: " Vous les recevez toutes dès maintenant."
27
27
  also: "%{name} peut aussi"
28
- details: "Détails techniques"
28
+ details: "Détails"
29
29
  scopes: "Portées"
30
30
  client: "Identifiants"
31
31
  credentials:
@@ -16,7 +16,7 @@ fr:
16
16
  name: "Nom"
17
17
  phone: "Téléphone"
18
18
  password: "Mot de passe"
19
- not_you: "Ce n’est pas vous ?"
19
+ not_you: "Utiliser un autre compte"
20
20
  sign_out: "Se déconnecter"
21
21
  use_passkey: "Utiliser une clé d’accès"
22
22
  or: "ou"
@@ -40,10 +40,12 @@ fr:
40
40
  tab_confirmation: "Confirmation"
41
41
  setup_cap: "Bienvenue !"
42
42
  setup_title: "Configurer"
43
- signup_title: "Créer un compte sur"
43
+ signup_title: "Créez votre compte"
44
44
  token: "Jeton de configuration"
45
- token_hint: "Inscrit dans les journaux du serveur, que seule la personne qui exploite masks peut lire."
46
- origin: "Configurer sur"
45
+ token_hint: "Il est imprimé dans le journal du serveur."
46
+ origin: "Ce masks répond à %{origin}."
47
+ pick_nickname: "Choisir un pseudo"
48
+ nickname_hint: "Les autres le voient. Laissez tel quel pour utiliser %{suggested}."
47
49
  once: "Cet écran ne s’affichera plus."
48
50
  docs: "Lire la documentation."
49
51
  confirm: "Confirmer le mot de passe"
@@ -57,10 +59,10 @@ fr:
57
59
  proving: "Vérification du navigateur"
58
60
 
59
61
  identify:
60
- heading: "Connectez-vous pour continuer"
62
+ heading: "Se connecter"
61
63
  heading_to: "Se connecter à %{client}"
62
- identifier: "Pseudo ou e-mail"
63
- signup_hint: "Nouveau ici ? Saisissez l’adresse que vous voulez utiliser, et un compte est créé pour elle."
64
+ identifier: "E-mail ou pseudo"
65
+ signup_hint: "Nouveau ici ? Saisissez votre e-mail et masks vous crée un compte."
64
66
 
65
67
  first_factor:
66
68
  title: "Saisissez votre mot de passe"
@@ -76,16 +78,16 @@ fr:
76
78
  sent_again: "Envoyé"
77
79
 
78
80
  second_factor:
79
- title: "Saisissez votre code"
80
- title_passkey: "Utilisez votre second facteur"
81
- trust: "Faire confiance à cet appareil pendant %{duration}"
81
+ title: "Confirmez que c'est vous"
82
+ title_passkey: "Confirmez que c'est vous avec votre clé d'accès"
83
+ trust: "Passer cette étape sur cet appareil pendant %{duration}"
82
84
  use_backup_code: "Utiliser un code de secours"
83
85
  stuck_insecure: "Le second facteur de ce compte est une clé d’accès, et le navigateur ne propose les clés d’accès qu’aux pages servies en HTTPS. Ouvrez cette page en HTTPS pour continuer."
84
86
  stuck_unsupported: "Le second facteur de ce compte est une clé d’accès, et ce navigateur ne prend pas en charge les clés d’accès. Ouvrez cette page dans un navigateur compatible pour continuer."
85
87
  stuck_no_script: "Le second facteur de ce compte est une clé d’accès, et une clé d’accès nécessite JavaScript. Activez JavaScript pour continuer."
86
88
  stuck_inbox: "Cette connexion a commencé depuis votre boîte de réception, donc un code envoyé à cette adresse ne peut pas la confirmer. Recommencez et connectez-vous avec votre mot de passe pour utiliser un code par e-mail."
87
89
  stuck_nothing: "Ce compte n’a aucun second facteur utilisable pour cette connexion. Un gestionnaire peut le réinitialiser."
88
- recovery_request: "Je ne peux utiliser aucune de ces options"
90
+ recovery_request: "Je ne peux utiliser aucun de ces moyens"
89
91
  recovery_ask: "Demander de l’aide à un gestionnaire"
90
92
  recovery_requested: "Un gestionnaire a été invité à réinitialiser vos seconds facteurs. Il peut vous contacter pour s’assurer qu’il s’agit bien de vous. Ensuite, reconnectez-vous pour en configurer un nouveau."
91
93
  sent_to: "Envoyé à %{to}."
@@ -101,16 +103,26 @@ fr:
101
103
  approval_checked: "Je l’ai approuvée"
102
104
 
103
105
  enrol:
104
- title: "Sécurisez votre compte"
105
- lede: "Ajoutez autant de seconds facteurs que vous le souhaitez. Ce compte en exige au moins un."
106
- lede_optional: "Ajoutez autant de seconds facteurs que vous le souhaitez."
106
+ title: "Protégez votre compte"
107
+ lede: "Choisissez une façon de confirmer que c'est vous à la connexion. Vous pourrez en ajouter d'autres plus tard."
108
+ lede_optional: "Choisissez une façon de confirmer que c'est vous à la connexion, ou passez pour l'instant."
109
+ on_title: "Votre compte est protégé"
110
+ on_lede: "Voici comment vous confirmez que c'est vous à la connexion."
111
+ on_label: "Activé"
112
+ passkey: "Clé d'accès"
107
113
  otp: "Application d’authentification"
114
+ otp_about: "Une application comme Google Authenticator ou 1Password affiche un code à six chiffres."
108
115
  otp_on: "Activée"
109
- scan_hint: "Scannez-le, ou saisissez cette clé à la main :"
116
+ scan_hint: "Scannez ceci avec votre application d'authentification, ou saisissez-y la clé :"
117
+ passkey_about: "Votre téléphone ou ordinateur vérifie que c'est vous avec votre visage, votre empreinte ou votre code PIN."
118
+ codes_email_about: "Un code est envoyé à %{to} à chaque connexion."
119
+ codes_sms_about: "Un code est envoyé à %{to} par SMS à chaque connexion."
120
+ another_way: "Choisir un autre moyen"
121
+ add_way: "Ajouter un autre moyen"
110
122
  open: "Ouvrir dans votre application d’authentification"
111
123
  turn_on: "L’activer"
112
124
  passkeys: "Clés d’accès"
113
- passkeys_none: "Aucune pour l’instant. Une clé qui vérifie un code PIN ou une empreinte digitale convient."
125
+ passkeys_none: "Aucune pour l'instant."
114
126
  passkeys_some: "%{count} ajoutée(s)"
115
127
  add_passkey: "Ajouter une clé d’accès"
116
128
  add_another_passkey: "En ajouter une autre"
@@ -118,17 +130,17 @@ fr:
118
130
  codes_email_hint: "Un code envoyé à %{to} confirme chaque connexion."
119
131
  codes_sms: "Codes par SMS"
120
132
  codes_sms_hint: "Un code envoyé par SMS au %{to} confirme chaque connexion."
121
- send_code: "Envoyer un code pour l’activer"
133
+ send_code: "M'envoyer un code"
122
134
  sent_to: "Envoyé à %{to}."
123
135
  backup_codes: "Codes de secours"
124
- backup_codes_waiting: "Générés pour vous dès qu’un facteur ci-dessus est activé."
125
- backup_codes_hint: "Chacun permet une seule connexion, quand vous n’avez rien d’autre sous la main. Ils ne seront plus affichés."
136
+ backup_codes_waiting: "Créés dès qu'un moyen ci-dessus est activé."
137
+ backup_codes_hint: "Chaque code vous connecte une fois si vous perdez votre autre moyen. Enregistrez-les maintenant. Ils ne sont plus affichés ensuite."
126
138
  backup_codes_left: "%{count} restant(s)"
127
139
  backup_codes_file: "Codes de secours pour %{account} sur %{origin}"
128
140
  copy: "Les copier"
129
141
  copied: "Copiés"
130
142
  download: "Les télécharger"
131
- kept: "J’ai conservé mes codes de secours en lieu sûr"
143
+ kept: "J'ai enregistré mes codes de secours"
132
144
  done: "Continuer"
133
145
  skip: "Ignorer pour l’instant"
134
146
 
@@ -163,7 +175,7 @@ fr:
163
175
  prove_email:
164
176
  title: "Consultez vos e-mails"
165
177
  lede: "Un code à six chiffres est en route vers %{email}. Saisissez-le pour continuer."
166
- no_mailer: "Ce serveur ne peut pas encore envoyer d’e-mails, donc une adresse ne peut pas servir à se connecter. Utilisez votre pseudo, ou adressez-vous à un gestionnaire."
178
+ no_mailer: "Ce serveur ne peut pas encore envoyer d'e-mail, donc il ne peut pas vérifier votre adresse. Connectez-vous avec votre pseudo, ou demandez à la personne qui l'administre de confirmer l'adresse pour vous."
167
179
 
168
180
  setup_configure:
169
181
  called: "Ce serveur s’appelle"
@@ -202,17 +214,19 @@ fr:
202
214
  as: "%{organization}, en tant que %{role}"
203
215
 
204
216
  consent:
205
- title: "Autoriser %{client} ?"
206
- access: "Accès"
207
- no_access: "Rien d’autre que la confirmation de votre identité."
208
- audience: "En votre nom sur"
217
+ title: "%{client} veut vous connecter"
218
+ access: "Il saura"
219
+ no_access: "Seulement que vous avez un compte ici."
220
+ audience: "Il peut agir pour vous sur %{resources}."
209
221
  details: "Exactement ceci"
210
222
  returns_to: "Puis retour à"
223
+ more: "Détails"
224
+ scopes: "Autorisations"
211
225
  site: "À propos de %{client}"
212
226
  terms: "Ses conditions d’utilisation"
213
227
  privacy: "Sa politique de confidentialité"
214
228
  allow: "Autoriser"
215
- deny: "Refuser"
229
+ deny: "Pas maintenant"
216
230
  working: "Autorisation"
217
231
 
218
232
  settled:
@@ -221,7 +235,7 @@ fr:
221
235
  waiting: "Retour en cours"
222
236
 
223
237
  warnings:
224
- invalid-credentials: "Ce pseudo et ce mot de passe ne correspondent pas."
238
+ invalid-credentials: "Cet e-mail ou pseudo et ce mot de passe ne correspondent pas."
225
239
  invalid-code: "Ce code n’est pas valide."
226
240
  invalid-backup-code: "Ce code de secours n’est pas valide."
227
241
  invalid-passkey: "Cette clé d’accès n’a pas pu être utilisée."
@@ -233,7 +247,7 @@ fr:
233
247
  passkey-crowded: "Ce compte a déjà le nombre maximal de clés d’accès que ce serveur conserve."
234
248
  second-factor-required: "Activez au moins un second facteur pour continuer."
235
249
  backup-codes-unkept: "Conservez vos codes de secours avant de continuer."
236
- missing-identifier: "Saisissez votre pseudo ou votre e-mail."
250
+ missing-identifier: "Saisissez votre e-mail ou votre pseudo."
237
251
  missing-first-factor: "Cette étape a expiré. Recommencez."
238
252
  too-many-attempts: "Trop de tentatives. Patientez quelques minutes."
239
253
  too-many-attempts-for-account: "Trop de tentatives pour ce compte."
@@ -258,7 +272,7 @@ fr:
258
272
  work-unsolved: "Ce navigateur n'a pas terminé la vérification qui écarte les inscriptions automatisées. Réessayez."
259
273
  invitation-expired: "Cette invitation n’est plus valide. Demandez-en une autre."
260
274
  reset-expired: "Ce lien de réinitialisation n’est plus valide. Demandez-en un autre."
261
- no-mailer: "Ce serveur ne peut pas envoyer d’e-mails. Adressez-vous à un gestionnaire."
275
+ no-mailer: "Ce serveur ne peut pas encore envoyer d'e-mail, donc il ne peut pas réinitialiser votre mot de passe. Demandez un lien de réinitialisation à la personne qui l'administre."
262
276
  sso-failed: "Cette connexion n’a pas abouti. Réessayez."
263
277
  sso-expired: "Cette connexion a pris trop de temps. Réessayez."
264
278
  sso-unavailable: "Ce mode de connexion n’est pas disponible."
@@ -65,13 +65,20 @@ fr:
65
65
  proven: "Chaque domaine revendiqué a toujours son enregistrement TXT."
66
66
  missing: "L'enregistrement TXT manque pour %{domains}. Une revendication est libérée une semaine après la disparition de son enregistrement."
67
67
  advice: "Remettez l'enregistrement TXT au nom indiqué sur la page Domaines."
68
+ proxy:
69
+ title: "Proxy inverse"
70
+ quiet: "Les en-têtes transmis ne viennent que de proxys de confiance, en HTTPS."
71
+ untrusted: "Des en-têtes transmis sont arrivés de %{addresses}, qui ne figure pas dans MASKS_TRUSTED_PROXIES, et ont donc été ignorés. Tous les visiteurs derrière ce proxy partagent une adresse et une même limite."
72
+ plain: "Le proxy à %{addresses} transmet les requêtes en HTTP non chiffré. masks réserve ses cookies au HTTPS, donc les navigateurs les rejettent et la connexion tourne en boucle."
73
+ one: "Les %{count} événements de la dernière heure viennent tous de %{address}, une adresse privée, qui est presque sûrement le proxy lui-même."
74
+ advice: "Ajoutez le proxy à MASKS_TRUSTED_PROXIES et faites-lui envoyer X-Forwarded-For et X-Forwarded-Proto. Cherchez dans le journal du serveur les lignes qui commencent par proxy:."
68
75
  keys:
69
76
  title: "Clés de signature"
70
77
  missing: "Ce locataire n'a aucune clé de signature active, donc rien ne peut être signé."
71
- manual: "Les clés tournent à la main. La clé active a %{days} jours."
78
+ manual: "Les clés tournent à la main, donc rien ne remplace la clé active de lui-même. Elle a %{days} jours."
72
79
  fresh: "La clé active a %{days} jours et tourne tous les %{period} jours."
73
80
  stale: "La clé active a %{days} jours, au-delà de sa rotation de %{period} jours."
74
- advice: "Faites tourner la clé sur la page Paramètres, ou lisez la tâche signing_keys dans le journal du serveur."
81
+ advice: "Choisissez un calendrier de rotation sur la page Paramètres, faites tourner la clé là, ou lisez la tâche signing_keys dans le journal du serveur."
75
82
  release:
76
83
  available: "La version %{version} est disponible."
77
84
  operator: "Cette version demande une étape d'un opérateur. Lisez ses notes avant de mettre à jour."
@@ -0,0 +1,5 @@
1
+ class DefaultKeyRotationToNinetyDays < ActiveRecord::Migration[8.1]
2
+ def change
3
+ change_column_default :tenants, :key_rotation_days, from: nil, to: 90
4
+ end
5
+ end
@@ -39,6 +39,7 @@ module Masks
39
39
  say ""
40
40
 
41
41
  engine? ? say_engine_database : say_server_database
42
+ say_cache_store if engine?
42
43
 
43
44
  say "In production, masks keeps the address its setup screen was first opened at, and builds the"
44
45
  say "issuer and every emailed link from it. To name the address yourself, set"
@@ -105,6 +106,24 @@ module Masks
105
106
  say ""
106
107
  end
107
108
 
109
+ def say_cache_store
110
+ say "masks holds one-time sign-in state, rate limits, and health findings in Rails.cache, so"
111
+ say "every process that serves it must share one cache store, such as :solid_cache_store,"
112
+ say ":redis_cache_store or :mem_cache_store. In production, masks refuses to boot on"
113
+ say ":memory_store or :null_store."
114
+
115
+ if Configuration.unshared_cache_store?(cache_store)
116
+ say ""
117
+ say "This app's cache_store is #{Array(cache_store).first.inspect}. Change it before you deploy.", :yellow
118
+ end
119
+
120
+ say ""
121
+ end
122
+
123
+ def cache_store
124
+ ::Rails.application&.config&.cache_store if defined?(::Rails.application)
125
+ end
126
+
108
127
  def say_server_database
109
128
  say "masks keeps its tables in the primary database. Connect as a role holding neither"
110
129
  say "SUPERUSER nor BYPASSRLS, and set config.active_record.schema_format = :sql, since"
@@ -4,6 +4,7 @@ module Masks
4
4
  module Server
5
5
  module Configuration
6
6
  MODES = %i[server engine].freeze
7
+ UNSHARED_CACHE_STORES = %i[memory_store null_store].freeze
7
8
 
8
9
  module_function
9
10
 
@@ -12,13 +13,6 @@ module Masks
12
13
  config.mode = ENV.fetch("MASKS_MODE", "server").to_sym
13
14
  config.database = nil
14
15
  config.secret = nil
15
- config.attempt_limit = ENV.fetch("MASKS_ATTEMPT_LIMIT", 10).to_i
16
- config.account_attempt_limit = ENV.fetch("MASKS_ACCOUNT_ATTEMPT_LIMIT", 5).to_i
17
- config.registration_limit = ENV.fetch("MASKS_REGISTRATION_LIMIT", 10).to_i
18
- config.recovery_limit = ENV.fetch("MASKS_RECOVERY_LIMIT", 5).to_i
19
- config.device_code_limit = ENV.fetch("MASKS_DEVICE_CODE_LIMIT", 30).to_i
20
- config.claim_limit = ENV.fetch("MASKS_CLAIM_LIMIT", 3).to_i
21
- config.claim_ceiling = ENV.fetch("MASKS_CLAIM_CEILING", 30).to_i
22
16
  config.setup_token = ENV["MASKS_SETUP_TOKEN"].presence
23
17
  config.recover = ENV["MASKS_RECOVER"].presence
24
18
  config.config_path = ENV["MASKS_CONFIG"].presence
@@ -88,7 +82,11 @@ module Masks
88
82
  }.compact
89
83
  end
90
84
 
91
- def validate!(config, local:, building:)
85
+ def unshared_cache_store?(cache_store)
86
+ UNSHARED_CACHE_STORES.include?(Array(cache_store).first&.to_sym)
87
+ end
88
+
89
+ def validate!(config, local:, building:, cache_store: nil)
92
90
  unless MODES.include?(config.mode)
93
91
  raise "masks runs in server or engine mode, and config.masks.mode is #{config.mode.inspect}."
94
92
  end
@@ -131,6 +129,14 @@ module Masks
131
129
  raise "masks in engine mode needs a database of its own. Set config.masks.database to " \
132
130
  "the name of a database.yml entry whose role cannot bypass row-level security."
133
131
  end
132
+
133
+ if unshared_cache_store?(cache_store)
134
+ raise "config.cache_store is #{Array(cache_store).first.inspect}, which every process keeps " \
135
+ "to itself. masks holds one-time sign-in state, rate limits, and health findings in " \
136
+ "Rails.cache, so a provider's callback redeemed in one process is lost in the next. " \
137
+ "Use a store every process shares, such as :solid_cache_store, :redis_cache_store " \
138
+ "or :mem_cache_store."
139
+ end
134
140
  end
135
141
  end
136
142
  end
@@ -20,7 +20,8 @@ module Masks
20
20
  Configuration.validate!(
21
21
  app.config.masks,
22
22
  local: ::Rails.env.local?,
23
- building: ENV["SECRET_KEY_BASE_DUMMY"].present?
23
+ building: ENV["SECRET_KEY_BASE_DUMMY"].present?,
24
+ cache_store: app.config.cache_store
24
25
  )
25
26
 
26
27
  middleware.insert_before Tenancy::Middleware, Isolation if app.config.masks.mode == :engine
@@ -1,7 +1,11 @@
1
1
  module Masks
2
2
  module Server
3
3
  class Forwarding
4
- HEADERS = %w[HTTP_X_FORWARDED_FOR HTTP_X_FORWARDED_HOST HTTP_CLIENT_IP HTTP_FORWARDED].freeze
4
+ HEADERS = %w[
5
+ HTTP_X_FORWARDED_FOR HTTP_X_FORWARDED_HOST HTTP_CLIENT_IP HTTP_FORWARDED
6
+ HTTP_X_FORWARDED_PROTO HTTP_X_FORWARDED_SCHEME HTTP_X_FORWARDED_SSL HTTP_X_FORWARDED_PORT
7
+ ].freeze
8
+ PROTO = "HTTP_X_FORWARDED_PROTO".freeze
5
9
 
6
10
  def initialize(app, proxies)
7
11
  @app = app
@@ -9,9 +13,20 @@ module Masks
9
13
  end
10
14
 
11
15
  def call(env)
12
- HEADERS.each { |header| env.delete(header) } unless trusted?(env["REMOTE_ADDR"])
16
+ address = env["REMOTE_ADDR"]
17
+ trusted = trusted?(address)
13
18
 
14
- @app.call(env)
19
+ unless trusted
20
+ Health.note_proxy!("untrusted", address) if HEADERS.any? { |header| env.key?(header) }
21
+ HEADERS.each { |header| env.delete(header) }
22
+ end
23
+
24
+ plain = trusted && plain?(env)
25
+ status, headers, body = @app.call(env)
26
+
27
+ Health.note_proxy!("plain", address) if plain && !sent_to_https?(status, headers)
28
+
29
+ [ status, headers, body ]
15
30
  end
16
31
 
17
32
  private
@@ -24,6 +39,14 @@ module Masks
24
39
  rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
25
40
  false
26
41
  end
42
+
43
+ def plain?(env)
44
+ env[PROTO].to_s.split(",").first.to_s.strip.casecmp?("http")
45
+ end
46
+
47
+ def sent_to_https?(status, headers)
48
+ (300..399).cover?(status) && headers["location"].to_s.downcase.start_with?("https://")
49
+ end
27
50
  end
28
51
  end
29
52
  end
@@ -34,7 +34,7 @@ module Masks
34
34
 
35
35
  Everything `/manage` can ask for and everything it can change. `/manage/graphql` accepts a
36
36
  bearer carrying `masks:manage` or one of the narrower
37
- [manage roles](/guides/security/#manage-roles), issued for this tenant's manage resource and
37
+ [manage roles](/build/security/#manage-roles), issued for this tenant's manage resource and
38
38
  no other. A mutation the bearer's roles do not cover answers with an error naming the scopes
39
39
  it needs.
40
40