@managemint-solutions/sdk 0.8.0 → 0.16.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.
Files changed (74) hide show
  1. package/README.md +73 -1
  2. package/dist/additional-details/index.d.ts +3 -1
  3. package/dist/additional-details/index.js +15 -28
  4. package/dist/additional-details/index.js.map +1 -1
  5. package/dist/audit/dto.d.ts +13 -0
  6. package/dist/audit/dto.js +90 -0
  7. package/dist/audit/dto.js.map +1 -0
  8. package/dist/audit/index.d.ts +104 -0
  9. package/dist/audit/index.js +308 -0
  10. package/dist/audit/index.js.map +1 -0
  11. package/dist/billing/dto.d.ts +33 -0
  12. package/dist/billing/dto.js +71 -0
  13. package/dist/billing/dto.js.map +1 -0
  14. package/dist/billing/index.d.ts +35 -0
  15. package/dist/billing/index.js +115 -0
  16. package/dist/billing/index.js.map +1 -0
  17. package/dist/client.d.ts +12 -0
  18. package/dist/client.js +23 -7
  19. package/dist/client.js.map +1 -1
  20. package/dist/clients/index.d.ts +3 -1
  21. package/dist/clients/index.js +25 -62
  22. package/dist/clients/index.js.map +1 -1
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.js +8 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/nest/index.d.ts +22 -0
  27. package/dist/nest/index.js +28 -1
  28. package/dist/nest/index.js.map +1 -1
  29. package/dist/notes/index.d.ts +3 -1
  30. package/dist/notes/index.js +16 -27
  31. package/dist/notes/index.js.map +1 -1
  32. package/dist/notifications/dto.d.ts +10 -0
  33. package/dist/notifications/dto.js +63 -0
  34. package/dist/notifications/dto.js.map +1 -0
  35. package/dist/notifications/index.d.ts +139 -0
  36. package/dist/notifications/index.js +354 -0
  37. package/dist/notifications/index.js.map +1 -0
  38. package/dist/organizations/dto.d.ts +62 -0
  39. package/dist/organizations/dto.js +445 -0
  40. package/dist/organizations/dto.js.map +1 -0
  41. package/dist/organizations/index.d.ts +72 -0
  42. package/dist/organizations/index.js +221 -0
  43. package/dist/organizations/index.js.map +1 -0
  44. package/dist/permissions/dto.d.ts +27 -0
  45. package/dist/permissions/dto.js +215 -0
  46. package/dist/permissions/dto.js.map +1 -0
  47. package/dist/permissions/index.d.ts +36 -0
  48. package/dist/permissions/index.js +110 -0
  49. package/dist/permissions/index.js.map +1 -0
  50. package/dist/projects/index.d.ts +3 -1
  51. package/dist/projects/index.js +25 -62
  52. package/dist/projects/index.js.map +1 -1
  53. package/dist/service-client/index.d.ts +72 -0
  54. package/dist/service-client/index.js +119 -0
  55. package/dist/service-client/index.js.map +1 -0
  56. package/dist/statuses/index.d.ts +3 -1
  57. package/dist/statuses/index.js +17 -28
  58. package/dist/statuses/index.js.map +1 -1
  59. package/dist/supporting-files/index.d.ts +3 -1
  60. package/dist/supporting-files/index.js +14 -20
  61. package/dist/supporting-files/index.js.map +1 -1
  62. package/dist/tasks/index.d.ts +3 -1
  63. package/dist/tasks/index.js +21 -50
  64. package/dist/tasks/index.js.map +1 -1
  65. package/dist/users/dto.d.ts +48 -0
  66. package/dist/users/dto.js +267 -0
  67. package/dist/users/dto.js.map +1 -0
  68. package/dist/users/index.d.ts +38 -0
  69. package/dist/users/index.js +144 -0
  70. package/dist/users/index.js.map +1 -0
  71. package/dist/webhook-events/index.d.ts +65 -0
  72. package/dist/webhook-events/index.js +109 -0
  73. package/dist/webhook-events/index.js.map +1 -0
  74. package/package.json +2 -2
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.OrganizationSignupResource = exports.OrganizationsResource = void 0;
18
+ const enum_1 = require("@managemint-solutions/entities/audit-trail/enum");
19
+ const audit_1 = require("../audit");
20
+ const errors_1 = require("../errors");
21
+ __exportStar(require("./dto"), exports);
22
+ // The organizations row *is* the organization: it has no organization_id column, hence
23
+ // `scopeByOrganization: false` wherever it is audited.
24
+ const ORGANIZATIONS_TABLE = {
25
+ table: 'organizations',
26
+ entityType: enum_1.AuditTrailEntityType.ORGANIZATION,
27
+ scopeByOrganization: false,
28
+ };
29
+ // The api maps this row into OrganizationEntity: the module keys stored here are priced
30
+ // against the organization's pricebook, and the flat address columns are nested. That is
31
+ // business logic, so the resource returns the row as the select string produces it.
32
+ const ORGANIZATION_SELECT = `
33
+ mms_id,
34
+ created_at,
35
+ type,
36
+ name,
37
+ trading_name,
38
+ vat_number,
39
+ registration_number,
40
+ email,
41
+ phone,
42
+ website,
43
+ marketing_consent,
44
+ industry,
45
+ currency,
46
+ updated_at,
47
+ last_updated_by:user_profiles!last_updated_by (
48
+ mms_id,
49
+ name,
50
+ surname,
51
+ email,
52
+ profile_image
53
+ ),
54
+ address_line_1,
55
+ address_line_2,
56
+ city,
57
+ state,
58
+ post_code,
59
+ country,
60
+ use_address_for_billing,
61
+ address_billing_line_1,
62
+ address_billing_line_2,
63
+ billing_city,
64
+ billing_state,
65
+ billing_post_code,
66
+ billing_country,
67
+ leave_calendar_start_month,
68
+ billing_cycle_locked,
69
+ modules,
70
+ payment_frequency,
71
+ last_payment_date,
72
+ next_payment_date,
73
+ billing_status,
74
+ billing_status_updated_at,
75
+ active_seat_count,
76
+ paid_seat_count,
77
+ card_expiring_soon,
78
+ pricebook_id
79
+ `;
80
+ /**
81
+ * The caller's own organization. Every method takes the id explicitly rather than reading it
82
+ * off the auth context, because the signup and webhook paths operate on an organization that
83
+ * is not the caller's — there is no caller at all.
84
+ */
85
+ class OrganizationsResource {
86
+ supabase;
87
+ auth;
88
+ table;
89
+ constructor(supabase, auth, audit) {
90
+ this.supabase = supabase;
91
+ this.auth = auth;
92
+ this.table = (0, audit_1.auditedTable)(supabase, auth, audit, ORGANIZATIONS_TABLE);
93
+ }
94
+ async getById(organizationId) {
95
+ const { data, error } = await this.supabase
96
+ .from('organizations')
97
+ .select(ORGANIZATION_SELECT)
98
+ .eq('mms_id', organizationId)
99
+ .single();
100
+ if (error)
101
+ throw (0, errors_1.mapPostgrestError)(error);
102
+ return data;
103
+ }
104
+ /** The caller's own organization, from the auth context. */
105
+ async get() {
106
+ return this.getById(this.auth.organization_id);
107
+ }
108
+ /**
109
+ * The whole row, unprojected. Billing reads a different handful of columns for each of its
110
+ * flows — provisioning, a module purchase, a seat charge — and they are all single-row
111
+ * lookups by primary key, so one read serves them all rather than a select string each.
112
+ */
113
+ async getRowById(organizationId) {
114
+ const { data, error } = await this.supabase
115
+ .from('organizations')
116
+ .select('*')
117
+ .eq('mms_id', organizationId)
118
+ .single();
119
+ if (error)
120
+ throw (0, errors_1.mapPostgrestError)(error);
121
+ return data;
122
+ }
123
+ /**
124
+ * A status move that only lands while the organization is still in `expectedFrom` — the
125
+ * compare-and-set that stops two concurrent webhooks both advancing the subscription.
126
+ * Resolves to null when someone else moved it first.
127
+ */
128
+ async moveBillingStatus(organizationId, expectedFrom, patch) {
129
+ return this.table.updateWhere(organizationId, (query) => query.eq('billing_status', expectedFrom), { ...patch, updated_at: new Date().toISOString() });
130
+ }
131
+ async update(organizationId, patch) {
132
+ await this.table.update(organizationId, {
133
+ ...patch,
134
+ updated_at: new Date().toISOString(),
135
+ last_updated_by: this.auth.mms_id,
136
+ });
137
+ return this.getById(organizationId);
138
+ }
139
+ /** Hard delete — used by the signup rollback. Returns the row as it was. */
140
+ async remove(organizationId) {
141
+ return this.table.remove(organizationId);
142
+ }
143
+ /**
144
+ * Claims a seat atomically. This is the serialization point for concurrent user creation —
145
+ * two admins adding at once get distinct seat numbers — so it is a function, not a
146
+ * read-then-write. The caller decides what to do with the billing status it returns.
147
+ */
148
+ async reserveSeat(organizationId) {
149
+ const { data, error } = await this.supabase.rpc('reserve_organization_seat', {
150
+ p_organization_id: organizationId,
151
+ });
152
+ if (error)
153
+ throw (0, errors_1.mapPostgrestError)(error);
154
+ // A set-returning function comes back from PostgREST as an array; a single returned row can
155
+ // also arrive bare, so both shapes are accepted.
156
+ return ((Array.isArray(data) ? data[0] : data) ?? null);
157
+ }
158
+ /**
159
+ * Gives a seat back. `active_seat_count` drops immediately; `paid_seat_count` is deliberately
160
+ * untouched, because there are no mid-cycle refunds and the paid seat holds until the cycle
161
+ * turns.
162
+ */
163
+ async releaseSeat(organizationId) {
164
+ const { error } = await this.supabase.rpc('release_organization_seat', {
165
+ p_organization_id: organizationId,
166
+ });
167
+ if (error)
168
+ throw (0, errors_1.mapPostgrestError)(error);
169
+ }
170
+ }
171
+ exports.OrganizationsResource = OrganizationsResource;
172
+ /**
173
+ * Signup, on the service client. `organizations` INSERT is `false` for `authenticated` — the
174
+ * caller has no account yet, so there is no RLS context to run under.
175
+ */
176
+ class OrganizationSignupResource {
177
+ supabase;
178
+ auditFor;
179
+ constructor(supabase, auditFor) {
180
+ this.supabase = supabase;
181
+ this.auditFor = auditFor;
182
+ }
183
+ /** Whether an account already exists for this address, checked before anything is created. */
184
+ async emailInUse(email) {
185
+ const { data, error } = await this.supabase
186
+ .from('users')
187
+ .select('mms_id')
188
+ .eq('email', email)
189
+ .maybeSingle();
190
+ if (error)
191
+ throw (0, errors_1.mapPostgrestError)(error);
192
+ return data !== null;
193
+ }
194
+ /**
195
+ * Creates the organization and records its own INSERT.
196
+ *
197
+ * This is the one write that cannot go through the audited helper: the actor's organization
198
+ * is the row being inserted, so it is not knowable until the insert has returned. The audit
199
+ * row is recorded here instead, with the new organization as both the actor's organization
200
+ * and the entity.
201
+ */
202
+ async create(payload) {
203
+ const { data, error } = await this.supabase
204
+ .from('organizations')
205
+ .insert(payload)
206
+ .select('*')
207
+ .single();
208
+ if (error)
209
+ throw (0, errors_1.mapPostgrestError)(error);
210
+ const row = data;
211
+ await this.auditFor(row.mms_id).record({
212
+ action: enum_1.AuditTrailAction.INSERT,
213
+ entityType: enum_1.AuditTrailEntityType.ORGANIZATION,
214
+ entityId: row.mms_id,
215
+ changes: (0, audit_1.snapshotChanges)(row, 'new'),
216
+ });
217
+ return row;
218
+ }
219
+ }
220
+ exports.OrganizationSignupResource = OrganizationSignupResource;
221
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/organizations/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { UpdatePermissionsDto as UpdatePermissionsDtoType } from '@managemint-solutions/entities/users/permissions/dto';
2
+ export declare class UpdatePermissionsDto implements UpdatePermissionsDtoType {
3
+ readonly create_clients: boolean;
4
+ readonly read_clients: boolean;
5
+ readonly update_clients: boolean;
6
+ readonly delete_clients: boolean;
7
+ readonly create_projects: boolean;
8
+ readonly read_projects: boolean;
9
+ readonly update_projects: boolean;
10
+ readonly delete_projects: boolean;
11
+ readonly create_tasks: boolean;
12
+ readonly read_tasks: boolean;
13
+ readonly update_tasks: boolean;
14
+ readonly delete_tasks: boolean;
15
+ readonly read_invoices: boolean;
16
+ readonly create_users: boolean;
17
+ readonly read_users: boolean;
18
+ readonly update_users: boolean;
19
+ readonly delete_users: boolean;
20
+ readonly read_user_permissions: boolean;
21
+ readonly update_user_permissions: boolean;
22
+ readonly read_organizations: boolean;
23
+ readonly update_organizations: boolean;
24
+ readonly create_payments: boolean;
25
+ readonly update_subscriptions: boolean;
26
+ readonly read_logs: boolean;
27
+ }
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UpdatePermissionsDto = void 0;
13
+ const class_validator_1 = require("class-validator");
14
+ class UpdatePermissionsDto {
15
+ // @IsBoolean({ message: 'View Dashboard must be a boolean' })
16
+ // readonly view_dashboard!: boolean;
17
+ create_clients;
18
+ read_clients;
19
+ update_clients;
20
+ delete_clients;
21
+ create_projects;
22
+ read_projects;
23
+ update_projects;
24
+ delete_projects;
25
+ // @IsBoolean({ message: 'Create Budgets must be a boolean' })
26
+ // readonly create_budgets!: boolean;
27
+ // @IsBoolean({ message: 'Read Budgets must be a boolean' })
28
+ // readonly read_budgets!: boolean;
29
+ // @IsBoolean({ message: 'Update Budgets must be a boolean' })
30
+ // readonly update_budgets!: boolean;
31
+ // @IsBoolean({ message: 'Delete Budgets must be a boolean' })
32
+ // readonly delete_budgets!: boolean;
33
+ create_tasks;
34
+ read_tasks;
35
+ update_tasks;
36
+ delete_tasks;
37
+ // @IsBoolean({ message: 'Create Documents must be a boolean' })
38
+ // readonly create_documents!: boolean;
39
+ // @IsBoolean({ message: 'Read Documents must be a boolean' })
40
+ // readonly read_documents!: boolean;
41
+ // @IsBoolean({ message: 'Update Documents must be a boolean' })
42
+ // readonly update_documents!: boolean;
43
+ // @IsBoolean({ message: 'Delete Documents must be a boolean' })
44
+ // readonly delete_documents!: boolean;
45
+ // @IsBoolean({ message: 'Create Leave must be a boolean' })
46
+ // readonly create_leave!: boolean;
47
+ // @IsBoolean({ message: 'Read Leave must be a boolean' })
48
+ // readonly read_leave!: boolean;
49
+ // @IsBoolean({ message: 'Update Leave must be a boolean' })
50
+ // readonly update_leave!: boolean;
51
+ // @IsBoolean({ message: 'Delete Leave must be a boolean' })
52
+ // readonly delete_leave!: boolean;
53
+ // @IsBoolean({ message: 'Create Leave Types must be a boolean' })
54
+ // readonly create_leave_types!: boolean;
55
+ // @IsBoolean({ message: 'Read Leave Types must be a boolean' })
56
+ // readonly read_leave_types!: boolean;
57
+ // @IsBoolean({ message: 'Update Leave Types must be a boolean' })
58
+ // readonly update_leave_types!: boolean;
59
+ // @IsBoolean({ message: 'Delete Leave Types must be a boolean' })
60
+ // readonly delete_leave_types!: boolean;
61
+ // @IsBoolean({ message: 'Create Leave Requests must be a boolean' })
62
+ // readonly create_leave_requests!: boolean;
63
+ // @IsBoolean({ message: 'Read Leave Requests must be a boolean' })
64
+ // readonly read_leave_requests!: boolean;
65
+ // @IsBoolean({ message: 'Update Leave Requests must be a boolean' })
66
+ // readonly update_leave_requests!: boolean;
67
+ // @IsBoolean({ message: 'Delete Leave Requests must be a boolean' })
68
+ // readonly delete_leave_requests!: boolean;
69
+ // @IsBoolean({ message: 'Create Invoices must be a boolean' })
70
+ // readonly create_invoices!: boolean;
71
+ read_invoices;
72
+ // @IsBoolean({ message: 'Update Invoices must be a boolean' })
73
+ // readonly update_invoices!: boolean;
74
+ // @IsBoolean({ message: 'Delete Invoices must be a boolean' })
75
+ // readonly delete_invoices!: boolean;
76
+ create_users;
77
+ read_users;
78
+ update_users;
79
+ delete_users;
80
+ // @IsBoolean({ message: 'Create User Permissions must be a boolean' })
81
+ // readonly create_user_permissions!: boolean;
82
+ read_user_permissions;
83
+ update_user_permissions;
84
+ // @IsBoolean({ message: 'Delete User Permissions must be a boolean' })
85
+ // readonly delete_user_permissions!: boolean;
86
+ // @IsBoolean({ message: 'Create Organizations must be a boolean' })
87
+ // readonly create_organizations!: boolean;
88
+ read_organizations;
89
+ update_organizations;
90
+ // @IsBoolean({ message: 'Delete Organizations must be a boolean' })
91
+ // readonly delete_organizations!: boolean;
92
+ create_payments;
93
+ // @IsBoolean({ message: 'Read Payments must be a boolean' })
94
+ // readonly read_payments!: boolean;
95
+ // @IsBoolean({ message: 'Update Payments must be a boolean' })
96
+ // readonly update_payments!: boolean;
97
+ // @IsBoolean({ message: 'Delete Payments must be a boolean' })
98
+ // readonly delete_payments!: boolean;
99
+ // @IsBoolean({ message: 'Create Notifications must be a boolean' })
100
+ // readonly create_notifications!: boolean;
101
+ // @IsBoolean({ message: 'Read Notifications must be a boolean' })
102
+ // readonly read_notifications!: boolean;
103
+ // @IsBoolean({ message: 'Update Notifications must be a boolean' })
104
+ // readonly update_notifications!: boolean;
105
+ // @IsBoolean({ message: 'Delete Notifications must be a boolean' })
106
+ // readonly delete_notifications!: boolean;
107
+ // @IsBoolean({ message: 'Create Subscriptions must be a boolean' })
108
+ // readonly create_subscriptions!: boolean;
109
+ // @IsBoolean({ message: 'Read Subscriptions must be a boolean' })
110
+ // readonly read_subscriptions!: boolean;
111
+ update_subscriptions;
112
+ // @IsBoolean({ message: 'Delete Subscriptions must be a boolean' })
113
+ // readonly delete_subscriptions!: boolean;
114
+ // @IsBoolean({ message: 'Create Logs must be a boolean' })
115
+ // readonly create_logs!: boolean;
116
+ read_logs;
117
+ }
118
+ exports.UpdatePermissionsDto = UpdatePermissionsDto;
119
+ __decorate([
120
+ (0, class_validator_1.IsBoolean)({ message: 'Create Clients must be a boolean' }),
121
+ __metadata("design:type", Boolean)
122
+ ], UpdatePermissionsDto.prototype, "create_clients", void 0);
123
+ __decorate([
124
+ (0, class_validator_1.IsBoolean)({ message: 'Read Clients must be a boolean' }),
125
+ __metadata("design:type", Boolean)
126
+ ], UpdatePermissionsDto.prototype, "read_clients", void 0);
127
+ __decorate([
128
+ (0, class_validator_1.IsBoolean)({ message: 'Update Clients must be a boolean' }),
129
+ __metadata("design:type", Boolean)
130
+ ], UpdatePermissionsDto.prototype, "update_clients", void 0);
131
+ __decorate([
132
+ (0, class_validator_1.IsBoolean)({ message: 'Delete Clients must be a boolean' }),
133
+ __metadata("design:type", Boolean)
134
+ ], UpdatePermissionsDto.prototype, "delete_clients", void 0);
135
+ __decorate([
136
+ (0, class_validator_1.IsBoolean)({ message: 'Create Projects must be a boolean' }),
137
+ __metadata("design:type", Boolean)
138
+ ], UpdatePermissionsDto.prototype, "create_projects", void 0);
139
+ __decorate([
140
+ (0, class_validator_1.IsBoolean)({ message: 'Read Projects must be a boolean' }),
141
+ __metadata("design:type", Boolean)
142
+ ], UpdatePermissionsDto.prototype, "read_projects", void 0);
143
+ __decorate([
144
+ (0, class_validator_1.IsBoolean)({ message: 'Update Projects must be a boolean' }),
145
+ __metadata("design:type", Boolean)
146
+ ], UpdatePermissionsDto.prototype, "update_projects", void 0);
147
+ __decorate([
148
+ (0, class_validator_1.IsBoolean)({ message: 'Delete Projects must be a boolean' }),
149
+ __metadata("design:type", Boolean)
150
+ ], UpdatePermissionsDto.prototype, "delete_projects", void 0);
151
+ __decorate([
152
+ (0, class_validator_1.IsBoolean)({ message: 'Create Tasks must be a boolean' }),
153
+ __metadata("design:type", Boolean)
154
+ ], UpdatePermissionsDto.prototype, "create_tasks", void 0);
155
+ __decorate([
156
+ (0, class_validator_1.IsBoolean)({ message: 'Read Tasks must be a boolean' }),
157
+ __metadata("design:type", Boolean)
158
+ ], UpdatePermissionsDto.prototype, "read_tasks", void 0);
159
+ __decorate([
160
+ (0, class_validator_1.IsBoolean)({ message: 'Update Tasks must be a boolean' }),
161
+ __metadata("design:type", Boolean)
162
+ ], UpdatePermissionsDto.prototype, "update_tasks", void 0);
163
+ __decorate([
164
+ (0, class_validator_1.IsBoolean)({ message: 'Delete Tasks must be a boolean' }),
165
+ __metadata("design:type", Boolean)
166
+ ], UpdatePermissionsDto.prototype, "delete_tasks", void 0);
167
+ __decorate([
168
+ (0, class_validator_1.IsBoolean)({ message: 'Read Invoices must be a boolean' }),
169
+ __metadata("design:type", Boolean)
170
+ ], UpdatePermissionsDto.prototype, "read_invoices", void 0);
171
+ __decorate([
172
+ (0, class_validator_1.IsBoolean)({ message: 'Create Users must be a boolean' }),
173
+ __metadata("design:type", Boolean)
174
+ ], UpdatePermissionsDto.prototype, "create_users", void 0);
175
+ __decorate([
176
+ (0, class_validator_1.IsBoolean)({ message: 'Read Users must be a boolean' }),
177
+ __metadata("design:type", Boolean)
178
+ ], UpdatePermissionsDto.prototype, "read_users", void 0);
179
+ __decorate([
180
+ (0, class_validator_1.IsBoolean)({ message: 'Update Users must be a boolean' }),
181
+ __metadata("design:type", Boolean)
182
+ ], UpdatePermissionsDto.prototype, "update_users", void 0);
183
+ __decorate([
184
+ (0, class_validator_1.IsBoolean)({ message: 'Delete Users must be a boolean' }),
185
+ __metadata("design:type", Boolean)
186
+ ], UpdatePermissionsDto.prototype, "delete_users", void 0);
187
+ __decorate([
188
+ (0, class_validator_1.IsBoolean)({ message: 'Read User Permissions must be a boolean' }),
189
+ __metadata("design:type", Boolean)
190
+ ], UpdatePermissionsDto.prototype, "read_user_permissions", void 0);
191
+ __decorate([
192
+ (0, class_validator_1.IsBoolean)({ message: 'Update User Permissions must be a boolean' }),
193
+ __metadata("design:type", Boolean)
194
+ ], UpdatePermissionsDto.prototype, "update_user_permissions", void 0);
195
+ __decorate([
196
+ (0, class_validator_1.IsBoolean)({ message: 'Read Organizations must be a boolean' }),
197
+ __metadata("design:type", Boolean)
198
+ ], UpdatePermissionsDto.prototype, "read_organizations", void 0);
199
+ __decorate([
200
+ (0, class_validator_1.IsBoolean)({ message: 'Update Organizations must be a boolean' }),
201
+ __metadata("design:type", Boolean)
202
+ ], UpdatePermissionsDto.prototype, "update_organizations", void 0);
203
+ __decorate([
204
+ (0, class_validator_1.IsBoolean)({ message: 'Create Payments must be a boolean' }),
205
+ __metadata("design:type", Boolean)
206
+ ], UpdatePermissionsDto.prototype, "create_payments", void 0);
207
+ __decorate([
208
+ (0, class_validator_1.IsBoolean)({ message: 'Update Subscriptions must be a boolean' }),
209
+ __metadata("design:type", Boolean)
210
+ ], UpdatePermissionsDto.prototype, "update_subscriptions", void 0);
211
+ __decorate([
212
+ (0, class_validator_1.IsBoolean)({ message: 'Read Logs must be a boolean' }),
213
+ __metadata("design:type", Boolean)
214
+ ], UpdatePermissionsDto.prototype, "read_logs", void 0);
215
+ //# sourceMappingURL=dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/permissions/dto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { PermissionsEntity } from '@managemint-solutions/entities/users';
2
+ import { type AuditActor, type AuditResource, type AuditRow } from '../audit';
3
+ import type { TypedSupabaseClient } from '../client';
4
+ export * from './dto';
5
+ /** Owner and admin bypass every individual flag, so the guard reads all three at once. */
6
+ export type PermissionFlags = {
7
+ is_owner: boolean;
8
+ is_admin: boolean;
9
+ } & Record<string, boolean>;
10
+ /**
11
+ * The `permissions` table. Rows are created by the `on_auth_user_created` trigger and deleted
12
+ * with the user — INSERT and DELETE are `false` for `authenticated` — so this resource only
13
+ * reads and updates.
14
+ */
15
+ export declare class PermissionsResource {
16
+ private readonly supabase;
17
+ private readonly auth;
18
+ private readonly table;
19
+ constructor(supabase: TypedSupabaseClient, auth: AuditActor, audit: AuditResource);
20
+ getForUser(userId: string): Promise<PermissionsEntity>;
21
+ /**
22
+ * The one lookup `PermissionsGuard` makes per gated request: the flag the route asked for,
23
+ * plus the two that bypass it. Returns null when the caller has no permissions row, which the
24
+ * guard treats as a denial.
25
+ */
26
+ flagsFor(userId: string, flag: string): Promise<PermissionFlags | null>;
27
+ /** Whether a user owns the organization — the guard behind "you cannot deactivate the owner". */
28
+ isOwner(userId: string): Promise<boolean>;
29
+ /** Who owns the organization. Null when there is no owner row yet — signup is mid-flight. */
30
+ ownerUserId(): Promise<string | null>;
31
+ /**
32
+ * Permissions are keyed by `user_id` on the wire but audited by the row's own `mms_id`, so
33
+ * the row is resolved before the write.
34
+ */
35
+ updateForUser(userId: string, patch: AuditRow): Promise<PermissionsEntity>;
36
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.PermissionsResource = void 0;
18
+ const enum_1 = require("@managemint-solutions/entities/audit-trail/enum");
19
+ const audit_1 = require("../audit");
20
+ const errors_1 = require("../errors");
21
+ __exportStar(require("./dto"), exports);
22
+ const PERMISSIONS_TABLE = {
23
+ table: 'permissions',
24
+ entityType: enum_1.AuditTrailEntityType.PERMISSION,
25
+ };
26
+ /**
27
+ * The `permissions` table. Rows are created by the `on_auth_user_created` trigger and deleted
28
+ * with the user — INSERT and DELETE are `false` for `authenticated` — so this resource only
29
+ * reads and updates.
30
+ */
31
+ class PermissionsResource {
32
+ supabase;
33
+ auth;
34
+ table;
35
+ constructor(supabase, auth, audit) {
36
+ this.supabase = supabase;
37
+ this.auth = auth;
38
+ this.table = (0, audit_1.auditedTable)(supabase, auth, audit, PERMISSIONS_TABLE);
39
+ }
40
+ async getForUser(userId) {
41
+ const { data, error } = await this.supabase
42
+ .from('permissions')
43
+ .select('*')
44
+ .eq('user_id', userId)
45
+ .eq('organization_id', this.auth.organization_id)
46
+ .single();
47
+ if (error)
48
+ throw (0, errors_1.mapPostgrestError)(error);
49
+ return data;
50
+ }
51
+ /**
52
+ * The one lookup `PermissionsGuard` makes per gated request: the flag the route asked for,
53
+ * plus the two that bypass it. Returns null when the caller has no permissions row, which the
54
+ * guard treats as a denial.
55
+ */
56
+ async flagsFor(userId, flag) {
57
+ const { data, error } = await this.supabase
58
+ .from('permissions')
59
+ .select(`is_owner, is_admin, ${flag}`)
60
+ .eq('user_id', userId)
61
+ .eq('organization_id', this.auth.organization_id)
62
+ .maybeSingle();
63
+ if (error)
64
+ throw (0, errors_1.mapPostgrestError)(error);
65
+ return (data ?? null);
66
+ }
67
+ /** Whether a user owns the organization — the guard behind "you cannot deactivate the owner". */
68
+ async isOwner(userId) {
69
+ const { data, error } = await this.supabase
70
+ .from('permissions')
71
+ .select('is_owner')
72
+ .eq('user_id', userId)
73
+ .eq('organization_id', this.auth.organization_id)
74
+ .maybeSingle();
75
+ if (error)
76
+ throw (0, errors_1.mapPostgrestError)(error);
77
+ return data?.is_owner === true;
78
+ }
79
+ /** Who owns the organization. Null when there is no owner row yet — signup is mid-flight. */
80
+ async ownerUserId() {
81
+ const { data, error } = await this.supabase
82
+ .from('permissions')
83
+ .select('user_id')
84
+ .eq('organization_id', this.auth.organization_id)
85
+ .eq('is_owner', true)
86
+ .limit(1)
87
+ .maybeSingle();
88
+ if (error)
89
+ throw (0, errors_1.mapPostgrestError)(error);
90
+ return data?.user_id ?? null;
91
+ }
92
+ /**
93
+ * Permissions are keyed by `user_id` on the wire but audited by the row's own `mms_id`, so
94
+ * the row is resolved before the write.
95
+ */
96
+ async updateForUser(userId, patch) {
97
+ const { data, error } = await this.supabase
98
+ .from('permissions')
99
+ .select('mms_id')
100
+ .eq('user_id', userId)
101
+ .eq('organization_id', this.auth.organization_id)
102
+ .single();
103
+ if (error)
104
+ throw (0, errors_1.mapPostgrestError)(error);
105
+ await this.table.update(data.mms_id, patch);
106
+ return this.getForUser(userId);
107
+ }
108
+ }
109
+ exports.PermissionsResource = PermissionsResource;
110
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,15 @@
1
1
  import type { MmsList } from '@managemint-solutions/entities/common';
2
2
  import type { ProjectEntity, ProjectSummary } from '@managemint-solutions/entities/projects';
3
3
  import type { AuthContext } from '../auth';
4
+ import { type AuditResource } from '../audit';
4
5
  import type { TypedSupabaseClient } from '../client';
5
6
  import type { CreateProjectDto, GetProjectsDto, UpdateProjectDto } from './dto';
6
7
  export * from './dto';
7
8
  export declare class ProjectsResource {
8
9
  private readonly supabase;
9
10
  private readonly auth;
10
- constructor(supabase: TypedSupabaseClient, auth: AuthContext);
11
+ private readonly table;
12
+ constructor(supabase: TypedSupabaseClient, auth: AuthContext, audit: AuditResource);
11
13
  list(query: GetProjectsDto): Promise<MmsList<ProjectSummary>>;
12
14
  getById(projectId: string): Promise<ProjectEntity>;
13
15
  create(input: CreateProjectDto): Promise<ProjectEntity>;