@owlmeans/client-auth 0.1.18-rc.8 → 0.1.18
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/README.md +283 -37
- package/agent-meta/manifest.json +50 -4
- package/agent-meta/skills/client-auth/SKILL.md +85 -23
- package/agent-meta/skills/client-auth/parts/login.md +77 -0
- package/agent-meta/skills/client-auth/parts/manager.md +37 -0
- package/build/components/dispatcher/component.d.ts.map +1 -1
- package/build/components/dispatcher/component.js +26 -6
- package/build/components/dispatcher/component.js.map +1 -1
- package/build/components/dispatcher/types.local.d.ts +7 -0
- package/build/components/dispatcher/types.local.d.ts.map +1 -0
- package/build/components/dispatcher/types.local.js +2 -0
- package/build/components/dispatcher/types.local.js.map +1 -0
- package/build/entrypoints.d.ts +7 -0
- package/build/entrypoints.d.ts.map +1 -0
- package/build/entrypoints.js +7 -0
- package/build/entrypoints.js.map +1 -0
- package/build/helper.d.ts +2 -1
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +28 -5
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/login/adopt/types.d.ts +26 -0
- package/build/login/adopt/types.d.ts.map +1 -0
- package/build/login/adopt/types.js +2 -0
- package/build/login/adopt/types.js.map +1 -0
- package/build/login/adopt.d.ts +7 -12
- package/build/login/adopt.d.ts.map +1 -1
- package/build/login/adopt.js +15 -14
- package/build/login/adopt.js.map +1 -1
- package/build/login/consts.d.ts +89 -4
- package/build/login/consts.d.ts.map +1 -1
- package/build/login/consts.js +93 -5
- package/build/login/consts.js.map +1 -1
- package/build/login/consts.local.d.ts +16 -0
- package/build/login/consts.local.d.ts.map +1 -0
- package/build/login/consts.local.js +30 -0
- package/build/login/consts.local.js.map +1 -0
- package/build/login/credit/types.d.ts +7 -0
- package/build/login/credit/types.d.ts.map +1 -0
- package/build/login/credit/types.js +2 -0
- package/build/login/credit/types.js.map +1 -0
- package/build/login/credit.d.ts +19 -0
- package/build/login/credit.d.ts.map +1 -0
- package/build/login/credit.js +58 -0
- package/build/login/credit.js.map +1 -0
- package/build/login/env/types.d.ts +35 -0
- package/build/login/env/types.d.ts.map +1 -0
- package/build/login/env/types.js +2 -0
- package/build/login/env/types.js.map +1 -0
- package/build/login/env.d.ts +5 -29
- package/build/login/env.d.ts.map +1 -1
- package/build/login/env.js +63 -80
- package/build/login/env.js.map +1 -1
- package/build/login/flow.d.ts +20 -0
- package/build/login/flow.d.ts.map +1 -0
- package/build/login/flow.js +39 -0
- package/build/login/flow.js.map +1 -0
- package/build/login/hook.d.ts +30 -4
- package/build/login/hook.d.ts.map +1 -1
- package/build/login/hook.js +53 -18
- package/build/login/hook.js.map +1 -1
- package/build/login/i18n/be.json +41 -0
- package/build/login/i18n/de.json +41 -0
- package/build/login/i18n/en.json +41 -0
- package/build/login/i18n/es.json +41 -0
- package/build/login/i18n/fr.json +41 -0
- package/build/login/i18n/pl.json +41 -0
- package/build/login/i18n/ru.json +41 -0
- package/build/login/i18n/uk.json +41 -0
- package/build/login/i18n.d.ts +2 -0
- package/build/login/i18n.d.ts.map +1 -0
- package/build/login/i18n.js +27 -0
- package/build/login/i18n.js.map +1 -0
- package/build/login/index.d.ts +20 -0
- package/build/login/index.d.ts.map +1 -1
- package/build/login/index.js +11 -0
- package/build/login/index.js.map +1 -1
- package/build/login/land/types.d.ts +52 -0
- package/build/login/land/types.d.ts.map +1 -0
- package/build/login/land/types.js +2 -0
- package/build/login/land/types.js.map +1 -0
- package/build/login/land.d.ts +6 -0
- package/build/login/land.d.ts.map +1 -0
- package/build/login/land.js +122 -0
- package/build/login/land.js.map +1 -0
- package/build/login/methods/types.d.ts +30 -0
- package/build/login/methods/types.d.ts.map +1 -0
- package/build/login/methods/types.js +2 -0
- package/build/login/methods/types.js.map +1 -0
- package/build/login/methods.d.ts +7 -0
- package/build/login/methods.d.ts.map +1 -0
- package/build/login/methods.js +87 -0
- package/build/login/methods.js.map +1 -0
- package/build/login/resume/types.d.ts +24 -0
- package/build/login/resume/types.d.ts.map +1 -0
- package/build/login/resume/types.js +2 -0
- package/build/login/resume/types.js.map +1 -0
- package/build/login/resume.d.ts +9 -0
- package/build/login/resume.d.ts.map +1 -0
- package/build/login/resume.js +38 -0
- package/build/login/resume.js.map +1 -0
- package/build/login/screen.d.ts +17 -0
- package/build/login/screen.d.ts.map +1 -0
- package/build/login/screen.js +66 -0
- package/build/login/screen.js.map +1 -0
- package/build/login/service.d.ts +6 -5
- package/build/login/service.d.ts.map +1 -1
- package/build/login/service.js +141 -15
- package/build/login/service.js.map +1 -1
- package/build/login/start/types.d.ts +29 -0
- package/build/login/start/types.d.ts.map +1 -0
- package/build/login/start/types.js +2 -0
- package/build/login/start/types.js.map +1 -0
- package/build/login/start.d.ts +5 -0
- package/build/login/start.d.ts.map +1 -0
- package/build/login/start.js +36 -0
- package/build/login/start.js.map +1 -0
- package/build/login/surrogate/types.d.ts +9 -0
- package/build/login/surrogate/types.d.ts.map +1 -0
- package/build/login/surrogate/types.js +2 -0
- package/build/login/surrogate/types.js.map +1 -0
- package/build/login/surrogate.d.ts +13 -0
- package/build/login/surrogate.d.ts.map +1 -0
- package/build/login/surrogate.js +33 -0
- package/build/login/surrogate.js.map +1 -0
- package/build/login/terms/types.d.ts +112 -0
- package/build/login/terms/types.d.ts.map +1 -0
- package/build/login/terms/types.js +2 -0
- package/build/login/terms/types.js.map +1 -0
- package/build/login/terms-config.d.ts +65 -0
- package/build/login/terms-config.d.ts.map +1 -0
- package/build/login/terms-config.js +2 -0
- package/build/login/terms-config.js.map +1 -0
- package/build/login/terms.d.ts +21 -0
- package/build/login/terms.d.ts.map +1 -0
- package/build/login/terms.js +235 -0
- package/build/login/terms.js.map +1 -0
- package/build/login/types.d.ts +223 -16
- package/build/login/types.d.ts.map +1 -1
- package/build/login/types.js +1 -16
- package/build/login/types.js.map +1 -1
- package/build/manager/components/authentication/control.d.ts.map +1 -1
- package/build/manager/components/authentication/control.js +3 -3
- package/build/manager/components/authentication/control.js.map +1 -1
- package/build/manager/components/authentication/types.d.ts +2 -2
- package/build/manager/components/authentication/types.d.ts.map +1 -1
- package/build/manager/components/tunnel-consumer.js +2 -2
- package/build/manager/components/tunnel-consumer.js.map +1 -1
- package/build/manager/entrypoints.d.ts +11 -0
- package/build/manager/entrypoints.d.ts.map +1 -0
- package/build/manager/entrypoints.js +17 -0
- package/build/manager/entrypoints.js.map +1 -0
- package/build/manager/errors.d.ts.map +1 -1
- package/build/manager/errors.js.map +1 -1
- package/build/manager/plugins/basic-ed25519.d.ts.map +1 -1
- package/build/manager/plugins/basic-ed25519.js +5 -0
- package/build/manager/plugins/basic-ed25519.js.map +1 -1
- package/build/manager/plugins/exports.d.ts +3 -0
- package/build/manager/plugins/exports.d.ts.map +1 -1
- package/build/manager/plugins/exports.js +2 -0
- package/build/manager/plugins/exports.js.map +1 -1
- package/build/manager/plugins/index.d.ts +2 -5
- package/build/manager/plugins/index.d.ts.map +1 -1
- package/build/manager/plugins/index.js +9 -1
- package/build/manager/plugins/index.js.map +1 -1
- package/build/manager/plugins/methods.d.ts +6 -0
- package/build/manager/plugins/methods.d.ts.map +1 -0
- package/build/manager/plugins/methods.js +65 -0
- package/build/manager/plugins/methods.js.map +1 -0
- package/build/manager/plugins/re-captcha.d.ts.map +1 -1
- package/build/manager/plugins/re-captcha.js +5 -0
- package/build/manager/plugins/re-captcha.js.map +1 -1
- package/build/manager/plugins/registry/types.d.ts +10 -0
- package/build/manager/plugins/registry/types.d.ts.map +1 -0
- package/build/manager/plugins/registry/types.js +2 -0
- package/build/manager/plugins/registry/types.js.map +1 -0
- package/build/manager/plugins/registry.d.ts +20 -0
- package/build/manager/plugins/registry.d.ts.map +1 -0
- package/build/manager/plugins/registry.js +23 -0
- package/build/manager/plugins/registry.js.map +1 -0
- package/build/manager/plugins/tunnel/wallet.d.ts.map +1 -1
- package/build/manager/plugins/tunnel-consumer.d.ts.map +1 -1
- package/build/manager/plugins/tunnel-consumer.js +10 -3
- package/build/manager/plugins/tunnel-consumer.js.map +1 -1
- package/build/manager/plugins/types.d.ts +53 -0
- package/build/manager/plugins/types.d.ts.map +1 -1
- package/build/service.d.ts.map +1 -1
- package/build/service.js +1 -1
- package/build/service.js.map +1 -1
- package/package.json +33 -30
- package/src/components/dispatcher/component.tsx +37 -14
- package/src/components/dispatcher/types.local.ts +7 -0
- package/src/entrypoints.ts +10 -0
- package/src/helper.ts +31 -5
- package/src/index.ts +1 -1
- package/src/login/adopt/types.ts +25 -0
- package/src/login/adopt.ts +21 -14
- package/src/login/consts.local.ts +34 -0
- package/src/login/consts.ts +105 -5
- package/src/login/credit/types.ts +6 -0
- package/src/login/credit.ts +69 -0
- package/src/login/env/types.ts +35 -0
- package/src/login/env.ts +60 -72
- package/src/login/flow.ts +44 -0
- package/src/login/hook.ts +58 -22
- package/src/login/i18n/be.json +41 -0
- package/src/login/i18n/de.json +41 -0
- package/src/login/i18n/en.json +41 -0
- package/src/login/i18n/es.json +41 -0
- package/src/login/i18n/fr.json +41 -0
- package/src/login/i18n/pl.json +41 -0
- package/src/login/i18n/ru.json +41 -0
- package/src/login/i18n/uk.json +41 -0
- package/src/login/i18n.ts +29 -0
- package/src/login/index.ts +21 -0
- package/src/login/land/types.ts +54 -0
- package/src/login/land.ts +149 -0
- package/src/login/methods/types.ts +32 -0
- package/src/login/methods.ts +109 -0
- package/src/login/resume/types.ts +24 -0
- package/src/login/resume.ts +45 -0
- package/src/login/screen.tsx +140 -0
- package/src/login/service.ts +181 -18
- package/src/login/start/types.ts +30 -0
- package/src/login/start.ts +44 -0
- package/src/login/surrogate/types.ts +9 -0
- package/src/login/surrogate.ts +37 -0
- package/src/login/terms/types.ts +126 -0
- package/src/login/terms-config.ts +55 -0
- package/src/login/terms.ts +315 -0
- package/src/login/types.ts +233 -17
- package/src/manager/README.md +37 -80
- package/src/manager/components/authentication/control.ts +3 -3
- package/src/manager/components/authentication/types.ts +2 -2
- package/src/manager/components/tunnel-consumer.tsx +2 -2
- package/src/manager/entrypoints.ts +18 -0
- package/src/manager/plugins/basic-ed25519.tsx +7 -0
- package/src/manager/plugins/exports.ts +3 -0
- package/src/manager/plugins/index.ts +11 -4
- package/src/manager/plugins/methods.ts +74 -0
- package/src/manager/plugins/re-captcha.tsx +7 -0
- package/src/manager/plugins/registry/types.ts +10 -0
- package/src/manager/plugins/registry.ts +33 -0
- package/src/manager/plugins/tunnel-consumer.tsx +12 -3
- package/src/manager/plugins/types.ts +54 -0
- package/src/service.ts +1 -1
- package/tests/context.ts +1 -2
- package/tests/i18n.spec.ts +68 -0
- package/tests/land.spec.ts +292 -0
- package/tests/login.spec.ts +332 -0
- package/tests/target.spec.ts +210 -0
- package/tests/terms-deferred.spec.ts +65 -0
- package/tests/terms.spec.ts +314 -0
- package/build/.gitkeep +0 -0
- package/src/manager/modules.ts +0 -18
- package/src/modules.ts +0 -13
package/src/login/env.ts
CHANGED
|
@@ -1,86 +1,74 @@
|
|
|
1
1
|
import { LOGIN_SURROGATE_MARKER, LOGIN_SURROGATE_NAME } from './consts.js'
|
|
2
2
|
import type { LoginEnv } from './types.js'
|
|
3
|
+
import type { LoginEnvHelper } from './env/types.js'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
return window.self !== window.top
|
|
13
|
-
} catch {
|
|
14
|
-
return true
|
|
5
|
+
export const createLoginEnvHelper = (): LoginEnvHelper => {
|
|
6
|
+
const isEmbedded = (): boolean => {
|
|
7
|
+
try {
|
|
8
|
+
return window.self !== window.top
|
|
9
|
+
} catch {
|
|
10
|
+
return true
|
|
11
|
+
}
|
|
15
12
|
}
|
|
16
|
-
}
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export const markSurrogate = (): void => {
|
|
29
|
-
if (typeof window === 'undefined' || window.name !== LOGIN_SURROGATE_NAME) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
window.sessionStorage.setItem(LOGIN_SURROGATE_MARKER, '1')
|
|
34
|
-
} catch {
|
|
35
|
-
// Storage can be unavailable (private modes, blocked cookies). The `window.name` check still
|
|
36
|
-
// covers the case where nothing cross-origin happened in between.
|
|
14
|
+
const markSurrogate = (): void => {
|
|
15
|
+
if (typeof window === 'undefined' || window.name !== LOGIN_SURROGATE_NAME) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
window.sessionStorage.setItem(LOGIN_SURROGATE_MARKER, '1')
|
|
20
|
+
} catch {
|
|
21
|
+
// Storage can be unavailable (private modes, blocked cookies). The `window.name` check still
|
|
22
|
+
// covers the case where nothing cross-origin happened in between.
|
|
23
|
+
}
|
|
37
24
|
}
|
|
38
|
-
}
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
26
|
+
const isSurrogate = (): boolean => {
|
|
27
|
+
if (typeof window === 'undefined') {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
if (window.name === LOGIN_SURROGATE_NAME) {
|
|
31
|
+
return true
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return window.sessionStorage.getItem(LOGIN_SURROGATE_MARKER) === '1'
|
|
35
|
+
} catch {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
44
38
|
}
|
|
45
|
-
if (window.name === LOGIN_SURROGATE_NAME) {
|
|
46
|
-
return true
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
return window.sessionStorage.getItem(LOGIN_SURROGATE_MARKER) === '1'
|
|
50
|
-
} catch {
|
|
51
|
-
return false
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
39
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
const clearSurrogate = (): void => {
|
|
41
|
+
if (typeof window === 'undefined') {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
window.sessionStorage.removeItem(LOGIN_SURROGATE_MARKER)
|
|
46
|
+
} catch { /* nothing to clean up if storage was never available */ }
|
|
59
47
|
}
|
|
60
|
-
try {
|
|
61
|
-
window.sessionStorage.removeItem(LOGIN_SURROGATE_MARKER)
|
|
62
|
-
} catch { /* nothing to clean up if storage was never available */ }
|
|
63
|
-
}
|
|
64
48
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* own descriptor.
|
|
71
|
-
*/
|
|
72
|
-
export const defaultLoginEnv = (): LoginEnv => {
|
|
73
|
-
const hasWindow = typeof window !== 'undefined'
|
|
74
|
-
if (!hasWindow) {
|
|
75
|
-
return { hasWindow, embedded: false, surrogate: false, hasOpener: false }
|
|
76
|
-
}
|
|
49
|
+
const defaultLoginEnv = (): LoginEnv => {
|
|
50
|
+
const hasWindow = typeof window !== 'undefined'
|
|
51
|
+
if (!hasWindow) {
|
|
52
|
+
return { hasWindow, embedded: false, surrogate: false, hasOpener: false }
|
|
53
|
+
}
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
55
|
+
return {
|
|
56
|
+
hasWindow,
|
|
57
|
+
embedded: isEmbedded(),
|
|
58
|
+
surrogate: isSurrogate(),
|
|
59
|
+
// `Cross-Origin-Opener-Policy: same-origin` from the provider severs this permanently, which
|
|
60
|
+
// is why it is observed rather than assumed from "we were opened by someone".
|
|
61
|
+
hasOpener: window.opener != null,
|
|
62
|
+
}
|
|
85
63
|
}
|
|
64
|
+
|
|
65
|
+
return { isEmbedded, markSurrogate, isSurrogate, clearSurrogate, defaultLoginEnv }
|
|
86
66
|
}
|
|
67
|
+
|
|
68
|
+
export const loginEnvHelper = createLoginEnvHelper()
|
|
69
|
+
|
|
70
|
+
/** @deprecated compat:factory-refactor — use `loginEnvHelper.markSurrogate()` */
|
|
71
|
+
export const markSurrogate = (): void => loginEnvHelper.markSurrogate()
|
|
72
|
+
|
|
73
|
+
/** @deprecated compat:factory-refactor — use `loginEnvHelper.clearSurrogate()` */
|
|
74
|
+
export const clearSurrogate = (): void => loginEnvHelper.clearSurrogate()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { FLOW_PLACEHOLDER, OidcAuthStep, STD_OIDC_FLOW } from '@owlmeans/flow'
|
|
2
|
+
import type { FlowModel } from '@owlmeans/flow'
|
|
3
|
+
import { DEFAULT_ENTITY } from '../consts.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Bring a freshly booted standard OIDC flow to the step an authorization request can be made from.
|
|
7
|
+
*
|
|
8
|
+
* `stdOidcFlow` starts at `Dispatch`, but `OidcAuthService.authenticate` refuses any state that is
|
|
9
|
+
* not `Ephemeral` and returns null — so an application whose flow was only booted can ask for an
|
|
10
|
+
* authorization URL all day and be told nothing, forever. The dispatcher in this package has always
|
|
11
|
+
* done this transition inline; a relying party that replaces that dispatcher (`web-oidc-rp`,
|
|
12
|
+
* `mui-oidc-rp`) inherited the requirement without the code, which is what left a sign-in button
|
|
13
|
+
* that reported no error and did nothing at all.
|
|
14
|
+
*
|
|
15
|
+
* `Ephemeral` is the branch for an application that is its OWN authority — its flow configuration
|
|
16
|
+
* maps the auth service to a placeholder, which is exactly the generated-application case. An app
|
|
17
|
+
* federated with a real auth service keeps its target and is left alone.
|
|
18
|
+
*
|
|
19
|
+
* Idempotent, and safe to call on every attempt: a flow already past `Dispatch`, or one that is
|
|
20
|
+
* not the standard OIDC flow at all, is returned untouched.
|
|
21
|
+
*/
|
|
22
|
+
export const enterOidcAuthorization = (model: FlowModel): FlowModel => {
|
|
23
|
+
const state = model.state()
|
|
24
|
+
if (state.flow !== STD_OIDC_FLOW || state.step !== OidcAuthStep.Dispatch) {
|
|
25
|
+
return model
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const target = model.step().service
|
|
29
|
+
if (state.service == null || state.service === '') {
|
|
30
|
+
model.target(target)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// The entity travels to this app's own backend, which resolves its default provider by `def`
|
|
34
|
+
// alone. It still has to BE there: the init endpoint rejects a body without one.
|
|
35
|
+
if (state.entityId == null) {
|
|
36
|
+
model.entity(DEFAULT_ENTITY)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (target === FLOW_PLACEHOLDER) {
|
|
40
|
+
model.transit(OidcAuthStep.Ephemeral, true)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return model
|
|
44
|
+
}
|
package/src/login/hook.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { useCallback } from 'react'
|
|
2
|
-
import type { MouseEvent } from 'react'
|
|
1
|
+
import { useCallback, type MouseEvent } from 'react'
|
|
3
2
|
import { useContext, useNavigate } from '@owlmeans/client'
|
|
4
3
|
import type { ClientContext } from '@owlmeans/client-context'
|
|
5
4
|
import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
|
|
6
5
|
import { DISPATCHER } from '@owlmeans/auth'
|
|
7
|
-
import {
|
|
8
|
-
import type {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
6
|
+
import type { LoginContext, LoginService } from './types.js'
|
|
7
|
+
import type { LandOptions } from './land/types.js'
|
|
8
|
+
import { LoginIntent, LOGIN_SERVICE } from './consts.js'
|
|
9
|
+
import { loginLandingOf } from './land.js'
|
|
10
|
+
import { surrogatePath } from './surrogate.js'
|
|
11
|
+
import { loginStartOf } from './start.js'
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Wiring for a "Log in" control: where it points, and what it does when clicked.
|
|
@@ -17,6 +18,12 @@ import { LOGIN_SERVICE } from './consts.js'
|
|
|
17
18
|
* an app embedded in a frame runs the flow one window up, because the provider refuses to be
|
|
18
19
|
* framed and its cookies are third-party there.
|
|
19
20
|
*
|
|
21
|
+
* `target` is the screen to land on once signed in — sign-in FIRST, then the screen, in an ordinary
|
|
22
|
+
* tab and in a framed application alike, with any pending post-sign-in step (a consent screen) run
|
|
23
|
+
* on the way. The control still leads to the dispatcher; the target is parked for the landing
|
|
24
|
+
* (`LoginRequest.target`), and somebody already signed in goes straight to it (`loginStartOf(ctx).startLogin`).
|
|
25
|
+
* Without a target the landing is the ordinary one.
|
|
26
|
+
*
|
|
20
27
|
* The returned handler is deliberately NOT async and awaits nothing before delegating: a window
|
|
21
28
|
* opened after the user gesture has finished being handled is eaten by the popup blocker.
|
|
22
29
|
*
|
|
@@ -29,17 +36,12 @@ export const useLogin = (target?: string): readonly [string, (event?: MouseEvent
|
|
|
29
36
|
const context = useContext() as unknown as ClientContext
|
|
30
37
|
const nav = useNavigate()
|
|
31
38
|
const dispatcher = context.entrypoint<ClientEntrypoint>(DISPATCHER)
|
|
32
|
-
const path = dispatcher.
|
|
39
|
+
const path = dispatcher.path()
|
|
33
40
|
|
|
34
41
|
const onLogin = useCallback((event?: MouseEvent) => {
|
|
35
42
|
event?.preventDefault()
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
url: path,
|
|
39
|
-
target,
|
|
40
|
-
// Only a component may call `useNavigate`, so the in-app continuation is handed to the
|
|
41
|
-
// plugin rather than reinvented by it.
|
|
42
|
-
navigate: () => { nav.go(target ?? DISPATCHER) },
|
|
43
|
+
void loginStartOf(context as unknown as LoginContext).startLogin({
|
|
44
|
+
url: path, target, go: alias => nav.go(alias),
|
|
43
45
|
})
|
|
44
46
|
}, [context, path, target])
|
|
45
47
|
|
|
@@ -49,15 +51,49 @@ export const useLogin = (target?: string): readonly [string, (event?: MouseEvent
|
|
|
49
51
|
/**
|
|
50
52
|
* Wiring for a "Log out" control.
|
|
51
53
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
+
* One control, one handler, no decision — the mirror of {@link useLogin}. Where the session has to
|
|
55
|
+
* be ended (here, or one window up in a surrogate whose storage partition this document cannot
|
|
56
|
+
* reach) is the login plugin's call.
|
|
57
|
+
*
|
|
58
|
+
* NOT async, and nothing is awaited before delegating: logging out of a framed application opens a
|
|
59
|
+
* window, and a window opened after the gesture has finished being handled is eaten by the popup
|
|
60
|
+
* blocker. The surrogate entrypoint is resolved INSIDE the hook for the same reason `useLogin`
|
|
61
|
+
* resolves the dispatcher there.
|
|
62
|
+
*
|
|
63
|
+
* The return shape stays a bare handler rather than `useLogin`'s tuple: a logout control has no
|
|
64
|
+
* address to point at, and every generated application carries a copy of a component that writes
|
|
65
|
+
* `const onLogOut = useLogout()`. `(event?: MouseEvent) => void` is assignable to `() => void`, so
|
|
66
|
+
* `onClick={onLogOut}` keeps compiling everywhere.
|
|
54
67
|
*/
|
|
55
|
-
export const useLogout = (): (() => void) => {
|
|
68
|
+
export const useLogout = (target?: string): ((event?: MouseEvent) => void) => {
|
|
56
69
|
const context = useContext() as unknown as ClientContext
|
|
70
|
+
const nav = useNavigate()
|
|
71
|
+
const path = surrogatePath(context as unknown as LoginContext, { intent: LoginIntent.Logout })
|
|
72
|
+
|
|
73
|
+
return useCallback((event?: MouseEvent) => {
|
|
74
|
+
event?.preventDefault()
|
|
75
|
+
const login = context.service<LoginService>(LOGIN_SERVICE)
|
|
76
|
+
void login.logout({
|
|
77
|
+
// An application whose entrypoint list predates the surrogate route logs out in place.
|
|
78
|
+
url: path ?? '',
|
|
79
|
+
...(target != null ? { navigate: () => { nav.go(target) } } : {}),
|
|
80
|
+
})
|
|
81
|
+
}, [context, path, target])
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* For a component that runs its own post-login step (the marketing-consent screen, for one) to
|
|
86
|
+
* call once it is satisfied — moves the flow on to the next step, or the ordinary landing.
|
|
87
|
+
*
|
|
88
|
+
* Not async at the call site by accident of its own — it is a callback a component holds and
|
|
89
|
+
* fires later, so nothing here needs the synchronous-gesture discipline `useLogin`/`useLogout` do.
|
|
90
|
+
*/
|
|
91
|
+
export const useContinueLogin = (): ((opts?: LandOptions) => Promise<void>) => {
|
|
92
|
+
const context = useContext() as unknown as ClientContext
|
|
93
|
+
const nav = useNavigate()
|
|
57
94
|
|
|
58
|
-
return useCallback(() => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}, [context])
|
|
95
|
+
return useCallback(async (opts?: LandOptions) => {
|
|
96
|
+
const landing = await loginLandingOf(context as unknown as LoginContext).continueLogin(opts)
|
|
97
|
+
await nav.go(landing.alias, { params: landing.params, query: landing.query })
|
|
98
|
+
}, [context, nav])
|
|
63
99
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Уваход",
|
|
4
|
+
"subtitle": "Абярыце спосаб уваходу.",
|
|
5
|
+
"busy": "Адкрываем акно ўваходу…",
|
|
6
|
+
"empty": "Для гэтай праграмы не наладжаны ніводзін спосаб уваходу.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Працягнуць з Google",
|
|
9
|
+
"oidc": "Працягнуць з {{provider}}",
|
|
10
|
+
"oidc-default": "Увайсці / Зарэгістравацца",
|
|
11
|
+
"oidc-client": "Працягнуць з {{provider}}",
|
|
12
|
+
"basic-ed25519": "Увайсці з ключом",
|
|
13
|
+
"pk-supervisor": "Сакрэтны ключ (аператар)",
|
|
14
|
+
"wallet-consumer": "Гаманец OwlMeans ID",
|
|
15
|
+
"one-time-token": "Увайсці па кодзе з ліста",
|
|
16
|
+
"fallback": "Працягнуць з {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "Я прачытаў(-ла) і прымаю {{documents}}.",
|
|
20
|
+
"terms": "Умовы карыстання",
|
|
21
|
+
"privacy": "Палітыку прыватнасці",
|
|
22
|
+
"cookies": "Палітыку файлаў cookie",
|
|
23
|
+
"billing": "Умовы аплаты",
|
|
24
|
+
"product": "Умовы прадукту {{product}}",
|
|
25
|
+
"notice": "Як мы апрацоўваем вашы асабістыя дадзеныя: {{notices}}.",
|
|
26
|
+
"revised": "Апошняе абнаўленне: {{date}}",
|
|
27
|
+
"required": "Каб працягнуць, пацвердзіце {{documents}}."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Уваход захоўвае сеансавы файл cookie. Прыміце неабходныя файлы cookie, каб працягнуць."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Працуе на OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "Уваход не завершаны. Паспрабуйце яшчэ раз.",
|
|
37
|
+
"blocked": "Акно ўваходу заблакавана. Націсніце значок заблакаванага ўсплывальнага акна ў адрасным радку браўзера, каб адкрыць яго."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Уваход выкананы. Можаце закрыць гэтае акно і вярнуцца ў праграму."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Anmelden",
|
|
4
|
+
"subtitle": "Wählen Sie, wie Sie fortfahren möchten.",
|
|
5
|
+
"busy": "Anmeldung wird geöffnet…",
|
|
6
|
+
"empty": "Für diese Anwendung ist keine Anmeldemethode konfiguriert.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Mit Google fortfahren",
|
|
9
|
+
"oidc": "Mit {{provider}} fortfahren",
|
|
10
|
+
"oidc-default": "Anmelden / Registrieren",
|
|
11
|
+
"oidc-client": "Mit {{provider}} fortfahren",
|
|
12
|
+
"basic-ed25519": "Mit einem Schlüssel anmelden",
|
|
13
|
+
"pk-supervisor": "Geheimer Schlüssel (Betreiber)",
|
|
14
|
+
"wallet-consumer": "OwlMeans-ID-Wallet",
|
|
15
|
+
"one-time-token": "Mit einem E-Mail-Code anmelden",
|
|
16
|
+
"fallback": "Mit {{method}} fortfahren"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "Ich habe {{documents}} gelesen und stimme ihnen zu.",
|
|
20
|
+
"terms": "Allgemeinen Geschäftsbedingungen",
|
|
21
|
+
"privacy": "Datenschutzerklärung",
|
|
22
|
+
"cookies": "Cookie-Richtlinie",
|
|
23
|
+
"billing": "Abrechnungsbedingungen",
|
|
24
|
+
"product": "{{product}}-Produktbedingungen",
|
|
25
|
+
"notice": "Wie wir Ihre personenbezogenen Daten verarbeiten: {{notices}}.",
|
|
26
|
+
"revised": "Zuletzt aktualisiert: {{date}}",
|
|
27
|
+
"required": "Bitte bestätigen Sie {{documents}}, um fortzufahren."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Bei der Anmeldung wird ein Sitzungs-Cookie gespeichert. Akzeptieren Sie die notwendigen Cookies, um fortzufahren."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Betrieben mit OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "Die Anmeldung wurde nicht abgeschlossen. Bitte versuchen Sie es erneut.",
|
|
37
|
+
"blocked": "Das Anmeldefenster wurde blockiert. Klicken Sie auf das Symbol für blockierte Pop-ups in der Adressleiste Ihres Browsers, um es zu öffnen."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Angemeldet. Sie können dieses Fenster schließen und in der Anwendung fortfahren."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Sign in",
|
|
4
|
+
"subtitle": "Choose how you would like to continue.",
|
|
5
|
+
"busy": "Opening sign-in…",
|
|
6
|
+
"empty": "No sign-in method is configured for this application.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Continue with Google",
|
|
9
|
+
"oidc": "Continue with {{provider}}",
|
|
10
|
+
"oidc-default": "Sign in / Sign up",
|
|
11
|
+
"oidc-client": "Continue with {{provider}}",
|
|
12
|
+
"basic-ed25519": "Sign in with a key",
|
|
13
|
+
"pk-supervisor": "Secret key (operator)",
|
|
14
|
+
"wallet-consumer": "OwlMeans ID wallet",
|
|
15
|
+
"one-time-token": "Sign in with an email code",
|
|
16
|
+
"fallback": "Continue with {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "I have read and agree to the {{documents}}.",
|
|
20
|
+
"terms": "Terms & Conditions",
|
|
21
|
+
"privacy": "Privacy Policy",
|
|
22
|
+
"cookies": "Cookie Policy",
|
|
23
|
+
"billing": "Billing Terms",
|
|
24
|
+
"product": "{{product}} Product Terms",
|
|
25
|
+
"notice": "How we handle your personal data: {{notices}}.",
|
|
26
|
+
"revised": "Last updated: {{date}}",
|
|
27
|
+
"required": "Please confirm the {{documents}} to continue."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Signing in stores a session cookie. Accept essential cookies to continue."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Powered by OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "Sign-in did not complete. Please try again.",
|
|
37
|
+
"blocked": "The sign-in window was blocked. Click the blocked pop-up icon in your browser's address bar to open it."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Signed in. You can close this window and continue in the application."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Iniciar sesión",
|
|
4
|
+
"subtitle": "Elige cómo quieres continuar.",
|
|
5
|
+
"busy": "Abriendo el inicio de sesión…",
|
|
6
|
+
"empty": "No hay ningún método de inicio de sesión configurado para esta aplicación.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Continuar con Google",
|
|
9
|
+
"oidc": "Continuar con {{provider}}",
|
|
10
|
+
"oidc-default": "Iniciar sesión / Registrarse",
|
|
11
|
+
"oidc-client": "Continuar con {{provider}}",
|
|
12
|
+
"basic-ed25519": "Iniciar sesión con una clave",
|
|
13
|
+
"pk-supervisor": "Clave secreta (operador)",
|
|
14
|
+
"wallet-consumer": "Cartera OwlMeans ID",
|
|
15
|
+
"one-time-token": "Iniciar sesión con un código por correo",
|
|
16
|
+
"fallback": "Continuar con {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "He leído y acepto {{documents}}.",
|
|
20
|
+
"terms": "Términos y Condiciones",
|
|
21
|
+
"privacy": "Política de Privacidad",
|
|
22
|
+
"cookies": "Política de Cookies",
|
|
23
|
+
"billing": "Condiciones de Facturación",
|
|
24
|
+
"product": "Condiciones del Producto {{product}}",
|
|
25
|
+
"notice": "Cómo tratamos tus datos personales: {{notices}}.",
|
|
26
|
+
"revised": "Última actualización: {{date}}",
|
|
27
|
+
"required": "Confirma {{documents}} para continuar."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Iniciar sesión guarda una cookie de sesión. Acepta las cookies esenciales para continuar."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Con tecnología de OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "El inicio de sesión no se completó. Inténtalo de nuevo.",
|
|
37
|
+
"blocked": "Se bloqueó la ventana de inicio de sesión. Haz clic en el icono de ventana emergente bloqueada en la barra de direcciones del navegador para abrirla."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Sesión iniciada. Puedes cerrar esta ventana y continuar en la aplicación."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Connexion",
|
|
4
|
+
"subtitle": "Choisissez comment continuer.",
|
|
5
|
+
"busy": "Ouverture de la connexion…",
|
|
6
|
+
"empty": "Aucune méthode de connexion n’est configurée pour cette application.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Continuer avec Google",
|
|
9
|
+
"oidc": "Continuer avec {{provider}}",
|
|
10
|
+
"oidc-default": "Connexion / Inscription",
|
|
11
|
+
"oidc-client": "Continuer avec {{provider}}",
|
|
12
|
+
"basic-ed25519": "Se connecter avec une clé",
|
|
13
|
+
"pk-supervisor": "Clé secrète (opérateur)",
|
|
14
|
+
"wallet-consumer": "Portefeuille d’identité OwlMeans",
|
|
15
|
+
"one-time-token": "Se connecter avec un code e-mail",
|
|
16
|
+
"fallback": "Continuer avec {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "J’ai lu et j’accepte {{documents}}.",
|
|
20
|
+
"terms": "conditions générales",
|
|
21
|
+
"privacy": "politique de confidentialité",
|
|
22
|
+
"cookies": "Politique relative aux cookies",
|
|
23
|
+
"billing": "Conditions de facturation",
|
|
24
|
+
"product": "Conditions du produit {{product}}",
|
|
25
|
+
"notice": "Comment nous traitons vos données personnelles : {{notices}}.",
|
|
26
|
+
"revised": "Dernière mise à jour : {{date}}",
|
|
27
|
+
"required": "Confirmez {{documents}} pour continuer."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "La connexion enregistre un cookie de session. Acceptez les cookies essentiels pour continuer."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Propulsé par OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "La connexion n’a pas abouti. Réessayez.",
|
|
37
|
+
"blocked": "La fenêtre de connexion a été bloquée. Cliquez sur l’icône de fenêtre contextuelle bloquée dans la barre d’adresse pour l’ouvrir."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Vous êtes connecté. Vous pouvez fermer cette fenêtre et continuer dans l’application."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Zaloguj się",
|
|
4
|
+
"subtitle": "Wybierz sposób, w jaki chcesz kontynuować.",
|
|
5
|
+
"busy": "Otwieranie logowania…",
|
|
6
|
+
"empty": "Dla tej aplikacji nie skonfigurowano żadnej metody logowania.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Kontynuuj z Google",
|
|
9
|
+
"oidc": "Kontynuuj z {{provider}}",
|
|
10
|
+
"oidc-default": "Zaloguj się / Zarejestruj się",
|
|
11
|
+
"oidc-client": "Kontynuuj z {{provider}}",
|
|
12
|
+
"basic-ed25519": "Zaloguj się kluczem",
|
|
13
|
+
"pk-supervisor": "Klucz tajny (operator)",
|
|
14
|
+
"wallet-consumer": "Portfel OwlMeans ID",
|
|
15
|
+
"one-time-token": "Zaloguj się kodem e-mail",
|
|
16
|
+
"fallback": "Kontynuuj z {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "Przeczytałem(-am) i akceptuję {{documents}}.",
|
|
20
|
+
"terms": "Regulamin",
|
|
21
|
+
"privacy": "Politykę prywatności",
|
|
22
|
+
"cookies": "Politykę plików cookie",
|
|
23
|
+
"billing": "Warunki rozliczeń",
|
|
24
|
+
"product": "Warunki produktu {{product}}",
|
|
25
|
+
"notice": "Jak przetwarzamy Twoje dane osobowe: {{notices}}.",
|
|
26
|
+
"revised": "Ostatnia aktualizacja: {{date}}",
|
|
27
|
+
"required": "Aby kontynuować, potwierdź {{documents}}."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Logowanie zapisuje plik cookie sesji. Zaakceptuj niezbędne pliki cookie, aby kontynuować."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Napędzane przez OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "Logowanie nie zostało ukończone. Spróbuj ponownie.",
|
|
37
|
+
"blocked": "Okno logowania zostało zablokowane. Kliknij ikonę zablokowanego okienka w pasku adresu przeglądarki, aby je otworzyć."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Zalogowano. Możesz zamknąć to okno i kontynuować w aplikacji."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Вход",
|
|
4
|
+
"subtitle": "Выберите способ входа.",
|
|
5
|
+
"busy": "Открываем окно входа…",
|
|
6
|
+
"empty": "Для этого приложения не настроен ни один способ входа.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Продолжить с Google",
|
|
9
|
+
"oidc": "Продолжить с {{provider}}",
|
|
10
|
+
"oidc-default": "Войти / Зарегистрироваться",
|
|
11
|
+
"oidc-client": "Продолжить с {{provider}}",
|
|
12
|
+
"basic-ed25519": "Войти с ключом",
|
|
13
|
+
"pk-supervisor": "Секретный ключ (оператор)",
|
|
14
|
+
"wallet-consumer": "Кошелёк OwlMeans ID",
|
|
15
|
+
"one-time-token": "Войти по коду из письма",
|
|
16
|
+
"fallback": "Продолжить с {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "Я прочитал(а) и принимаю {{documents}}.",
|
|
20
|
+
"terms": "Условия использования",
|
|
21
|
+
"privacy": "Политику конфиденциальности",
|
|
22
|
+
"cookies": "Политику файлов cookie",
|
|
23
|
+
"billing": "Условия оплаты",
|
|
24
|
+
"product": "Условия использования продукта {{product}}",
|
|
25
|
+
"notice": "Как мы обрабатываем ваши персональные данные: {{notices}}.",
|
|
26
|
+
"revised": "Последнее обновление: {{date}}",
|
|
27
|
+
"required": "Чтобы продолжить, подтвердите {{documents}}."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Вход сохраняет сессионный файл cookie. Примите необходимые файлы cookie, чтобы продолжить."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Работает на OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "Вход не завершён. Попробуйте ещё раз.",
|
|
37
|
+
"blocked": "Окно входа заблокировано. Нажмите на значок заблокированного всплывающего окна в адресной строке браузера, чтобы открыть его."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Вход выполнен. Можете закрыть это окно и вернуться в приложение."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Вхід",
|
|
4
|
+
"subtitle": "Оберіть спосіб входу.",
|
|
5
|
+
"busy": "Відкриваємо вікно входу…",
|
|
6
|
+
"empty": "Для цього застосунку не налаштовано жодного способу входу.",
|
|
7
|
+
"method": {
|
|
8
|
+
"google": "Продовжити з Google",
|
|
9
|
+
"oidc": "Продовжити з {{provider}}",
|
|
10
|
+
"oidc-default": "Увійти / Зареєструватися",
|
|
11
|
+
"oidc-client": "Продовжити з {{provider}}",
|
|
12
|
+
"basic-ed25519": "Увійти з ключем",
|
|
13
|
+
"pk-supervisor": "Секретний ключ (оператор)",
|
|
14
|
+
"wallet-consumer": "Гаманець OwlMeans ID",
|
|
15
|
+
"one-time-token": "Увійти за кодом з листа",
|
|
16
|
+
"fallback": "Продовжити з {{method}}"
|
|
17
|
+
},
|
|
18
|
+
"terms": {
|
|
19
|
+
"accept": "Я прочитав(-ла) і приймаю {{documents}}.",
|
|
20
|
+
"terms": "Умови користування",
|
|
21
|
+
"privacy": "Політику конфіденційності",
|
|
22
|
+
"cookies": "Політику файлів cookie",
|
|
23
|
+
"billing": "Умови оплати",
|
|
24
|
+
"product": "Умови продукту {{product}}",
|
|
25
|
+
"notice": "Як ми обробляємо ваші персональні дані: {{notices}}.",
|
|
26
|
+
"revised": "Востаннє оновлено: {{date}}",
|
|
27
|
+
"required": "Щоб продовжити, підтвердьте {{documents}}."
|
|
28
|
+
},
|
|
29
|
+
"consent": {
|
|
30
|
+
"required": "Вхід зберігає сеансовий файл cookie. Прийміть необхідні файли cookie, щоб продовжити."
|
|
31
|
+
},
|
|
32
|
+
"credit": {
|
|
33
|
+
"powered": "Працює на OwlMeans"
|
|
34
|
+
},
|
|
35
|
+
"error": {
|
|
36
|
+
"failed": "Вхід не завершено. Спробуйте ще раз.",
|
|
37
|
+
"blocked": "Вікно входу заблоковано. Натисніть значок заблокованого спливаючого вікна в адресному рядку браузера, щоб відкрити його."
|
|
38
|
+
},
|
|
39
|
+
"orphaned": "Вхід виконано. Можете закрити це вікно й повернутися до застосунку."
|
|
40
|
+
}
|
|
41
|
+
}
|