@ruiapp/rapid-core 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +188 -31
- package/dist/plugins/auth/AuthPlugin.d.ts +2 -0
- package/dist/plugins/auth/actionHandlers/createSession.d.ts +0 -4
- package/dist/plugins/auth/services/AuthService.d.ts +15 -0
- package/package.json +1 -1
- package/src/core/request.ts +30 -21
- package/src/index.ts +2 -0
- package/src/plugins/auth/AuthPlugin.ts +8 -0
- package/src/plugins/auth/actionHandlers/createSession.ts +7 -17
- package/src/plugins/auth/services/AuthService.ts +39 -0
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from "./core/server";
|
|
|
6
6
|
export * from "./core/http-types";
|
|
7
7
|
export * from "./core/actionHandler";
|
|
8
8
|
export * from "./utilities/jwtUtility";
|
|
9
|
+
export * from "./deno-std/http/cookie";
|
|
9
10
|
export { mapDbRowToEntity } from "./dataAccess/entityMapper";
|
|
10
11
|
export * as bootstrapApplicationConfig from "./bootstrapApplicationConfig";
|
|
11
12
|
export { default as MetaManagePlugin } from "./plugins/metaManage/MetaManagePlugin";
|
package/dist/index.js
CHANGED
|
@@ -1402,6 +1402,130 @@ function setCookie(headers, cookie) {
|
|
|
1402
1402
|
if (v) {
|
|
1403
1403
|
headers.append("Set-Cookie", v);
|
|
1404
1404
|
}
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Set the cookie header with empty value in the headers to delete it
|
|
1408
|
+
*
|
|
1409
|
+
* > Note: Deleting a `Cookie` will set its expiration date before now. Forcing
|
|
1410
|
+
* > the browser to delete it.
|
|
1411
|
+
*
|
|
1412
|
+
* @example
|
|
1413
|
+
* ```ts
|
|
1414
|
+
* import { deleteCookie } from "https://deno.land/std@$STD_VERSION/http/cookie.ts";
|
|
1415
|
+
*
|
|
1416
|
+
* const headers = new Headers();
|
|
1417
|
+
* deleteCookie(headers, "deno");
|
|
1418
|
+
*
|
|
1419
|
+
* const cookieHeader = headers.get("set-cookie");
|
|
1420
|
+
* console.log(cookieHeader); // deno=; Expires=Thus, 01 Jan 1970 00:00:00 GMT
|
|
1421
|
+
* ```
|
|
1422
|
+
*
|
|
1423
|
+
* @param headers The headers instance to delete the cookie from
|
|
1424
|
+
* @param name Name of cookie
|
|
1425
|
+
* @param attributes Additional cookie attributes
|
|
1426
|
+
*/
|
|
1427
|
+
function deleteCookie(headers, name, attributes) {
|
|
1428
|
+
setCookie(headers, {
|
|
1429
|
+
name: name,
|
|
1430
|
+
value: "",
|
|
1431
|
+
expires: new Date(0),
|
|
1432
|
+
...attributes,
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
function parseSetCookie(value) {
|
|
1436
|
+
const attrs = value.split(";").map((attr) => {
|
|
1437
|
+
const [key, ...values] = attr.trim().split("=");
|
|
1438
|
+
return [key, values.join("=")];
|
|
1439
|
+
});
|
|
1440
|
+
const cookie = {
|
|
1441
|
+
name: attrs[0][0],
|
|
1442
|
+
value: attrs[0][1],
|
|
1443
|
+
};
|
|
1444
|
+
for (const [key, value] of attrs.slice(1)) {
|
|
1445
|
+
switch (key.toLocaleLowerCase()) {
|
|
1446
|
+
case "expires":
|
|
1447
|
+
cookie.expires = new Date(value);
|
|
1448
|
+
break;
|
|
1449
|
+
case "max-age":
|
|
1450
|
+
cookie.maxAge = Number(value);
|
|
1451
|
+
if (cookie.maxAge < 0) {
|
|
1452
|
+
console.warn("Max-Age must be an integer superior or equal to 0. Cookie ignored.");
|
|
1453
|
+
return null;
|
|
1454
|
+
}
|
|
1455
|
+
break;
|
|
1456
|
+
case "domain":
|
|
1457
|
+
cookie.domain = value;
|
|
1458
|
+
break;
|
|
1459
|
+
case "path":
|
|
1460
|
+
cookie.path = value;
|
|
1461
|
+
break;
|
|
1462
|
+
case "secure":
|
|
1463
|
+
cookie.secure = true;
|
|
1464
|
+
break;
|
|
1465
|
+
case "httponly":
|
|
1466
|
+
cookie.httpOnly = true;
|
|
1467
|
+
break;
|
|
1468
|
+
case "samesite":
|
|
1469
|
+
cookie.sameSite = value;
|
|
1470
|
+
break;
|
|
1471
|
+
default:
|
|
1472
|
+
if (!Array.isArray(cookie.unparsed)) {
|
|
1473
|
+
cookie.unparsed = [];
|
|
1474
|
+
}
|
|
1475
|
+
cookie.unparsed.push([key, value].join("="));
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
if (cookie.name.startsWith("__Secure-")) {
|
|
1479
|
+
/** This requirement is mentioned in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie but not the RFC. */
|
|
1480
|
+
if (!cookie.secure) {
|
|
1481
|
+
console.warn("Cookies with names starting with `__Secure-` must be set with the secure flag. Cookie ignored.");
|
|
1482
|
+
return null;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
if (cookie.name.startsWith("__Host-")) {
|
|
1486
|
+
if (!cookie.secure) {
|
|
1487
|
+
console.warn("Cookies with names starting with `__Host-` must be set with the secure flag. Cookie ignored.");
|
|
1488
|
+
return null;
|
|
1489
|
+
}
|
|
1490
|
+
if (cookie.domain !== undefined) {
|
|
1491
|
+
console.warn("Cookies with names starting with `__Host-` must not have a domain specified. Cookie ignored.");
|
|
1492
|
+
return null;
|
|
1493
|
+
}
|
|
1494
|
+
if (cookie.path !== "/") {
|
|
1495
|
+
console.warn("Cookies with names starting with `__Host-` must have path be `/`. Cookie has been ignored.");
|
|
1496
|
+
return null;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
return cookie;
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Parse set-cookies of a header
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* ```ts
|
|
1506
|
+
* import { getSetCookies } from "https://deno.land/std@$STD_VERSION/http/cookie.ts";
|
|
1507
|
+
*
|
|
1508
|
+
* const headers = new Headers([
|
|
1509
|
+
* ["Set-Cookie", "lulu=meow; Secure; Max-Age=3600"],
|
|
1510
|
+
* ["Set-Cookie", "booya=kasha; HttpOnly; Path=/"],
|
|
1511
|
+
* ]);
|
|
1512
|
+
*
|
|
1513
|
+
* const cookies = getSetCookies(headers);
|
|
1514
|
+
* console.log(cookies); // [{ name: "lulu", value: "meow", secure: true, maxAge: 3600 }, { name: "booya", value: "kahsa", httpOnly: true, path: "/ }]
|
|
1515
|
+
* ```
|
|
1516
|
+
*
|
|
1517
|
+
* @param headers The headers instance to get set-cookies from
|
|
1518
|
+
* @return List of cookies
|
|
1519
|
+
*/
|
|
1520
|
+
function getSetCookies(headers) {
|
|
1521
|
+
// TODO(lino-levan): remove this ts-ignore when Typescript 5.2 lands in Deno
|
|
1522
|
+
// @ts-ignore Typescript's TS Dom types will be out of date until 5.2
|
|
1523
|
+
return headers
|
|
1524
|
+
.getSetCookie()
|
|
1525
|
+
/** Parse each `set-cookie` header separately */
|
|
1526
|
+
.map(parseSetCookie)
|
|
1527
|
+
/** Skip empty cookies */
|
|
1528
|
+
.filter(Boolean);
|
|
1405
1529
|
}
|
|
1406
1530
|
|
|
1407
1531
|
const GlobalRequest = global.Request;
|
|
@@ -1427,31 +1551,37 @@ class RapidRequest {
|
|
|
1427
1551
|
return;
|
|
1428
1552
|
}
|
|
1429
1553
|
const requestMethod = this.method;
|
|
1430
|
-
if (requestMethod
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
this.#body = {
|
|
1435
|
-
type: "json",
|
|
1436
|
-
value: await req.json(),
|
|
1437
|
-
};
|
|
1438
|
-
}
|
|
1439
|
-
else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
1440
|
-
const bodyText = await req.text();
|
|
1441
|
-
this.#body = {
|
|
1442
|
-
type: "form",
|
|
1443
|
-
value: qs__default["default"].parse(bodyText),
|
|
1444
|
-
};
|
|
1445
|
-
}
|
|
1446
|
-
else if (contentType.startsWith("multipart/form-data")) {
|
|
1447
|
-
this.#body = {
|
|
1448
|
-
type: "form-data",
|
|
1449
|
-
value: await parseFormDataBody(req),
|
|
1450
|
-
};
|
|
1451
|
-
}
|
|
1554
|
+
if (requestMethod !== "POST" && requestMethod !== "PUT" && requestMethod !== "PATCH") {
|
|
1555
|
+
this.#body = null;
|
|
1556
|
+
this.#bodyParsed = true;
|
|
1557
|
+
return;
|
|
1452
1558
|
}
|
|
1453
|
-
|
|
1559
|
+
const contentLength = parseInt(this.#headers.get("Content-Length") || "0", 10);
|
|
1560
|
+
if (!contentLength) {
|
|
1454
1561
|
this.#body = null;
|
|
1562
|
+
this.#bodyParsed = true;
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
const req = this.#raw;
|
|
1566
|
+
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
1567
|
+
if (contentType.includes("json")) {
|
|
1568
|
+
this.#body = {
|
|
1569
|
+
type: "json",
|
|
1570
|
+
value: await req.json(),
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
1574
|
+
const bodyText = await req.text();
|
|
1575
|
+
this.#body = {
|
|
1576
|
+
type: "form",
|
|
1577
|
+
value: qs__default["default"].parse(bodyText),
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
else if (contentType.startsWith("multipart/form-data")) {
|
|
1581
|
+
this.#body = {
|
|
1582
|
+
type: "form-data",
|
|
1583
|
+
value: await parseFormDataBody(req),
|
|
1584
|
+
};
|
|
1455
1585
|
}
|
|
1456
1586
|
this.#bodyParsed = true;
|
|
1457
1587
|
}
|
|
@@ -6292,14 +6422,12 @@ async function handler$d(plugin, ctx, options) {
|
|
|
6292
6422
|
if (!isMatch) {
|
|
6293
6423
|
throw new Error("用户名或密码错误。");
|
|
6294
6424
|
}
|
|
6295
|
-
const
|
|
6296
|
-
const token =
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
act: user.login,
|
|
6302
|
-
}, secretKey);
|
|
6425
|
+
const authService = server.getService("authService");
|
|
6426
|
+
const token = authService.createUserAccessToken({
|
|
6427
|
+
issuer: "authManager",
|
|
6428
|
+
userId: user.id,
|
|
6429
|
+
userLogin: user.login,
|
|
6430
|
+
});
|
|
6303
6431
|
setCookie(response.headers, {
|
|
6304
6432
|
name: ctx.server.config.sessionCookieName,
|
|
6305
6433
|
value: token,
|
|
@@ -6533,10 +6661,31 @@ var signout$1 = {
|
|
|
6533
6661
|
|
|
6534
6662
|
var pluginRoutes$7 = [changePassword, getMyProfile$1, resetPassword, signin$1, signout$1];
|
|
6535
6663
|
|
|
6664
|
+
class AuthService {
|
|
6665
|
+
#server;
|
|
6666
|
+
#jwtKey;
|
|
6667
|
+
constructor(server, jwtKey) {
|
|
6668
|
+
this.#server = server;
|
|
6669
|
+
this.#jwtKey = jwtKey;
|
|
6670
|
+
}
|
|
6671
|
+
createUserAccessToken(options) {
|
|
6672
|
+
const secretKey = Buffer.from(this.#jwtKey, "base64");
|
|
6673
|
+
const token = createJwt({
|
|
6674
|
+
iss: options.issuer,
|
|
6675
|
+
sub: "userAccessToken",
|
|
6676
|
+
aud: "" + options.userId,
|
|
6677
|
+
iat: Math.floor(Date.now() / 1000),
|
|
6678
|
+
act: options.userLogin,
|
|
6679
|
+
}, secretKey);
|
|
6680
|
+
return token;
|
|
6681
|
+
}
|
|
6682
|
+
}
|
|
6683
|
+
|
|
6536
6684
|
/**
|
|
6537
6685
|
* Auth manager plugin
|
|
6538
6686
|
*/
|
|
6539
6687
|
class AuthPlugin {
|
|
6688
|
+
#authService;
|
|
6540
6689
|
get code() {
|
|
6541
6690
|
return "authManager";
|
|
6542
6691
|
}
|
|
@@ -6560,6 +6709,10 @@ class AuthPlugin {
|
|
|
6560
6709
|
async configureModels(server, applicationConfig) {
|
|
6561
6710
|
server.appendApplicationConfig({ models: pluginModels$5 });
|
|
6562
6711
|
}
|
|
6712
|
+
async configureServices(server, applicationConfig) {
|
|
6713
|
+
this.#authService = new AuthService(server, server.config.jwtKey);
|
|
6714
|
+
server.registerService("authService", this.#authService);
|
|
6715
|
+
}
|
|
6563
6716
|
async configureRoutes(server, applicationConfig) {
|
|
6564
6717
|
server.appendApplicationConfig({ routes: pluginRoutes$7 });
|
|
6565
6718
|
}
|
|
@@ -8543,6 +8696,10 @@ exports.WebhooksPlugin = WebhooksPlugin;
|
|
|
8543
8696
|
exports.bootstrapApplicationConfig = bootstrapApplicationConfig$1;
|
|
8544
8697
|
exports.createJwt = createJwt;
|
|
8545
8698
|
exports.decodeJwt = decodeJwt;
|
|
8699
|
+
exports.deleteCookie = deleteCookie;
|
|
8546
8700
|
exports.generateJwtSecretKey = generateJwtSecretKey;
|
|
8701
|
+
exports.getCookies = getCookies;
|
|
8702
|
+
exports.getSetCookies = getSetCookies;
|
|
8547
8703
|
exports.mapDbRowToEntity = mapDbRowToEntity;
|
|
8704
|
+
exports.setCookie = setCookie;
|
|
8548
8705
|
exports.verifyJwt = verifyJwt;
|
|
@@ -5,6 +5,7 @@ import { RpdApplicationConfig } from "../../types";
|
|
|
5
5
|
import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
|
|
6
6
|
import { RouteContext } from "../../core/routeContext";
|
|
7
7
|
declare class AuthPlugin implements RapidPlugin {
|
|
8
|
+
#private;
|
|
8
9
|
get code(): string;
|
|
9
10
|
get description(): string;
|
|
10
11
|
get extendingAbilities(): RpdServerPluginExtendingAbilities[];
|
|
@@ -12,6 +13,7 @@ declare class AuthPlugin implements RapidPlugin {
|
|
|
12
13
|
get configurations(): RpdConfigurationItemOptions[];
|
|
13
14
|
registerActionHandlers(server: IRpdServer): Promise<any>;
|
|
14
15
|
configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
16
|
+
configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
15
17
|
configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
16
18
|
onPrepareRouteContext(server: IRpdServer, routeContext: RouteContext): Promise<void>;
|
|
17
19
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { ActionHandlerContext } from "../../../core/actionHandler";
|
|
2
2
|
import { RapidPlugin } from "../../../core/server";
|
|
3
|
-
export interface UserAccessToken {
|
|
4
|
-
sub: "userAccessToken";
|
|
5
|
-
aud: string;
|
|
6
|
-
}
|
|
7
3
|
export declare const code = "createSession";
|
|
8
4
|
export declare function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any): Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IRpdServer } from "../../../core/server";
|
|
2
|
+
export interface UserAccessToken {
|
|
3
|
+
sub: "userAccessToken";
|
|
4
|
+
aud: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CreateUserAccessTokenOptions {
|
|
7
|
+
issuer: string;
|
|
8
|
+
userId: number;
|
|
9
|
+
userLogin: string;
|
|
10
|
+
}
|
|
11
|
+
export default class AuthService {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(server: IRpdServer, jwtKey: string);
|
|
14
|
+
createUserAccessToken(options: CreateUserAccessTokenOptions): string;
|
|
15
|
+
}
|
package/package.json
CHANGED
package/src/core/request.ts
CHANGED
|
@@ -36,28 +36,37 @@ export class RapidRequest {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const requestMethod = this.method;
|
|
39
|
-
if (requestMethod
|
|
40
|
-
const req = this.#raw;
|
|
41
|
-
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
42
|
-
if (contentType.includes("json")) {
|
|
43
|
-
this.#body = {
|
|
44
|
-
type: "json",
|
|
45
|
-
value: await req.json(),
|
|
46
|
-
};
|
|
47
|
-
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
48
|
-
const bodyText = await req.text();
|
|
49
|
-
this.#body = {
|
|
50
|
-
type: "form",
|
|
51
|
-
value: qs.parse(bodyText),
|
|
52
|
-
};
|
|
53
|
-
} else if (contentType.startsWith("multipart/form-data")) {
|
|
54
|
-
this.#body = {
|
|
55
|
-
type: "form-data",
|
|
56
|
-
value: await parseFormDataBody(req),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
39
|
+
if (requestMethod !== "POST" && requestMethod !== "PUT" && requestMethod !== "PATCH") {
|
|
60
40
|
this.#body = null;
|
|
41
|
+
this.#bodyParsed = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const contentLength = parseInt(this.#headers.get("Content-Length") || "0", 10);
|
|
46
|
+
if (!contentLength) {
|
|
47
|
+
this.#body = null;
|
|
48
|
+
this.#bodyParsed = true;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const req = this.#raw;
|
|
53
|
+
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
54
|
+
if (contentType.includes("json")) {
|
|
55
|
+
this.#body = {
|
|
56
|
+
type: "json",
|
|
57
|
+
value: await req.json(),
|
|
58
|
+
};
|
|
59
|
+
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
60
|
+
const bodyText = await req.text();
|
|
61
|
+
this.#body = {
|
|
62
|
+
type: "form",
|
|
63
|
+
value: qs.parse(bodyText),
|
|
64
|
+
};
|
|
65
|
+
} else if (contentType.startsWith("multipart/form-data")) {
|
|
66
|
+
this.#body = {
|
|
67
|
+
type: "form-data",
|
|
68
|
+
value: await parseFormDataBody(req),
|
|
69
|
+
};
|
|
61
70
|
}
|
|
62
71
|
this.#bodyParsed = true;
|
|
63
72
|
}
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export * from "./core/actionHandler";
|
|
|
12
12
|
|
|
13
13
|
export * from "./utilities/jwtUtility";
|
|
14
14
|
|
|
15
|
+
export * from "./deno-std/http/cookie";
|
|
16
|
+
|
|
15
17
|
export { mapDbRowToEntity } from "./dataAccess/entityMapper";
|
|
16
18
|
|
|
17
19
|
export * as bootstrapApplicationConfig from "./bootstrapApplicationConfig";
|
|
@@ -16,8 +16,11 @@ import pluginModels from "./models";
|
|
|
16
16
|
import pluginRoutes from "./routes";
|
|
17
17
|
import { RouteContext } from "~/core/routeContext";
|
|
18
18
|
import { verifyJwt } from "~/utilities/jwtUtility";
|
|
19
|
+
import AuthService from "./services/AuthService";
|
|
19
20
|
|
|
20
21
|
class AuthPlugin implements RapidPlugin {
|
|
22
|
+
#authService!: AuthService;
|
|
23
|
+
|
|
21
24
|
get code(): string {
|
|
22
25
|
return "authManager";
|
|
23
26
|
}
|
|
@@ -48,6 +51,11 @@ class AuthPlugin implements RapidPlugin {
|
|
|
48
51
|
server.appendApplicationConfig({ models: pluginModels });
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
async configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
|
|
55
|
+
this.#authService = new AuthService(server, server.config.jwtKey);
|
|
56
|
+
server.registerService("authService", this.#authService);
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
|
|
52
60
|
server.appendApplicationConfig({ routes: pluginRoutes });
|
|
53
61
|
}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import bcrypt from "bcrypt";
|
|
2
2
|
import { setCookie } from "~/deno-std/http/cookie";
|
|
3
|
-
import { createJwt } from "~/utilities/jwtUtility";
|
|
4
3
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
5
4
|
import { RapidPlugin } from "~/core/server";
|
|
6
5
|
import LicenseService from "~/plugins/license/LicenseService";
|
|
7
6
|
import { get } from "lodash";
|
|
8
|
-
|
|
9
|
-
export interface UserAccessToken {
|
|
10
|
-
sub: "userAccessToken";
|
|
11
|
-
aud: string;
|
|
12
|
-
}
|
|
7
|
+
import AuthService from "../services/AuthService";
|
|
13
8
|
|
|
14
9
|
export const code = "createSession";
|
|
15
10
|
|
|
@@ -54,17 +49,12 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
54
49
|
throw new Error("用户名或密码错误。");
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
const
|
|
58
|
-
const token =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
iat: Math.floor(Date.now() / 1000),
|
|
64
|
-
act: user.login,
|
|
65
|
-
} as UserAccessToken,
|
|
66
|
-
secretKey,
|
|
67
|
-
);
|
|
52
|
+
const authService = server.getService<AuthService>("authService");
|
|
53
|
+
const token = authService.createUserAccessToken({
|
|
54
|
+
issuer: "authManager",
|
|
55
|
+
userId: user.id,
|
|
56
|
+
userLogin: user.login,
|
|
57
|
+
});
|
|
68
58
|
|
|
69
59
|
setCookie(response.headers, {
|
|
70
60
|
name: ctx.server.config.sessionCookieName,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { IRpdServer } from "~/core/server";
|
|
2
|
+
import { createJwt } from "~/utilities/jwtUtility";
|
|
3
|
+
|
|
4
|
+
export interface UserAccessToken {
|
|
5
|
+
sub: "userAccessToken";
|
|
6
|
+
aud: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface CreateUserAccessTokenOptions {
|
|
10
|
+
issuer: string;
|
|
11
|
+
userId: number;
|
|
12
|
+
userLogin: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default class AuthService {
|
|
16
|
+
#server: IRpdServer;
|
|
17
|
+
#jwtKey: string;
|
|
18
|
+
|
|
19
|
+
constructor(server: IRpdServer, jwtKey: string) {
|
|
20
|
+
this.#server = server;
|
|
21
|
+
this.#jwtKey = jwtKey;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
createUserAccessToken(options: CreateUserAccessTokenOptions): string {
|
|
25
|
+
const secretKey = Buffer.from(this.#jwtKey, "base64");
|
|
26
|
+
const token = createJwt(
|
|
27
|
+
{
|
|
28
|
+
iss: options.issuer,
|
|
29
|
+
sub: "userAccessToken",
|
|
30
|
+
aud: "" + options.userId,
|
|
31
|
+
iat: Math.floor(Date.now() / 1000),
|
|
32
|
+
act: options.userLogin,
|
|
33
|
+
} as UserAccessToken,
|
|
34
|
+
secretKey,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return token;
|
|
38
|
+
}
|
|
39
|
+
}
|