@things-factory/auth-ui 10.1.215 → 10.1.219
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.
- package/dist-client/bootstrap.js +18 -14
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/abstract-password-reset.d.ts +5 -0
- package/dist-client/components/abstract-password-reset.js +20 -0
- package/dist-client/components/abstract-password-reset.js.map +1 -1
- package/dist-client/components/ownership-transfer-popup.d.ts +3 -1
- package/dist-client/components/ownership-transfer-popup.js +38 -41
- package/dist-client/components/ownership-transfer-popup.js.map +1 -1
- package/dist-client/components/password-setup-link-popup.d.ts +46 -0
- package/dist-client/components/password-setup-link-popup.js +254 -0
- package/dist-client/components/password-setup-link-popup.js.map +1 -0
- package/dist-client/components/user-detail.d.ts +20 -30
- package/dist-client/components/user-detail.js +114 -186
- package/dist-client/components/user-detail.js.map +1 -1
- package/dist-client/components/user-invite.d.ts +18 -25
- package/dist-client/components/user-invite.js +157 -181
- package/dist-client/components/user-invite.js.map +1 -1
- package/dist-client/components/user-popups-standard.test.js +69 -0
- package/dist-client/components/user-popups-standard.test.js.map +1 -0
- package/dist-client/components/user-role-editor.js +5 -26
- package/dist-client/components/user-role-editor.js.map +1 -1
- package/dist-client/components/user-status-renderer.js +4 -0
- package/dist-client/components/user-status-renderer.js.map +1 -1
- package/dist-client/entries/auth/reset-password.d.ts +1 -0
- package/dist-client/entries/auth/reset-password.js +5 -1
- package/dist-client/entries/auth/reset-password.js.map +1 -1
- package/dist-client/index.js +10 -28
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/user/user-list-page.d.ts +5 -1
- package/dist-client/pages/user/user-list-page.js +14 -5
- package/dist-client/pages/user/user-list-page.js.map +1 -1
- package/dist-client/route.js +0 -3
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/link-token.d.ts +3 -3
- package/dist-client/utils/link-token.js +4 -4
- package/dist-client/utils/link-token.js.map +1 -1
- package/dist-client/utils/link-token.test.js +2 -2
- package/dist-client/utils/link-token.test.js.map +1 -1
- package/package.json +6 -5
- package/things-factory.config.js +0 -1
- package/translations/en.json +30 -20
- package/translations/es.json +30 -20
- package/translations/ja.json +30 -20
- package/translations/ko.json +30 -20
- package/translations/ms.json +30 -20
- package/translations/zh.json +30 -20
- package/dist-client/components/accept-invitation.d.ts +0 -47
- package/dist-client/components/accept-invitation.js +0 -258
- package/dist-client/components/accept-invitation.js.map +0 -1
- package/dist-client/entries/auth/accept-invitation.d.ts +0 -3
- package/dist-client/entries/auth/accept-invitation.js +0 -10
- package/dist-client/entries/auth/accept-invitation.js.map +0 -1
- package/dist-client/pages/invitation/invitation-list-query.test.js +0 -69
- package/dist-client/pages/invitation/invitation-list-query.test.js.map +0 -1
- package/dist-client/pages/invitation/invitations.d.ts +0 -63
- package/dist-client/pages/invitation/invitations.js +0 -284
- package/dist-client/pages/invitation/invitations.js.map +0 -1
- /package/dist-client/{pages/invitation/invitation-list-query.test.d.ts → components/user-popups-standard.test.d.ts} +0 -0
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ## Why the token is in the fragment
|
|
5
5
|
*
|
|
6
|
-
* A browser does not send what follows `#`, so a link shaped `…/
|
|
7
|
-
* reaches the server as `/
|
|
8
|
-
* `/
|
|
6
|
+
* A browser does not send what follows `#`, so a link shaped `…/reset-password#<token>`
|
|
7
|
+
* reaches the server as `/reset-password` and nothing else — and the same for
|
|
8
|
+
* `/unlock-user` and `/verify`. The token never appears in an
|
|
9
9
|
* access log, a proxy log, or a `Referer` sent onward to some other site.
|
|
10
10
|
*
|
|
11
11
|
* That leaves the places the browser itself keeps it: the address bar and the history entry.
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ## Why the token is in the fragment
|
|
5
5
|
*
|
|
6
|
-
* A browser does not send what follows `#`, so a link shaped `…/
|
|
7
|
-
* reaches the server as `/
|
|
8
|
-
* `/
|
|
6
|
+
* A browser does not send what follows `#`, so a link shaped `…/reset-password#<token>`
|
|
7
|
+
* reaches the server as `/reset-password` and nothing else — and the same for
|
|
8
|
+
* `/unlock-user` and `/verify`. The token never appears in an
|
|
9
9
|
* access log, a proxy log, or a `Referer` sent onward to some other site.
|
|
10
10
|
*
|
|
11
11
|
* That leaves the places the browser itself keeps it: the address bar and the history entry.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* anchor — to the server as a credential attempt. It answers empty instead, and the page shows
|
|
21
21
|
* the box where the code from the mail can be pasted.
|
|
22
22
|
*/
|
|
23
|
-
/** 16 bytes as hex, which is what `
|
|
23
|
+
/** 16 bytes as hex, which is what `makeVerificationToken` produces. */
|
|
24
24
|
const TOKEN = /^[0-9a-f]{32}$/;
|
|
25
25
|
export function readLinkToken(href) {
|
|
26
26
|
if (!href) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-token.js","sourceRoot":"","sources":["../../client/utils/link-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,
|
|
1
|
+
{"version":3,"file":"link-token.js","sourceRoot":"","sources":["../../client/utils/link-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,uEAAuE;AACvE,MAAM,KAAK,GAAG,gBAAgB,CAAA;AAS9B,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IACjC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAE9B,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;IACnC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;IAEjC;;;OAGG;IACH,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAE5E,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAA;AACrD,CAAC","sourcesContent":["/**\n * Taking the token out of a mailed link, and out of the address bar. (Pure rule.)\n *\n * ## Why the token is in the fragment\n *\n * A browser does not send what follows `#`, so a link shaped `…/reset-password#<token>`\n * reaches the server as `/reset-password` and nothing else — and the same for\n * `/unlock-user` and `/verify`. The token never appears in an\n * access log, a proxy log, or a `Referer` sent onward to some other site.\n *\n * That leaves the places the browser itself keeps it: the address bar and the history entry.\n * Both are cleared by replacing the URL with the one this returns as `clean`, which is why the\n * two answers come back together — reading the token and removing it are one act, and a caller\n * that did the first without the second would leave it on screen.\n *\n * ## What it refuses to read\n *\n * A token is hex from `crypto.randomBytes(16)`. Anything else in the fragment is not one, and\n * taking it anyway would send whatever a link happened to carry — a tracking fragment, a page\n * anchor — to the server as a credential attempt. It answers empty instead, and the page shows\n * the box where the code from the mail can be pasted.\n */\n\n/** 16 bytes as hex, which is what `makeVerificationToken` produces. */\nconst TOKEN = /^[0-9a-f]{32}$/\n\nexport type LinkToken = {\n /** The token, or an empty string when the link carries none this rule will read. */\n token: string\n /** The same URL without its fragment, for the caller to replace the address with. */\n clean: string\n}\n\nexport function readLinkToken(href: string): LinkToken {\n if (!href) {\n return { token: '', clean: '' }\n }\n\n const hash = href.indexOf('#')\n\n if (hash < 0) {\n return { token: '', clean: href }\n }\n\n const clean = href.slice(0, hash)\n\n /*\n * `#invite=<token>` as well as a bare `#<token>`. Both shapes turn up in mail clients that\n * rewrite links, and neither costs anything to accept.\n */\n const raw = decodeURIComponent(href.slice(hash + 1)).replace(/^invite=/, '')\n\n return { token: TOKEN.test(raw) ? raw : '', clean }\n}\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { readLinkToken } from './link-token';
|
|
2
2
|
/**
|
|
3
|
-
* Reading the
|
|
3
|
+
* Reading the token out of a mailed link, and handing back the link without it.
|
|
4
4
|
*
|
|
5
5
|
* The two answers travel together because removing the token is not optional: the fragment keeps
|
|
6
6
|
* it out of server and proxy logs, and replacing the address is what keeps it out of the browser
|
|
7
7
|
* history and off the screen. A caller that read it and forgot to replace would undo the point.
|
|
8
8
|
*/
|
|
9
9
|
const TOKEN = '0123456789abcdef0123456789abcdef';
|
|
10
|
-
const PAGE = 'https://acme.example.com/
|
|
10
|
+
const PAGE = 'https://acme.example.com/auth/reset-password';
|
|
11
11
|
describe('a link with a token in it', () => {
|
|
12
12
|
it('reads a bare fragment', () => {
|
|
13
13
|
expect(readLinkToken(`${PAGE}#${TOKEN}`)).toEqual({ token: TOKEN, clean: PAGE });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-token.test.js","sourceRoot":"","sources":["../../client/utils/link-token.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C;;;;;;GAMG;AAEH,MAAM,KAAK,GAAG,kCAAkC,CAAA;AAChD,MAAM,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"link-token.test.js","sourceRoot":"","sources":["../../client/utils/link-token.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { readLinkToken } from './link-token'\n\n/**\n * Reading the token out of a mailed link, and handing back the link without it.\n *\n * The two answers travel together because removing the token is not optional: the fragment keeps\n * it out of server and proxy logs, and replacing the address is what keeps it out of the browser\n * history and off the screen. A caller that read it and forgot to replace would undo the point.\n */\n\nconst TOKEN = '0123456789abcdef0123456789abcdef'\nconst PAGE = 'https://acme.example.com/auth/reset-password'\n\ndescribe('a link with a token in it', () => {\n it('reads a bare fragment', () => {\n expect(readLinkToken(`${PAGE}#${TOKEN}`)).toEqual({ token: TOKEN, clean: PAGE })\n })\n\n it('reads the named form some mail clients produce', () => {\n expect(readLinkToken(`${PAGE}#invite=${TOKEN}`)).toEqual({ token: TOKEN, clean: PAGE })\n })\n\n it('reads one that arrived percent-encoded', () => {\n expect(readLinkToken(`${PAGE}#invite%3D${TOKEN}`).token).toEqual(TOKEN)\n })\n\n it('hands back the address without the fragment', () => {\n /* ⚠ What the caller replaces the address with. Without it the token stays on screen and in\n this history entry, which is the half of the hiding the fragment does not do by itself. */\n expect(readLinkToken(`${PAGE}?x=1#${TOKEN}`).clean).toEqual(`${PAGE}?x=1`)\n })\n})\n\ndescribe('a link with nothing usable in it', () => {\n it('has no fragment at all', () => {\n expect(readLinkToken(PAGE)).toEqual({ token: '', clean: PAGE })\n })\n\n it('has an empty fragment', () => {\n expect(readLinkToken(`${PAGE}#`)).toEqual({ token: '', clean: PAGE })\n })\n\n it('⚠ carries something that is not a token', () => {\n /*\n * ⚠ A page anchor, a tracking fragment, anything a link happened to pick up. Sending it as a\n * credential attempt would be this page volunteering whatever it was given.\n */\n expect(readLinkToken(`${PAGE}#section-2`).token).toEqual('')\n expect(readLinkToken(`${PAGE}#utm_source=mail`).token).toEqual('')\n expect(readLinkToken(`${PAGE}#<script>`).token).toEqual('')\n })\n\n it('carries something token-shaped but the wrong length', () => {\n expect(readLinkToken(`${PAGE}#0123456789abcdef`).token).toEqual('')\n expect(readLinkToken(`${PAGE}#${TOKEN}ff`).token).toEqual('')\n })\n\n it('carries hex in the wrong case', () => {\n /* `makeInvitationToken` produces lower-case hex. Anything else did not come from us. */\n expect(readLinkToken(`${PAGE}#${TOKEN.toUpperCase()}`).token).toEqual('')\n })\n\n it('still hands back a clean address to replace with', () => {\n /* Even a fragment that is not ours should not be left sitting in the bar for this page. */\n expect(readLinkToken(`${PAGE}#section-2`).clean).toEqual(PAGE)\n })\n\n it('is given nothing at all', () => {\n expect(readLinkToken('')).toEqual({ token: '', clean: '' })\n expect(readLinkToken(undefined as any)).toEqual({ token: '', clean: '' })\n })\n})\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/auth-ui",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.219",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -40,11 +40,12 @@
|
|
|
40
40
|
"@operato/shell": "^10.29.39",
|
|
41
41
|
"@operato/styles": "^10.0.0",
|
|
42
42
|
"@operato/utils": "^10.29.39",
|
|
43
|
-
"@things-factory/
|
|
44
|
-
"@things-factory/
|
|
45
|
-
"@things-factory/
|
|
43
|
+
"@things-factory/apptool-base": "^10.1.218",
|
|
44
|
+
"@things-factory/auth-base": "^10.1.218",
|
|
45
|
+
"@things-factory/component-ui": "^10.1.218",
|
|
46
|
+
"@things-factory/more-base": "^10.1.219",
|
|
46
47
|
"base64url": "^3.0.1",
|
|
47
48
|
"clipboard": "^2.0.6"
|
|
48
49
|
},
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "1e96a252aafc460942bf5093b5aeed24828783d4"
|
|
50
51
|
}
|
package/things-factory.config.js
CHANGED
|
@@ -12,7 +12,6 @@ export default {
|
|
|
12
12
|
{ tagname: 'role-privilege-page', page: 'role-privileges' },
|
|
13
13
|
{ tagname: 'user-list-page', page: 'users' },
|
|
14
14
|
{ tagname: 'audit-page', page: 'audit' },
|
|
15
|
-
{ tagname: 'invitations-page', page: 'invitations' },
|
|
16
15
|
{ tagname: 'partner-management', page: 'partners' },
|
|
17
16
|
{ tagname: 'domain-management', page: 'domains' },
|
|
18
17
|
{ tagname: 'domain-owner-management', page: 'domain-owners' },
|
package/translations/en.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"button.accept invitation": "accept invitation",
|
|
3
2
|
"button.activate": "activate",
|
|
4
3
|
"button.add passkey": "Add a passkey",
|
|
5
4
|
"button.add what it can do": "Add what it can do",
|
|
@@ -41,7 +40,7 @@
|
|
|
41
40
|
"button.stand it here": "stand it here",
|
|
42
41
|
"button.submit": "submit",
|
|
43
42
|
"button.terminate contract": "terminate",
|
|
44
|
-
"button.transfer owner": "
|
|
43
|
+
"button.transfer owner": "make $t(term.domain) owner",
|
|
45
44
|
"button.unlock": "unlock",
|
|
46
45
|
"button.withdraw": "withdraw",
|
|
47
46
|
"error.cannot_modify_system_subdomain": "the 'system' subdomain cannot be modified.",
|
|
@@ -139,8 +138,6 @@
|
|
|
139
138
|
"label.execute": "Execute",
|
|
140
139
|
"label.inactive-user": "inactive",
|
|
141
140
|
"label.inherited": "Inherited",
|
|
142
|
-
"label.invitation code": "invitation code",
|
|
143
|
-
"label.invitations": "invitations",
|
|
144
141
|
"label.invite customer": "invite customer",
|
|
145
142
|
"label.invite user": "invite user",
|
|
146
143
|
"label.language": "language",
|
|
@@ -160,7 +157,6 @@
|
|
|
160
157
|
"label.search_domain": "search domain",
|
|
161
158
|
"label.select_domain": "select domain",
|
|
162
159
|
"label.send activation email": "send activation email",
|
|
163
|
-
"label.send invitation": "send invitation",
|
|
164
160
|
"label.signin with": "signin with {title}",
|
|
165
161
|
"label.state": "state",
|
|
166
162
|
"label.subject": "subject",
|
|
@@ -175,8 +171,11 @@
|
|
|
175
171
|
"text.a blank seat opens nothing until you give it privileges": "A blank seat opens nothing until you give it privileges.",
|
|
176
172
|
"text.a role of this name exists and will be added to": "A role of this name already exists. It will be used as it stands and these privileges added to it.",
|
|
177
173
|
"text.a role of this name is already visible": "a role of this name is already visible",
|
|
178
|
-
"text.account
|
|
179
|
-
"
|
|
174
|
+
"text.add user puts an account into this domain": "One account works in several $t(term.domain)s. Find it by email, put it into this $t(term.domain) and give it roles.",
|
|
175
|
+
"label.account exists": "if the account exists",
|
|
176
|
+
"text.they join this domain at once": "they join this $t(term.domain) at once.",
|
|
177
|
+
"label.no account": "if there is no account",
|
|
178
|
+
"text.roles decide the screens they open": "decide which screens they can open.",
|
|
180
179
|
"text.add template privileges": "adds the {count} privileges the {template} template grants and this role lacks: {list}",
|
|
181
180
|
"text.add_domain_owner_description": "grant another domain member owner permission.",
|
|
182
181
|
"text.already in this domain": "already here",
|
|
@@ -192,7 +191,7 @@
|
|
|
192
191
|
"text.are_you_sure_to_delete_x": "are you sure to delete {x}",
|
|
193
192
|
"text.are_you_sure_to_remove_domain_owner": "are you sure to remove {x} as a domain owner?",
|
|
194
193
|
"text.are_you_sure_to_terminate_contract": "are you sure to terminate contract?",
|
|
195
|
-
"text.are_you_sure_to_transfer_owner": "
|
|
194
|
+
"text.are_you_sure_to_transfer_owner": "make this user the $t(term.domain) owner?",
|
|
196
195
|
"text.are_you_sure_to_x": "are you sure to {x}?",
|
|
197
196
|
"text.are_you_sure_to_x_user": "are you sure to {x} user?",
|
|
198
197
|
"text.attribute management": "attribute management",
|
|
@@ -205,14 +204,31 @@
|
|
|
205
204
|
"text.cannot be undone": "Cannot be undone",
|
|
206
205
|
"text.cannot_delete": "cannot be deleted",
|
|
207
206
|
"text.change password": "change password",
|
|
208
|
-
"text.choose a password to finish joining": "choose a password to finish joining.",
|
|
209
207
|
"text.click login history": "If you want to see your recent login history, click",
|
|
210
208
|
"text.completed": "completed",
|
|
211
209
|
"text.confirm password": "confirm password",
|
|
212
|
-
"text.confirm the address this invitation was sent to": "enter the address this invitation was sent to.",
|
|
213
210
|
"text.copied": "copied",
|
|
214
211
|
"text.copying needs a secure connection": "copying needs a secure connection — select the value and copy it by hand",
|
|
215
212
|
"text.could not be saved": "could not be saved — see the message above for the reason",
|
|
213
|
+
"text.could not look up the account": "could not check the account.",
|
|
214
|
+
"button.issue link": "issue link",
|
|
215
|
+
"button.copied": "copied",
|
|
216
|
+
"button.reissue setup link": "reissue setup link",
|
|
217
|
+
"button.password reset link": "password reset link",
|
|
218
|
+
"label.how the link travels": "how the link travels",
|
|
219
|
+
"label.send by mail": "send by mail",
|
|
220
|
+
"label.copy the link": "copy the link",
|
|
221
|
+
"label.password-setup-pending-user": "awaiting password",
|
|
222
|
+
"title.password setup link": "password setup link",
|
|
223
|
+
"title.set a new password": "set a new password",
|
|
224
|
+
"text.a new link retires the last one": "This account is waiting for its password. A new link retires the last one.",
|
|
225
|
+
"text.the current password stops and sessions end": "Issuing stops the current password at once and ends open sessions. They set a new one through the link.",
|
|
226
|
+
"text.the link works once for 48 hours and asks for the address": "The link works once, for 48 hours, and asks for this email address when opened.",
|
|
227
|
+
"text.hand it over yourself": "hand it over yourself, by message or on paper",
|
|
228
|
+
"text.the link was mailed to x until y": "The link was mailed to {x}. It works until {y}.",
|
|
229
|
+
"text.this link is shown only now until y": "This link is shown only now. It works until {y}; if it is lost, issue another.",
|
|
230
|
+
"text.an account is made and a setup link handed over": "an account is made and a password setup link handed over. They set their password through it within 48 hours.",
|
|
231
|
+
"text.the address this link was sent for": "the address this link was sent for",
|
|
216
232
|
"text.could not register": "could not register — see the message above for the reason",
|
|
217
233
|
"text.create role": "create role",
|
|
218
234
|
"text.credentials": "credentials",
|
|
@@ -239,11 +255,9 @@
|
|
|
239
255
|
"text.inherited roles are edited in their own domain": "These roles are defined in a parent domain and can only be changed there.",
|
|
240
256
|
"text.invalid-email": "that is not an email address",
|
|
241
257
|
"text.invalid-username": "use an id or an email address",
|
|
242
|
-
"text.invitation resent": "invitation sent again.",
|
|
243
258
|
"text.missing against template": "{count} missing",
|
|
244
259
|
"text.new password": "new password",
|
|
245
260
|
"text.no account and no default password": "No account uses this address, and this system has no default password. They have to sign up first.",
|
|
246
|
-
"text.no account so an invitation will be mailed": "no account yet, so an invitation will be mailed. they choose their own password.",
|
|
247
261
|
"text.no description for this privilege": "No description has been written for this privilege yet.",
|
|
248
262
|
"text.no description for this role": "No description yet — write one in the role list.",
|
|
249
263
|
"text.no domain available": "no domain available",
|
|
@@ -263,13 +277,12 @@
|
|
|
263
277
|
"text.nothing matches x": "No module name contains \"{x}\".",
|
|
264
278
|
"text.opens nothing, receives approvals": "opens nothing — this seat receives approvals",
|
|
265
279
|
"text.owner opens everything without a role": "As the owner you can open every screen without a role. Everyone else needs one.",
|
|
266
|
-
"text.owner_transfer_completed": "
|
|
267
|
-
"text.password becomes the default and must be told to them": "The password goes back to the default. No email is sent, so you have to tell them the new password yourself.",
|
|
280
|
+
"text.owner_transfer_completed": "made $t(term.domain) owner.",
|
|
268
281
|
"text.password rule": "make sure it's at least 15 characters OR at least 8 characters including a number and a lowercase letter.",
|
|
269
282
|
"text.passwords do not match": "these passwords don't match.",
|
|
270
283
|
"text.pick a module on the left": "Pick a module on the left to see what it lets this role do.",
|
|
271
284
|
"text.pick a seat to see what it opens": "Pick a seat to see what it opens.",
|
|
272
|
-
"text.please enter the email of the user you want to transfer owner": "
|
|
285
|
+
"text.please enter the email of the user you want to transfer owner": "enter the email of the user to make $t(term.domain) owner",
|
|
273
286
|
"text.please enter username or email": "please enter username or email",
|
|
274
287
|
"text.please try again": "Try again in a moment.",
|
|
275
288
|
"text.please_fill_all_required_fields": "please fill all required fields",
|
|
@@ -297,7 +310,6 @@
|
|
|
297
310
|
"text.the appliance could not be loaded": "the appliance could not be loaded",
|
|
298
311
|
"text.the application could not be loaded": "the application could not be loaded",
|
|
299
312
|
"text.the binding could not be loaded": "the binding could not be loaded",
|
|
300
|
-
"text.the code is printed in the invitation email": "the code is printed in the invitation email.",
|
|
301
313
|
"text.the current access token stops working immediately": "the current access token stops working immediately, and anything using it has to be given the new one.",
|
|
302
314
|
"text.the current secret stops working immediately": "the current secret stops working immediately, and anything using it has to be given the new one.",
|
|
303
315
|
"text.the list could not be loaded": "the list could not be loaded",
|
|
@@ -305,7 +317,6 @@
|
|
|
305
317
|
"text.this credential has been revoked": "this credential was revoked. the appliance cannot reach the system until a new access token is issued.",
|
|
306
318
|
"text.this domain is top level and inherits from nowhere": "top level — nothing is inherited here",
|
|
307
319
|
"text.this field is required": "this field is required",
|
|
308
|
-
"text.this invitation cannot be used": "this invitation cannot be used.",
|
|
309
320
|
"text.this plant may call the seat what it likes": "Call the seat whatever this plant calls it.",
|
|
310
321
|
"text.this role no longer exists": "this role no longer exists",
|
|
311
322
|
"text.token expiry time": "token expiry time",
|
|
@@ -328,11 +339,9 @@
|
|
|
328
339
|
"text.x_cannot_delete": "{x} cannot be deleted",
|
|
329
340
|
"text.x_created_successfully": "{x} created successfully",
|
|
330
341
|
"text.x_deleted_successfully": "{x} deleted successfully",
|
|
331
|
-
"text.you have joined. sign in to continue": "you have joined. sign in to continue.",
|
|
332
342
|
"text.your account is locked": "your account is locked.",
|
|
333
343
|
"text.your account is not activated": "your account is not activated.",
|
|
334
344
|
"text.your email address": "your email address",
|
|
335
|
-
"title.accept invitation": "accept invitation",
|
|
336
345
|
"title.activate account": "activate account",
|
|
337
346
|
"title.add domain owner": "add domain owner",
|
|
338
347
|
"title.add template privileges": "add template privileges",
|
|
@@ -350,7 +359,7 @@
|
|
|
350
359
|
"title.move to this domain": "move to this domain",
|
|
351
360
|
"title.nothing selected": "nothing selected",
|
|
352
361
|
"title.open attributes view": "open attributes view",
|
|
353
|
-
"title.owner_transfer": "owner
|
|
362
|
+
"title.owner_transfer": "$t(term.domain) owner",
|
|
354
363
|
"title.partners": "partners",
|
|
355
364
|
"title.passkey offer": "Add a passkey",
|
|
356
365
|
"title.protected-privileges": "protected privileges",
|
|
@@ -361,6 +370,7 @@
|
|
|
361
370
|
"title.sign in": "sign in",
|
|
362
371
|
"title.sign up": "sign up",
|
|
363
372
|
"title.unlock account": "unlock account",
|
|
373
|
+
"title.user details": "user details",
|
|
364
374
|
"access-request.title.access requests": "access requests",
|
|
365
375
|
"access-request.title.my access requests": "my access requests",
|
|
366
376
|
"access-request.title.decide": "decide the access request",
|
package/translations/es.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"button.accept invitation": "aceptar invitación",
|
|
3
2
|
"button.activate": "activar",
|
|
4
3
|
"button.add passkey": "Añadir una llave de acceso",
|
|
5
4
|
"button.add what it can do": "Añadir lo que puede hacer",
|
|
@@ -41,7 +40,7 @@
|
|
|
41
40
|
"button.stand it here": "colocarlo aquí",
|
|
42
41
|
"button.submit": "enviar",
|
|
43
42
|
"button.terminate contract": "rescindir",
|
|
44
|
-
"button.transfer owner": "
|
|
43
|
+
"button.transfer owner": "designar propietario del $t(term.domain)",
|
|
45
44
|
"button.unlock": "desbloquear",
|
|
46
45
|
"button.withdraw": "retirar",
|
|
47
46
|
"error.cannot_modify_system_subdomain": "el subdominio 'system' no se puede modificar.",
|
|
@@ -139,8 +138,6 @@
|
|
|
139
138
|
"label.execute": "Ejecutar",
|
|
140
139
|
"label.inactive-user": "inactivo",
|
|
141
140
|
"label.inherited": "Heredado",
|
|
142
|
-
"label.invitation code": "código de invitación",
|
|
143
|
-
"label.invitations": "invitaciones",
|
|
144
141
|
"label.invite customer": "invitar cliente",
|
|
145
142
|
"label.invite user": "invitar usuario",
|
|
146
143
|
"label.language": "idioma",
|
|
@@ -160,7 +157,6 @@
|
|
|
160
157
|
"label.search_domain": "buscar dominio",
|
|
161
158
|
"label.select_domain": "seleccionar dominio",
|
|
162
159
|
"label.send activation email": "enviar correo de activación",
|
|
163
|
-
"label.send invitation": "enviar invitación",
|
|
164
160
|
"label.signin with": "iniciar sesión con {title}",
|
|
165
161
|
"label.state": "estado",
|
|
166
162
|
"label.subject": "asunto",
|
|
@@ -175,8 +171,11 @@
|
|
|
175
171
|
"text.a blank seat opens nothing until you give it privileges": "Un puesto vacío no da acceso a nada hasta que se le asignen privilegios.",
|
|
176
172
|
"text.a role of this name exists and will be added to": "Ya existe un rol con este nombre. Se usará tal como está y se le añadirán estos privilegios.",
|
|
177
173
|
"text.a role of this name is already visible": "ya se muestra un rol con este nombre",
|
|
178
|
-
"text.account
|
|
179
|
-
"
|
|
174
|
+
"text.add user puts an account into this domain": "Una cuenta sirve para varios dominios. Búsquela por correo, añádala a este dominio y asígnele roles.",
|
|
175
|
+
"label.account exists": "si la cuenta existe",
|
|
176
|
+
"text.they join this domain at once": "se une a este dominio de inmediato.",
|
|
177
|
+
"label.no account": "si no hay cuenta",
|
|
178
|
+
"text.roles decide the screens they open": "deciden qué pantallas puede abrir.",
|
|
180
179
|
"text.add template privileges": "añade los {count} privilegios que concede la plantilla {template} y que faltan en este rol: {list}",
|
|
181
180
|
"text.add_domain_owner_description": "conceder permiso de propietario a otro miembro del dominio.",
|
|
182
181
|
"text.already in this domain": "ya está aquí",
|
|
@@ -192,7 +191,7 @@
|
|
|
192
191
|
"text.are_you_sure_to_delete_x": "¿está seguro de que desea eliminar {x}?",
|
|
193
192
|
"text.are_you_sure_to_remove_domain_owner": "¿está seguro de que desea quitar a {x} como propietario del dominio?",
|
|
194
193
|
"text.are_you_sure_to_terminate_contract": "¿está seguro de que desea rescindir el contrato?",
|
|
195
|
-
"text.are_you_sure_to_transfer_owner": "¿
|
|
194
|
+
"text.are_you_sure_to_transfer_owner": "¿designar a este usuario como propietario del $t(term.domain)?",
|
|
196
195
|
"text.are_you_sure_to_x": "¿está seguro de que desea {x}?",
|
|
197
196
|
"text.are_you_sure_to_x_user": "¿está seguro de que desea {x} al usuario?",
|
|
198
197
|
"text.attribute management": "gestión de atributos",
|
|
@@ -205,14 +204,31 @@
|
|
|
205
204
|
"text.cannot be undone": "No se puede deshacer",
|
|
206
205
|
"text.cannot_delete": "no se puede eliminar",
|
|
207
206
|
"text.change password": "cambiar contraseña",
|
|
208
|
-
"text.choose a password to finish joining": "elija una contraseña para completar el registro.",
|
|
209
207
|
"text.click login history": "Si desea ver su historial reciente de inicio de sesión, haga clic",
|
|
210
208
|
"text.completed": "completado",
|
|
211
209
|
"text.confirm password": "confirmar contraseña",
|
|
212
|
-
"text.confirm the address this invitation was sent to": "introduzca la dirección a la que se envió esta invitación.",
|
|
213
210
|
"text.copied": "copiado",
|
|
214
211
|
"text.copying needs a secure connection": "para copiar se necesita una conexión segura — seleccione el valor y cópielo manualmente",
|
|
215
212
|
"text.could not be saved": "no se pudo guardar — consulte el motivo en el mensaje anterior",
|
|
213
|
+
"text.could not look up the account": "no se pudo comprobar la cuenta.",
|
|
214
|
+
"button.issue link": "emitir enlace",
|
|
215
|
+
"button.copied": "copiado",
|
|
216
|
+
"button.reissue setup link": "volver a emitir el enlace",
|
|
217
|
+
"button.password reset link": "enlace para restablecer la contraseña",
|
|
218
|
+
"label.how the link travels": "cómo se entrega el enlace",
|
|
219
|
+
"label.send by mail": "enviar por correo",
|
|
220
|
+
"label.copy the link": "copiar el enlace",
|
|
221
|
+
"label.password-setup-pending-user": "pendiente de contraseña",
|
|
222
|
+
"title.password setup link": "enlace de configuración de contraseña",
|
|
223
|
+
"title.set a new password": "establecer una nueva contraseña",
|
|
224
|
+
"text.a new link retires the last one": "Esta cuenta espera su contraseña. Un enlace nuevo anula el anterior.",
|
|
225
|
+
"text.the current password stops and sessions end": "Al emitirlo, la contraseña actual deja de funcionar y se cierran las sesiones abiertas. La persona establece una nueva con el enlace.",
|
|
226
|
+
"text.the link works once for 48 hours and asks for the address": "El enlace sirve una vez, durante 48 horas, y pide esta dirección de correo al abrirse.",
|
|
227
|
+
"text.hand it over yourself": "entréguelo usted mismo, por mensaje o en papel",
|
|
228
|
+
"text.the link was mailed to x until y": "El enlace se envió a {x}. Sirve hasta {y}.",
|
|
229
|
+
"text.this link is shown only now until y": "Este enlace se muestra solo ahora. Sirve hasta {y}; si se pierde, emita otro.",
|
|
230
|
+
"text.an account is made and a setup link handed over": "se crea la cuenta y se entrega un enlace de configuración de contraseña. La persona la establece con él en 48 horas.",
|
|
231
|
+
"text.the address this link was sent for": "la dirección a la que se envió este enlace",
|
|
216
232
|
"text.could not register": "no se pudo registrar — consulte el motivo en el mensaje anterior",
|
|
217
233
|
"text.create role": "crear rol",
|
|
218
234
|
"text.credentials": "credenciales",
|
|
@@ -239,11 +255,9 @@
|
|
|
239
255
|
"text.inherited roles are edited in their own domain": "Estos roles están definidos en un dominio principal y solo se pueden cambiar allí.",
|
|
240
256
|
"text.invalid-email": "no es una dirección de correo electrónico",
|
|
241
257
|
"text.invalid-username": "use un ID o una dirección de correo electrónico",
|
|
242
|
-
"text.invitation resent": "invitación enviada de nuevo.",
|
|
243
258
|
"text.missing against template": "faltan {count}",
|
|
244
259
|
"text.new password": "nueva contraseña",
|
|
245
260
|
"text.no account and no default password": "Ninguna cuenta usa esta dirección y este sistema no tiene contraseña predeterminada. La persona debe registrarse primero.",
|
|
246
|
-
"text.no account so an invitation will be mailed": "aún no hay cuenta, así que se enviará una invitación por correo. la persona elegirá su propia contraseña.",
|
|
247
261
|
"text.no description for this privilege": "Todavía no se ha redactado una descripción para este privilegio.",
|
|
248
262
|
"text.no description for this role": "Todavía no hay descripción — redáctela en la lista de roles.",
|
|
249
263
|
"text.no domain available": "no hay ningún dominio disponible",
|
|
@@ -263,13 +277,12 @@
|
|
|
263
277
|
"text.nothing matches x": "Ningún nombre de módulo contiene \"{x}\".",
|
|
264
278
|
"text.opens nothing, receives approvals": "no da acceso a nada — este puesto recibe aprobaciones",
|
|
265
279
|
"text.owner opens everything without a role": "Como propietario, puede abrir todas las pantallas sin un rol. Los demás necesitan uno.",
|
|
266
|
-
"text.owner_transfer_completed": "
|
|
267
|
-
"text.password becomes the default and must be told to them": "La contraseña vuelve a la predeterminada. No se envía ningún correo, así que deberá comunicarle usted mismo la nueva contraseña.",
|
|
280
|
+
"text.owner_transfer_completed": "designado como propietario del $t(term.domain).",
|
|
268
281
|
"text.password rule": "debe tener al menos 15 caracteres, o al menos 8 caracteres incluidos un número y una letra minúscula.",
|
|
269
282
|
"text.passwords do not match": "las contraseñas no coinciden.",
|
|
270
283
|
"text.pick a module on the left": "Seleccione un módulo a la izquierda para ver lo que este rol puede hacer en él.",
|
|
271
284
|
"text.pick a seat to see what it opens": "Seleccione un puesto para ver a qué da acceso.",
|
|
272
|
-
"text.please enter the email of the user you want to transfer owner": "introduzca el correo
|
|
285
|
+
"text.please enter the email of the user you want to transfer owner": "introduzca el correo del usuario que será propietario del $t(term.domain)",
|
|
273
286
|
"text.please enter username or email": "introduzca el nombre de usuario o el correo electrónico",
|
|
274
287
|
"text.please try again": "Vuelva a intentarlo en un momento.",
|
|
275
288
|
"text.please_fill_all_required_fields": "complete todos los campos obligatorios",
|
|
@@ -297,7 +310,6 @@
|
|
|
297
310
|
"text.the appliance could not be loaded": "no se pudo cargar el dispositivo",
|
|
298
311
|
"text.the application could not be loaded": "no se pudo cargar la aplicación",
|
|
299
312
|
"text.the binding could not be loaded": "no se pudo cargar la vinculación",
|
|
300
|
-
"text.the code is printed in the invitation email": "el código figura en el correo de invitación.",
|
|
301
313
|
"text.the current access token stops working immediately": "el token de acceso actual deja de funcionar de inmediato, y todo lo que lo use deberá recibir el nuevo.",
|
|
302
314
|
"text.the current secret stops working immediately": "el secreto actual deja de funcionar de inmediato, y todo lo que lo use deberá recibir el nuevo.",
|
|
303
315
|
"text.the list could not be loaded": "no se pudo cargar la lista",
|
|
@@ -305,7 +317,6 @@
|
|
|
305
317
|
"text.this credential has been revoked": "esta credencial se ha revocado. el dispositivo no podrá acceder al sistema hasta que se emita un nuevo token de acceso.",
|
|
306
318
|
"text.this domain is top level and inherits from nowhere": "nivel superior — aquí no se hereda nada",
|
|
307
319
|
"text.this field is required": "este campo es obligatorio",
|
|
308
|
-
"text.this invitation cannot be used": "esta invitación no se puede usar.",
|
|
309
320
|
"text.this plant may call the seat what it likes": "Llame al puesto como lo llamen en esta planta.",
|
|
310
321
|
"text.this role no longer exists": "este rol ya no existe",
|
|
311
322
|
"text.token expiry time": "hora de caducidad del token",
|
|
@@ -328,11 +339,9 @@
|
|
|
328
339
|
"text.x_cannot_delete": "{x} no se puede eliminar",
|
|
329
340
|
"text.x_created_successfully": "{x} creado correctamente",
|
|
330
341
|
"text.x_deleted_successfully": "{x} eliminado correctamente",
|
|
331
|
-
"text.you have joined. sign in to continue": "se ha unido. inicie sesión para continuar.",
|
|
332
342
|
"text.your account is locked": "su cuenta está bloqueada.",
|
|
333
343
|
"text.your account is not activated": "su cuenta no está activada.",
|
|
334
344
|
"text.your email address": "su dirección de correo electrónico",
|
|
335
|
-
"title.accept invitation": "aceptar invitación",
|
|
336
345
|
"title.activate account": "activar cuenta",
|
|
337
346
|
"title.add domain owner": "añadir propietario del dominio",
|
|
338
347
|
"title.add template privileges": "añadir privilegios de la plantilla",
|
|
@@ -350,7 +359,7 @@
|
|
|
350
359
|
"title.move to this domain": "ir a este dominio",
|
|
351
360
|
"title.nothing selected": "no hay nada seleccionado",
|
|
352
361
|
"title.open attributes view": "abrir vista de atributos",
|
|
353
|
-
"title.owner_transfer": "
|
|
362
|
+
"title.owner_transfer": "propietario del $t(term.domain)",
|
|
354
363
|
"title.partners": "socios",
|
|
355
364
|
"title.passkey offer": "Añadir una llave de acceso",
|
|
356
365
|
"title.protected-privileges": "privilegios protegidos",
|
|
@@ -361,6 +370,7 @@
|
|
|
361
370
|
"title.sign in": "iniciar sesión",
|
|
362
371
|
"title.sign up": "registrarse",
|
|
363
372
|
"title.unlock account": "desbloquear cuenta",
|
|
373
|
+
"title.user details": "detalles del usuario",
|
|
364
374
|
"access-request.title.access requests": "solicitudes de acceso",
|
|
365
375
|
"access-request.title.my access requests": "mis solicitudes de acceso",
|
|
366
376
|
"access-request.title.decide": "resolver la solicitud de acceso",
|