masks-server 0.9.0 → 0.10.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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/masks/server/client_authentication.rb +3 -2
- data/app/controllers/masks/server/addresses_controller.rb +6 -1
- data/app/controllers/masks/server/application_controller.rb +29 -1
- data/app/controllers/masks/server/authorize_controller.rb +23 -18
- data/app/controllers/masks/server/device_verifications_controller.rb +1 -1
- data/app/controllers/masks/server/logins_controller.rb +2 -1
- data/app/controllers/masks/server/notifications_controller.rb +11 -1
- data/app/controllers/masks/server/profiles_controller.rb +5 -0
- data/app/controllers/masks/server/saml_controller.rb +1 -7
- data/app/controllers/masks/server/tokens_controller.rb +8 -0
- data/app/graphql/masks/server/manage/mutations/create_actor.rb +1 -0
- data/app/graphql/masks/server/manage/mutations/update_actor.rb +1 -0
- data/app/graphql/masks/server/manage/mutations/update_client.rb +4 -0
- data/app/graphql/masks/server/manage/types/client_type.rb +2 -0
- data/app/graphql/masks/server/manage/types/query_type.rb +7 -0
- data/app/jobs/masks/server/cleanup_job.rb +1 -0
- data/app/ldap/masks/server/ldap/listener.rb +16 -3
- data/app/logins/masks/server/login_states/confirmation.rb +9 -3
- data/app/logins/masks/server/login_states/signup.rb +1 -0
- data/app/models/masks/server/actor.rb +25 -2
- data/app/models/masks/server/client.rb +15 -0
- data/app/models/masks/server/client_keys.rb +12 -1
- data/app/models/masks/server/declared.rb +2 -1
- data/app/models/masks/server/event.rb +1 -0
- data/app/models/masks/server/notifications.rb +8 -0
- data/app/models/masks/server/pending_request.rb +8 -0
- data/app/models/masks/server/refresh_token.rb +8 -0
- data/app/models/masks/server/released_nickname.rb +26 -0
- data/app/models/masks/server/scim/filter.rb +45 -5
- data/app/models/masks/server/scim/user.rb +1 -0
- data/app/models/masks/server/session.rb +3 -4
- data/app/views/masks/server/account/_info.html.erb +12 -4
- data/app/views/masks/server/account/index.html.erb +1 -1
- data/app/views/masks/server/authorize/error.html.erb +2 -2
- data/config/locales/de/account.yml +4 -0
- data/config/locales/de/actors.yml +2 -0
- data/config/locales/de/authorize.yml +2 -0
- data/config/locales/de/events.yml +2 -0
- data/config/locales/de/flashes.yml +1 -0
- data/config/locales/de/logins.yml +1 -0
- data/config/locales/de/manage/client.yml +3 -0
- data/config/locales/de/manage/ldap.yml +1 -0
- data/config/locales/de/notifications.yml +1 -0
- data/config/locales/en/account.yml +4 -0
- data/config/locales/en/actors.yml +2 -0
- data/config/locales/en/authorize.yml +2 -0
- data/config/locales/en/events.yml +2 -0
- data/config/locales/en/flashes.yml +1 -0
- data/config/locales/en/logins.yml +1 -0
- data/config/locales/en/manage/client.yml +3 -0
- data/config/locales/en/manage/ldap.yml +1 -0
- data/config/locales/en/notifications.yml +1 -0
- data/config/locales/es/account.yml +4 -0
- data/config/locales/es/actors.yml +2 -0
- data/config/locales/es/authorize.yml +2 -0
- data/config/locales/es/events.yml +2 -0
- data/config/locales/es/flashes.yml +1 -0
- data/config/locales/es/logins.yml +1 -0
- data/config/locales/es/manage/client.yml +3 -0
- data/config/locales/es/manage/ldap.yml +1 -0
- data/config/locales/es/notifications.yml +1 -0
- data/config/locales/fr/account.yml +4 -0
- data/config/locales/fr/actors.yml +2 -0
- data/config/locales/fr/authorize.yml +2 -0
- data/config/locales/fr/events.yml +2 -0
- data/config/locales/fr/flashes.yml +1 -0
- data/config/locales/fr/logins.yml +1 -0
- data/config/locales/fr/manage/client.yml +3 -0
- data/config/locales/fr/manage/ldap.yml +1 -0
- data/config/locales/fr/notifications.yml +1 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20261018100000_create_released_nicknames.rb +22 -0
- data/db/migrate/20261018110000_add_refresh_token_absolute_lifetime_to_clients.rb +5 -0
- data/lib/masks/server/configuration.rb +8 -0
- data/lib/masks/server/tenancy/middleware.rb +9 -1
- data/public/masks-assets/.vite/manifest.json +2 -2
- data/public/masks-assets/assets/{app-B27oPUll.css → app-D7W0gAyT.css} +1 -1
- data/public/masks-assets/assets/manage-DR9qQiBU.js +569 -0
- data/public/masks-assets/assets/manage-DR9qQiBU.js.map +1 -0
- data/version.txt +1 -1
- metadata +7 -4
- data/public/masks-assets/assets/manage-Dbfiy3Mj.js +0 -567
- data/public/masks-assets/assets/manage-Dbfiy3Mj.js.map +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Masks
|
|
2
|
+
module Server
|
|
3
|
+
class ReleasedNickname < ApplicationRecord
|
|
4
|
+
include TenantScoped
|
|
5
|
+
|
|
6
|
+
HOLD = 30.days
|
|
7
|
+
|
|
8
|
+
belongs_to :actor, optional: true
|
|
9
|
+
|
|
10
|
+
scope :holding, ->(nickname) { where(nickname: nickname.to_s.downcase).where("released_at > ?", HOLD.ago) }
|
|
11
|
+
scope :lapsed, -> { where(released_at: ...HOLD.ago) }
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
def release!(nickname, actor:)
|
|
15
|
+
return if nickname.blank?
|
|
16
|
+
|
|
17
|
+
find_or_initialize_by(nickname: nickname.downcase).update!(actor: actor, released_at: Time.current)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def held_from?(nickname, actor)
|
|
21
|
+
holding(nickname).where.not(actor_id: actor.id).or(holding(nickname).where(actor_id: nil)).exists?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
require "strscan"
|
|
2
|
+
|
|
1
3
|
module Masks
|
|
2
4
|
module Server
|
|
3
5
|
module Scim
|
|
4
6
|
class Filter
|
|
5
|
-
|
|
7
|
+
LONGEST = 512
|
|
8
|
+
TOKEN = /"(?:[^"\\]|\\.)*"|(?:[^\s"\[]|\[[^\]]*\])+/
|
|
9
|
+
PATH = /\A[A-Za-z][\w.:\[\]" ]*\z/
|
|
10
|
+
VALUE = /\A(?:"(?:[^"\\]|\\.)*"|true|false|null|[\d.]+)\z/
|
|
11
|
+
OPERATORS = %w[eq ne co sw ew pr gt ge lt le].freeze
|
|
6
12
|
ATTRIBUTES = {
|
|
7
13
|
"id" => "actors.uuid",
|
|
8
14
|
"username" => :user_name,
|
|
@@ -30,7 +36,9 @@ module Masks
|
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
def apply(relation)
|
|
33
|
-
|
|
39
|
+
raise Error.new(:bad_request, "a filter is at most #{LONGEST} characters", scim_type: "invalidFilter") if @expression.length > LONGEST
|
|
40
|
+
|
|
41
|
+
clauses = clauses_of(tokens)
|
|
34
42
|
|
|
35
43
|
raise Error.new(:bad_request, "at most four comparisons joined by and are understood", scim_type: "invalidFilter") if clauses.size > 4
|
|
36
44
|
|
|
@@ -39,12 +47,44 @@ module Masks
|
|
|
39
47
|
|
|
40
48
|
private
|
|
41
49
|
|
|
50
|
+
def tokens
|
|
51
|
+
scanner = StringScanner.new(@expression)
|
|
52
|
+
held = []
|
|
53
|
+
|
|
54
|
+
until scanner.eos?
|
|
55
|
+
next if scanner.skip(/\s+/)
|
|
56
|
+
|
|
57
|
+
token = scanner.scan(TOKEN)
|
|
58
|
+
|
|
59
|
+
raise unreadable(@expression) if token.nil?
|
|
60
|
+
|
|
61
|
+
held << token
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
held
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def clauses_of(tokens)
|
|
68
|
+
clauses = [ [] ]
|
|
69
|
+
|
|
70
|
+
tokens.each do |token|
|
|
71
|
+
token.casecmp?("and") ? clauses << [] : clauses.last << token
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
clauses
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def unreadable(clause)
|
|
78
|
+
Error.new(:bad_request, "#{clause.strip} is not a filter this server reads", scim_type: "invalidFilter")
|
|
79
|
+
end
|
|
80
|
+
|
|
42
81
|
def compare(relation, clause)
|
|
43
|
-
|
|
82
|
+
path, operator, raw = clause
|
|
44
83
|
|
|
45
|
-
raise
|
|
84
|
+
raise unreadable(clause.join(" ")) unless clause.size.between?(2, 3)
|
|
85
|
+
raise unreadable(clause.join(" ")) unless PATH.match?(path) && OPERATORS.include?(operator.downcase)
|
|
86
|
+
raise unreadable(clause.join(" ")) unless raw.nil? || VALUE.match?(raw)
|
|
46
87
|
|
|
47
|
-
path, operator, raw = match.captures
|
|
48
88
|
key = normalized(path)
|
|
49
89
|
column = @columns[key]
|
|
50
90
|
operator = operator.downcase
|
|
@@ -72,11 +72,10 @@ module Masks
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def first_factored!(held, at: nil)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
changes.merge!(first_factor: held["factor"], provider_id: held["provider_id"]) if held["factor"].present? && held != first_factored_by
|
|
75
|
+
self.authenticated_at = at if at && at > authenticated_at
|
|
76
|
+
assign_attributes(first_factor: held["factor"], provider_id: held["provider_id"]) if held["factor"].present?
|
|
78
77
|
|
|
79
|
-
|
|
78
|
+
save! if changed?
|
|
80
79
|
end
|
|
81
80
|
|
|
82
81
|
def bound?
|
|
@@ -46,7 +46,11 @@
|
|
|
46
46
|
</summary>
|
|
47
47
|
|
|
48
48
|
<div class="entry-body">
|
|
49
|
-
<p class="aside"><%= account_text("notifications.lede") %></p>
|
|
49
|
+
<p class="aside"><%= account_text("notifications.lede") %> <%= account_text("notifications.kept") %></p>
|
|
50
|
+
|
|
51
|
+
<% unless fresh %>
|
|
52
|
+
<p class="aside"><%= account_text("notifications.again") %></p>
|
|
53
|
+
<% end %>
|
|
50
54
|
|
|
51
55
|
<% unless Masks::Server::Notifications.mailable?(actor) %>
|
|
52
56
|
<p class="aside aside-bad"><%= account_text("notifications.silent") %></p>
|
|
@@ -63,8 +67,12 @@
|
|
|
63
67
|
<% actions.each do |action| %>
|
|
64
68
|
<label class="switch">
|
|
65
69
|
<span><%= t("events.actions.#{action}") %></span>
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
<% if Masks::Server::Notifications.always?(action) %>
|
|
71
|
+
<span class="switch-kept"><%= account_text("notifications.always") %></span>
|
|
72
|
+
<% else %>
|
|
73
|
+
<%= check_box_tag "notifications[]", action, actor.notified?(action),
|
|
74
|
+
id: "notify-#{action.tr('.', '-')}" %>
|
|
75
|
+
<% end %>
|
|
68
76
|
</label>
|
|
69
77
|
<% end %>
|
|
70
78
|
</div>
|
|
@@ -72,7 +80,7 @@
|
|
|
72
80
|
<% end %>
|
|
73
81
|
|
|
74
82
|
<div class="action-row">
|
|
75
|
-
<button type="submit" class="action action-sm"><%= account_text("notifications.submit") %></button>
|
|
83
|
+
<button type="submit" class="action action-sm"><%= account_text(fresh ? "notifications.submit" : "notifications.submit_again") %></button>
|
|
76
84
|
</div>
|
|
77
85
|
<% end %>
|
|
78
86
|
</div>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
<%= render "masks/server/account/apps", apps: @apps, connections: @connections, linkable: @linkable %>
|
|
33
33
|
|
|
34
|
-
<%= render "masks/server/account/info", actor: @actor, directed: @directed %>
|
|
34
|
+
<%= render "masks/server/account/info", actor: @actor, directed: @directed, fresh: @fresh %>
|
|
35
35
|
|
|
36
36
|
<%= render "masks/server/account/activity", events: @events %>
|
|
37
37
|
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<div id="authorize-error" class="flow" data-error="<%= @error_code %>">
|
|
5
5
|
<span class="state state-bad"><%= t(".stopped") %></span>
|
|
6
6
|
|
|
7
|
-
<h1 class="prompt-title"><%= t(".heading") %></h1>
|
|
7
|
+
<h1 class="prompt-title"><%= @refused ? t(".refused") : t(".heading") %></h1>
|
|
8
8
|
|
|
9
9
|
<p class="said"><%= @error_code %> — <%= @error_description %></p>
|
|
10
10
|
|
|
11
|
-
<p class="prompt-lede"><%= t(".contact") %></p>
|
|
11
|
+
<p class="prompt-lede"><%= @refused ? t(".nothing_shared") : t(".contact") %></p>
|
|
12
12
|
</div>
|
|
@@ -251,6 +251,10 @@ de:
|
|
|
251
251
|
lede: "Alles hier ist aktiv, bis Sie es deaktivieren. Diese Nachrichten kommen, sobald etwas passiert, und auf keine kann geantwortet werden."
|
|
252
252
|
silent: "Es wird nichts gesendet, weil diese Nachrichten nur an eine bestätigte E-Mail-Adresse gehen."
|
|
253
253
|
submit: "Speichern"
|
|
254
|
+
kept: "Ein geändertes oder zurückgesetztes Passwort und eine riskante Anmeldung werden immer gemeldet."
|
|
255
|
+
always: "Immer"
|
|
256
|
+
again: "Ihre letzte Anmeldung ist eine Weile her, daher werden Sie zuerst gebeten, sich erneut anzumelden."
|
|
257
|
+
submit_again: "Erneut anmelden"
|
|
254
258
|
|
|
255
259
|
export:
|
|
256
260
|
heading: "Ihr Konto herunterladen"
|
|
@@ -5,3 +5,5 @@ de:
|
|
|
5
5
|
stopped: "Angehalten"
|
|
6
6
|
heading: "Die App hat etwas angefordert, das dieser Server nicht tut."
|
|
7
7
|
contact: "Es wurde nichts geteilt. Die App muss das beheben."
|
|
8
|
+
refused: "Diese Anmeldung wurde abgelehnt."
|
|
9
|
+
nothing_shared: "Mit der App wurde nichts geteilt. Sie können diese Seite schließen."
|
|
@@ -129,6 +129,7 @@ de:
|
|
|
129
129
|
directed: "Das Verzeichnis Ihrer Organisation verwaltet Ihren Namen."
|
|
130
130
|
invalid: "%{errors}"
|
|
131
131
|
updated: "Ihre Angaben wurden gespeichert."
|
|
132
|
+
again: "Melden Sie sich erneut an, um Ihren Spitznamen zu ändern. Ihre letzte Anmeldung ist eine Weile her."
|
|
132
133
|
|
|
133
134
|
verifications:
|
|
134
135
|
too_many_requests: "Zu viele Anfragen. Warten Sie einige Minuten."
|
|
@@ -238,6 +238,7 @@ de:
|
|
|
238
238
|
too-many-attempts: "Zu viele Versuche. Warten Sie einige Minuten."
|
|
239
239
|
too-many-attempts-for-account: "Zu viele Versuche für dieses Konto."
|
|
240
240
|
too-many-codes: "An diese Adresse wurden zu viele Codes gesendet. Warten Sie einige Minuten."
|
|
241
|
+
too-many-texts: "An diese Nummer wurden zu viele Codes gesendet. Warten Sie einige Minuten."
|
|
241
242
|
prove-email-first: "Geben Sie zuerst den an diese Adresse gesendeten Code ein."
|
|
242
243
|
no-account-for-email: "Kein Konto hier verwendet diese Adresse."
|
|
243
244
|
invalid-setup-token: "Dieses Einrichtungstoken ist falsch."
|
|
@@ -115,6 +115,8 @@ de:
|
|
|
115
115
|
sector_placeholder: "nötig, wenn seine Redirect-URIs mehrere Hosts umfassen"
|
|
116
116
|
unattended: "Meldet sich als er selbst an (client_credentials)"
|
|
117
117
|
rotate: "Secret rotieren"
|
|
118
|
+
secret_expires: "Das Secret läuft am %{day} ab."
|
|
119
|
+
secret_expired: "Das Secret ist am %{day} abgelaufen. Rotieren Sie es, sonst kann sich nichts mehr damit anmelden."
|
|
118
120
|
archive: "Archivieren"
|
|
119
121
|
saml:
|
|
120
122
|
title: "SAML"
|
|
@@ -146,6 +148,7 @@ de:
|
|
|
146
148
|
consent: "Akteure um Zustimmung bitten"
|
|
147
149
|
access: "Access-Tokens gelten (Minuten, leer für eine Stunde)"
|
|
148
150
|
refresh: "Refresh-Tokens gelten ungenutzt (Tage, leer für 30)"
|
|
151
|
+
refresh_absolute: "Refresh-Tokens enden nach der Anmeldung (Tage, leer für 90)"
|
|
149
152
|
consent_lifetime: "Zustimmung gilt (Tage, leer bis zum Widerruf)"
|
|
150
153
|
logout: "Back-Channel-Logout-URI"
|
|
151
154
|
logout_session: "Sein Logout-Token benennt die Sitzung (sid)"
|
|
@@ -17,6 +17,7 @@ de:
|
|
|
17
17
|
address: "Adresse"
|
|
18
18
|
port: "Port %{port}"
|
|
19
19
|
ldaps: "Port %{port}, LDAPS"
|
|
20
|
+
local_only: "Ohne Zertifikat antwortet das Verzeichnis nur auf dem eigenen Rechner dieses Servers, damit kein Passwort unverschlüsselt über das Netz geht. Setzen Sie MASKS_LDAP_CERT und MASKS_LDAP_KEY, um LDAPS auf jeder Adresse anzubieten, oder MASKS_LDAP_PLAINTEXT=true in einem privaten Netz, dem Sie vertrauen."
|
|
20
21
|
label: "Bezeichnung"
|
|
21
22
|
issue: "Zugang ausstellen"
|
|
22
23
|
shown_once: "Dieses Geheimnis wird nur einmal angezeigt. Kopieren Sie es jetzt."
|
|
@@ -251,6 +251,10 @@ en:
|
|
|
251
251
|
lede: "Everything here is on until you turn it off. These arrive as they happen, and none of them can be replied to."
|
|
252
252
|
silent: "Nothing is being sent, because these only go to a confirmed email address."
|
|
253
253
|
submit: "Save"
|
|
254
|
+
kept: "A changed or reset password and a risky sign-in are always announced."
|
|
255
|
+
always: "Always"
|
|
256
|
+
again: "You signed in a while ago, so you will be asked to sign in again first."
|
|
257
|
+
submit_again: "Sign in again"
|
|
254
258
|
|
|
255
259
|
export:
|
|
256
260
|
heading: "Download your account"
|
|
@@ -129,6 +129,7 @@ en:
|
|
|
129
129
|
directed: "Your organization's directory manages your name."
|
|
130
130
|
invalid: "%{errors}"
|
|
131
131
|
updated: "Your details have been saved."
|
|
132
|
+
again: "Sign in again to change your nickname. It has been a while since you did."
|
|
132
133
|
|
|
133
134
|
verifications:
|
|
134
135
|
too_many_requests: "Too many requests. Wait a few minutes."
|
|
@@ -238,6 +238,7 @@ en:
|
|
|
238
238
|
too-many-attempts: "Too many attempts. Wait a few minutes."
|
|
239
239
|
too-many-attempts-for-account: "Too many attempts for that account."
|
|
240
240
|
too-many-codes: "Too many codes have gone to that address. Wait a few minutes."
|
|
241
|
+
too-many-texts: "Too many codes have gone to that number. Wait a few minutes."
|
|
241
242
|
prove-email-first: "Enter the code sent to that address first."
|
|
242
243
|
no-account-for-email: "No account here uses that address."
|
|
243
244
|
invalid-setup-token: "That setup token is wrong."
|
|
@@ -115,6 +115,8 @@ en:
|
|
|
115
115
|
sector_placeholder: "needed when its redirect URIs span several hosts"
|
|
116
116
|
unattended: "Signs in as itself (client_credentials)"
|
|
117
117
|
rotate: "Rotate secret"
|
|
118
|
+
secret_expires: "The secret expires on %{day}."
|
|
119
|
+
secret_expired: "The secret expired on %{day}. Rotate it, or nothing can sign in with it."
|
|
118
120
|
archive: "Archive"
|
|
119
121
|
saml:
|
|
120
122
|
title: "SAML"
|
|
@@ -146,6 +148,7 @@ en:
|
|
|
146
148
|
consent: "Ask actors to consent"
|
|
147
149
|
access: "Access tokens last (minutes, blank for an hour)"
|
|
148
150
|
refresh: "Refresh tokens last unused (days, blank for 30)"
|
|
151
|
+
refresh_absolute: "Refresh tokens stop after a sign-in (days, blank for 90)"
|
|
149
152
|
consent_lifetime: "Consent lasts (days, blank until revoked)"
|
|
150
153
|
logout: "Back-channel logout URI"
|
|
151
154
|
logout_session: "Its logout token names the session (sid)"
|
|
@@ -17,6 +17,7 @@ en:
|
|
|
17
17
|
address: "Address"
|
|
18
18
|
port: "Port %{port}"
|
|
19
19
|
ldaps: "Port %{port}, LDAPS"
|
|
20
|
+
local_only: "Without a certificate, the directory answers only on this server's own machine, so no password crosses the network in the clear. Set MASKS_LDAP_CERT and MASKS_LDAP_KEY to serve LDAPS on every address, or MASKS_LDAP_PLAINTEXT=true on a private network you trust."
|
|
20
21
|
label: "Label"
|
|
21
22
|
issue: "Issue a credential"
|
|
22
23
|
shown_once: "This secret is shown once. Copy it now."
|
|
@@ -251,6 +251,10 @@ es:
|
|
|
251
251
|
lede: "Todo lo de aquí está activado hasta que lo desactives. Llegan en el momento en que ocurre y no se puede responder a ninguno."
|
|
252
252
|
silent: "No se envía nada, porque solo van a una dirección de correo confirmada."
|
|
253
253
|
submit: "Guardar"
|
|
254
|
+
kept: "Una contraseña cambiada o restablecida y un inicio de sesión de riesgo se avisan siempre."
|
|
255
|
+
always: "Siempre"
|
|
256
|
+
again: "Hace tiempo que iniciaste sesión, así que primero se te pedirá que vuelvas a iniciarla."
|
|
257
|
+
submit_again: "Volver a iniciar sesión"
|
|
254
258
|
|
|
255
259
|
export:
|
|
256
260
|
heading: "Descargar tu cuenta"
|
|
@@ -5,3 +5,5 @@ es:
|
|
|
5
5
|
stopped: "Detenida"
|
|
6
6
|
heading: "La aplicación pidió algo que este servidor no hará."
|
|
7
7
|
contact: "No se compartió nada. La aplicación tiene que corregirlo."
|
|
8
|
+
refused: "Este inicio de sesión fue rechazado."
|
|
9
|
+
nothing_shared: "No se compartió nada con la aplicación. Puede cerrar esta página."
|
|
@@ -129,6 +129,7 @@ es:
|
|
|
129
129
|
directed: "El directorio de tu organización gestiona tu nombre."
|
|
130
130
|
invalid: "%{errors}"
|
|
131
131
|
updated: "Se guardaron tus datos."
|
|
132
|
+
again: "Vuelve a iniciar sesión para cambiar tu apodo. Hace tiempo que no lo haces."
|
|
132
133
|
|
|
133
134
|
verifications:
|
|
134
135
|
too_many_requests: "Demasiadas solicitudes. Espera unos minutos."
|
|
@@ -238,6 +238,7 @@ es:
|
|
|
238
238
|
too-many-attempts: "Demasiados intentos. Espera unos minutos."
|
|
239
239
|
too-many-attempts-for-account: "Demasiados intentos para esa cuenta."
|
|
240
240
|
too-many-codes: "Se enviaron demasiados códigos a esa dirección. Espera unos minutos."
|
|
241
|
+
too-many-texts: "Se enviaron demasiados códigos a ese número. Espera unos minutos."
|
|
241
242
|
prove-email-first: "Primero escribe el código enviado a esa dirección."
|
|
242
243
|
no-account-for-email: "Ninguna cuenta de aquí usa esa dirección."
|
|
243
244
|
invalid-setup-token: "Ese token de configuración no es correcto."
|
|
@@ -115,6 +115,8 @@ es:
|
|
|
115
115
|
sector_placeholder: "necesario cuando sus URI de redirección abarcan varios hosts"
|
|
116
116
|
unattended: "Inicia sesión por sí mismo (client_credentials)"
|
|
117
117
|
rotate: "Rotar secreto"
|
|
118
|
+
secret_expires: "El secreto caduca el %{day}."
|
|
119
|
+
secret_expired: "El secreto caducó el %{day}. Rótalo, o nada podrá iniciar sesión con él."
|
|
118
120
|
archive: "Archivar"
|
|
119
121
|
saml:
|
|
120
122
|
title: "SAML"
|
|
@@ -146,6 +148,7 @@ es:
|
|
|
146
148
|
consent: "Pedir el consentimiento de los actores"
|
|
147
149
|
access: "Los tokens de acceso duran (minutos, vacío para una hora)"
|
|
148
150
|
refresh: "Los tokens de actualización duran sin usarse (días, vacío para 30)"
|
|
151
|
+
refresh_absolute: "Los tokens de actualización terminan tras el inicio de sesión (días, vacío para 90)"
|
|
149
152
|
consent_lifetime: "El consentimiento dura (días, vacío hasta que se revoque)"
|
|
150
153
|
logout: "URI de cierre de sesión por back-channel"
|
|
151
154
|
logout_session: "Su token de cierre de sesión nombra la sesión (sid)"
|
|
@@ -17,6 +17,7 @@ es:
|
|
|
17
17
|
address: "Dirección"
|
|
18
18
|
port: "Puerto %{port}"
|
|
19
19
|
ldaps: "Puerto %{port}, LDAPS"
|
|
20
|
+
local_only: "Sin certificado, el directorio responde solo en la propia máquina de este servidor, para que ninguna contraseña cruce la red sin cifrar. Defina MASKS_LDAP_CERT y MASKS_LDAP_KEY para servir LDAPS en todas las direcciones, o MASKS_LDAP_PLAINTEXT=true en una red privada de confianza."
|
|
20
21
|
label: "Etiqueta"
|
|
21
22
|
issue: "Emitir una credencial"
|
|
22
23
|
shown_once: "Este secreto se muestra una sola vez. Cópialo ahora."
|
|
@@ -251,6 +251,10 @@ fr:
|
|
|
251
251
|
lede: "Tout ce qui figure ici est activé jusqu’à ce que vous le désactiviez. Ces e-mails arrivent au fil des événements, et il n’est pas possible d’y répondre."
|
|
252
252
|
silent: "Rien n’est envoyé, car ces e-mails ne partent que vers une adresse e-mail confirmée."
|
|
253
253
|
submit: "Enregistrer"
|
|
254
|
+
kept: "Un mot de passe modifié ou réinitialisé et une connexion à risque sont toujours signalés."
|
|
255
|
+
always: "Toujours"
|
|
256
|
+
again: "Votre dernière connexion remonte à un moment, vous devrez donc d’abord vous reconnecter."
|
|
257
|
+
submit_again: "Se reconnecter"
|
|
254
258
|
|
|
255
259
|
export:
|
|
256
260
|
heading: "Télécharger votre compte"
|
|
@@ -5,3 +5,5 @@ fr:
|
|
|
5
5
|
stopped: "Interrompu"
|
|
6
6
|
heading: "L’application a demandé quelque chose que ce serveur refuse de faire."
|
|
7
7
|
contact: "Rien n’a été partagé. C’est à l’application de corriger le problème."
|
|
8
|
+
refused: "Cette connexion a été refusée."
|
|
9
|
+
nothing_shared: "Rien n’a été partagé avec l’application. Vous pouvez fermer cette page."
|
|
@@ -129,6 +129,7 @@ fr:
|
|
|
129
129
|
directed: "L’annuaire de votre organisation gère votre nom."
|
|
130
130
|
invalid: "%{errors}"
|
|
131
131
|
updated: "Vos informations ont été enregistrées."
|
|
132
|
+
again: "Reconnectez-vous pour changer votre pseudo. Votre dernière connexion remonte à un moment."
|
|
132
133
|
|
|
133
134
|
verifications:
|
|
134
135
|
too_many_requests: "Trop de demandes. Attendez quelques minutes."
|
|
@@ -238,6 +238,7 @@ fr:
|
|
|
238
238
|
too-many-attempts: "Trop de tentatives. Patientez quelques minutes."
|
|
239
239
|
too-many-attempts-for-account: "Trop de tentatives pour ce compte."
|
|
240
240
|
too-many-codes: "Trop de codes ont été envoyés à cette adresse. Patientez quelques minutes."
|
|
241
|
+
too-many-texts: "Trop de codes ont été envoyés à ce numéro. Patientez quelques minutes."
|
|
241
242
|
prove-email-first: "Saisissez d’abord le code envoyé à cette adresse."
|
|
242
243
|
no-account-for-email: "Aucun compte ici n’utilise cette adresse."
|
|
243
244
|
invalid-setup-token: "Ce jeton de configuration est incorrect."
|
|
@@ -115,6 +115,8 @@ fr:
|
|
|
115
115
|
sector_placeholder: "nécessaire quand ses URI de redirection couvrent plusieurs hôtes"
|
|
116
116
|
unattended: "Se connecte en son propre nom (client_credentials)"
|
|
117
117
|
rotate: "Renouveler le secret"
|
|
118
|
+
secret_expires: "Le secret expire le %{day}."
|
|
119
|
+
secret_expired: "Le secret a expiré le %{day}. Renouvelez-le, sinon rien ne peut se connecter avec."
|
|
118
120
|
archive: "Archiver"
|
|
119
121
|
saml:
|
|
120
122
|
title: "SAML"
|
|
@@ -146,6 +148,7 @@ fr:
|
|
|
146
148
|
consent: "Demander le consentement des acteurs"
|
|
147
149
|
access: "Durée des jetons d’accès (minutes, vide pour une heure)"
|
|
148
150
|
refresh: "Durée des jetons d’actualisation sans utilisation (jours, vide pour 30)"
|
|
151
|
+
refresh_absolute: "Fin des jetons d’actualisation après la connexion (jours, vide pour 90)"
|
|
149
152
|
consent_lifetime: "Durée du consentement (jours, vide jusqu’à révocation)"
|
|
150
153
|
logout: "URI de déconnexion back-channel"
|
|
151
154
|
logout_session: "Son jeton de déconnexion indique la session (sid)"
|
|
@@ -17,6 +17,7 @@ fr:
|
|
|
17
17
|
address: "Adresse"
|
|
18
18
|
port: "Port %{port}"
|
|
19
19
|
ldaps: "Port %{port}, LDAPS"
|
|
20
|
+
local_only: "Sans certificat, l’annuaire ne répond que sur la machine de ce serveur, pour qu’aucun mot de passe ne traverse le réseau en clair. Définissez MASKS_LDAP_CERT et MASKS_LDAP_KEY pour servir LDAPS sur toutes les adresses, ou MASKS_LDAP_PLAINTEXT=true sur un réseau privé de confiance."
|
|
20
21
|
label: "Libellé"
|
|
21
22
|
issue: "Émettre un identifiant"
|
|
22
23
|
shown_once: "Ce secret n'est affiché qu'une fois. Copiez-le maintenant."
|
data/config/routes.rb
CHANGED
|
@@ -18,6 +18,7 @@ Masks::Server::Engine.routes.draw do
|
|
|
18
18
|
post "/ssf/events", to: "received_signals#create", as: :received_signals
|
|
19
19
|
|
|
20
20
|
match "/authorize", to: "authorize#show", via: %i[get post], as: :authorize
|
|
21
|
+
get "/authorize/refused", to: "authorize#refused", as: :authorize_refused
|
|
21
22
|
post "/par", to: "pushed_authorizations#create", as: :pushed_authorization
|
|
22
23
|
post "/device_authorization", to: "device_authorizations#create", as: :device_authorization
|
|
23
24
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CreateReleasedNicknames < ActiveRecord::Migration[8.1]
|
|
2
|
+
include Masks::Server::TenantIsolation
|
|
3
|
+
|
|
4
|
+
def up
|
|
5
|
+
create_table :released_nicknames do |t|
|
|
6
|
+
t.references :tenant, null: false, foreign_key: { on_delete: :cascade }, index: false
|
|
7
|
+
t.references :actor, foreign_key: { on_delete: :nullify }, index: false
|
|
8
|
+
t.string :nickname, null: false
|
|
9
|
+
t.datetime :released_at, null: false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :released_nicknames, %i[tenant_id nickname], unique: true
|
|
13
|
+
add_index :released_nicknames, :released_at
|
|
14
|
+
|
|
15
|
+
enable_row_level_security(:released_nicknames)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def down
|
|
19
|
+
disable_row_level_security(:released_nicknames)
|
|
20
|
+
drop_table :released_nicknames
|
|
21
|
+
end
|
|
22
|
+
end
|