@valentine-efagene/qshelter-common 2.0.89 → 2.0.90

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.
@@ -53,6 +53,7 @@ export * from './Settings';
53
53
  export * from './Social';
54
54
  export * from './StepEventAttachment';
55
55
  export * from './Tenant';
56
+ export * from './TenantMembership';
56
57
  export * from './Transaction';
57
58
  export * from './User';
58
59
  export * from './UserRole';
@@ -53,6 +53,7 @@ export * from './Settings';
53
53
  export * from './Social';
54
54
  export * from './StepEventAttachment';
55
55
  export * from './Tenant';
56
+ export * from './TenantMembership';
56
57
  export * from './Transaction';
57
58
  export * from './User';
58
59
  export * from './UserRole';
@@ -13,29 +13,61 @@ export declare enum PolicyEventType {
13
13
  PERMISSION_DELETED = "POLICY.PERMISSION_DELETED",
14
14
  ROLE_PERMISSION_ASSIGNED = "POLICY.ROLE_PERMISSION_ASSIGNED",
15
15
  ROLE_PERMISSION_REVOKED = "POLICY.ROLE_PERMISSION_REVOKED",
16
+ TENANT_MEMBERSHIP_CREATED = "POLICY.TENANT_MEMBERSHIP_CREATED",
17
+ TENANT_MEMBERSHIP_UPDATED = "POLICY.TENANT_MEMBERSHIP_UPDATED",
18
+ TENANT_MEMBERSHIP_DELETED = "POLICY.TENANT_MEMBERSHIP_DELETED",
16
19
  FULL_SYNC_REQUESTED = "POLICY.FULL_SYNC_REQUESTED"
17
20
  }
21
+ /**
22
+ * Role data with tenant scoping
23
+ */
18
24
  export interface RoleData {
19
25
  id: string;
20
26
  name: string;
21
27
  description?: string | null;
28
+ tenantId?: string | null;
29
+ isSystem?: boolean;
30
+ isActive?: boolean;
22
31
  }
32
+ /**
33
+ * Permission with path-based authorization
34
+ * Matches the authorizer's expected policy structure
35
+ */
23
36
  export interface PermissionData {
24
37
  id: string;
25
38
  name: string;
26
39
  description?: string | null;
27
- resource: string;
28
- action: string;
40
+ path: string;
41
+ methods: string[];
42
+ effect: 'ALLOW' | 'DENY';
43
+ tenantId?: string | null;
29
44
  }
45
+ /**
46
+ * Role with full permission details for policy sync
47
+ */
30
48
  export interface RolePermissionData {
31
49
  roleId: string;
32
50
  roleName: string;
51
+ tenantId?: string | null;
33
52
  permissions: Array<{
34
53
  id: string;
35
- resource: string;
36
- action: string;
54
+ path: string;
55
+ methods: string[];
56
+ effect: 'ALLOW' | 'DENY';
37
57
  }>;
38
58
  }
59
+ /**
60
+ * Tenant membership data for federated users
61
+ */
62
+ export interface TenantMembershipData {
63
+ id: string;
64
+ userId: string;
65
+ tenantId: string;
66
+ roleId: string;
67
+ roleName: string;
68
+ isActive: boolean;
69
+ isDefault: boolean;
70
+ }
39
71
  export interface PolicyEventMeta {
40
72
  source: string;
41
73
  timestamp: string;
@@ -86,4 +118,17 @@ export interface FullSyncRequestedEvent extends PolicyEvent<{
86
118
  }> {
87
119
  eventType: PolicyEventType.FULL_SYNC_REQUESTED;
88
120
  }
89
- export type AnyPolicyEvent = RoleCreatedEvent | RoleUpdatedEvent | RoleDeletedEvent | PermissionCreatedEvent | PermissionUpdatedEvent | PermissionDeletedEvent | RolePermissionAssignedEvent | RolePermissionRevokedEvent | FullSyncRequestedEvent;
121
+ export interface TenantMembershipCreatedEvent extends PolicyEvent<TenantMembershipData> {
122
+ eventType: PolicyEventType.TENANT_MEMBERSHIP_CREATED;
123
+ }
124
+ export interface TenantMembershipUpdatedEvent extends PolicyEvent<TenantMembershipData> {
125
+ eventType: PolicyEventType.TENANT_MEMBERSHIP_UPDATED;
126
+ }
127
+ export interface TenantMembershipDeletedEvent extends PolicyEvent<{
128
+ membershipId: string;
129
+ userId: string;
130
+ tenantId: string;
131
+ }> {
132
+ eventType: PolicyEventType.TENANT_MEMBERSHIP_DELETED;
133
+ }
134
+ export type AnyPolicyEvent = RoleCreatedEvent | RoleUpdatedEvent | RoleDeletedEvent | PermissionCreatedEvent | PermissionUpdatedEvent | PermissionDeletedEvent | RolePermissionAssignedEvent | RolePermissionRevokedEvent | FullSyncRequestedEvent | TenantMembershipCreatedEvent | TenantMembershipUpdatedEvent | TenantMembershipDeletedEvent;
@@ -17,6 +17,10 @@ export var PolicyEventType;
17
17
  // Role-Permission association events
18
18
  PolicyEventType["ROLE_PERMISSION_ASSIGNED"] = "POLICY.ROLE_PERMISSION_ASSIGNED";
19
19
  PolicyEventType["ROLE_PERMISSION_REVOKED"] = "POLICY.ROLE_PERMISSION_REVOKED";
20
+ // Tenant membership events (for federated users)
21
+ PolicyEventType["TENANT_MEMBERSHIP_CREATED"] = "POLICY.TENANT_MEMBERSHIP_CREATED";
22
+ PolicyEventType["TENANT_MEMBERSHIP_UPDATED"] = "POLICY.TENANT_MEMBERSHIP_UPDATED";
23
+ PolicyEventType["TENANT_MEMBERSHIP_DELETED"] = "POLICY.TENANT_MEMBERSHIP_DELETED";
20
24
  // Bulk sync events
21
25
  PolicyEventType["FULL_SYNC_REQUESTED"] = "POLICY.FULL_SYNC_REQUESTED";
22
26
  })(PolicyEventType || (PolicyEventType = {}));
@@ -1,4 +1,4 @@
1
- import { PolicyEventType, PolicyEventMeta, RoleData, PermissionData, RolePermissionData } from './policy-event';
1
+ import { PolicyEventType, PolicyEventMeta, RoleData, PermissionData, RolePermissionData, TenantMembershipData } from './policy-event';
2
2
  /**
3
3
  * Configuration for the policy event publisher
4
4
  */
@@ -52,6 +52,18 @@ export declare class PolicyEventPublisher {
52
52
  * Publish role permission revoked event
53
53
  */
54
54
  publishRolePermissionRevoked(data: RolePermissionData, meta?: Partial<PolicyEventMeta>): Promise<string>;
55
+ /**
56
+ * Publish tenant membership created event
57
+ */
58
+ publishTenantMembershipCreated(data: TenantMembershipData, meta?: Partial<PolicyEventMeta>): Promise<string>;
59
+ /**
60
+ * Publish tenant membership updated event
61
+ */
62
+ publishTenantMembershipUpdated(data: TenantMembershipData, meta?: Partial<PolicyEventMeta>): Promise<string>;
63
+ /**
64
+ * Publish tenant membership deleted event
65
+ */
66
+ publishTenantMembershipDeleted(membershipId: string, userId: string, tenantId: string, meta?: Partial<PolicyEventMeta>): Promise<string>;
55
67
  /**
56
68
  * Publish full sync requested event
57
69
  */
@@ -119,6 +119,30 @@ export class PolicyEventPublisher {
119
119
  async publishRolePermissionRevoked(data, meta) {
120
120
  return this.publish(PolicyEventType.ROLE_PERMISSION_REVOKED, data, meta);
121
121
  }
122
+ /**
123
+ * Publish tenant membership created event
124
+ */
125
+ async publishTenantMembershipCreated(data, meta) {
126
+ return this.publish(PolicyEventType.TENANT_MEMBERSHIP_CREATED, data, {
127
+ ...meta,
128
+ tenantId: data.tenantId,
129
+ });
130
+ }
131
+ /**
132
+ * Publish tenant membership updated event
133
+ */
134
+ async publishTenantMembershipUpdated(data, meta) {
135
+ return this.publish(PolicyEventType.TENANT_MEMBERSHIP_UPDATED, data, {
136
+ ...meta,
137
+ tenantId: data.tenantId,
138
+ });
139
+ }
140
+ /**
141
+ * Publish tenant membership deleted event
142
+ */
143
+ async publishTenantMembershipDeleted(membershipId, userId, tenantId, meta) {
144
+ return this.publish(PolicyEventType.TENANT_MEMBERSHIP_DELETED, { membershipId, userId, tenantId }, { ...meta, tenantId });
145
+ }
122
146
  /**
123
147
  * Publish full sync requested event
124
148
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valentine-efagene/qshelter-common",
3
- "version": "2.0.89",
3
+ "version": "2.0.90",
4
4
  "description": "Shared database schemas and utilities for QShelter services",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -0,0 +1,79 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the column `action` on the `permissions` table. All the data in the column will be lost.
5
+ - You are about to drop the column `resource` on the `permissions` table. All the data in the column will be lost.
6
+ - A unique constraint covering the columns `[path,tenantId]` on the table `permissions` will be added. If there are existing duplicate values, this will fail.
7
+ - A unique constraint covering the columns `[name,tenantId]` on the table `roles` will be added. If there are existing duplicate values, this will fail.
8
+ - Added the required column `path` to the `permissions` table without a default value. This is not possible if the table is not empty.
9
+
10
+ */
11
+ -- DropIndex
12
+ DROP INDEX `permissions_name_key` ON `permissions`;
13
+
14
+ -- DropIndex
15
+ DROP INDEX `permissions_resource_action_key` ON `permissions`;
16
+
17
+ -- DropIndex
18
+ DROP INDEX `permissions_resource_idx` ON `permissions`;
19
+
20
+ -- DropIndex
21
+ DROP INDEX `roles_name_key` ON `roles`;
22
+
23
+ -- AlterTable
24
+ ALTER TABLE `permissions` DROP COLUMN `action`,
25
+ DROP COLUMN `resource`,
26
+ ADD COLUMN `effect` ENUM('ALLOW', 'DENY') NOT NULL DEFAULT 'ALLOW',
27
+ ADD COLUMN `isSystem` BOOLEAN NOT NULL DEFAULT false,
28
+ ADD COLUMN `methods` JSON NOT NULL,
29
+ ADD COLUMN `path` VARCHAR(191) NOT NULL,
30
+ ADD COLUMN `tenantId` VARCHAR(191) NULL;
31
+
32
+ -- AlterTable
33
+ ALTER TABLE `roles` ADD COLUMN `isActive` BOOLEAN NOT NULL DEFAULT true,
34
+ ADD COLUMN `isSystem` BOOLEAN NOT NULL DEFAULT false,
35
+ ADD COLUMN `tenantId` VARCHAR(191) NULL;
36
+
37
+ -- CreateTable
38
+ CREATE TABLE `tenant_memberships` (
39
+ `id` VARCHAR(191) NOT NULL,
40
+ `userId` VARCHAR(191) NOT NULL,
41
+ `tenantId` VARCHAR(191) NOT NULL,
42
+ `roleId` VARCHAR(191) NOT NULL,
43
+ `isActive` BOOLEAN NOT NULL DEFAULT true,
44
+ `isDefault` BOOLEAN NOT NULL DEFAULT false,
45
+ `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
46
+ `updatedAt` DATETIME(3) NOT NULL,
47
+
48
+ INDEX `tenant_memberships_tenantId_idx`(`tenantId`),
49
+ INDEX `tenant_memberships_userId_idx`(`userId`),
50
+ UNIQUE INDEX `tenant_memberships_userId_tenantId_key`(`userId`, `tenantId`),
51
+ PRIMARY KEY (`id`)
52
+ ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
53
+
54
+ -- CreateIndex
55
+ CREATE INDEX `permissions_tenantId_idx` ON `permissions`(`tenantId`);
56
+
57
+ -- CreateIndex
58
+ CREATE UNIQUE INDEX `permissions_path_tenantId_key` ON `permissions`(`path`, `tenantId`);
59
+
60
+ -- CreateIndex
61
+ CREATE INDEX `roles_tenantId_idx` ON `roles`(`tenantId`);
62
+
63
+ -- CreateIndex
64
+ CREATE UNIQUE INDEX `roles_name_tenantId_key` ON `roles`(`name`, `tenantId`);
65
+
66
+ -- AddForeignKey
67
+ ALTER TABLE `roles` ADD CONSTRAINT `roles_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
68
+
69
+ -- AddForeignKey
70
+ ALTER TABLE `permissions` ADD CONSTRAINT `permissions_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
71
+
72
+ -- AddForeignKey
73
+ ALTER TABLE `tenant_memberships` ADD CONSTRAINT `tenant_memberships_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
74
+
75
+ -- AddForeignKey
76
+ ALTER TABLE `tenant_memberships` ADD CONSTRAINT `tenant_memberships_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
77
+
78
+ -- AddForeignKey
79
+ ALTER TABLE `tenant_memberships` ADD CONSTRAINT `tenant_memberships_roleId_fkey` FOREIGN KEY (`roleId`) REFERENCES `roles`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;