@infuro/cms-core 1.0.30 → 1.0.33
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 +20 -15
- package/dist/admin.cjs +13061 -7814
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +13 -2
- package/dist/admin.d.ts +13 -2
- package/dist/admin.js +8416 -3167
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +5667 -1110
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +2 -2
- package/dist/api.d.ts +2 -2
- package/dist/api.js +5418 -855
- package/dist/api.js.map +1 -1
- package/dist/auth.cjs +620 -76
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +93 -52
- package/dist/auth.d.ts +93 -52
- package/dist/auth.js +578 -52
- package/dist/auth.js.map +1 -1
- package/dist/cli.cjs +19 -15
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +19 -15
- package/dist/cli.js.map +1 -1
- package/dist/{index-BPQSXgXF.d.cts → index-DWd5Gjc4.d.ts} +38 -5
- package/dist/{index-D9SdaDJ0.d.ts → index-rZTnpK7y.d.cts} +38 -5
- package/dist/index.cjs +5921 -1177
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +334 -59
- package/dist/index.d.ts +334 -59
- package/dist/index.js +5733 -1026
- package/dist/index.js.map +1 -1
- package/dist/migrations/1775400000001-AddDiscountAndOrderAddresses.ts +274 -0
- package/dist/migrations/1775800000000-VendorsAndVendorUsers.ts +74 -0
- package/dist/migrations/1775900000000-StoreVendorIdColumns.ts +124 -0
- package/dist/migrations/1775910000000-VendorOwnerRbacSeed.ts +54 -0
- package/dist/migrations/1775920000000-VendorOwnerSettingsPermission.ts +25 -0
- package/dist/migrations/1775930000000-VendorGroupStorePermissions.ts +54 -0
- package/dist/migrations/1775940000000-VendorRls.ts +71 -0
- package/dist/migrations/1775950000000-VendorCustomers.ts +87 -0
- package/dist/migrations/1775950000001-VendorCustomersPermissions.ts +67 -0
- package/dist/migrations/1778652250860-CreateCurrencyTables.ts +16 -0
- package/dist/migrations/1778652250861-OrderAddressTables.ts +88 -0
- package/dist/migrations/1778652250862-UpdateDiscountandRules.ts +100 -0
- package/dist/migrations/1778652250863-MakeCouponCodeNullable.ts +19 -0
- package/dist/migrations/1778652250864-RemoveUniqueConstraintFromDiscountCouponCode.ts +22 -0
- package/dist/migrations/1778652250865-FixOrdersAddressForeignKeys.ts +71 -0
- package/dist/migrations/1778660000000-DiscountVendorId.ts +90 -0
- package/dist/migrations/1778660000001-FixOrdersAddressFkToOrderAddresses.ts +79 -0
- package/dist/migrations/1778660000002-VendorUserIdInviteStatus.ts +61 -0
- package/dist/migrations/1778660000003-AddQrTokenToOrders.ts +32 -0
- package/dist/migrations/1779100000000-ChatConversationLeadEmailSent.ts +16 -0
- package/dist/migrations/1779200000000-LlmAgentScope.ts +72 -0
- package/dist/theme.d.cts +2 -2
- package/dist/theme.d.ts +2 -2
- package/dist/{types-D34wmivy.d.cts → types-DCVaXlPV.d.cts} +1 -1
- package/dist/{types-D34wmivy.d.ts → types-DCVaXlPV.d.ts} +1 -1
- package/dist/vendor-scope-DTYhJk_I.d.cts +129 -0
- package/dist/vendor-scope-DTYhJk_I.d.ts +129 -0
- package/package.json +3 -2
- package/dist/helpers-dlrF_49e.d.cts +0 -60
- package/dist/helpers-dlrF_49e.d.ts +0 -60
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
export class VendorUserIdInviteStatus1778660000002 implements MigrationInterface {
|
|
4
|
+
name = 'VendorUserIdInviteStatus1778660000002';
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
DO $$ BEGIN
|
|
9
|
+
CREATE TYPE "vendors_invitestatus_enum" AS ENUM ('none', 'pending', 'expired', 'accepted');
|
|
10
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
11
|
+
END $$
|
|
12
|
+
`);
|
|
13
|
+
|
|
14
|
+
await queryRunner.query(`
|
|
15
|
+
ALTER TABLE "vendors"
|
|
16
|
+
ADD COLUMN IF NOT EXISTS "userId" integer
|
|
17
|
+
`);
|
|
18
|
+
await queryRunner.query(`
|
|
19
|
+
ALTER TABLE "vendors"
|
|
20
|
+
ADD COLUMN IF NOT EXISTS "inviteStatus" "vendors_invitestatus_enum" NOT NULL DEFAULT 'none'
|
|
21
|
+
`);
|
|
22
|
+
|
|
23
|
+
await queryRunner.query(`
|
|
24
|
+
DO $$ BEGIN
|
|
25
|
+
ALTER TABLE "vendors" ADD CONSTRAINT "FK_vendors_userId"
|
|
26
|
+
FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
|
|
27
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
28
|
+
END $$
|
|
29
|
+
`);
|
|
30
|
+
|
|
31
|
+
await queryRunner.query(`
|
|
32
|
+
UPDATE "vendors" v
|
|
33
|
+
SET "userId" = vu."userId"
|
|
34
|
+
FROM "vendor_users" vu
|
|
35
|
+
WHERE v."userId" IS NULL
|
|
36
|
+
AND vu."vendorId" = v.id
|
|
37
|
+
AND vu.role = 'owner'
|
|
38
|
+
`);
|
|
39
|
+
|
|
40
|
+
await queryRunner.query(`
|
|
41
|
+
UPDATE "vendors" v
|
|
42
|
+
SET "inviteStatus" = CASE
|
|
43
|
+
WHEN u.blocked THEN 'pending'::"vendors_invitestatus_enum"
|
|
44
|
+
ELSE 'accepted'::"vendors_invitestatus_enum"
|
|
45
|
+
END
|
|
46
|
+
FROM "vendor_users" vu
|
|
47
|
+
INNER JOIN "users" u ON u.id = vu."userId"
|
|
48
|
+
WHERE vu."vendorId" = v.id
|
|
49
|
+
AND vu.role = 'owner'
|
|
50
|
+
AND v."userId" IS NOT NULL
|
|
51
|
+
AND v."inviteStatus" = 'none'::"vendors_invitestatus_enum"
|
|
52
|
+
`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
56
|
+
await queryRunner.query(`ALTER TABLE "vendors" DROP CONSTRAINT IF EXISTS "FK_vendors_userId"`);
|
|
57
|
+
await queryRunner.query(`ALTER TABLE "vendors" DROP COLUMN IF EXISTS "inviteStatus"`);
|
|
58
|
+
await queryRunner.query(`ALTER TABLE "vendors" DROP COLUMN IF EXISTS "userId"`);
|
|
59
|
+
await queryRunner.query(`DROP TYPE IF EXISTS "vendors_invitestatus_enum"`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
export class AddQrTokenToOrders1778660000003
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
name = 'AddQrTokenToOrders1778660000003';
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
ALTER TABLE "orders"
|
|
11
|
+
ADD COLUMN "qrToken" character varying
|
|
12
|
+
`);
|
|
13
|
+
|
|
14
|
+
await queryRunner.query(`
|
|
15
|
+
ALTER TABLE "orders"
|
|
16
|
+
ADD CONSTRAINT "UQ_orders_qrToken"
|
|
17
|
+
UNIQUE ("qrToken")
|
|
18
|
+
`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
22
|
+
await queryRunner.query(`
|
|
23
|
+
ALTER TABLE "orders"
|
|
24
|
+
DROP CONSTRAINT "UQ_orders_qrToken"
|
|
25
|
+
`);
|
|
26
|
+
|
|
27
|
+
await queryRunner.query(`
|
|
28
|
+
ALTER TABLE "orders"
|
|
29
|
+
DROP COLUMN "qrToken"
|
|
30
|
+
`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
/** Tracks when a lead notification email was sent for a chat conversation (avoid duplicates). */
|
|
4
|
+
export class ChatConversationLeadEmailSent1779100000000 implements MigrationInterface {
|
|
5
|
+
name = 'ChatConversationLeadEmailSent1779100000000';
|
|
6
|
+
|
|
7
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
8
|
+
await queryRunner.query(
|
|
9
|
+
`ALTER TABLE "chat_conversations" ADD COLUMN IF NOT EXISTS "leadEmailSentAt" TIMESTAMP`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
14
|
+
await queryRunner.query(`ALTER TABLE "chat_conversations" DROP COLUMN IF EXISTS "leadEmailSentAt"`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Adds `llm_agents.scope` (chatbot, blog_creation, social_media_post, blog_metadata, email_intent_chatbot),
|
|
5
|
+
* backfills existing rows by slug, seeds the email-intent classifier agent, and enforces one active row per scope.
|
|
6
|
+
*/
|
|
7
|
+
const EMAIL_INTENT_AGENT_NAME = 'Chat Lead Intent Classifier';
|
|
8
|
+
const EMAIL_INTENT_AGENT_SLUG = 'email-intent-chatbot';
|
|
9
|
+
const EMAIL_INTENT_SCOPE = 'email_intent_chatbot';
|
|
10
|
+
|
|
11
|
+
const EMAIL_INTENT_SYSTEM = `Classify the visitor message using the configured intent table.
|
|
12
|
+
Prefer a specific business intent when the visitor shows clear buying, support, or partnership signals.
|
|
13
|
+
Use NONE for greetings-only, FAQ, spam, or off-topic messages.`;
|
|
14
|
+
|
|
15
|
+
export class LlmAgentScope1779200000000 implements MigrationInterface {
|
|
16
|
+
name = 'LlmAgentScope1779200000000';
|
|
17
|
+
|
|
18
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
19
|
+
await queryRunner.query(`
|
|
20
|
+
ALTER TABLE "llm_agents"
|
|
21
|
+
ADD COLUMN IF NOT EXISTS "scope" character varying
|
|
22
|
+
`);
|
|
23
|
+
|
|
24
|
+
await queryRunner.query(`
|
|
25
|
+
UPDATE "llm_agents"
|
|
26
|
+
SET "scope" = 'chatbot'
|
|
27
|
+
WHERE "deleted" = false AND "scope" IS NULL AND "slug" = 'site-chat-assistant'
|
|
28
|
+
`);
|
|
29
|
+
await queryRunner.query(`
|
|
30
|
+
UPDATE "llm_agents"
|
|
31
|
+
SET "scope" = 'blog_creation'
|
|
32
|
+
WHERE "deleted" = false AND "scope" IS NULL AND "slug" = 'blog-generator'
|
|
33
|
+
`);
|
|
34
|
+
await queryRunner.query(`
|
|
35
|
+
UPDATE "llm_agents"
|
|
36
|
+
SET "scope" = 'social_media_post'
|
|
37
|
+
WHERE "deleted" = false AND "scope" IS NULL AND "slug" = 'blog-generator-social'
|
|
38
|
+
`);
|
|
39
|
+
await queryRunner.query(`
|
|
40
|
+
UPDATE "llm_agents"
|
|
41
|
+
SET "scope" = 'blog_metadata'
|
|
42
|
+
WHERE "deleted" = false AND "scope" IS NULL AND "slug" = 'blog-generator-metadata'
|
|
43
|
+
`);
|
|
44
|
+
|
|
45
|
+
await queryRunner.query(
|
|
46
|
+
`
|
|
47
|
+
INSERT INTO "llm_agents" ("name", "slug", "scope", "system_instruction", "enabled", "createdAt", "updatedAt", "deleted")
|
|
48
|
+
SELECT $1::varchar, $2::varchar, $3::varchar, $4::text, true, now(), now(), false
|
|
49
|
+
WHERE NOT EXISTS (
|
|
50
|
+
SELECT 1 FROM "llm_agents" a
|
|
51
|
+
WHERE a."deleted" = false AND (a."scope" = $3::varchar OR a."slug" = $2::varchar)
|
|
52
|
+
)
|
|
53
|
+
`,
|
|
54
|
+
[EMAIL_INTENT_AGENT_NAME, EMAIL_INTENT_AGENT_SLUG, EMAIL_INTENT_SCOPE, EMAIL_INTENT_SYSTEM]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
await queryRunner.query(`
|
|
58
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "UQ_llm_agents_scope_active"
|
|
59
|
+
ON "llm_agents" ("scope")
|
|
60
|
+
WHERE "deleted" = false AND "scope" IS NOT NULL
|
|
61
|
+
`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
65
|
+
await queryRunner.query(`DROP INDEX IF EXISTS "UQ_llm_agents_scope_active"`);
|
|
66
|
+
await queryRunner.query(`
|
|
67
|
+
DELETE FROM "llm_agents"
|
|
68
|
+
WHERE "slug" = $1 AND "scope" = $2
|
|
69
|
+
`, [EMAIL_INTENT_AGENT_SLUG, EMAIL_INTENT_SCOPE]);
|
|
70
|
+
await queryRunner.query(`ALTER TABLE "llm_agents" DROP COLUMN IF EXISTS "scope"`);
|
|
71
|
+
}
|
|
72
|
+
}
|
package/dist/theme.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ComponentMeta,
|
|
2
|
-
export { L as LayoutConfig,
|
|
1
|
+
import { C as ComponentMeta, c as ThemeConfig, a as NavbarConfig, F as FooterConfig } from './types-DCVaXlPV.cjs';
|
|
2
|
+
export { L as LayoutConfig, N as NavItem, P as PropDefinition, b as PropType, T as ThemeComponent } from './types-DCVaXlPV.cjs';
|
|
3
3
|
import React$1 from 'react';
|
|
4
4
|
|
|
5
5
|
declare function createTheme(config: ThemeConfig): ThemeConfig;
|
package/dist/theme.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ComponentMeta,
|
|
2
|
-
export { L as LayoutConfig,
|
|
1
|
+
import { C as ComponentMeta, c as ThemeConfig, a as NavbarConfig, F as FooterConfig } from './types-DCVaXlPV.js';
|
|
2
|
+
export { L as LayoutConfig, N as NavItem, P as PropDefinition, b as PropType, T as ThemeComponent } from './types-DCVaXlPV.js';
|
|
3
3
|
import React$1 from 'react';
|
|
4
4
|
|
|
5
5
|
declare function createTheme(config: ThemeConfig): ThemeConfig;
|
|
@@ -75,4 +75,4 @@ interface ThemeConfig {
|
|
|
75
75
|
layout?: LayoutConfig;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export type { ComponentMeta as C, FooterConfig as F, LayoutConfig as L,
|
|
78
|
+
export type { ComponentMeta as C, FooterConfig as F, LayoutConfig as L, NavItem as N, PropDefinition as P, ThemeComponent as T, NavbarConfig as a, PropType as b, ThemeConfig as c };
|
|
@@ -75,4 +75,4 @@ interface ThemeConfig {
|
|
|
75
75
|
layout?: LayoutConfig;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export type { ComponentMeta as C, FooterConfig as F, LayoutConfig as L,
|
|
78
|
+
export type { ComponentMeta as C, FooterConfig as F, LayoutConfig as L, NavItem as N, PropDefinition as P, ThemeComponent as T, NavbarConfig as a, PropType as b, ThemeConfig as c };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/** Canonical name for new installs / migrations */
|
|
2
|
+
declare const ADMIN_GROUP_NAME = "Administrator";
|
|
3
|
+
/** System administrator group (roles UI + users / user_groups / permissions bypass). */
|
|
4
|
+
declare function isSuperAdminGroupName(name: string | null | undefined): boolean;
|
|
5
|
+
type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';
|
|
6
|
+
type EntityPermissionFlags = {
|
|
7
|
+
c: boolean;
|
|
8
|
+
r: boolean;
|
|
9
|
+
u: boolean;
|
|
10
|
+
d: boolean;
|
|
11
|
+
};
|
|
12
|
+
declare function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[];
|
|
13
|
+
declare function permissionRowsToRecord(rows: Array<{
|
|
14
|
+
entity: string;
|
|
15
|
+
canCreate: boolean;
|
|
16
|
+
canRead: boolean;
|
|
17
|
+
canUpdate: boolean;
|
|
18
|
+
canDelete: boolean;
|
|
19
|
+
}> | undefined): Record<string, EntityPermissionFlags>;
|
|
20
|
+
declare function hasEntityPermission(record: Record<string, EntityPermissionFlags> | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Administrator bypass is now full entity access via `isRBACAdmin` in `sessionHasEntityAccess`.
|
|
24
|
+
* Kept for backwards-compatible imports.
|
|
25
|
+
*/
|
|
26
|
+
declare const RBAC_ADMIN_ONLY_ENTITIES: Set<string>;
|
|
27
|
+
interface SessionUser {
|
|
28
|
+
id?: string;
|
|
29
|
+
email?: string | null;
|
|
30
|
+
name?: string | null;
|
|
31
|
+
groupId?: number;
|
|
32
|
+
/** User group display name (from login). */
|
|
33
|
+
groupName?: string | null;
|
|
34
|
+
/** @deprecated use entityPerms / isRBACAdmin */
|
|
35
|
+
permissions?: string[];
|
|
36
|
+
/** Administrator group: bypasses entity-level RBAC on all resources */
|
|
37
|
+
isRBACAdmin?: boolean;
|
|
38
|
+
entityPerms?: Record<string, EntityPermissionFlags>;
|
|
39
|
+
/** When false and not isRBACAdmin, admin API/UI is denied. */
|
|
40
|
+
adminAccess?: boolean;
|
|
41
|
+
/** Vendor stores this user can access (from vendor_users). */
|
|
42
|
+
vendorIds?: number[];
|
|
43
|
+
/** Active vendor for scoped CRUD (vendor staff). */
|
|
44
|
+
activeVendorId?: number | null;
|
|
45
|
+
/** Role for the active vendor link (`vendor_users.role`). */
|
|
46
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
47
|
+
/** Set at login: vendor store portal (not platform admin). */
|
|
48
|
+
isVendorPortal?: boolean;
|
|
49
|
+
/** Set at login: vendor store owner (team + permissions). */
|
|
50
|
+
isVendorOwner?: boolean;
|
|
51
|
+
}
|
|
52
|
+
declare function sessionHasEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
53
|
+
declare function canManageRoles(user: SessionUser | null | undefined): boolean;
|
|
54
|
+
type GetSession = () => Promise<{
|
|
55
|
+
user?: SessionUser;
|
|
56
|
+
} | null>;
|
|
57
|
+
declare const OPEN_ENDPOINTS: Array<Record<string, string[]>>;
|
|
58
|
+
declare const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]>;
|
|
59
|
+
declare function isOpenEndpoint(pathname: string): boolean;
|
|
60
|
+
declare function getRequiredPermission(pathname: string): string[] | null;
|
|
61
|
+
declare function isPublicMethod(pathname: string, method: string): boolean;
|
|
62
|
+
interface AuthHelpers {
|
|
63
|
+
requireAuth(req: Request): Promise<Response | null>;
|
|
64
|
+
requirePermission(req: Request, permission: string): Promise<Response | null>;
|
|
65
|
+
requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;
|
|
66
|
+
requireAdminAccess(req: Request): Promise<Response | null>;
|
|
67
|
+
getAuthenticatedUser(): Promise<SessionUser | null>;
|
|
68
|
+
}
|
|
69
|
+
declare function createAuthHelpers(getSession: GetSession, NextResponse: {
|
|
70
|
+
json: (body: unknown, init?: {
|
|
71
|
+
status?: number;
|
|
72
|
+
}) => Response;
|
|
73
|
+
}): AuthHelpers;
|
|
74
|
+
/** Pass return value into `createCmsApiHandler` (includes `getSessionUser` for vendor store APIs). */
|
|
75
|
+
declare function createCmsAuthBundle(getSession: GetSession, NextResponse: {
|
|
76
|
+
json: (body: unknown, init?: {
|
|
77
|
+
status?: number;
|
|
78
|
+
}) => Response;
|
|
79
|
+
}): {
|
|
80
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
81
|
+
requireAdminAccess: (req: Request) => Promise<Response | null>;
|
|
82
|
+
requireEntityPermission: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
83
|
+
getSessionUser: () => Promise<SessionUser | null>;
|
|
84
|
+
getAuthenticatedUser: () => Promise<SessionUser | null>;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** Entities with a `vendorId` column (store data). */
|
|
88
|
+
declare const VENDOR_SCOPED_STORE_ENTITIES: Set<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Store admin RBAC for vendor portal users (read/create/update/delete fallbacks in rbac-debug).
|
|
91
|
+
* Includes entities without `vendorId` that are still part of the store admin UI.
|
|
92
|
+
*/
|
|
93
|
+
declare const VENDOR_STORE_RBAC_ENTITIES: Set<string>;
|
|
94
|
+
type VendorScope = {
|
|
95
|
+
type: 'all';
|
|
96
|
+
} | {
|
|
97
|
+
type: 'vendor';
|
|
98
|
+
vendorId: number;
|
|
99
|
+
vendorIds: number[];
|
|
100
|
+
} | {
|
|
101
|
+
type: 'deny';
|
|
102
|
+
};
|
|
103
|
+
declare const VENDOR_OWNER_GROUP_NAME = "Vendor Owner";
|
|
104
|
+
/** User groups treated as vendor store staff (sidebar + scoped admin). */
|
|
105
|
+
declare function isVendorGroupName(name: string | null | undefined): boolean;
|
|
106
|
+
declare function isPlatformAdministrator(user: SessionUser | null | undefined): boolean;
|
|
107
|
+
/** Vendor portal UI (store + store admin), not platform admin. */
|
|
108
|
+
declare function isVendorPortalUser(user: SessionUser | null | undefined): boolean;
|
|
109
|
+
declare function isVendorStaff(user: SessionUser | null | undefined): boolean;
|
|
110
|
+
/** Vendor store owner (manages team + role permissions for their group). */
|
|
111
|
+
declare function isVendorOwner(user: SessionUser | null | undefined): boolean;
|
|
112
|
+
declare function canManageVendorTeam(user: SessionUser | null | undefined): boolean;
|
|
113
|
+
declare function canManageVendorRoles(user: SessionUser | null | undefined): boolean;
|
|
114
|
+
/** Platform admins (Administrator group) can onboard vendors. */
|
|
115
|
+
declare function canOnboardVendors(user: SessionUser | null | undefined): boolean;
|
|
116
|
+
declare function resolveVendorScopeFromSessionUser(user: SessionUser | null | undefined): VendorScope;
|
|
117
|
+
/** Compute portal flags at login (persist on JWT). */
|
|
118
|
+
declare function vendorPortalFlagsFromUser(input: {
|
|
119
|
+
email: string;
|
|
120
|
+
isRBACAdmin: boolean;
|
|
121
|
+
groupName?: string | null;
|
|
122
|
+
vendorIds?: number[];
|
|
123
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
124
|
+
}): {
|
|
125
|
+
isVendorPortal: boolean;
|
|
126
|
+
isVendorOwner: boolean;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { ADMIN_GROUP_NAME as A, type EntityCrudAction as E, type GetSession as G, OPEN_ENDPOINTS as O, PERMISSION_REQUIRED_ENDPOINTS as P, RBAC_ADMIN_ONLY_ENTITIES as R, type SessionUser as S, VENDOR_OWNER_GROUP_NAME as V, type AuthHelpers as a, type EntityPermissionFlags as b, VENDOR_SCOPED_STORE_ENTITIES as c, VENDOR_STORE_RBAC_ENTITIES as d, type VendorScope as e, canManageRoles as f, canManageVendorRoles as g, canManageVendorTeam as h, canOnboardVendors as i, createAuthHelpers as j, createCmsAuthBundle as k, getPermissionableEntityKeys as l, getRequiredPermission as m, hasEntityPermission as n, isOpenEndpoint as o, isPlatformAdministrator as p, isPublicMethod as q, isSuperAdminGroupName as r, isVendorGroupName as s, isVendorOwner as t, isVendorPortalUser as u, isVendorStaff as v, permissionRowsToRecord as w, resolveVendorScopeFromSessionUser as x, sessionHasEntityAccess as y, vendorPortalFlagsFromUser as z };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/** Canonical name for new installs / migrations */
|
|
2
|
+
declare const ADMIN_GROUP_NAME = "Administrator";
|
|
3
|
+
/** System administrator group (roles UI + users / user_groups / permissions bypass). */
|
|
4
|
+
declare function isSuperAdminGroupName(name: string | null | undefined): boolean;
|
|
5
|
+
type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';
|
|
6
|
+
type EntityPermissionFlags = {
|
|
7
|
+
c: boolean;
|
|
8
|
+
r: boolean;
|
|
9
|
+
u: boolean;
|
|
10
|
+
d: boolean;
|
|
11
|
+
};
|
|
12
|
+
declare function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[];
|
|
13
|
+
declare function permissionRowsToRecord(rows: Array<{
|
|
14
|
+
entity: string;
|
|
15
|
+
canCreate: boolean;
|
|
16
|
+
canRead: boolean;
|
|
17
|
+
canUpdate: boolean;
|
|
18
|
+
canDelete: boolean;
|
|
19
|
+
}> | undefined): Record<string, EntityPermissionFlags>;
|
|
20
|
+
declare function hasEntityPermission(record: Record<string, EntityPermissionFlags> | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Administrator bypass is now full entity access via `isRBACAdmin` in `sessionHasEntityAccess`.
|
|
24
|
+
* Kept for backwards-compatible imports.
|
|
25
|
+
*/
|
|
26
|
+
declare const RBAC_ADMIN_ONLY_ENTITIES: Set<string>;
|
|
27
|
+
interface SessionUser {
|
|
28
|
+
id?: string;
|
|
29
|
+
email?: string | null;
|
|
30
|
+
name?: string | null;
|
|
31
|
+
groupId?: number;
|
|
32
|
+
/** User group display name (from login). */
|
|
33
|
+
groupName?: string | null;
|
|
34
|
+
/** @deprecated use entityPerms / isRBACAdmin */
|
|
35
|
+
permissions?: string[];
|
|
36
|
+
/** Administrator group: bypasses entity-level RBAC on all resources */
|
|
37
|
+
isRBACAdmin?: boolean;
|
|
38
|
+
entityPerms?: Record<string, EntityPermissionFlags>;
|
|
39
|
+
/** When false and not isRBACAdmin, admin API/UI is denied. */
|
|
40
|
+
adminAccess?: boolean;
|
|
41
|
+
/** Vendor stores this user can access (from vendor_users). */
|
|
42
|
+
vendorIds?: number[];
|
|
43
|
+
/** Active vendor for scoped CRUD (vendor staff). */
|
|
44
|
+
activeVendorId?: number | null;
|
|
45
|
+
/** Role for the active vendor link (`vendor_users.role`). */
|
|
46
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
47
|
+
/** Set at login: vendor store portal (not platform admin). */
|
|
48
|
+
isVendorPortal?: boolean;
|
|
49
|
+
/** Set at login: vendor store owner (team + permissions). */
|
|
50
|
+
isVendorOwner?: boolean;
|
|
51
|
+
}
|
|
52
|
+
declare function sessionHasEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
53
|
+
declare function canManageRoles(user: SessionUser | null | undefined): boolean;
|
|
54
|
+
type GetSession = () => Promise<{
|
|
55
|
+
user?: SessionUser;
|
|
56
|
+
} | null>;
|
|
57
|
+
declare const OPEN_ENDPOINTS: Array<Record<string, string[]>>;
|
|
58
|
+
declare const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]>;
|
|
59
|
+
declare function isOpenEndpoint(pathname: string): boolean;
|
|
60
|
+
declare function getRequiredPermission(pathname: string): string[] | null;
|
|
61
|
+
declare function isPublicMethod(pathname: string, method: string): boolean;
|
|
62
|
+
interface AuthHelpers {
|
|
63
|
+
requireAuth(req: Request): Promise<Response | null>;
|
|
64
|
+
requirePermission(req: Request, permission: string): Promise<Response | null>;
|
|
65
|
+
requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;
|
|
66
|
+
requireAdminAccess(req: Request): Promise<Response | null>;
|
|
67
|
+
getAuthenticatedUser(): Promise<SessionUser | null>;
|
|
68
|
+
}
|
|
69
|
+
declare function createAuthHelpers(getSession: GetSession, NextResponse: {
|
|
70
|
+
json: (body: unknown, init?: {
|
|
71
|
+
status?: number;
|
|
72
|
+
}) => Response;
|
|
73
|
+
}): AuthHelpers;
|
|
74
|
+
/** Pass return value into `createCmsApiHandler` (includes `getSessionUser` for vendor store APIs). */
|
|
75
|
+
declare function createCmsAuthBundle(getSession: GetSession, NextResponse: {
|
|
76
|
+
json: (body: unknown, init?: {
|
|
77
|
+
status?: number;
|
|
78
|
+
}) => Response;
|
|
79
|
+
}): {
|
|
80
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
81
|
+
requireAdminAccess: (req: Request) => Promise<Response | null>;
|
|
82
|
+
requireEntityPermission: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
83
|
+
getSessionUser: () => Promise<SessionUser | null>;
|
|
84
|
+
getAuthenticatedUser: () => Promise<SessionUser | null>;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** Entities with a `vendorId` column (store data). */
|
|
88
|
+
declare const VENDOR_SCOPED_STORE_ENTITIES: Set<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Store admin RBAC for vendor portal users (read/create/update/delete fallbacks in rbac-debug).
|
|
91
|
+
* Includes entities without `vendorId` that are still part of the store admin UI.
|
|
92
|
+
*/
|
|
93
|
+
declare const VENDOR_STORE_RBAC_ENTITIES: Set<string>;
|
|
94
|
+
type VendorScope = {
|
|
95
|
+
type: 'all';
|
|
96
|
+
} | {
|
|
97
|
+
type: 'vendor';
|
|
98
|
+
vendorId: number;
|
|
99
|
+
vendorIds: number[];
|
|
100
|
+
} | {
|
|
101
|
+
type: 'deny';
|
|
102
|
+
};
|
|
103
|
+
declare const VENDOR_OWNER_GROUP_NAME = "Vendor Owner";
|
|
104
|
+
/** User groups treated as vendor store staff (sidebar + scoped admin). */
|
|
105
|
+
declare function isVendorGroupName(name: string | null | undefined): boolean;
|
|
106
|
+
declare function isPlatformAdministrator(user: SessionUser | null | undefined): boolean;
|
|
107
|
+
/** Vendor portal UI (store + store admin), not platform admin. */
|
|
108
|
+
declare function isVendorPortalUser(user: SessionUser | null | undefined): boolean;
|
|
109
|
+
declare function isVendorStaff(user: SessionUser | null | undefined): boolean;
|
|
110
|
+
/** Vendor store owner (manages team + role permissions for their group). */
|
|
111
|
+
declare function isVendorOwner(user: SessionUser | null | undefined): boolean;
|
|
112
|
+
declare function canManageVendorTeam(user: SessionUser | null | undefined): boolean;
|
|
113
|
+
declare function canManageVendorRoles(user: SessionUser | null | undefined): boolean;
|
|
114
|
+
/** Platform admins (Administrator group) can onboard vendors. */
|
|
115
|
+
declare function canOnboardVendors(user: SessionUser | null | undefined): boolean;
|
|
116
|
+
declare function resolveVendorScopeFromSessionUser(user: SessionUser | null | undefined): VendorScope;
|
|
117
|
+
/** Compute portal flags at login (persist on JWT). */
|
|
118
|
+
declare function vendorPortalFlagsFromUser(input: {
|
|
119
|
+
email: string;
|
|
120
|
+
isRBACAdmin: boolean;
|
|
121
|
+
groupName?: string | null;
|
|
122
|
+
vendorIds?: number[];
|
|
123
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
124
|
+
}): {
|
|
125
|
+
isVendorPortal: boolean;
|
|
126
|
+
isVendorOwner: boolean;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { ADMIN_GROUP_NAME as A, type EntityCrudAction as E, type GetSession as G, OPEN_ENDPOINTS as O, PERMISSION_REQUIRED_ENDPOINTS as P, RBAC_ADMIN_ONLY_ENTITIES as R, type SessionUser as S, VENDOR_OWNER_GROUP_NAME as V, type AuthHelpers as a, type EntityPermissionFlags as b, VENDOR_SCOPED_STORE_ENTITIES as c, VENDOR_STORE_RBAC_ENTITIES as d, type VendorScope as e, canManageRoles as f, canManageVendorRoles as g, canManageVendorTeam as h, canOnboardVendors as i, createAuthHelpers as j, createCmsAuthBundle as k, getPermissionableEntityKeys as l, getRequiredPermission as m, hasEntityPermission as n, isOpenEndpoint as o, isPlatformAdministrator as p, isPublicMethod as q, isSuperAdminGroupName as r, isVendorGroupName as s, isVendorOwner as t, isVendorPortalUser as u, isVendorStaff as v, permissionRowsToRecord as w, resolveVendorScopeFromSessionUser as x, sessionHasEntityAccess as y, vendorPortalFlagsFromUser as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infuro/cms-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"lru-cache": "^11.0.0",
|
|
123
123
|
"lucide-react": "^0.476.0",
|
|
124
124
|
"next-themes": "^0.2.1",
|
|
125
|
-
"nodemailer": "^
|
|
125
|
+
"nodemailer": "^7.0.7",
|
|
126
126
|
"papaparse": "^5.4.1",
|
|
127
127
|
"pdf-parse": "^1.1.1",
|
|
128
128
|
"pg": "^8.20.0",
|
|
@@ -130,6 +130,7 @@
|
|
|
130
130
|
"cron-parser": "^4.9.0",
|
|
131
131
|
"razorpay": "^2.9.6",
|
|
132
132
|
"react-chartjs-2": "^5.3.0",
|
|
133
|
+
"react-qr-code": "^2.0.21",
|
|
133
134
|
"reflect-metadata": "^0.2.2",
|
|
134
135
|
"rss-parser": "^3.13.0",
|
|
135
136
|
"sonner": "^2.0.6",
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/** Canonical name for new installs / migrations */
|
|
2
|
-
declare const ADMIN_GROUP_NAME = "Administrator";
|
|
3
|
-
/** System administrator group (roles UI + users / user_groups / permissions bypass). */
|
|
4
|
-
declare function isSuperAdminGroupName(name: string | null | undefined): boolean;
|
|
5
|
-
type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';
|
|
6
|
-
type EntityPermissionFlags = {
|
|
7
|
-
c: boolean;
|
|
8
|
-
r: boolean;
|
|
9
|
-
u: boolean;
|
|
10
|
-
d: boolean;
|
|
11
|
-
};
|
|
12
|
-
declare function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[];
|
|
13
|
-
declare function permissionRowsToRecord(rows: Array<{
|
|
14
|
-
entity: string;
|
|
15
|
-
canCreate: boolean;
|
|
16
|
-
canRead: boolean;
|
|
17
|
-
canUpdate: boolean;
|
|
18
|
-
canDelete: boolean;
|
|
19
|
-
}> | undefined): Record<string, EntityPermissionFlags>;
|
|
20
|
-
declare function hasEntityPermission(record: Record<string, EntityPermissionFlags> | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
21
|
-
|
|
22
|
-
/** isRBACAdmin bypasses entity checks only for these (users / roles plumbing). */
|
|
23
|
-
declare const RBAC_ADMIN_ONLY_ENTITIES: Set<string>;
|
|
24
|
-
interface SessionUser {
|
|
25
|
-
id?: string;
|
|
26
|
-
email?: string | null;
|
|
27
|
-
name?: string | null;
|
|
28
|
-
groupId?: number;
|
|
29
|
-
/** @deprecated use entityPerms / isRBACAdmin */
|
|
30
|
-
permissions?: string[];
|
|
31
|
-
/** Administrator group: full access only for users, user_groups, permissions */
|
|
32
|
-
isRBACAdmin?: boolean;
|
|
33
|
-
entityPerms?: Record<string, EntityPermissionFlags>;
|
|
34
|
-
/** When false and not isRBACAdmin, admin API/UI is denied. */
|
|
35
|
-
adminAccess?: boolean;
|
|
36
|
-
}
|
|
37
|
-
declare function sessionHasEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
38
|
-
declare function canManageRoles(user: SessionUser | null | undefined): boolean;
|
|
39
|
-
type GetSession = () => Promise<{
|
|
40
|
-
user?: SessionUser;
|
|
41
|
-
} | null>;
|
|
42
|
-
declare const OPEN_ENDPOINTS: Array<Record<string, string[]>>;
|
|
43
|
-
declare const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]>;
|
|
44
|
-
declare function isOpenEndpoint(pathname: string): boolean;
|
|
45
|
-
declare function getRequiredPermission(pathname: string): string[] | null;
|
|
46
|
-
declare function isPublicMethod(pathname: string, method: string): boolean;
|
|
47
|
-
interface AuthHelpers {
|
|
48
|
-
requireAuth(req: Request): Promise<Response | null>;
|
|
49
|
-
requirePermission(req: Request, permission: string): Promise<Response | null>;
|
|
50
|
-
requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;
|
|
51
|
-
requireAdminAccess(req: Request): Promise<Response | null>;
|
|
52
|
-
getAuthenticatedUser(): Promise<SessionUser | null>;
|
|
53
|
-
}
|
|
54
|
-
declare function createAuthHelpers(getSession: GetSession, NextResponse: {
|
|
55
|
-
json: (body: unknown, init?: {
|
|
56
|
-
status?: number;
|
|
57
|
-
}) => Response;
|
|
58
|
-
}): AuthHelpers;
|
|
59
|
-
|
|
60
|
-
export { ADMIN_GROUP_NAME as A, type EntityCrudAction as E, type GetSession as G, OPEN_ENDPOINTS as O, PERMISSION_REQUIRED_ENDPOINTS as P, RBAC_ADMIN_ONLY_ENTITIES as R, type SessionUser as S, type AuthHelpers as a, type EntityPermissionFlags as b, canManageRoles as c, createAuthHelpers as d, getRequiredPermission as e, isPublicMethod as f, getPermissionableEntityKeys as g, hasEntityPermission as h, isOpenEndpoint as i, isSuperAdminGroupName as j, permissionRowsToRecord as p, sessionHasEntityAccess as s };
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/** Canonical name for new installs / migrations */
|
|
2
|
-
declare const ADMIN_GROUP_NAME = "Administrator";
|
|
3
|
-
/** System administrator group (roles UI + users / user_groups / permissions bypass). */
|
|
4
|
-
declare function isSuperAdminGroupName(name: string | null | undefined): boolean;
|
|
5
|
-
type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';
|
|
6
|
-
type EntityPermissionFlags = {
|
|
7
|
-
c: boolean;
|
|
8
|
-
r: boolean;
|
|
9
|
-
u: boolean;
|
|
10
|
-
d: boolean;
|
|
11
|
-
};
|
|
12
|
-
declare function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[];
|
|
13
|
-
declare function permissionRowsToRecord(rows: Array<{
|
|
14
|
-
entity: string;
|
|
15
|
-
canCreate: boolean;
|
|
16
|
-
canRead: boolean;
|
|
17
|
-
canUpdate: boolean;
|
|
18
|
-
canDelete: boolean;
|
|
19
|
-
}> | undefined): Record<string, EntityPermissionFlags>;
|
|
20
|
-
declare function hasEntityPermission(record: Record<string, EntityPermissionFlags> | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
21
|
-
|
|
22
|
-
/** isRBACAdmin bypasses entity checks only for these (users / roles plumbing). */
|
|
23
|
-
declare const RBAC_ADMIN_ONLY_ENTITIES: Set<string>;
|
|
24
|
-
interface SessionUser {
|
|
25
|
-
id?: string;
|
|
26
|
-
email?: string | null;
|
|
27
|
-
name?: string | null;
|
|
28
|
-
groupId?: number;
|
|
29
|
-
/** @deprecated use entityPerms / isRBACAdmin */
|
|
30
|
-
permissions?: string[];
|
|
31
|
-
/** Administrator group: full access only for users, user_groups, permissions */
|
|
32
|
-
isRBACAdmin?: boolean;
|
|
33
|
-
entityPerms?: Record<string, EntityPermissionFlags>;
|
|
34
|
-
/** When false and not isRBACAdmin, admin API/UI is denied. */
|
|
35
|
-
adminAccess?: boolean;
|
|
36
|
-
}
|
|
37
|
-
declare function sessionHasEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
38
|
-
declare function canManageRoles(user: SessionUser | null | undefined): boolean;
|
|
39
|
-
type GetSession = () => Promise<{
|
|
40
|
-
user?: SessionUser;
|
|
41
|
-
} | null>;
|
|
42
|
-
declare const OPEN_ENDPOINTS: Array<Record<string, string[]>>;
|
|
43
|
-
declare const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]>;
|
|
44
|
-
declare function isOpenEndpoint(pathname: string): boolean;
|
|
45
|
-
declare function getRequiredPermission(pathname: string): string[] | null;
|
|
46
|
-
declare function isPublicMethod(pathname: string, method: string): boolean;
|
|
47
|
-
interface AuthHelpers {
|
|
48
|
-
requireAuth(req: Request): Promise<Response | null>;
|
|
49
|
-
requirePermission(req: Request, permission: string): Promise<Response | null>;
|
|
50
|
-
requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;
|
|
51
|
-
requireAdminAccess(req: Request): Promise<Response | null>;
|
|
52
|
-
getAuthenticatedUser(): Promise<SessionUser | null>;
|
|
53
|
-
}
|
|
54
|
-
declare function createAuthHelpers(getSession: GetSession, NextResponse: {
|
|
55
|
-
json: (body: unknown, init?: {
|
|
56
|
-
status?: number;
|
|
57
|
-
}) => Response;
|
|
58
|
-
}): AuthHelpers;
|
|
59
|
-
|
|
60
|
-
export { ADMIN_GROUP_NAME as A, type EntityCrudAction as E, type GetSession as G, OPEN_ENDPOINTS as O, PERMISSION_REQUIRED_ENDPOINTS as P, RBAC_ADMIN_ONLY_ENTITIES as R, type SessionUser as S, type AuthHelpers as a, type EntityPermissionFlags as b, canManageRoles as c, createAuthHelpers as d, getRequiredPermission as e, isPublicMethod as f, getPermissionableEntityKeys as g, hasEntityPermission as h, isOpenEndpoint as i, isSuperAdminGroupName as j, permissionRowsToRecord as p, sessionHasEntityAccess as s };
|