imean-service-engine-htmx-plugin 1.1.0 → 1.2.0
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.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +109 -29
- package/dist/index.mjs +109 -29
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -50,6 +50,10 @@ interface PermissionResult {
|
|
|
50
50
|
interface AuthProvider {
|
|
51
51
|
/** Cookie 中存储 token 的 key(默认 "auth_token") */
|
|
52
52
|
cookieKey?: string;
|
|
53
|
+
/** 登录页面 URL(当用户未登录且需要权限时重定向到此页面) */
|
|
54
|
+
loginUrl?: string;
|
|
55
|
+
/** 退出登录页面 URL(用于退出登录功能) */
|
|
56
|
+
logoutUrl?: string;
|
|
53
57
|
/** 将 token 转换为用户信息 */
|
|
54
58
|
tokenToUser: (token: string, ctx: Context) => UserInfo | null | Promise<UserInfo | null>;
|
|
55
59
|
/** 权限校验钩子(可选,如果不提供则使用默认实现) */
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,10 @@ interface PermissionResult {
|
|
|
50
50
|
interface AuthProvider {
|
|
51
51
|
/** Cookie 中存储 token 的 key(默认 "auth_token") */
|
|
52
52
|
cookieKey?: string;
|
|
53
|
+
/** 登录页面 URL(当用户未登录且需要权限时重定向到此页面) */
|
|
54
|
+
loginUrl?: string;
|
|
55
|
+
/** 退出登录页面 URL(用于退出登录功能) */
|
|
56
|
+
logoutUrl?: string;
|
|
53
57
|
/** 将 token 转换为用户信息 */
|
|
54
58
|
tokenToUser: (token: string, ctx: Context) => UserInfo | null | Promise<UserInfo | null>;
|
|
55
59
|
/** 权限校验钩子(可选,如果不提供则使用默认实现) */
|
package/dist/index.js
CHANGED
|
@@ -149,7 +149,7 @@ var init_Header = __esm({
|
|
|
149
149
|
"src/components/Header.tsx"() {
|
|
150
150
|
init_Breadcrumb();
|
|
151
151
|
Header = (props) => {
|
|
152
|
-
const { breadcrumbs = [], userInfo, sidebarCollapsed = false } = props;
|
|
152
|
+
const { breadcrumbs = [], userInfo, sidebarCollapsed = false, logoutUrl } = props;
|
|
153
153
|
return /* @__PURE__ */ jsxRuntime.jsx("header", { className: "bg-white border-b border-gray-200 shadow-sm sticky top-0 z-40", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
154
154
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 flex-1 min-w-0", children: [
|
|
155
155
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -215,7 +215,36 @@ var init_Header = __esm({
|
|
|
215
215
|
alt: userInfo.name || "\u7528\u6237",
|
|
216
216
|
className: "w-8 h-8 rounded-full"
|
|
217
217
|
}
|
|
218
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white text-sm font-medium", children: (userInfo.name || userInfo.email || "U").charAt(0).toUpperCase() })
|
|
218
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white text-sm font-medium", children: (userInfo.name || userInfo.email || "U").charAt(0).toUpperCase() }),
|
|
219
|
+
logoutUrl && /* @__PURE__ */ jsxRuntime.jsx(
|
|
220
|
+
"a",
|
|
221
|
+
{
|
|
222
|
+
href: logoutUrl,
|
|
223
|
+
"hx-get": logoutUrl,
|
|
224
|
+
"hx-target": "body",
|
|
225
|
+
"hx-swap": "outerHTML",
|
|
226
|
+
className: "p-2 rounded-lg hover:bg-gray-100 transition-colors",
|
|
227
|
+
title: "\u9000\u51FA\u767B\u5F55",
|
|
228
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
229
|
+
"svg",
|
|
230
|
+
{
|
|
231
|
+
className: "w-5 h-5 text-gray-600",
|
|
232
|
+
fill: "none",
|
|
233
|
+
stroke: "currentColor",
|
|
234
|
+
viewBox: "0 0 24 24",
|
|
235
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
236
|
+
"path",
|
|
237
|
+
{
|
|
238
|
+
strokeLinecap: "round",
|
|
239
|
+
strokeLinejoin: "round",
|
|
240
|
+
strokeWidth: 2,
|
|
241
|
+
d: "M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
)
|
|
219
248
|
] })
|
|
220
249
|
] }) }) });
|
|
221
250
|
};
|
|
@@ -417,6 +446,7 @@ var init_Layout = __esm({
|
|
|
417
446
|
const sidebarCollapsed = props.sidebarCollapsed || false;
|
|
418
447
|
const breadcrumbs = props.adminContext.breadcrumbs;
|
|
419
448
|
const userInfo = props.adminContext.userInfo;
|
|
449
|
+
const logoutUrl = props.adminContext.pluginOptions.authProvider?.logoutUrl;
|
|
420
450
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-screen", id: "main-content", children: [
|
|
421
451
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
422
452
|
"aside",
|
|
@@ -446,7 +476,8 @@ var init_Layout = __esm({
|
|
|
446
476
|
{
|
|
447
477
|
breadcrumbs,
|
|
448
478
|
userInfo,
|
|
449
|
-
sidebarCollapsed: sidebarCollapsed || false
|
|
479
|
+
sidebarCollapsed: sidebarCollapsed || false,
|
|
480
|
+
logoutUrl
|
|
450
481
|
}
|
|
451
482
|
),
|
|
452
483
|
/* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-auto bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: props.children }) })
|
|
@@ -657,15 +688,28 @@ function PermissionDeniedPage(adminContext, operationId, fromPath, registeredOpe
|
|
|
657
688
|
{
|
|
658
689
|
title: `\u6743\u9650\u4E0D\u8DB3 - ${adminContext.pluginOptions.title}`,
|
|
659
690
|
description: "\u60A8\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6B64\u8D44\u6E90",
|
|
660
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { id: "main-content", className: "min-h-screen flex items-center justify-center px-4", children: /* @__PURE__ */ jsxRuntime.
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
691
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { id: "main-content", className: "min-h-screen flex items-center justify-center px-4", children: /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "max-w-2xl w-full p-8", children: [
|
|
692
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
693
|
+
PermissionDeniedContent,
|
|
694
|
+
{
|
|
695
|
+
adminContext,
|
|
696
|
+
operationId,
|
|
697
|
+
fromPath,
|
|
698
|
+
registeredOperations
|
|
699
|
+
}
|
|
700
|
+
),
|
|
701
|
+
adminContext.pluginOptions.authProvider?.loginUrl && !adminContext.userInfo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
702
|
+
Button,
|
|
703
|
+
{
|
|
704
|
+
variant: "primary",
|
|
705
|
+
href: adminContext.pluginOptions.authProvider.loginUrl,
|
|
706
|
+
hxGet: adminContext.pluginOptions.authProvider.loginUrl,
|
|
707
|
+
hxTarget: "body",
|
|
708
|
+
hxSwap: "outerHTML",
|
|
709
|
+
children: "\u524D\u5F80\u767B\u5F55"
|
|
710
|
+
}
|
|
711
|
+
) })
|
|
712
|
+
] }) })
|
|
669
713
|
}
|
|
670
714
|
);
|
|
671
715
|
}
|
|
@@ -2951,7 +2995,7 @@ async function getUserInfo(ctx, authProvider) {
|
|
|
2951
2995
|
}
|
|
2952
2996
|
return await authProvider.tokenToUser(token, ctx);
|
|
2953
2997
|
}
|
|
2954
|
-
function checkPermissionDefault(userInfo, operation) {
|
|
2998
|
+
function checkPermissionDefault(userInfo, operation, loginUrl) {
|
|
2955
2999
|
if (!operation) {
|
|
2956
3000
|
return { allowed: true };
|
|
2957
3001
|
}
|
|
@@ -2959,7 +3003,9 @@ function checkPermissionDefault(userInfo, operation) {
|
|
|
2959
3003
|
return {
|
|
2960
3004
|
allowed: false,
|
|
2961
3005
|
message: "\u672A\u767B\u5F55\uFF0C\u65E0\u6CD5\u8BBF\u95EE\u6B64\u8D44\u6E90",
|
|
2962
|
-
operationId: operation
|
|
3006
|
+
operationId: operation,
|
|
3007
|
+
redirectUrl: loginUrl
|
|
3008
|
+
// 如果提供了 loginUrl,则重定向到登录页面
|
|
2963
3009
|
};
|
|
2964
3010
|
}
|
|
2965
3011
|
const userPermissions = userInfo.permissions || [];
|
|
@@ -3009,6 +3055,13 @@ function generateOperationId(ctx, moduleName, moduleOptions, serviceName) {
|
|
|
3009
3055
|
}
|
|
3010
3056
|
return `${servicePrefix}${lowerModuleName}.read`;
|
|
3011
3057
|
} else if (moduleOptions.type === "custom") {
|
|
3058
|
+
if (method === "post") {
|
|
3059
|
+
return `${servicePrefix}${lowerModuleName}.create`;
|
|
3060
|
+
} else if (method === "put") {
|
|
3061
|
+
return `${servicePrefix}${lowerModuleName}.edit`;
|
|
3062
|
+
} else if (method === "delete") {
|
|
3063
|
+
return `${servicePrefix}${lowerModuleName}.delete`;
|
|
3064
|
+
}
|
|
3012
3065
|
return `${servicePrefix}${lowerModuleName}.read`;
|
|
3013
3066
|
}
|
|
3014
3067
|
return `${servicePrefix}${lowerModuleName}.read`;
|
|
@@ -3028,6 +3081,9 @@ async function handlePermissionDenied(ctx, adminContext, permissionResult, getOp
|
|
|
3028
3081
|
getRegisteredOperations
|
|
3029
3082
|
);
|
|
3030
3083
|
} else {
|
|
3084
|
+
if (permissionResult.redirectUrl) {
|
|
3085
|
+
return ctx.redirect(permissionResult.redirectUrl);
|
|
3086
|
+
}
|
|
3031
3087
|
return redirectToPermissionDeniedPage(
|
|
3032
3088
|
ctx,
|
|
3033
3089
|
operationId,
|
|
@@ -3110,7 +3166,8 @@ var RouteHandler = class {
|
|
|
3110
3166
|
} else {
|
|
3111
3167
|
permissionResult = checkPermissionDefault(
|
|
3112
3168
|
userInfo,
|
|
3113
|
-
operation
|
|
3169
|
+
operation,
|
|
3170
|
+
this.pluginOptions.authProvider?.loginUrl
|
|
3114
3171
|
);
|
|
3115
3172
|
}
|
|
3116
3173
|
if (!permissionResult.allowed) {
|
|
@@ -3464,73 +3521,90 @@ var HtmxAdminPlugin = class {
|
|
|
3464
3521
|
generateOperationId(moduleName, moduleType, method, path) {
|
|
3465
3522
|
const lowerModuleName = moduleName.toLowerCase();
|
|
3466
3523
|
const lowerMethod = method.toLowerCase();
|
|
3524
|
+
const servicePrefix = this.serviceName ? `${this.serviceName}.` : "";
|
|
3467
3525
|
if (moduleType === "list") {
|
|
3468
3526
|
return {
|
|
3469
|
-
operationId: `${lowerModuleName}.read`,
|
|
3527
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3470
3528
|
operationType: "read"
|
|
3471
3529
|
};
|
|
3472
3530
|
} else if (moduleType === "detail") {
|
|
3473
3531
|
if (lowerMethod === "delete") {
|
|
3474
3532
|
return {
|
|
3475
|
-
operationId: `${lowerModuleName}.delete`,
|
|
3533
|
+
operationId: `${servicePrefix}${lowerModuleName}.delete`,
|
|
3476
3534
|
operationType: "delete"
|
|
3477
3535
|
};
|
|
3478
3536
|
}
|
|
3479
3537
|
return {
|
|
3480
|
-
operationId: `${lowerModuleName}.read`,
|
|
3538
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3481
3539
|
operationType: "read"
|
|
3482
3540
|
};
|
|
3483
3541
|
} else if (moduleType === "form") {
|
|
3484
3542
|
if (path.includes("/new")) {
|
|
3485
3543
|
if (lowerMethod === "get") {
|
|
3486
3544
|
return {
|
|
3487
|
-
operationId: `${lowerModuleName}.create`,
|
|
3545
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3488
3546
|
operationType: "create"
|
|
3489
3547
|
};
|
|
3490
3548
|
}
|
|
3491
3549
|
return {
|
|
3492
|
-
operationId: `${lowerModuleName}.create`,
|
|
3550
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3493
3551
|
operationType: "create"
|
|
3494
3552
|
};
|
|
3495
3553
|
} else if (path.includes("/edit/")) {
|
|
3496
3554
|
if (lowerMethod === "get") {
|
|
3497
3555
|
return {
|
|
3498
|
-
operationId: `${lowerModuleName}.edit`,
|
|
3556
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3499
3557
|
operationType: "edit"
|
|
3500
3558
|
};
|
|
3501
3559
|
}
|
|
3502
3560
|
return {
|
|
3503
|
-
operationId: `${lowerModuleName}.edit`,
|
|
3561
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3504
3562
|
operationType: "edit"
|
|
3505
3563
|
};
|
|
3506
3564
|
} else if (lowerMethod === "post") {
|
|
3507
3565
|
return {
|
|
3508
|
-
operationId: `${lowerModuleName}.create`,
|
|
3566
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3509
3567
|
operationType: "create"
|
|
3510
3568
|
};
|
|
3511
3569
|
} else if (lowerMethod === "put") {
|
|
3512
3570
|
return {
|
|
3513
|
-
operationId: `${lowerModuleName}.edit`,
|
|
3571
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3514
3572
|
operationType: "edit"
|
|
3515
3573
|
};
|
|
3516
3574
|
} else if (lowerMethod === "delete") {
|
|
3517
3575
|
return {
|
|
3518
|
-
operationId: `${lowerModuleName}.delete`,
|
|
3576
|
+
operationId: `${servicePrefix}${lowerModuleName}.delete`,
|
|
3519
3577
|
operationType: "delete"
|
|
3520
3578
|
};
|
|
3521
3579
|
}
|
|
3522
3580
|
return {
|
|
3523
|
-
operationId: `${lowerModuleName}.read`,
|
|
3581
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3524
3582
|
operationType: "read"
|
|
3525
3583
|
};
|
|
3526
3584
|
} else if (moduleType === "custom") {
|
|
3585
|
+
if (lowerMethod === "post") {
|
|
3586
|
+
return {
|
|
3587
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3588
|
+
operationType: "create"
|
|
3589
|
+
};
|
|
3590
|
+
} else if (lowerMethod === "put") {
|
|
3591
|
+
return {
|
|
3592
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3593
|
+
operationType: "edit"
|
|
3594
|
+
};
|
|
3595
|
+
} else if (lowerMethod === "delete") {
|
|
3596
|
+
return {
|
|
3597
|
+
operationId: `${servicePrefix}${lowerModuleName}.delete`,
|
|
3598
|
+
operationType: "delete"
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3527
3601
|
return {
|
|
3528
|
-
operationId: `${lowerModuleName}.read`,
|
|
3602
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3529
3603
|
operationType: "read"
|
|
3530
3604
|
};
|
|
3531
3605
|
}
|
|
3532
3606
|
return {
|
|
3533
|
-
operationId: `${lowerModuleName}.read`,
|
|
3607
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3534
3608
|
operationType: "read"
|
|
3535
3609
|
};
|
|
3536
3610
|
}
|
|
@@ -3615,7 +3689,13 @@ var HtmxAdminPlugin = class {
|
|
|
3615
3689
|
{ method: "put", path: `${basePath}/:id` },
|
|
3616
3690
|
{ method: "delete", path: `${basePath}/:id` }
|
|
3617
3691
|
],
|
|
3618
|
-
custom
|
|
3692
|
+
// custom 类型注册所有 HTTP 方法,允许模块在 render 方法中根据请求方法进行扩展
|
|
3693
|
+
custom: [
|
|
3694
|
+
{ method: "get", path: basePath },
|
|
3695
|
+
{ method: "post", path: basePath },
|
|
3696
|
+
{ method: "put", path: basePath },
|
|
3697
|
+
{ method: "delete", path: basePath }
|
|
3698
|
+
]
|
|
3619
3699
|
};
|
|
3620
3700
|
const routes = routeConfig[type];
|
|
3621
3701
|
for (const route of routes) {
|
package/dist/index.mjs
CHANGED
|
@@ -147,7 +147,7 @@ var init_Header = __esm({
|
|
|
147
147
|
"src/components/Header.tsx"() {
|
|
148
148
|
init_Breadcrumb();
|
|
149
149
|
Header = (props) => {
|
|
150
|
-
const { breadcrumbs = [], userInfo, sidebarCollapsed = false } = props;
|
|
150
|
+
const { breadcrumbs = [], userInfo, sidebarCollapsed = false, logoutUrl } = props;
|
|
151
151
|
return /* @__PURE__ */ jsx("header", { className: "bg-white border-b border-gray-200 shadow-sm sticky top-0 z-40", children: /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
152
152
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 flex-1 min-w-0", children: [
|
|
153
153
|
/* @__PURE__ */ jsx(
|
|
@@ -213,7 +213,36 @@ var init_Header = __esm({
|
|
|
213
213
|
alt: userInfo.name || "\u7528\u6237",
|
|
214
214
|
className: "w-8 h-8 rounded-full"
|
|
215
215
|
}
|
|
216
|
-
) : /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white text-sm font-medium", children: (userInfo.name || userInfo.email || "U").charAt(0).toUpperCase() })
|
|
216
|
+
) : /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white text-sm font-medium", children: (userInfo.name || userInfo.email || "U").charAt(0).toUpperCase() }),
|
|
217
|
+
logoutUrl && /* @__PURE__ */ jsx(
|
|
218
|
+
"a",
|
|
219
|
+
{
|
|
220
|
+
href: logoutUrl,
|
|
221
|
+
"hx-get": logoutUrl,
|
|
222
|
+
"hx-target": "body",
|
|
223
|
+
"hx-swap": "outerHTML",
|
|
224
|
+
className: "p-2 rounded-lg hover:bg-gray-100 transition-colors",
|
|
225
|
+
title: "\u9000\u51FA\u767B\u5F55",
|
|
226
|
+
children: /* @__PURE__ */ jsx(
|
|
227
|
+
"svg",
|
|
228
|
+
{
|
|
229
|
+
className: "w-5 h-5 text-gray-600",
|
|
230
|
+
fill: "none",
|
|
231
|
+
stroke: "currentColor",
|
|
232
|
+
viewBox: "0 0 24 24",
|
|
233
|
+
children: /* @__PURE__ */ jsx(
|
|
234
|
+
"path",
|
|
235
|
+
{
|
|
236
|
+
strokeLinecap: "round",
|
|
237
|
+
strokeLinejoin: "round",
|
|
238
|
+
strokeWidth: 2,
|
|
239
|
+
d: "M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
|
|
240
|
+
}
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
)
|
|
217
246
|
] })
|
|
218
247
|
] }) }) });
|
|
219
248
|
};
|
|
@@ -415,6 +444,7 @@ var init_Layout = __esm({
|
|
|
415
444
|
const sidebarCollapsed = props.sidebarCollapsed || false;
|
|
416
445
|
const breadcrumbs = props.adminContext.breadcrumbs;
|
|
417
446
|
const userInfo = props.adminContext.userInfo;
|
|
447
|
+
const logoutUrl = props.adminContext.pluginOptions.authProvider?.logoutUrl;
|
|
418
448
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-screen", id: "main-content", children: [
|
|
419
449
|
/* @__PURE__ */ jsx(
|
|
420
450
|
"aside",
|
|
@@ -444,7 +474,8 @@ var init_Layout = __esm({
|
|
|
444
474
|
{
|
|
445
475
|
breadcrumbs,
|
|
446
476
|
userInfo,
|
|
447
|
-
sidebarCollapsed: sidebarCollapsed || false
|
|
477
|
+
sidebarCollapsed: sidebarCollapsed || false,
|
|
478
|
+
logoutUrl
|
|
448
479
|
}
|
|
449
480
|
),
|
|
450
481
|
/* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "p-6", children: props.children }) })
|
|
@@ -655,15 +686,28 @@ function PermissionDeniedPage(adminContext, operationId, fromPath, registeredOpe
|
|
|
655
686
|
{
|
|
656
687
|
title: `\u6743\u9650\u4E0D\u8DB3 - ${adminContext.pluginOptions.title}`,
|
|
657
688
|
description: "\u60A8\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6B64\u8D44\u6E90",
|
|
658
|
-
children: /* @__PURE__ */ jsx("div", { id: "main-content", className: "min-h-screen flex items-center justify-center px-4", children: /* @__PURE__ */
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
689
|
+
children: /* @__PURE__ */ jsx("div", { id: "main-content", className: "min-h-screen flex items-center justify-center px-4", children: /* @__PURE__ */ jsxs(Card, { className: "max-w-2xl w-full p-8", children: [
|
|
690
|
+
/* @__PURE__ */ jsx(
|
|
691
|
+
PermissionDeniedContent,
|
|
692
|
+
{
|
|
693
|
+
adminContext,
|
|
694
|
+
operationId,
|
|
695
|
+
fromPath,
|
|
696
|
+
registeredOperations
|
|
697
|
+
}
|
|
698
|
+
),
|
|
699
|
+
adminContext.pluginOptions.authProvider?.loginUrl && !adminContext.userInfo && /* @__PURE__ */ jsx("div", { className: "mt-8 text-center", children: /* @__PURE__ */ jsx(
|
|
700
|
+
Button,
|
|
701
|
+
{
|
|
702
|
+
variant: "primary",
|
|
703
|
+
href: adminContext.pluginOptions.authProvider.loginUrl,
|
|
704
|
+
hxGet: adminContext.pluginOptions.authProvider.loginUrl,
|
|
705
|
+
hxTarget: "body",
|
|
706
|
+
hxSwap: "outerHTML",
|
|
707
|
+
children: "\u524D\u5F80\u767B\u5F55"
|
|
708
|
+
}
|
|
709
|
+
) })
|
|
710
|
+
] }) })
|
|
667
711
|
}
|
|
668
712
|
);
|
|
669
713
|
}
|
|
@@ -2949,7 +2993,7 @@ async function getUserInfo(ctx, authProvider) {
|
|
|
2949
2993
|
}
|
|
2950
2994
|
return await authProvider.tokenToUser(token, ctx);
|
|
2951
2995
|
}
|
|
2952
|
-
function checkPermissionDefault(userInfo, operation) {
|
|
2996
|
+
function checkPermissionDefault(userInfo, operation, loginUrl) {
|
|
2953
2997
|
if (!operation) {
|
|
2954
2998
|
return { allowed: true };
|
|
2955
2999
|
}
|
|
@@ -2957,7 +3001,9 @@ function checkPermissionDefault(userInfo, operation) {
|
|
|
2957
3001
|
return {
|
|
2958
3002
|
allowed: false,
|
|
2959
3003
|
message: "\u672A\u767B\u5F55\uFF0C\u65E0\u6CD5\u8BBF\u95EE\u6B64\u8D44\u6E90",
|
|
2960
|
-
operationId: operation
|
|
3004
|
+
operationId: operation,
|
|
3005
|
+
redirectUrl: loginUrl
|
|
3006
|
+
// 如果提供了 loginUrl,则重定向到登录页面
|
|
2961
3007
|
};
|
|
2962
3008
|
}
|
|
2963
3009
|
const userPermissions = userInfo.permissions || [];
|
|
@@ -3007,6 +3053,13 @@ function generateOperationId(ctx, moduleName, moduleOptions, serviceName) {
|
|
|
3007
3053
|
}
|
|
3008
3054
|
return `${servicePrefix}${lowerModuleName}.read`;
|
|
3009
3055
|
} else if (moduleOptions.type === "custom") {
|
|
3056
|
+
if (method === "post") {
|
|
3057
|
+
return `${servicePrefix}${lowerModuleName}.create`;
|
|
3058
|
+
} else if (method === "put") {
|
|
3059
|
+
return `${servicePrefix}${lowerModuleName}.edit`;
|
|
3060
|
+
} else if (method === "delete") {
|
|
3061
|
+
return `${servicePrefix}${lowerModuleName}.delete`;
|
|
3062
|
+
}
|
|
3010
3063
|
return `${servicePrefix}${lowerModuleName}.read`;
|
|
3011
3064
|
}
|
|
3012
3065
|
return `${servicePrefix}${lowerModuleName}.read`;
|
|
@@ -3026,6 +3079,9 @@ async function handlePermissionDenied(ctx, adminContext, permissionResult, getOp
|
|
|
3026
3079
|
getRegisteredOperations
|
|
3027
3080
|
);
|
|
3028
3081
|
} else {
|
|
3082
|
+
if (permissionResult.redirectUrl) {
|
|
3083
|
+
return ctx.redirect(permissionResult.redirectUrl);
|
|
3084
|
+
}
|
|
3029
3085
|
return redirectToPermissionDeniedPage(
|
|
3030
3086
|
ctx,
|
|
3031
3087
|
operationId,
|
|
@@ -3108,7 +3164,8 @@ var RouteHandler = class {
|
|
|
3108
3164
|
} else {
|
|
3109
3165
|
permissionResult = checkPermissionDefault(
|
|
3110
3166
|
userInfo,
|
|
3111
|
-
operation
|
|
3167
|
+
operation,
|
|
3168
|
+
this.pluginOptions.authProvider?.loginUrl
|
|
3112
3169
|
);
|
|
3113
3170
|
}
|
|
3114
3171
|
if (!permissionResult.allowed) {
|
|
@@ -3462,73 +3519,90 @@ var HtmxAdminPlugin = class {
|
|
|
3462
3519
|
generateOperationId(moduleName, moduleType, method, path) {
|
|
3463
3520
|
const lowerModuleName = moduleName.toLowerCase();
|
|
3464
3521
|
const lowerMethod = method.toLowerCase();
|
|
3522
|
+
const servicePrefix = this.serviceName ? `${this.serviceName}.` : "";
|
|
3465
3523
|
if (moduleType === "list") {
|
|
3466
3524
|
return {
|
|
3467
|
-
operationId: `${lowerModuleName}.read`,
|
|
3525
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3468
3526
|
operationType: "read"
|
|
3469
3527
|
};
|
|
3470
3528
|
} else if (moduleType === "detail") {
|
|
3471
3529
|
if (lowerMethod === "delete") {
|
|
3472
3530
|
return {
|
|
3473
|
-
operationId: `${lowerModuleName}.delete`,
|
|
3531
|
+
operationId: `${servicePrefix}${lowerModuleName}.delete`,
|
|
3474
3532
|
operationType: "delete"
|
|
3475
3533
|
};
|
|
3476
3534
|
}
|
|
3477
3535
|
return {
|
|
3478
|
-
operationId: `${lowerModuleName}.read`,
|
|
3536
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3479
3537
|
operationType: "read"
|
|
3480
3538
|
};
|
|
3481
3539
|
} else if (moduleType === "form") {
|
|
3482
3540
|
if (path.includes("/new")) {
|
|
3483
3541
|
if (lowerMethod === "get") {
|
|
3484
3542
|
return {
|
|
3485
|
-
operationId: `${lowerModuleName}.create`,
|
|
3543
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3486
3544
|
operationType: "create"
|
|
3487
3545
|
};
|
|
3488
3546
|
}
|
|
3489
3547
|
return {
|
|
3490
|
-
operationId: `${lowerModuleName}.create`,
|
|
3548
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3491
3549
|
operationType: "create"
|
|
3492
3550
|
};
|
|
3493
3551
|
} else if (path.includes("/edit/")) {
|
|
3494
3552
|
if (lowerMethod === "get") {
|
|
3495
3553
|
return {
|
|
3496
|
-
operationId: `${lowerModuleName}.edit`,
|
|
3554
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3497
3555
|
operationType: "edit"
|
|
3498
3556
|
};
|
|
3499
3557
|
}
|
|
3500
3558
|
return {
|
|
3501
|
-
operationId: `${lowerModuleName}.edit`,
|
|
3559
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3502
3560
|
operationType: "edit"
|
|
3503
3561
|
};
|
|
3504
3562
|
} else if (lowerMethod === "post") {
|
|
3505
3563
|
return {
|
|
3506
|
-
operationId: `${lowerModuleName}.create`,
|
|
3564
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3507
3565
|
operationType: "create"
|
|
3508
3566
|
};
|
|
3509
3567
|
} else if (lowerMethod === "put") {
|
|
3510
3568
|
return {
|
|
3511
|
-
operationId: `${lowerModuleName}.edit`,
|
|
3569
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3512
3570
|
operationType: "edit"
|
|
3513
3571
|
};
|
|
3514
3572
|
} else if (lowerMethod === "delete") {
|
|
3515
3573
|
return {
|
|
3516
|
-
operationId: `${lowerModuleName}.delete`,
|
|
3574
|
+
operationId: `${servicePrefix}${lowerModuleName}.delete`,
|
|
3517
3575
|
operationType: "delete"
|
|
3518
3576
|
};
|
|
3519
3577
|
}
|
|
3520
3578
|
return {
|
|
3521
|
-
operationId: `${lowerModuleName}.read`,
|
|
3579
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3522
3580
|
operationType: "read"
|
|
3523
3581
|
};
|
|
3524
3582
|
} else if (moduleType === "custom") {
|
|
3583
|
+
if (lowerMethod === "post") {
|
|
3584
|
+
return {
|
|
3585
|
+
operationId: `${servicePrefix}${lowerModuleName}.create`,
|
|
3586
|
+
operationType: "create"
|
|
3587
|
+
};
|
|
3588
|
+
} else if (lowerMethod === "put") {
|
|
3589
|
+
return {
|
|
3590
|
+
operationId: `${servicePrefix}${lowerModuleName}.edit`,
|
|
3591
|
+
operationType: "edit"
|
|
3592
|
+
};
|
|
3593
|
+
} else if (lowerMethod === "delete") {
|
|
3594
|
+
return {
|
|
3595
|
+
operationId: `${servicePrefix}${lowerModuleName}.delete`,
|
|
3596
|
+
operationType: "delete"
|
|
3597
|
+
};
|
|
3598
|
+
}
|
|
3525
3599
|
return {
|
|
3526
|
-
operationId: `${lowerModuleName}.read`,
|
|
3600
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3527
3601
|
operationType: "read"
|
|
3528
3602
|
};
|
|
3529
3603
|
}
|
|
3530
3604
|
return {
|
|
3531
|
-
operationId: `${lowerModuleName}.read`,
|
|
3605
|
+
operationId: `${servicePrefix}${lowerModuleName}.read`,
|
|
3532
3606
|
operationType: "read"
|
|
3533
3607
|
};
|
|
3534
3608
|
}
|
|
@@ -3613,7 +3687,13 @@ var HtmxAdminPlugin = class {
|
|
|
3613
3687
|
{ method: "put", path: `${basePath}/:id` },
|
|
3614
3688
|
{ method: "delete", path: `${basePath}/:id` }
|
|
3615
3689
|
],
|
|
3616
|
-
custom
|
|
3690
|
+
// custom 类型注册所有 HTTP 方法,允许模块在 render 方法中根据请求方法进行扩展
|
|
3691
|
+
custom: [
|
|
3692
|
+
{ method: "get", path: basePath },
|
|
3693
|
+
{ method: "post", path: basePath },
|
|
3694
|
+
{ method: "put", path: basePath },
|
|
3695
|
+
{ method: "delete", path: basePath }
|
|
3696
|
+
]
|
|
3617
3697
|
};
|
|
3618
3698
|
const routes = routeConfig[type];
|
|
3619
3699
|
for (const route of routes) {
|