@tachybase/module-auth 1.6.0 → 1.6.2

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 CHANGED
@@ -1,117 +1,117 @@
1
- # Auth
2
-
3
- 提供基础认证功能和扩展认证器管理功能。
4
-
5
- ## 使用方法
6
-
7
- ### 认证器管理
8
- 页面:应用配置 - 认证
9
-
10
-
11
- <img src="https://s2.loli.net/2023/05/15/NdriQZvBuE6hGRS.png" width="800px" />
12
-
13
- #### 内置认证器
14
- - 名称:basic
15
- - 认证类型:邮箱密码登录
16
-
17
- <img src="https://s2.loli.net/2023/05/15/HC4gtx9fQPrqvac.png" width="300px" />
18
-
19
- <img src="https://s2.loli.net/2023/05/15/fcLqypdhOxnksbg.png" width="300px" />
20
-
21
- #### 增加认证器
22
- Add new - 选择认证类型
23
-
24
- <img src="https://s2.loli.net/2023/05/15/CR7UTDt2WzbEfgs.png" width="300px" />
25
-
26
- #### 启用/禁用
27
- Actions - Edit - 勾选/取消Enabled
28
-
29
- <img src="https://s2.loli.net/2023/05/15/2utpSHly9fzCKX5.png" width="400px" />
30
-
31
- #### 配置认证器
32
- Actions - Edit
33
-
34
- ## 开发一个登录插件
35
- ### 接口
36
- Tachybase内核提供了扩展登录方式的接入和管理。扩展登录插件的核心逻辑处理,需要继承内核的`Auth`类,并对相应的标准接口进行实现。
37
- 参考`core/auth/auth.ts`
38
-
39
- ```TypeScript
40
- import { Auth } from '@tachybase/auth';
41
-
42
- class CustomAuth extends Auth {
43
- set user(user) {}
44
- get user() {}
45
-
46
- async check() {}
47
- async signIn() {}
48
- }
49
- ```
50
-
51
- 多数情况下,扩展的用户登录方式也将沿用现有的jwt逻辑来生成用户访问API的凭证,插件也可以继承`BaseAuth`类以便复用部分逻辑代码,如`check`, `signIn`接口。
52
-
53
- ```TypeScript
54
- import { BaseAuth } from '@tachybase/auth';
55
-
56
- class CustomAuth extends BaseAuth {
57
- constructor(config: AuthConfig) {
58
- const userCollection = config.ctx.db.getCollection('users');
59
- super({ ...config, userCollection });
60
- }
61
-
62
- async validate() {}
63
- }
64
- ```
65
-
66
- ### 用户数据
67
-
68
- `@tachybase/module-auth`插件提供了`usersAuthenticators`表来建立users和authenticators,即用户和认证方式的关联。
69
- 通常情况下,扩展登录方式用`users`和`usersAuthenticators`来存储相应的用户数据即可,特殊情况下才需要自己新增Collection.
70
- `users`存储的是最基础的用户数据,邮箱、昵称和密码。
71
- `usersAuthenticators`存储扩展登录方式数据
72
- - uuid: 该种认证方式的用户唯一标识,如手机号、微信openid等
73
- - meta: JSON字段,其他需要保存的信息
74
- - userId: 用户id
75
- - authenticator:认证器名字
76
-
77
- 对于用户操作,`Authenticator`模型也提供了几个封装的方法,可以在`CustomAuth`类中通过`this.authenticator[方法名]`使用:
78
- - `findUser(uuid: string): UserModel` - 查询用户
79
- - `newUser(uuid: string, values?: any): UserModel` - 创建新用户
80
- - `findOrCreateUser(uuid: string, userValues?: any): UserModel` - 查找或创建新用户
81
-
82
- ### 注册
83
- 扩展的登录方式需要向内核注册。
84
- ```TypeScript
85
- async load() {
86
- this.app.authManager.registerTypes('custom-auth-type', {
87
- auth: CustomAuth,
88
- });
89
- }
90
- ```
91
-
92
- ### 客户端API
93
- #### OptionsComponentProvider
94
- 可供用户配置的认证器配置项
95
- - authType 认证方式
96
- - component 配置组件
97
- ```TypeScript
98
- <OptionsComponentProvider authType="custom-auth-type" component={Options} />
99
- ```
100
-
101
- `Options`组件使用的值是`authenticator`的`options`字段,如果有需要暴露在前端的配置,应该放在`options.public`字段中。`authenticators:publicList`接口会返回`options.public`字段的值。
102
-
103
- #### SigninPageProvider
104
- 自定义登录页界面
105
- - authType 认证方式
106
- - tabTitle 登录页tab标题
107
- - component 登录页组件
108
-
109
- #### SignupPageProvider
110
- 自定义注册页界面
111
- - authType 认证方式
112
- - component 注册页组件
113
-
114
- #### SigninPageExtensionProvider
115
- 自定义登录页下方的扩展内容
116
- - authType 认证方式
117
- - component 扩展组件
1
+ # Auth
2
+
3
+ 提供基础认证功能和扩展认证器管理功能。
4
+
5
+ ## 使用方法
6
+
7
+ ### 认证器管理
8
+ 页面:应用配置 - 认证
9
+
10
+
11
+ <img src="https://s2.loli.net/2023/05/15/NdriQZvBuE6hGRS.png" width="800px" />
12
+
13
+ #### 内置认证器
14
+ - 名称:basic
15
+ - 认证类型:邮箱密码登录
16
+
17
+ <img src="https://s2.loli.net/2023/05/15/HC4gtx9fQPrqvac.png" width="300px" />
18
+
19
+ <img src="https://s2.loli.net/2023/05/15/fcLqypdhOxnksbg.png" width="300px" />
20
+
21
+ #### 增加认证器
22
+ Add new - 选择认证类型
23
+
24
+ <img src="https://s2.loli.net/2023/05/15/CR7UTDt2WzbEfgs.png" width="300px" />
25
+
26
+ #### 启用/禁用
27
+ Actions - Edit - 勾选/取消Enabled
28
+
29
+ <img src="https://s2.loli.net/2023/05/15/2utpSHly9fzCKX5.png" width="400px" />
30
+
31
+ #### 配置认证器
32
+ Actions - Edit
33
+
34
+ ## 开发一个登录插件
35
+ ### 接口
36
+ Tachybase内核提供了扩展登录方式的接入和管理。扩展登录插件的核心逻辑处理,需要继承内核的`Auth`类,并对相应的标准接口进行实现。
37
+ 参考`core/auth/auth.ts`
38
+
39
+ ```TypeScript
40
+ import { Auth } from '@tachybase/auth';
41
+
42
+ class CustomAuth extends Auth {
43
+ set user(user) {}
44
+ get user() {}
45
+
46
+ async check() {}
47
+ async signIn() {}
48
+ }
49
+ ```
50
+
51
+ 多数情况下,扩展的用户登录方式也将沿用现有的jwt逻辑来生成用户访问API的凭证,插件也可以继承`BaseAuth`类以便复用部分逻辑代码,如`check`, `signIn`接口。
52
+
53
+ ```TypeScript
54
+ import { BaseAuth } from '@tachybase/auth';
55
+
56
+ class CustomAuth extends BaseAuth {
57
+ constructor(config: AuthConfig) {
58
+ const userCollection = config.ctx.db.getCollection('users');
59
+ super({ ...config, userCollection });
60
+ }
61
+
62
+ async validate() {}
63
+ }
64
+ ```
65
+
66
+ ### 用户数据
67
+
68
+ `@tachybase/module-auth`插件提供了`usersAuthenticators`表来建立users和authenticators,即用户和认证方式的关联。
69
+ 通常情况下,扩展登录方式用`users`和`usersAuthenticators`来存储相应的用户数据即可,特殊情况下才需要自己新增Collection.
70
+ `users`存储的是最基础的用户数据,邮箱、昵称和密码。
71
+ `usersAuthenticators`存储扩展登录方式数据
72
+ - uuid: 该种认证方式的用户唯一标识,如手机号、微信openid等
73
+ - meta: JSON字段,其他需要保存的信息
74
+ - userId: 用户id
75
+ - authenticator:认证器名字
76
+
77
+ 对于用户操作,`Authenticator`模型也提供了几个封装的方法,可以在`CustomAuth`类中通过`this.authenticator[方法名]`使用:
78
+ - `findUser(uuid: string): UserModel` - 查询用户
79
+ - `newUser(uuid: string, values?: any): UserModel` - 创建新用户
80
+ - `findOrCreateUser(uuid: string, userValues?: any): UserModel` - 查找或创建新用户
81
+
82
+ ### 注册
83
+ 扩展的登录方式需要向内核注册。
84
+ ```TypeScript
85
+ async load() {
86
+ this.app.authManager.registerTypes('custom-auth-type', {
87
+ auth: CustomAuth,
88
+ });
89
+ }
90
+ ```
91
+
92
+ ### 客户端API
93
+ #### OptionsComponentProvider
94
+ 可供用户配置的认证器配置项
95
+ - authType 认证方式
96
+ - component 配置组件
97
+ ```TypeScript
98
+ <OptionsComponentProvider authType="custom-auth-type" component={Options} />
99
+ ```
100
+
101
+ `Options`组件使用的值是`authenticator`的`options`字段,如果有需要暴露在前端的配置,应该放在`options.public`字段中。`authenticators:publicList`接口会返回`options.public`字段的值。
102
+
103
+ #### SigninPageProvider
104
+ 自定义登录页界面
105
+ - authType 认证方式
106
+ - tabTitle 登录页tab标题
107
+ - component 登录页组件
108
+
109
+ #### SignupPageProvider
110
+ 自定义注册页界面
111
+ - authType 认证方式
112
+ - component 注册页组件
113
+
114
+ #### SigninPageExtensionProvider
115
+ 自定义登录页下方的扩展内容
116
+ - authType 认证方式
117
+ - component 扩展组件
package/client.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from './dist/client';
2
- export { default } from './dist/client';
1
+ export * from './dist/client';
2
+ export { default } from './dist/client';
package/client.js CHANGED
@@ -1,65 +1,65 @@
1
- 'use strict';
2
-
3
- function _getRequireWildcardCache(nodeInterop) {
4
- if (typeof WeakMap !== 'function') return null;
5
- var cacheBabelInterop = new WeakMap();
6
- var cacheNodeInterop = new WeakMap();
7
- return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {
8
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
9
- })(nodeInterop);
10
- }
11
-
12
- function _interopRequireWildcard(obj, nodeInterop) {
13
- if (!nodeInterop && obj && obj.__esModule) {
14
- return obj;
15
- }
16
- if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
17
- return { default: obj };
18
- }
19
- var cache = _getRequireWildcardCache(nodeInterop);
20
- if (cache && cache.has(obj)) {
21
- return cache.get(obj);
22
- }
23
- var newObj = {};
24
- var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
25
- for (var key in obj) {
26
- if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
27
- var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
28
- if (desc && (desc.get || desc.set)) {
29
- Object.defineProperty(newObj, key, desc);
30
- } else {
31
- newObj[key] = obj[key];
32
- }
33
- }
34
- }
35
- newObj.default = obj;
36
- if (cache) {
37
- cache.set(obj, newObj);
38
- }
39
- return newObj;
40
- }
41
-
42
- var _index = _interopRequireWildcard(require('./dist/client'));
43
-
44
- Object.defineProperty(exports, '__esModule', {
45
- value: true,
46
- });
47
- var _exportNames = {};
48
- Object.defineProperty(exports, 'default', {
49
- enumerable: true,
50
- get: function get() {
51
- return _index.default;
52
- },
53
- });
54
-
55
- Object.keys(_index).forEach(function (key) {
56
- if (key === 'default' || key === '__esModule') return;
57
- if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
58
- if (key in exports && exports[key] === _index[key]) return;
59
- Object.defineProperty(exports, key, {
60
- enumerable: true,
61
- get: function get() {
62
- return _index[key];
63
- },
64
- });
65
- });
1
+ 'use strict';
2
+
3
+ function _getRequireWildcardCache(nodeInterop) {
4
+ if (typeof WeakMap !== 'function') return null;
5
+ var cacheBabelInterop = new WeakMap();
6
+ var cacheNodeInterop = new WeakMap();
7
+ return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {
8
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
9
+ })(nodeInterop);
10
+ }
11
+
12
+ function _interopRequireWildcard(obj, nodeInterop) {
13
+ if (!nodeInterop && obj && obj.__esModule) {
14
+ return obj;
15
+ }
16
+ if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
17
+ return { default: obj };
18
+ }
19
+ var cache = _getRequireWildcardCache(nodeInterop);
20
+ if (cache && cache.has(obj)) {
21
+ return cache.get(obj);
22
+ }
23
+ var newObj = {};
24
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
25
+ for (var key in obj) {
26
+ if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
27
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
28
+ if (desc && (desc.get || desc.set)) {
29
+ Object.defineProperty(newObj, key, desc);
30
+ } else {
31
+ newObj[key] = obj[key];
32
+ }
33
+ }
34
+ }
35
+ newObj.default = obj;
36
+ if (cache) {
37
+ cache.set(obj, newObj);
38
+ }
39
+ return newObj;
40
+ }
41
+
42
+ var _index = _interopRequireWildcard(require('./dist/client'));
43
+
44
+ Object.defineProperty(exports, '__esModule', {
45
+ value: true,
46
+ });
47
+ var _exportNames = {};
48
+ Object.defineProperty(exports, 'default', {
49
+ enumerable: true,
50
+ get: function get() {
51
+ return _index.default;
52
+ },
53
+ });
54
+
55
+ Object.keys(_index).forEach(function (key) {
56
+ if (key === 'default' || key === '__esModule') return;
57
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
58
+ if (key in exports && exports[key] === _index[key]) return;
59
+ Object.defineProperty(exports, key, {
60
+ enumerable: true,
61
+ get: function get() {
62
+ return _index[key];
63
+ },
64
+ });
65
+ });
@@ -4,7 +4,7 @@
4
4
  width: 100%;
5
5
  left: 0;
6
6
  text-align: center;
7
- `,children:c.jsx(i.PoweredBy,{})})]})}const Ze=()=>{var n;const o=i.usePlugin(_).authTypes.getEntities(),t={};for(const[r,s]of o)(n=s.components)!=null&&n.SignInForm&&(t[r]=s.components.SignInForm);return t},Je=(e=[])=>{var s;const t=i.usePlugin(_).authTypes.getEntities(),n={};for(const[a,u]of t)(s=u.components)!=null&&s.SignInButton&&(n[a]=u.components.SignInButton);const r=Object.keys(n);return e.filter(a=>r.includes(a.authType)).map((a,u)=>f.createElement(n[a.authType],{key:u,authenticator:a}))},Qe=()=>{const{t:e}=w();i.useCurrentDocumentTitle("Signin"),i.useViewport();const o=Ze(),t=f.useContext(j),n=Je(t);if(!t.length)return c.jsx("div",{style:{color:"#ccc"},children:e("No authentication methods available.")});const r=t.map(s=>{const a=o[s.authType];if(!a)return;const u=`${e("Sign-in")} (${e(s.authTypeTitle||s.authType)})`;return E({component:f.createElement(a,{authenticator:s}),tabTitle:s.title||s.name==="basic"?u:`${e(s.name)}`},s)}).filter(s=>s);return c.jsxs(x.Space,{direction:"vertical",className:i.css`
7
+ `,children:c.jsx(i.PoweredBy,{})})]})}const Ze=()=>{var n;const o=i.usePlugin(_).authTypes.getEntities(),t={};for(const[r,s]of o)(n=s.components)!=null&&n.SignInForm&&(t[r]=s.components.SignInForm);return t},Je=(e=[])=>{var s;const t=i.usePlugin(_).authTypes.getEntities(),n={};for(const[a,u]of t)(s=u.components)!=null&&s.SignInButton&&(n[a]=u.components.SignInButton);const r=Object.keys(n);return Array.isArray(e)?e.filter(a=>r.includes(a.authType)).map((a,u)=>f.createElement(n[a.authType],{key:u,authenticator:a})):(console.error("[useSignInButtons] authenticators is not an array:",{type:typeof e,value:e}),[])},Qe=()=>{const{t:e}=w();i.useCurrentDocumentTitle("Signin"),i.useViewport();const o=Ze(),t=f.useContext(j),n=Je(t);if(!t.length)return c.jsx("div",{style:{color:"#ccc"},children:e("No authentication methods available.")});const r=t.map(s=>{const a=o[s.authType];if(!a)return;const u=`${e("Sign-in")} (${e(s.authTypeTitle||s.authType)})`;return E({component:f.createElement(a,{authenticator:s}),tabTitle:s.title||s.name==="basic"?u:`${e(s.name)}`},s)}).filter(s=>s);return c.jsxs(x.Space,{direction:"vertical",className:i.css`
8
8
  display: flex;
9
9
  `,children:[r.length>1?c.jsx(x.Tabs,{items:r.map(s=>({label:s.tabTitle,key:s.name,children:s.component}))}):r.length?c.jsx("div",{children:r[0].component}):c.jsx(c.Fragment,{}),c.jsx(x.Space,{direction:"vertical",className:i.css`
10
10
  display: flex;
@@ -1,14 +1,14 @@
1
1
  module.exports = {
2
2
  "react": "18.3.1",
3
- "@tachybase/client": "1.6.0",
3
+ "@tachybase/client": "1.6.1",
4
4
  "react-router-dom": "6.28.1",
5
- "@tego/client": "1.3.52",
5
+ "@tego/client": "1.6.1-alpha.2",
6
6
  "axios": "1.13.0",
7
7
  "lodash": "4.17.21",
8
- "@tego/server": "1.3.52",
9
- "@tachybase/test": "1.3.52",
8
+ "@tego/server": "1.6.1-alpha.2",
10
9
  "antd": "5.22.5",
11
- "@tachybase/schema": "1.3.52",
10
+ "@tachybase/schema": "1.6.1-alpha.2",
12
11
  "react-i18next": "16.2.1",
13
- "@ant-design/icons": "5.6.1"
12
+ "@ant-design/icons": "6.1.0",
13
+ "@tachybase/test": "1.6.1-alpha.2"
14
14
  };
@@ -1,56 +1,63 @@
1
- {
2
- "Allow to sign in with": "Allow to sign in with",
3
- "Allow to sign up": "Allow to sign up",
4
- "Are you sure to unbind this authenticator?": "Are you sure to unbind this authenticator?",
5
- "Auth Type": "Auth Type",
6
- "Auth UID": "Auth UID",
7
- "Authentication": "Authentication",
8
- "Authentication login bind": "Authentication login bind",
9
- "Authenticators": "Authenticators",
10
- "Bind": "Bind",
11
- "Days": "Days",
12
- "Expired token refresh limit": "Expired token refresh limit",
13
- "Hours": "Hours",
14
- "In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.": "In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.",
15
- "Minutes": "Minutes",
16
- "No authentication methods available.": "No authentication methods available.",
17
- "Not a valid cellphone number, please re-enter": "Not a valid cellphone number, please re-enter",
18
- "Not allowed to sign up": "Not allowed to sign up",
19
- "Password is not allowed to be changed": "Password is not allowed to be changed",
20
- "Please enter a valid email": "Please enter a valid email",
21
- "Please enter a valid username": "Please enter a valid username",
22
- "Please enter your username or email": "Please enter your username or email",
23
- "Please keep and enable at least one authenticator": "Please keep and enable at least one authenticator",
24
- "SMS": "SMS",
25
- "Saved successfully!": "Saved successfully!",
26
- "Seconds": "Seconds",
27
- "Session validity period": "Session validity period",
28
- "Sign in via email": "Sign in via email",
29
- "Sign in via password": "Sign in via password",
30
- "Sign-in": "Sign-in",
31
- "The authentication allows users to sign in via username or email.": "The authentication allows users to sign in via username or email.",
32
- "The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.": "The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.",
33
- "The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.": "The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.",
34
- "The password is inconsistent, please re-enter": "The password is inconsistent, please re-enter",
35
- "The password is incorrect, please re-enter": "The password is incorrect, please re-enter",
36
- "The phone number has been registered, please login directly": "The phone number has been registered, please login directly",
37
- "The phone number is not registered, please register first": "The phone number is not registered, please register first",
38
- "The username or email is incorrect, please re-enter": "The username or email is incorrect, please re-enter",
39
- "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)",
40
- "Token policy": "Token policy",
41
- "Token validity period": "Token validity period",
42
- "Token validity period must be less than session validity period!": "Token validity period must be less than session validity period!",
43
- "Unauthenticated. Please sign in to continue.": "Unauthenticated. Please sign in to continue.",
44
- "Unbind": "Unbind",
45
- "User can bind or unbind the sign in type": "User can bind or unbind the sign in type",
46
- "User not found. Please sign in again to continue.": "User not found. Please sign in again to continue.",
47
- "Username/Email": "Username/Email",
48
- "Your account has been disabled, please contact administrator if you have any questions": "Your account has been disabled, please contact administrator if you have any questions",
49
- "Your account has been locked due to multiple failed login attempts. Please try again later.": "Your account has been locked due to multiple failed login attempts. Please try again later.",
50
- "Your account is under review, please wait for administrator approval": "Your account is under review, please wait for administrator approval",
51
- "Your session has expired. Please sign in again.": "Your session has expired. Please sign in again.",
52
- "gitea": "Gitea",
53
- "sms": "SMS",
54
- "wechat": "WeChat",
55
- "work-wechat": "WeCom"
56
- }
1
+ {
2
+ "Allow to sign in with": "Allow to sign in with",
3
+ "Allow to sign up": "Allow to sign up",
4
+ "Are you sure to unbind this authenticator?": "Are you sure to unbind this authenticator?",
5
+ "Auth Type": "Auth Type",
6
+ "Auth UID": "Auth UID",
7
+ "Authentication": "Authentication",
8
+ "Authentication login bind": "Authentication login bind",
9
+ "Authenticators": "Authenticators",
10
+ "Bind": "Bind",
11
+ "Days": "Days",
12
+ "Expired token refresh limit": "Expired token refresh limit",
13
+ "Hours": "Hours",
14
+ "In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.": "In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.",
15
+ "Invalid status": "Invalid status",
16
+ "Minutes": "Minutes",
17
+ "No authentication methods available.": "No authentication methods available.",
18
+ "Not a valid cellphone number, please re-enter": "Not a valid cellphone number, please re-enter",
19
+ "Not allowed to sign up": "Not allowed to sign up",
20
+ "Password is not allowed to be changed": "Password is not allowed to be changed",
21
+ "Please enter a valid email": "Please enter a valid email",
22
+ "Please enter a valid username": "Please enter a valid username",
23
+ "Please enter your username or email": "Please enter your username or email",
24
+ "Please keep and enable at least one authenticator": "Please keep and enable at least one authenticator",
25
+ "SMS": "SMS",
26
+ "Saved successfully!": "Saved successfully!",
27
+ "Seconds": "Seconds",
28
+ "Session validity period": "Session validity period",
29
+ "Sign in via email": "Sign in via email",
30
+ "Sign in via password": "Sign in via password",
31
+ "Sign-in": "Sign-in",
32
+ "Status expired, auto restored": "Status expired, auto restored",
33
+ "System error, please contact administrator": "System error, please contact administrator",
34
+ "The authentication allows users to sign in via username or email.": "The authentication allows users to sign in via username or email.",
35
+ "The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.": "The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.",
36
+ "The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.": "The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.",
37
+ "The password is inconsistent, please re-enter": "The password is inconsistent, please re-enter",
38
+ "The password is incorrect, please re-enter": "The password is incorrect, please re-enter",
39
+ "The phone number has been registered, please login directly": "The phone number has been registered, please login directly",
40
+ "The phone number is not registered, please register first": "The phone number is not registered, please register first",
41
+ "The username or email is incorrect, please re-enter": "The username or email is incorrect, please re-enter",
42
+ "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)",
43
+ "Token policy": "Token policy",
44
+ "Token validity period": "Token validity period",
45
+ "Token validity period must be less than session validity period!": "Token validity period must be less than session validity period!",
46
+ "Unauthenticated. Please sign in to continue.": "Unauthenticated. Please sign in to continue.",
47
+ "Unbind": "Unbind",
48
+ "Unknown status": "Unknown status",
49
+ "User can bind or unbind the sign in type": "User can bind or unbind the sign in type",
50
+ "User not found. Please sign in again to continue.": "User not found. Please sign in again to continue.",
51
+ "User status does not allow login": "User status does not allow login",
52
+ "User status is invalid, please contact administrator": "User status is invalid, please contact administrator",
53
+ "Username/Email": "Username/Email",
54
+ "Your account has been disabled, please contact administrator if you have any questions": "Your account has been disabled, please contact administrator if you have any questions",
55
+ "Your account has been locked due to multiple failed login attempts. Please try again later.": "Your account has been locked due to multiple failed login attempts. Please try again later.",
56
+ "Your account is under review, please wait for administrator approval": "Your account is under review, please wait for administrator approval",
57
+ "Your account status has changed. Please sign in again.": "Your account status has changed. Please sign in again.",
58
+ "Your session has expired. Please sign in again.": "Your session has expired. Please sign in again.",
59
+ "gitea": "Gitea",
60
+ "sms": "SMS",
61
+ "wechat": "WeChat",
62
+ "work-wechat": "WeCom"
63
+ }
@@ -1,29 +1,36 @@
1
- {
2
- "Allow to sign in with": "다음으로 로그인 허용",
3
- "Allow to sign up": "가입 허용",
4
- "Auth Type": "인증 유형",
5
- "Auth UID": "인증 UID",
6
- "Authentication": "인증",
7
- "Authenticators": "인증기",
8
- "No authentication methods available.": "사용 가능한 인증 방법이 없습니다.",
9
- "Not a valid cellphone number, please re-enter": "유효하지 않은 휴대폰 번호입니다. 다시 입력하세요.",
10
- "Not allowed to sign up": "가입할 없음",
11
- "Please enter a valid email": "유효한 이메일을 입력하세요.",
12
- "Please enter a valid username": "유효한 사용자 이름을 입력하세요.",
13
- "Please enter your username or email": "사용자 이름 또는 이메일을 입력하세요.",
14
- "Please keep and enable at least one authenticator": "최소한 하나의 인증기를 유지하고 활성화하세요.",
15
- "SMS": "SMS",
16
- "Sign in via email": "이메일로 로그인",
17
- "Sign in via password": "비밀번호로 로그인",
18
- "Sign-in": "로그인",
19
- "The authentication allows users to sign in via username or email.": "이 인증 방식을 사용하면 사용자가 사용자 이름 또는 이메일로 로그인할 수 있습니다.",
20
- "The password is inconsistent, please re-enter": "비밀번호가 일치하지 않습니다. 다시 입력하세요.",
21
- "The password is incorrect, please re-enter": "비밀번호가 잘못되었습니다. 다시 입력하세요.",
22
- "The phone number has been registered, please login directly": "전화번호가 이미 등록되어 있습니다. 직접 로그인하세요.",
23
- "The phone number is not registered, please register first": "전화번호가 등록되어 있지 않습니다. 먼저 등록하세요.",
24
- "The username or email is incorrect, please re-enter": "사용자 이름 또는 이메일이 잘못되었습니다. 다시 입력하세요.",
25
- "Username/Email": "사용자 이름/이메일",
26
- "Your account has been disabled, please contact administrator if you have any questions": "Your account has been disabled, please contact administrator if you have any questions",
27
- "Your account has been locked due to multiple failed login attempts. Please try again later.": "Your account has been locked due to multiple failed login attempts. Please try again later.",
28
- "Your account is under review, please wait for administrator approval": "Your account is under review, please wait for administrator approval"
29
- }
1
+ {
2
+ "Allow to sign in with": "다음으로 로그인 허용",
3
+ "Allow to sign up": "가입 허용",
4
+ "Auth Type": "인증 유형",
5
+ "Auth UID": "인증 UID",
6
+ "Authentication": "인증",
7
+ "Authenticators": "인증기",
8
+ "Invalid status": "상태 오류",
9
+ "No authentication methods available.": "사용 가능한 인증 방법이 없습니다.",
10
+ "Not a valid cellphone number, please re-enter": "유효하지 않은 휴대폰 번호입니다. 다시 입력하세요.",
11
+ "Not allowed to sign up": "가입할 없음",
12
+ "Please enter a valid email": "유효한 이메일을 입력하세요.",
13
+ "Please enter a valid username": "유효한 사용자 이름을 입력하세요.",
14
+ "Please enter your username or email": "사용자 이름 또는 이메일을 입력하세요.",
15
+ "Please keep and enable at least one authenticator": "최소한 하나의 인증기를 유지하고 활성화하세요.",
16
+ "SMS": "SMS",
17
+ "Sign in via email": "이메일로 로그인",
18
+ "Sign in via password": "비밀번호로 로그인",
19
+ "Sign-in": "로그인",
20
+ "Status expired, auto restored": "상태가 만료되었습니다. 자동으로 복구되었습니다.",
21
+ "System error, please contact administrator": "시스템 오류입니다. 관리자에게 문의하세요.",
22
+ "The authentication allows users to sign in via username or email.": " 인증 방식을 사용하면 사용자가 사용자 이름 또는 이메일로 로그인할 수 있습니다.",
23
+ "The password is inconsistent, please re-enter": "비밀번호가 일치하지 않습니다. 다시 입력하세요.",
24
+ "The password is incorrect, please re-enter": "비밀번호가 잘못되었습니다. 다시 입력하세요.",
25
+ "The phone number has been registered, please login directly": "전화번호가 이미 등록되어 있습니다. 직접 로그인하세요.",
26
+ "The phone number is not registered, please register first": "전화번호가 등록되어 있지 않습니다. 먼저 등록하세요.",
27
+ "The username or email is incorrect, please re-enter": "사용자 이름 또는 이메일이 잘못되었습니다. 다시 입력하세요.",
28
+ "Unknown status": " 없는 상태",
29
+ "User status does not allow login": "사용자 상태가 로그인을 허용하지 않습니다.",
30
+ "User status is invalid, please contact administrator": "사용자 상태가 오류입니다. 관리자에게 문의하세요.",
31
+ "Username/Email": "사용자 이름/이메일",
32
+ "Your account has been disabled, please contact administrator if you have any questions": "Your account has been disabled, please contact administrator if you have any questions",
33
+ "Your account has been locked due to multiple failed login attempts. Please try again later.": "Your account has been locked due to multiple failed login attempts. Please try again later.",
34
+ "Your account is under review, please wait for administrator approval": "Your account is under review, please wait for administrator approval",
35
+ "Your account status has changed. Please sign in again.": "사용자 상태가 변경되었습니다. 다시 로그인하세요."
36
+ }