@yongdall/user 0.4.6 → 0.5.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/index.d.mts +21 -21
- package/index.mjs +1 -1
- package/package.json +10 -9
- package/routers.yongdall.mjs +2 -2
- package/{user--pUQPO_O.mjs → user-ejRy16ds.mjs} +40 -40
- package/user-ejRy16ds.mjs.map +1 -0
- package/yongdall/enumeration.mjs +11 -0
- package/yongdall/enumeration.mjs.map +1 -0
- package/yongdall/migration.mjs +14 -0
- package/yongdall/migration.mjs.map +1 -0
- package/yongdall/model.mjs +10 -0
- package/yongdall/model.mjs.map +1 -0
- package/yongdall/user.mjs +29 -0
- package/yongdall/user.mjs.map +1 -0
- package/yongdall.plugin.yml +1 -0
- package/hooks.yongdall.mjs +0 -41
- package/hooks.yongdall.mjs.map +0 -1
- package/user--pUQPO_O.mjs.map +0 -1
package/index.d.mts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
1
|
+
import * as imodel2 from "imodel";
|
|
2
|
+
import * as _yongdall_model0 from "@yongdall/model";
|
|
3
3
|
|
|
4
4
|
//#region plugins/user/models/User.d.mts
|
|
5
|
-
declare const _default:
|
|
6
|
-
username:
|
|
7
|
-
account:
|
|
8
|
-
userId:
|
|
9
|
-
type:
|
|
5
|
+
declare const _default: _yongdall_model0.ModelTable<{
|
|
6
|
+
username: imodel2.FieldDefine<_yongdall_model0.ModelTable<{
|
|
7
|
+
account: imodel2.FieldDefine<"string", false, false>;
|
|
8
|
+
userId: imodel2.FieldDefine<"uuid", false, false>;
|
|
9
|
+
type: imodel2.FieldDefine<"string", false, false>;
|
|
10
10
|
}, "user.account">, false, false>;
|
|
11
|
-
id:
|
|
12
|
-
name:
|
|
13
|
-
enabled:
|
|
14
|
-
createdAt:
|
|
15
|
-
updatedAt:
|
|
11
|
+
id: imodel2.FieldDefine<"uuid", false, false>;
|
|
12
|
+
name: imodel2.FieldDefine<"string", false, false>;
|
|
13
|
+
enabled: imodel2.FieldDefine<"bool", false, false>;
|
|
14
|
+
createdAt: imodel2.FieldDefine<"timestamp", false, false>;
|
|
15
|
+
updatedAt: imodel2.FieldDefine<"timestamp", false, false>;
|
|
16
16
|
}, "user">;
|
|
17
17
|
//#endregion
|
|
18
18
|
//#region plugins/user/models/UserAccount.d.mts
|
|
19
|
-
declare const _default$1:
|
|
20
|
-
account:
|
|
21
|
-
userId:
|
|
22
|
-
type:
|
|
19
|
+
declare const _default$1: _yongdall_model0.ModelTable<{
|
|
20
|
+
account: imodel2.FieldDefine<"string", false, false>;
|
|
21
|
+
userId: imodel2.FieldDefine<"uuid", false, false>;
|
|
22
|
+
type: imodel2.FieldDefine<"string", false, false>;
|
|
23
23
|
}, "user.account">;
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region plugins/user/models/UserPassword.d.mts
|
|
26
|
-
declare const _default$2:
|
|
27
|
-
userId:
|
|
28
|
-
password:
|
|
29
|
-
deadline:
|
|
30
|
-
updatedAt:
|
|
26
|
+
declare const _default$2: _yongdall_model0.ModelTable<{
|
|
27
|
+
userId: imodel2.FieldDefine<"uuid", false, false>;
|
|
28
|
+
password: imodel2.FieldDefine<"string", false, false>;
|
|
29
|
+
deadline: imodel2.FieldDefine<"timestamp", false, true>;
|
|
30
|
+
updatedAt: imodel2.FieldDefine<"timestamp", false, false>;
|
|
31
31
|
}, "user.password">;
|
|
32
32
|
//#endregion
|
|
33
33
|
//#region plugins/user/common/verifyNewPassword.d.mts
|
package/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as verifyPassword, c as
|
|
1
|
+
import { a as verifyPassword, c as UserAccount_default, i as setPassword, l as verifyNewPassword, n as getPasswordHash, o as UserPassword_default, r as loadUserInfo, s as User_default, t as findUser } from "./user-ejRy16ds.mjs";
|
|
2
2
|
|
|
3
3
|
export { User_default as User, UserAccount_default as UserAccount, UserPassword_default as UserPassword, findUser, getPasswordHash, loadUserInfo, setPassword, verifyNewPassword, verifyPassword };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yongdall/user",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -12,17 +12,18 @@
|
|
|
12
12
|
"author": "",
|
|
13
13
|
"license": "ISC",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@yongdall/connection": "^0.
|
|
16
|
-
"@yongdall/context": "^0.
|
|
17
|
-
"@yongdall/model": "^0.
|
|
18
|
-
"@yongdall/core": "^0.
|
|
19
|
-
"@yongdall/http": "^0.
|
|
15
|
+
"@yongdall/connection": "^0.5.0",
|
|
16
|
+
"@yongdall/context": "^0.5.0",
|
|
17
|
+
"@yongdall/model": "^0.5.0",
|
|
18
|
+
"@yongdall/core": "^0.5.2",
|
|
19
|
+
"@yongdall/http": "^0.5.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@yongdall/
|
|
23
|
-
"@yongdall/types": "^0.
|
|
22
|
+
"@yongdall/migrate": "^0.5.0",
|
|
23
|
+
"@yongdall/types": "^0.5.0",
|
|
24
|
+
"@yongdall/web": "^0.5.0"
|
|
24
25
|
},
|
|
25
26
|
"peerDependencies": {
|
|
26
|
-
"@yongdall/web": "^0.
|
|
27
|
+
"@yongdall/web": "^0.5.0"
|
|
27
28
|
}
|
|
28
29
|
}
|
package/routers.yongdall.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as setPassword,
|
|
2
|
-
import { getUser, hasUserPermission, isSingleUser, verifyUser } from "@yongdall/core";
|
|
1
|
+
import { i as setPassword, l as verifyNewPassword } from "./user-ejRy16ds.mjs";
|
|
3
2
|
import { ApiRouter, useBody } from "@yongdall/http";
|
|
3
|
+
import { getUser, hasUserPermission, isSingleUser, verifyUser } from "@yongdall/core";
|
|
4
4
|
|
|
5
5
|
//#region plugins/user/routers.yongdall.mjs
|
|
6
6
|
const plugin = new ApiRouter();
|
|
@@ -1,7 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useSalt } from "@yongdall/core";
|
|
2
|
+
import { useConnection, useDatabase } from "@yongdall/connection";
|
|
3
3
|
import { Query, Where, createField, createModel, now, uuid } from "@yongdall/model";
|
|
4
4
|
|
|
5
|
+
//#region plugins/user/common/verifyNewPassword.mjs
|
|
6
|
+
const signTypeRegex = [
|
|
7
|
+
/[a-z]/,
|
|
8
|
+
/[A-Z]/,
|
|
9
|
+
/[0-9]/,
|
|
10
|
+
/[~!@#$%^&*()_+{}|<>?,./:";'\\\[\]-]/
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param {string} password
|
|
15
|
+
*/
|
|
16
|
+
function* verifyNewPassword(password) {
|
|
17
|
+
if (password.length < 8) yield "密码不足 8 位";
|
|
18
|
+
if (signTypeRegex.filter((r) => r.test(password)).length < 3) yield `密码至少包含小写字母、大写字母、数字、符号中的 3 种`;
|
|
19
|
+
if (password.toLowerCase().includes("admin")) yield `密码不能包含admin`;
|
|
20
|
+
if ([...password].find((a, index, list) => list[index - 1] === a && list[index + 1] === a)) yield `密码不能包含三位以上的相同的字母或数字`;
|
|
21
|
+
if ([...password].find((a, index, list) => {
|
|
22
|
+
const p = list[index - 1];
|
|
23
|
+
const n = list[index + 1];
|
|
24
|
+
if (!p || !n) return false;
|
|
25
|
+
const x = p.charCodeAt(0);
|
|
26
|
+
const y = a.charCodeAt(0);
|
|
27
|
+
const z = n.charCodeAt(0);
|
|
28
|
+
const u = x - y;
|
|
29
|
+
const v = y - z;
|
|
30
|
+
if (u === v && (v === 1 || v === -1)) return true;
|
|
31
|
+
})) yield `密码不能包含三位以上的连续的字母或数字`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
5
35
|
//#region plugins/user/models/UserAccount.mjs
|
|
6
36
|
var UserAccount_default = createModel("user.account", {
|
|
7
37
|
account: createField("string", {
|
|
@@ -112,36 +142,6 @@ var UserPassword_default = createModel("user.password", {
|
|
|
112
142
|
})
|
|
113
143
|
});
|
|
114
144
|
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region plugins/user/common/verifyNewPassword.mjs
|
|
117
|
-
const signTypeRegex = [
|
|
118
|
-
/[a-z]/,
|
|
119
|
-
/[A-Z]/,
|
|
120
|
-
/[0-9]/,
|
|
121
|
-
/[~!@#$%^&*()_+{}|<>?,./:";'\\\[\]-]/
|
|
122
|
-
];
|
|
123
|
-
/**
|
|
124
|
-
*
|
|
125
|
-
* @param {string} password
|
|
126
|
-
*/
|
|
127
|
-
function* verifyNewPassword(password) {
|
|
128
|
-
if (password.length < 8) yield "密码不足 8 位";
|
|
129
|
-
if (signTypeRegex.filter((r) => r.test(password)).length < 3) yield `密码至少包含小写字母、大写字母、数字、符号中的 3 种`;
|
|
130
|
-
if (password.toLowerCase().includes("admin")) yield `密码不能包含admin`;
|
|
131
|
-
if ([...password].find((a, index, list) => list[index - 1] === a && list[index + 1] === a)) yield `密码不能包含三位以上的相同的字母或数字`;
|
|
132
|
-
if ([...password].find((a, index, list) => {
|
|
133
|
-
const p = list[index - 1];
|
|
134
|
-
const n = list[index + 1];
|
|
135
|
-
if (!p || !n) return false;
|
|
136
|
-
const x = p.charCodeAt(0);
|
|
137
|
-
const y = a.charCodeAt(0);
|
|
138
|
-
const z = n.charCodeAt(0);
|
|
139
|
-
const u = x - y;
|
|
140
|
-
const v = y - z;
|
|
141
|
-
if (u === v && (v === 1 || v === -1)) return true;
|
|
142
|
-
})) yield `密码不能包含三位以上的连续的字母或数字`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
145
|
//#endregion
|
|
146
146
|
//#region plugins/user/index.mjs
|
|
147
147
|
const USER_INFO_KEY = "user:info";
|
|
@@ -150,8 +150,8 @@ const USER_INFO_KEY = "user:info";
|
|
|
150
150
|
* @param {string} userId
|
|
151
151
|
*/
|
|
152
152
|
async function loadUserInfo(userId) {
|
|
153
|
-
return
|
|
154
|
-
return (await
|
|
153
|
+
return useConnection("cache").memoize(USER_INFO_KEY, userId, async () => {
|
|
154
|
+
return (await useDatabase().select(new Query(User_default).where({ id: userId }).limit(1)))[0];
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
157
|
const allTypes = [
|
|
@@ -168,7 +168,7 @@ async function findUser(account, types) {
|
|
|
168
168
|
const typeSet = typeof types === "string" ? new Set(types) : new Set(types);
|
|
169
169
|
const t = typeSet.size ? allTypes.filter((v) => typeSet.has(v)) : allTypes;
|
|
170
170
|
if (!t.length) return "";
|
|
171
|
-
return (await
|
|
171
|
+
return (await useDatabase().select(new Query(UserAccount_default).where("account", account.toLowerCase()).where("type", "in", t).limit(1)))[0]?.userId || "";
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
174
|
* 使用 HMAC-SHA256 对一个或多个值进行哈希,使用 salt 作为密钥。
|
|
@@ -206,7 +206,7 @@ async function hash(salt, value, ...values) {
|
|
|
206
206
|
* @param {string} userId
|
|
207
207
|
*/
|
|
208
208
|
async function getPasswordHash(password, userId) {
|
|
209
|
-
return await hash(
|
|
209
|
+
return await hash(await useSalt(), password, userId);
|
|
210
210
|
}
|
|
211
211
|
/**
|
|
212
212
|
*
|
|
@@ -215,7 +215,7 @@ async function getPasswordHash(password, userId) {
|
|
|
215
215
|
* @returns {Promise<-2 | -1 | 1 | 2>}
|
|
216
216
|
*/
|
|
217
217
|
async function verifyPassword(userId, password) {
|
|
218
|
-
const item = await
|
|
218
|
+
const item = await useDatabase().first(new Query(UserPassword_default).select("password", "deadline").where({ userId }));
|
|
219
219
|
if (!item) return -2;
|
|
220
220
|
if (item.password !== await getPasswordHash(password, userId)) return -1;
|
|
221
221
|
if (!item.deadline) return 1;
|
|
@@ -232,7 +232,7 @@ async function verifyPassword(userId, password) {
|
|
|
232
232
|
async function setPassword(userId, password, deadline) {
|
|
233
233
|
if (!password) return false;
|
|
234
234
|
const value = await getPasswordHash(password, userId);
|
|
235
|
-
const connection =
|
|
235
|
+
const connection = useDatabase();
|
|
236
236
|
if (await connection.first(new Query(UserPassword_default).select("password").where({ userId }))) await connection.update(UserPassword_default, {
|
|
237
237
|
password: value,
|
|
238
238
|
deadline: deadline instanceof Date && deadline.valueOf() ? deadline : null
|
|
@@ -246,5 +246,5 @@ async function setPassword(userId, password, deadline) {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
//#endregion
|
|
249
|
-
export { verifyPassword as a,
|
|
250
|
-
//# sourceMappingURL=user
|
|
249
|
+
export { verifyPassword as a, UserAccount_default as c, setPassword as i, verifyNewPassword as l, getPasswordHash as n, UserPassword_default as o, loadUserInfo as r, User_default as s, findUser as t };
|
|
250
|
+
//# sourceMappingURL=user-ejRy16ds.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-ejRy16ds.mjs","names":["UserAccount","User","UserAccount","UserPassword"],"sources":["../../plugins/user/common/verifyNewPassword.mjs","../../plugins/user/models/UserAccount.mjs","../../plugins/user/models/User.mjs","../../plugins/user/models/UserPassword.mjs","../../plugins/user/index.mjs"],"sourcesContent":["const signTypeRegex = [\n\t/[a-z]/,\n\t/[A-Z]/,\n\t/[0-9]/,\n\t/[~!@#$%^&*()_+{}|<>?,./:\";'\\\\\\[\\]-]/,\n]\n/**\n * \n * @param {string} password \n */\nexport function* verifyNewPassword(password) {\n\tif (password.length < 8) { yield '密码不足 8 位'; }\n\t\n\tif (signTypeRegex.filter(r => r.test(password)).length < 3) {\n\t\tyield `密码至少包含小写字母、大写字母、数字、符号中的 3 种`;\n\t}\n\tif (password.toLowerCase().includes('admin')) {\n\t\tyield `密码不能包含admin`;\n\t}\n\tif ([...password].find((a,index, list) => list[index - 1] === a && list[index + 1] === a)) {\n\t\tyield `密码不能包含三位以上的相同的字母或数字`;\n\t}\n\tif ([...password].find((a,index, list) => {\n\t\tconst p = list[index - 1];\n\t\tconst n = list[index + 1];\n\t\tif (!p || !n) { return false; }\n\t\tconst x = p.charCodeAt(0);\n\t\tconst y = a.charCodeAt(0);\n\t\tconst z = n.charCodeAt(0);\n\t\tconst u = x - y;\n\t\tconst v = y - z;\n\t\tif (u === v && (v === 1 || v === -1)) { return true}\n\t})) {\n\t\tyield `密码不能包含三位以上的连续的字母或数字`;\n\t}\n}\n","import { createModel, createField, now } from '@yongdall/model';\n\n\nexport default createModel('user.account', {\n\taccount: createField('string', { nullable: false, label: '帐号', unique: true }),\n\tuserId: createField('uuid', { nullable: false, label: '用户', primary: 1 }),\n\ttype: createField('string', { nullable: false, default: '', primary: 2, label: '类型' }),\n});\n","import { createField, createModel, now, uuid } from '@yongdall/model';\nimport UserAccount from './UserAccount.mjs';\n\nexport default createModel('user', {\n\tusername: createField(UserAccount, { label: '登陆账号', constraints: {userId: {field: 'id'}, type: {value: 'username'}}}),\n\tid: createField('uuid', { nullable: false, default: uuid, uncreatable: true, primary: 1 }),\n\tname: createField('string', { nullable: false, default: '', label: '名称', layout: { colSpan: 6, head: 2 } }),\n\tenabled: createField('bool', { nullable: false, default: true, label: '是否启用帐号' }),\n\tcreatedAt: createField('timestamp', { nullable: false, creating: now, label: '创建日期' }),\n\tupdatedAt: createField('timestamp', { nullable: false, creating: now, updating: now, label: '最后更新日期' }),\n}, {\n\tlabel: '用户',\n\tlabelField: 'name',\n\n\tpermissions: [\n\t\t{ permission: 'system:user', fields: '*', authorizations: ['options', 'query', 'read', 'create', 'update', 'destroy', 'add', 'remove'] },\n\t],\n\tscripts: ['@yongdall/user#models.user'],\n});\n","import { createField, createModel, now } from '@yongdall/model';\n\n\nexport default createModel('user.password', {\n\tuserId: createField('uuid', { nullable: false, label: '用户', primary: 1 }),\n\tpassword: createField('string', { nullable: false, default: '', label: '新密码', renderer: 'password', layout: {colSpan: 6} }),\n\tdeadline: createField('timestamp', { nullable: true, label: '有效期', layout: {colSpan: 6} }),\n\tupdatedAt: createField('timestamp', { nullable: false, creating: now, updating: now, label: '最后更新日期', layout: {colSpan: 6} }),\n})\n","import { useConnection, useDatabase } from '@yongdall/connection';\nimport { Query, Where } from '@yongdall/model';\nimport { useSalt } from '@yongdall/core';\nimport { User, UserAccount, UserPassword } from './models/index.mjs';\n\nexport * from './models/index.mjs';\nexport { verifyNewPassword } from './common/verifyNewPassword.mjs';\n\nconst USER_INFO_KEY = 'user:info';\n\n/**\n * \n * @param {string} userId \n */\nexport async function loadUserInfo(userId) {\n\n\treturn useConnection('cache').memoize(USER_INFO_KEY, userId, async () => {\n\t\tconst rdb = useDatabase();\n\t\tconst info = await rdb.select(new Query(User).where({ id: userId }).limit(1));\n\t\treturn info[0];\n\t});\n}\n\nconst allTypes = ['username', 'phone', 'email'];\n\n/**\n * \n * @param {string} account \n * @param {string | string[] | Set<string> | null} [types] \n */\nexport async function findUser(account, types) {\n\tconst typeSet = typeof types === 'string' ? new Set(types) : new Set(types);\n\tconst t = typeSet.size ? allTypes.filter(v => typeSet.has(v)) : allTypes;\n\tif (!t.length) { return ''; }\n\tconst rdb = useDatabase();\n\tconst info = await rdb.select(\n\t\tnew Query(UserAccount)\n\t\t\t.where('account', account.toLowerCase())\n\t\t\t.where('type', 'in', t)\n\t\t\t.limit(1),\n\t);\n\treturn info[0]?.userId || '';\n}\n/**\n * 使用 HMAC-SHA256 对一个或多个值进行哈希,使用 salt 作为密钥。\n * 输出为 base64url 格式。\n *\n * @param {string | ArrayBuffer | ArrayBufferView<ArrayBuffer>} salt\n * @param {string | number} value\n * @param {...(string | number)} values\n * @returns {Promise<string>}\n */\nasync function hash(salt, value, ...values) {\n\t// 1. 准备密钥(salt)\n\t/** @type {ArrayBuffer | ArrayBufferView<ArrayBuffer>} */\n\tlet keyBuffer;\n\tif (salt instanceof ArrayBuffer || ArrayBuffer.isView(salt)) {\n\t\tkeyBuffer = salt;\n\t} else if (typeof salt === 'string') {\n\t\tkeyBuffer = new TextEncoder().encode(salt);\n\t} else {\n\t\tthrow new Error('`salt` 参数必须为字符串或 Uint8Array');\n\t}\n\n\t// 2. 导入 HMAC 密钥\n\tconst cryptoKey = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tkeyBuffer,\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign']\n\t);\n\n\t// 3. 构造输入数据\n\t/** @type {string[]} */\n\tlet data = [];\n\n\t// 处理第一个 value\n\tif (typeof value === 'number') {\n\t\tdata.push(String(value));\n\t} else if (typeof value === 'string') {\n\t\t// JSON.stringify(value).slice(1, -1) 相当于去掉引号,等价于直接编码字符串内容\n\t\tdata.push(JSON.stringify(value).slice(1, -1));\n\t} else {\n\t\tthrow new Error('`value` 参数必须为字符串或数字');\n\t}\n\n\t// 处理后续 values\n\tfor (const v of values) {\n\t\tif (typeof v === 'number') {\n\t\t\tdata.push(String(v));\n\t\t} else if (typeof v === 'string') {\n\t\t\tdata.push(JSON.stringify(v).slice(1, -1));\n\t\t}\n\t}\n\n\t// 合并所有数据\n\tconst messageBuffer = new TextEncoder().encode(data.join('\\n'));\n\n\t// 4. 生成 HMAC\n\tconst signature = await crypto.subtle.sign('HMAC', cryptoKey, messageBuffer);\n\n\t// 5. 转为 base64url 格式\n\tconst base64 = btoa(String.fromCharCode(...new Uint8Array(signature)));\n\treturn base64\n\t\t.replace(/\\+/g, '-')\n\t\t.replace(/\\//g, '_')\n\t\t.replace(/=+$/, ''); // 移除填充\n}\n/**\n * \n * @param {string} password \n * @param {string} userId \n */\nexport async function getPasswordHash(password, userId) {\n\tconst salt = await useSalt();\n\treturn await hash(salt, password, userId);\n\n}\n/**\n * \n * @param {string} userId \n * @param {string} password \n * @returns {Promise<-2 | -1 | 1 | 2>}\n */\nexport async function verifyPassword(userId, password) {\n\tconst item = await useDatabase().first(\n\t\tnew Query(UserPassword)\n\t\t\t.select('password', 'deadline')\n\t\t\t.where({ userId })\n\t);\n\tif (!item) { return -2; }\n\tif (item.password !== await getPasswordHash(password, userId)) { return -1; }\n\tif (!item.deadline) { return 1; }\n\tif (Number(item.deadline) < Date.now()) { return 2; }\n\treturn 1;\n}\n/**\n * \n * @param {string} userId \n * @param {string?} password \n * @param {Date?} [deadline] \n * @returns {Promise<boolean>}\n */\n\nexport async function setPassword(userId, password, deadline) {\n\tif (!password) { return false; }\n\tconst value = await getPasswordHash(password, userId);\n\n\n\tconst connection = useDatabase();\n\tconst item = await connection.first(\n\t\tnew Query(UserPassword)\n\t\t\t.select('password')\n\t\t\t.where({ userId })\n\t);\n\tif (item) {\n\t\tawait connection.update(UserPassword, {\n\t\t\tpassword: value,\n\t\t\tdeadline: deadline instanceof Date && deadline.valueOf() ? deadline : null,\n\t\t}, Where.and('userId', userId));\n\t} else {\n\t\tawait connection.create(UserPassword, {\n\t\t\tuserId,\n\t\t\tpassword: value,\n\t\t\tdeadline: deadline instanceof Date && deadline.valueOf() ? deadline : null,\n\t\t});\n\n\t}\n\treturn true;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region plugins/user/yongdall/enumeration.mjs
|
|
2
|
+
const page = [{
|
|
3
|
+
page: "@yongdall/user#password",
|
|
4
|
+
label: "修改用户密码",
|
|
5
|
+
type: "configuration",
|
|
6
|
+
applicationPage: "configuration"
|
|
7
|
+
}];
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { page };
|
|
11
|
+
//# sourceMappingURL=enumeration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enumeration.mjs","names":[],"sources":["../../../plugins/user/yongdall/enumeration.mjs"],"sourcesContent":["export const page = [\n\t{ page: '@yongdall/user#password', label: '修改用户密码', type: 'configuration', applicationPage: 'configuration' },\n];\n"],"mappings":";AAAA,MAAa,OAAO,CACnB;CAAE,MAAM;CAA2B,OAAO;CAAU,MAAM;CAAiB,iBAAiB;CAAiB,CAC7G"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { c as UserAccount_default, o as UserPassword_default, s as User_default } from "../user-ejRy16ds.mjs";
|
|
2
|
+
|
|
3
|
+
//#region plugins/user/yongdall/migration.mjs
|
|
4
|
+
/** @import { Profile } from '@yongdall/migrate' */
|
|
5
|
+
/** @type {Profile['models']} */
|
|
6
|
+
const models = [
|
|
7
|
+
User_default,
|
|
8
|
+
UserAccount_default,
|
|
9
|
+
UserPassword_default
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { models };
|
|
14
|
+
//# sourceMappingURL=migration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.mjs","names":["User","UserAccount","UserPassword"],"sources":["../../../plugins/user/yongdall/migration.mjs"],"sourcesContent":["/** @import { Profile } from '@yongdall/migrate' */\nimport { User, UserAccount, UserPassword } from '../index.mjs';\n\n\n/** @type {Profile['models']} */\nexport const models = [\n\tUser,\n\tUserAccount,\n\tUserPassword,\n];\n"],"mappings":";;;;;AAKA,MAAa,SAAS;CACrBA;CACAC;CACAC;CACA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { s as User_default } from "../user-ejRy16ds.mjs";
|
|
2
|
+
|
|
3
|
+
//#region plugins/user/yongdall/model.mjs
|
|
4
|
+
/** @import { ModelProfile } from '@yongdall/core' */
|
|
5
|
+
/** @type {ModelProfile['models']} */
|
|
6
|
+
const models = { user: User_default };
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { models };
|
|
10
|
+
//# sourceMappingURL=model.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.mjs","names":["User"],"sources":["../../../plugins/user/yongdall/model.mjs"],"sourcesContent":["/** @import { ModelProfile } from '@yongdall/core' */\nimport { User, loadUserInfo, findUser, verifyPassword, setPassword } from '../index.mjs';\n\n/** @type {ModelProfile['models']} */\nexport const models = {\n\tuser: User,\n};\n"],"mappings":";;;;;AAIA,MAAa,SAAS,EACrB,MAAMA,cACN"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { a as verifyPassword, i as setPassword, r as loadUserInfo, t as findUser } from "../user-ejRy16ds.mjs";
|
|
2
|
+
|
|
3
|
+
//#region plugins/user/yongdall/user.mjs
|
|
4
|
+
/** @import { UserManager } from '@yongdall/core' */
|
|
5
|
+
/** @type {UserManager['find']} */
|
|
6
|
+
const find = (account, types) => {
|
|
7
|
+
if (typeof account !== "string") return "";
|
|
8
|
+
return findUser(account, types);
|
|
9
|
+
};
|
|
10
|
+
/** @type {UserManager['verify']} */
|
|
11
|
+
const verify = { password(userId, password) {
|
|
12
|
+
return verifyPassword(userId, password);
|
|
13
|
+
} };
|
|
14
|
+
/** @type {UserManager['setVerify']} */
|
|
15
|
+
const setVerify = { password(userId, password, deadline) {
|
|
16
|
+
return setPassword(userId, password, deadline);
|
|
17
|
+
} };
|
|
18
|
+
/** @type {UserManager['load']} */
|
|
19
|
+
const load = async (userId) => {
|
|
20
|
+
return await loadUserInfo(userId) || {};
|
|
21
|
+
};
|
|
22
|
+
/** @type {UserManager['exist']} */
|
|
23
|
+
const exist = async (userId, login) => {
|
|
24
|
+
return Boolean(await loadUserInfo(userId).then((u) => login ? u?.enabled : u));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { exist, find, load, setVerify, verify };
|
|
29
|
+
//# sourceMappingURL=user.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.mjs","names":[],"sources":["../../../plugins/user/yongdall/user.mjs"],"sourcesContent":["/** @import { UserManager } from '@yongdall/core' */\nimport { loadUserInfo, findUser, verifyPassword, setPassword } from '../index.mjs';\n\n/** @type {UserManager['find']} */\nexport const find = (account, types) => {\n\tif (typeof account !== 'string') { return ''; }\n\treturn findUser(account, types);\n};\n/** @type {UserManager['verify']} */\nexport const verify = {\n\tpassword(userId, password) {\n\t\treturn verifyPassword(userId, password);\n\t}\n};\n/** @type {UserManager['setVerify']} */\nexport const setVerify = {\n\tpassword(userId, password, deadline) {\n\t\treturn setPassword(userId, password, deadline);\n\t}\n};\n/** @type {UserManager['load']} */\nexport const load = async (userId) => {\n\treturn await loadUserInfo(userId) || {};\n};\n/** @type {UserManager['exist']} */\nexport const exist = async (userId, login) => {\n\treturn Boolean(await loadUserInfo(userId).then(u => login ? u?.enabled : u));\n};\n"],"mappings":";;;;;AAIA,MAAa,QAAQ,SAAS,UAAU;AACvC,KAAI,OAAO,YAAY,SAAY,QAAO;AAC1C,QAAO,SAAS,SAAS,MAAM;;;AAGhC,MAAa,SAAS,EACrB,SAAS,QAAQ,UAAU;AAC1B,QAAO,eAAe,QAAQ,SAAS;GAExC;;AAED,MAAa,YAAY,EACxB,SAAS,QAAQ,UAAU,UAAU;AACpC,QAAO,YAAY,QAAQ,UAAU,SAAS;GAE/C;;AAED,MAAa,OAAO,OAAO,WAAW;AACrC,QAAO,MAAM,aAAa,OAAO,IAAI,EAAE;;;AAGxC,MAAa,QAAQ,OAAO,QAAQ,UAAU;AAC7C,QAAO,QAAQ,MAAM,aAAa,OAAO,CAAC,MAAK,MAAK,QAAQ,GAAG,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
label: 基础用户管理
|
package/hooks.yongdall.mjs
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { a as verifyPassword, c as User_default, i as setPassword, l as UserAccount_default, r as loadUserInfo, s as UserPassword_default, t as findUser } from "./user--pUQPO_O.mjs";
|
|
2
|
-
import { getUser } from "@yongdall/core";
|
|
3
|
-
|
|
4
|
-
//#region plugins/user/hooks.yongdall.mjs
|
|
5
|
-
/** @type {Hooks.Define['models']} */
|
|
6
|
-
const models = { user: User_default };
|
|
7
|
-
/** @type {Hooks.Define['migrationModels']} */
|
|
8
|
-
const migrationModels = [
|
|
9
|
-
User_default,
|
|
10
|
-
UserAccount_default,
|
|
11
|
-
UserPassword_default
|
|
12
|
-
];
|
|
13
|
-
/** @type {Partial<Hooks['userManager']>} */
|
|
14
|
-
const userManager = {
|
|
15
|
-
find(account, types) {
|
|
16
|
-
if (typeof account !== "string") return "";
|
|
17
|
-
return findUser(account, types);
|
|
18
|
-
},
|
|
19
|
-
verify: { password(userId, password) {
|
|
20
|
-
return verifyPassword(userId, password);
|
|
21
|
-
} },
|
|
22
|
-
setVerify: { password(userId, password, deadline) {
|
|
23
|
-
return setPassword(userId, password, deadline);
|
|
24
|
-
} },
|
|
25
|
-
async load(userId) {
|
|
26
|
-
return await loadUserInfo(userId) || {};
|
|
27
|
-
},
|
|
28
|
-
async exist(userId, login) {
|
|
29
|
-
return Boolean(await loadUserInfo(userId).then((u) => login ? u?.enabled : u));
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const enumerations = { page: [{
|
|
33
|
-
page: "@yongdall/user#password",
|
|
34
|
-
label: "修改用户密码",
|
|
35
|
-
type: "configuration",
|
|
36
|
-
applicationPage: "configuration"
|
|
37
|
-
}] };
|
|
38
|
-
|
|
39
|
-
//#endregion
|
|
40
|
-
export { enumerations, migrationModels, models, userManager };
|
|
41
|
-
//# sourceMappingURL=hooks.yongdall.mjs.map
|
package/hooks.yongdall.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.yongdall.mjs","names":["User","UserAccount","UserPassword"],"sources":["../../plugins/user/hooks.yongdall.mjs"],"sourcesContent":["/** @import { Hooks } from '@yongdall/core' */\nimport { getUser } from '@yongdall/core';\nimport { User, UserAccount, UserPassword, loadUserInfo, findUser, verifyPassword, getPasswordHash, setPassword } from './index.mjs';\n\n/** @type {Hooks.Define['models']} */\nexport const models = {\n\tuser: User,\n};\n\n/** @type {Hooks.Define['migrationModels']} */\nexport const migrationModels = [\n\tUser,\n\tUserAccount,\n\tUserPassword,\n];\n\n/** @type {Partial<Hooks['userManager']>} */\nexport const userManager = {\n\tfind(account, types) {\n\t\tif (typeof account !== 'string') { return ''; }\n\t\treturn findUser(account, types);\n\t},\n\tverify: {\n\t\tpassword(userId, password) {\n\t\t\treturn verifyPassword(userId, password);\n\t\t}\n\t},\n\tsetVerify: {\n\t\tpassword(userId, password, deadline) {\n\t\t\treturn setPassword(userId, password, deadline);\n\t\t}\n\n\t},\n\tasync load(userId) {\n\t\treturn await loadUserInfo(userId) || {};\n\t},\n\tasync exist(userId, login) {\n\t\treturn Boolean(await loadUserInfo(userId).then(u => login ? u?.enabled : u));\n\t}\n};\n\nexport const enumerations = {\n\tpage: [\n\t\t{ page: '@yongdall/user#password', label: '修改用户密码', type: 'configuration', applicationPage: 'configuration' },\n\t]\n};\n"],"mappings":";;;;;AAKA,MAAa,SAAS,EACrB,MAAMA,cACN;;AAGD,MAAa,kBAAkB;CAC9BA;CACAC;CACAC;CACA;;AAGD,MAAa,cAAc;CAC1B,KAAK,SAAS,OAAO;AACpB,MAAI,OAAO,YAAY,SAAY,QAAO;AAC1C,SAAO,SAAS,SAAS,MAAM;;CAEhC,QAAQ,EACP,SAAS,QAAQ,UAAU;AAC1B,SAAO,eAAe,QAAQ,SAAS;IAExC;CACD,WAAW,EACV,SAAS,QAAQ,UAAU,UAAU;AACpC,SAAO,YAAY,QAAQ,UAAU,SAAS;IAG/C;CACD,MAAM,KAAK,QAAQ;AAClB,SAAO,MAAM,aAAa,OAAO,IAAI,EAAE;;CAExC,MAAM,MAAM,QAAQ,OAAO;AAC1B,SAAO,QAAQ,MAAM,aAAa,OAAO,CAAC,MAAK,MAAK,QAAQ,GAAG,UAAU,EAAE,CAAC;;CAE7E;AAED,MAAa,eAAe,EAC3B,MAAM,CACL;CAAE,MAAM;CAA2B,OAAO;CAAU,MAAM;CAAiB,iBAAiB;CAAiB,CAC7G,EACD"}
|
package/user--pUQPO_O.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user--pUQPO_O.mjs","names":["UserAccount","User","UserAccount","UserPassword"],"sources":["../../plugins/user/models/UserAccount.mjs","../../plugins/user/models/User.mjs","../../plugins/user/models/UserPassword.mjs","../../plugins/user/common/verifyNewPassword.mjs","../../plugins/user/index.mjs"],"sourcesContent":["import { createModel, createField, now } from '@yongdall/model';\n\n\nexport default createModel('user.account', {\n\taccount: createField('string', { nullable: false, label: '帐号', unique: true }),\n\tuserId: createField('uuid', { nullable: false, label: '用户', primary: 1 }),\n\ttype: createField('string', { nullable: false, default: '', primary: 2, label: '类型' }),\n});\n","import { createField, createModel, now, uuid } from '@yongdall/model';\nimport UserAccount from './UserAccount.mjs';\n\nexport default createModel('user', {\n\tusername: createField(UserAccount, { label: '登陆账号', constraints: {userId: {field: 'id'}, type: {value: 'username'}}}),\n\tid: createField('uuid', { nullable: false, default: uuid, uncreatable: true, primary: 1 }),\n\tname: createField('string', { nullable: false, default: '', label: '名称', layout: { colSpan: 6, head: 2 } }),\n\tenabled: createField('bool', { nullable: false, default: true, label: '是否启用帐号' }),\n\tcreatedAt: createField('timestamp', { nullable: false, creating: now, label: '创建日期' }),\n\tupdatedAt: createField('timestamp', { nullable: false, creating: now, updating: now, label: '最后更新日期' }),\n}, {\n\tlabel: '用户',\n\tlabelField: 'name',\n\n\tpermissions: [\n\t\t{ permission: 'system:user', fields: '*', authorizations: ['options', 'query', 'read', 'create', 'update', 'destroy', 'add', 'remove'] },\n\t],\n\tscripts: ['@yongdall/user#models.user'],\n});\n","import { createField, createModel, now } from '@yongdall/model';\n\n\nexport default createModel('user.password', {\n\tuserId: createField('uuid', { nullable: false, label: '用户', primary: 1 }),\n\tpassword: createField('string', { nullable: false, default: '', label: '新密码', renderer: 'password', layout: {colSpan: 6} }),\n\tdeadline: createField('timestamp', { nullable: true, label: '有效期', layout: {colSpan: 6} }),\n\tupdatedAt: createField('timestamp', { nullable: false, creating: now, updating: now, label: '最后更新日期', layout: {colSpan: 6} }),\n})\n","const signTypeRegex = [\n\t/[a-z]/,\n\t/[A-Z]/,\n\t/[0-9]/,\n\t/[~!@#$%^&*()_+{}|<>?,./:\";'\\\\\\[\\]-]/,\n]\n/**\n * \n * @param {string} password \n */\nexport function* verifyNewPassword(password) {\n\tif (password.length < 8) { yield '密码不足 8 位'; }\n\t\n\tif (signTypeRegex.filter(r => r.test(password)).length < 3) {\n\t\tyield `密码至少包含小写字母、大写字母、数字、符号中的 3 种`;\n\t}\n\tif (password.toLowerCase().includes('admin')) {\n\t\tyield `密码不能包含admin`;\n\t}\n\tif ([...password].find((a,index, list) => list[index - 1] === a && list[index + 1] === a)) {\n\t\tyield `密码不能包含三位以上的相同的字母或数字`;\n\t}\n\tif ([...password].find((a,index, list) => {\n\t\tconst p = list[index - 1];\n\t\tconst n = list[index + 1];\n\t\tif (!p || !n) { return false; }\n\t\tconst x = p.charCodeAt(0);\n\t\tconst y = a.charCodeAt(0);\n\t\tconst z = n.charCodeAt(0);\n\t\tconst u = x - y;\n\t\tconst v = y - z;\n\t\tif (u === v && (v === 1 || v === -1)) { return true}\n\t})) {\n\t\tyield `密码不能包含三位以上的连续的字母或数字`;\n\t}\n}\n","import { connect } from '@yongdall/connection';\nimport { Query, Where } from '@yongdall/model';\nimport { useTenant } from '@yongdall/core';\nimport { User, UserAccount, UserPassword } from './models/index.mjs';\n\nexport * from './models/index.mjs';\nexport { verifyNewPassword } from './common/verifyNewPassword.mjs'\n\nconst USER_INFO_KEY = 'user:info';\n\n/**\n * \n * @param {string} userId \n */\nexport async function loadUserInfo(userId) {\n\n\treturn connect('cache').memoize(USER_INFO_KEY, userId, async () => {\n\t\tconst rdb = connect('rdb');\n\t\tconst info = await rdb.select(new Query(User).where({ id: userId }).limit(1));\n\t\treturn info[0];\n\t});\n}\n\nconst allTypes = ['username', 'phone', 'email'];\n\n/**\n * \n * @param {string} account \n * @param {string | string[] | Set<string> | null} [types] \n */\nexport async function findUser(account, types){\n\tconst typeSet = typeof types === 'string' ? new Set(types) : new Set(types);\n\tconst t = typeSet.size ? allTypes.filter(v => typeSet.has(v)) : allTypes;\n\tif (!t.length) { return ''; }\n\tconst rdb = connect('rdb');\n\tconst info = await rdb.select(\n\t\tnew Query(UserAccount)\n\t\t\t.where('account', account.toLowerCase())\n\t\t\t.where('type', 'in', t)\n\t\t\t.limit(1),\n\t);\n\treturn info[0]?.userId || '';\n}\n/**\n * 使用 HMAC-SHA256 对一个或多个值进行哈希,使用 salt 作为密钥。\n * 输出为 base64url 格式。\n *\n * @param {string | ArrayBuffer | ArrayBufferView<ArrayBuffer>} salt\n * @param {string | number} value\n * @param {...(string | number)} values\n * @returns {Promise<string>}\n */\nasync function hash(salt, value, ...values) {\n\t// 1. 准备密钥(salt)\n\t/** @type {ArrayBuffer | ArrayBufferView<ArrayBuffer>} */\n\tlet keyBuffer;\n\tif (salt instanceof ArrayBuffer || ArrayBuffer.isView(salt)) {\n\t\tkeyBuffer = salt;\n\t} else if (typeof salt === 'string') {\n\t\tkeyBuffer = new TextEncoder().encode(salt);\n\t} else {\n\t\tthrow new Error('`salt` 参数必须为字符串或 Uint8Array');\n\t}\n\n\t// 2. 导入 HMAC 密钥\n\tconst cryptoKey = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tkeyBuffer,\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign']\n\t);\n\n\t// 3. 构造输入数据\n\t/** @type {string[]} */\n\tlet data = [];\n\n\t// 处理第一个 value\n\tif (typeof value === 'number') {\n\t\tdata.push(String(value));\n\t} else if (typeof value === 'string') {\n\t\t// JSON.stringify(value).slice(1, -1) 相当于去掉引号,等价于直接编码字符串内容\n\t\tdata.push(JSON.stringify(value).slice(1, -1));\n\t} else {\n\t\tthrow new Error('`value` 参数必须为字符串或数字');\n\t}\n\n\t// 处理后续 values\n\tfor (const v of values) {\n\t\tif (typeof v === 'number') {\n\t\t\tdata.push(String(v));\n\t\t} else if (typeof v === 'string') {\n\t\t\tdata.push(JSON.stringify(v).slice(1, -1));\n\t\t}\n\t}\n\n\t// 合并所有数据\n\tconst messageBuffer = new TextEncoder().encode(data.join('\\n'))\n\n\t// 4. 生成 HMAC\n\tconst signature = await crypto.subtle.sign('HMAC', cryptoKey, messageBuffer);\n\n\t// 5. 转为 base64url 格式\n\tconst base64 = btoa(String.fromCharCode(...new Uint8Array(signature)));\n\treturn base64\n\t\t.replace(/\\+/g, '-')\n\t\t.replace(/\\//g, '_')\n\t\t.replace(/=+$/, ''); // 移除填充\n}\n/**\n * \n * @param {string} password \n * @param {string} userId \n */\nexport async function getPasswordHash(password, userId) {\n\tconst tenant = await useTenant();\n\treturn await hash(tenant.salt, password, userId)\n\n}\n/**\n * \n * @param {string} userId \n * @param {string} password \n * @returns {Promise<-2 | -1 | 1 | 2>}\n */\nexport async function verifyPassword(userId, password) {\n\tconst item = await connect('rdb').first(\n\t\tnew Query(UserPassword)\n\t\t.select('password', 'deadline')\n\t\t.where({ userId })\n\t);\n\tif (!item) { return -2; }\n\tif (item.password !== await getPasswordHash(password, userId)) { return -1; }\n\tif (!item.deadline) { return 1; }\n\tif (Number(item.deadline) < Date.now()) { return 2; }\n\treturn 1;\n}\n/**\n * \n * @param {string} userId \n * @param {string?} password \n * @param {Date?} [deadline] \n * @returns {Promise<boolean>}\n */\n\nexport async function setPassword(userId, password, deadline) {\n\tif (!password) { return false; }\n\tconst value = await getPasswordHash(password, userId);\n\t\n\n\tconst connection = connect('rdb');\n\tconst item = await connection.first(\n\t\tnew Query(UserPassword)\n\t\t.select('password')\n\t\t.where({ userId })\n\t);\n\tif (item) {\n\t\tawait connection.update(UserPassword, {\n\t\t\tpassword: value,\n\t\t\tdeadline: deadline instanceof Date && deadline.valueOf() ? deadline : null,\n\t\t}, Where.and('userId', userId));\n\t} else {\n\t\tawait connection.create(UserPassword, {\n\t\t\tuserId,\n\t\t\tpassword: value,\n\t\t\tdeadline: deadline instanceof Date && deadline.valueOf() ? deadline : null,\n\t\t});\n\n\t}\n\treturn true;\n\t\n}\n"],"mappings":"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"}
|