@7365admin1/core 3.60.0 → 3.60.1-staging.273
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/.changeset/org-update-diagnosable-error.md +14 -0
- package/.changeset/patrol-email-scope-restore.md +16 -0
- package/.changeset/role-read-self-arm.md +5 -0
- package/.changeset/user-email-allowlist-subscription-authz.md +21 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +1421 -1192
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1460 -1231
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/backfill-org-owner-roles.test.mjs +152 -0
- package/tools/backfill-org-owner-roles/backfill.mjs +218 -0
- package/tools/backfill-org-owner-roles/dry-run-devtools-snippet.js +81 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Say what is wrong when an organisation cannot be saved.
|
|
6
|
+
|
|
7
|
+
`PUT /api/organizations/:id` — the write behind onboarding step 1 and the staff
|
|
8
|
+
Client List edit — collapsed every MongoDB write error into a 500 reading
|
|
9
|
+
"Failed to update organization.", with only `error.message` in the log. A
|
|
10
|
+
duplicate-key refusal (the `organizations` collection still carries a unique
|
|
11
|
+
index an earlier version of this file created and nothing ever dropped) is now
|
|
12
|
+
a 400 naming the field the caller has to change, a typed error raised
|
|
13
|
+
underneath is no longer turned into a 500, and the log line carries the error
|
|
14
|
+
name, code, key and the organisation id.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Restore and extend the site scoping on the patrol-log email endpoints.
|
|
6
|
+
|
|
7
|
+
#1967 added a `requireSiteReach` guard to `POST /api/patrol-logs/email`. #1981,
|
|
8
|
+
branched before #1967 landed, rewrote the same controller to add the history
|
|
9
|
+
endpoints and dropped the guard. Neither repo runs its tests in CI, so the e2e
|
|
10
|
+
test #1967 shipped has been failing on `main` unnoticed ever since.
|
|
11
|
+
|
|
12
|
+
All five endpoints now resolve the caller from the session: the two that name a
|
|
13
|
+
site (`send`, `getAll`) check that site, and the three that name a record
|
|
14
|
+
(`resend`, `getById`, `deleteById`) check the site stored on the record. The
|
|
15
|
+
`createdBy` pinning is restored with them, so a send cannot be filed under
|
|
16
|
+
another user's name.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope `GET /api/roles/id/:id`: a caller may read a role they themselves hold (resolved from the session's own `members` rows), otherwise the role's organisation rule applies. Closes the cross-tenant read of any organisation's role name and permissions.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Narrow the account-by-e-mail lookup to identity only, and scope the two open subscription reads
|
|
6
|
+
|
|
7
|
+
`GET /api/users/email/:email` and its v2 twin `GET /api/users/v2/email/:email`
|
|
8
|
+
stripped the password hash and session id from the reply but answered every
|
|
9
|
+
other stored field, so any signed-in account could read any other account's
|
|
10
|
+
NRIC, contact number, date of birth, gender, default organisation, status and
|
|
11
|
+
profile just by knowing the e-mail address — across every client on the
|
|
12
|
+
platform. Both now answer `{_id, name, email}` and nothing else. An
|
|
13
|
+
organisation gate would have been the wrong fix: this endpoint exists for the
|
|
14
|
+
invite flow, where the person being looked up is deliberately not in the
|
|
15
|
+
caller's organisation yet.
|
|
16
|
+
|
|
17
|
+
`GET /api/subscriptions/org/:id` answered any organisation's billing record —
|
|
18
|
+
plan, seat count, price, currency, renewal date — to any signed-in account, and
|
|
19
|
+
`GET /api/subscriptions/` answered every subscription on the platform in one
|
|
20
|
+
list. They now carry `requireOrgAccess` and `requirePlatformStaff`, the two
|
|
21
|
+
gates already used elsewhere in the same file.
|
package/dist/index.d.ts
CHANGED
|
@@ -718,6 +718,8 @@ type TOrg = {
|
|
|
718
718
|
nature: string;
|
|
719
719
|
email?: string;
|
|
720
720
|
contact?: string;
|
|
721
|
+
/** Chosen by the owner while creating the organisation. */
|
|
722
|
+
country?: string;
|
|
721
723
|
busInst?: string;
|
|
722
724
|
status?: string;
|
|
723
725
|
defaultSite?: string;
|
|
@@ -753,6 +755,7 @@ declare const orgSchema: Joi.ObjectSchema<any>;
|
|
|
753
755
|
declare function MOrg(value: TOrg): TOrg;
|
|
754
756
|
|
|
755
757
|
declare function useOrgRepo(): {
|
|
758
|
+
getByCreatorAndNature: (createdBy: string | ObjectId, nature: string) => Promise<TOrg | null>;
|
|
756
759
|
createIndex: () => Promise<void>;
|
|
757
760
|
createTextIndex: () => Promise<void>;
|
|
758
761
|
createUniqueIndex: () => Promise<void>;
|
|
@@ -10192,6 +10195,13 @@ type TVerificationCode = {
|
|
|
10192
10195
|
attempts?: number;
|
|
10193
10196
|
/** Set when the code was accepted; the code itself is cleared at that point. */
|
|
10194
10197
|
verifiedAt?: string | null;
|
|
10198
|
+
/**
|
|
10199
|
+
* The PASSWORD gate, used instead of a code when the invitee already has an
|
|
10200
|
+
* account (a second organisation under the same person). Counted per
|
|
10201
|
+
* invitation so a fumbled attempt here never locks the real sign-in.
|
|
10202
|
+
*/
|
|
10203
|
+
passwordAttempts?: number;
|
|
10204
|
+
lockedUntil?: string | null;
|
|
10195
10205
|
};
|
|
10196
10206
|
/**
|
|
10197
10207
|
* Where an invitee got to in onboarding, kept on the invitation so it survives
|
|
@@ -10338,6 +10348,11 @@ declare function useVerificationRepoV2(): {
|
|
|
10338
10348
|
org?: string | ObjectId | null | undefined;
|
|
10339
10349
|
completed?: boolean | undefined;
|
|
10340
10350
|
}, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
|
|
10351
|
+
setInvitePasswordGate: ({ _id, attempts, lockedUntil, }: {
|
|
10352
|
+
_id: string | ObjectId;
|
|
10353
|
+
attempts: number;
|
|
10354
|
+
lockedUntil: string | null;
|
|
10355
|
+
}, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
|
|
10341
10356
|
};
|
|
10342
10357
|
|
|
10343
10358
|
declare function useVerificationServiceV2(): {
|
|
@@ -10448,6 +10463,55 @@ declare function useVerificationServiceV2(): {
|
|
|
10448
10463
|
org: string;
|
|
10449
10464
|
completedAt: string | null;
|
|
10450
10465
|
}>;
|
|
10466
|
+
verifyInvitePassword: ({ inviteId, password, }: {
|
|
10467
|
+
inviteId: string;
|
|
10468
|
+
password: string;
|
|
10469
|
+
}) => Promise<{
|
|
10470
|
+
status: string;
|
|
10471
|
+
lockedUntil: string | null | undefined;
|
|
10472
|
+
secondsRemaining: number;
|
|
10473
|
+
message: string;
|
|
10474
|
+
sid?: undefined;
|
|
10475
|
+
user?: undefined;
|
|
10476
|
+
email?: undefined;
|
|
10477
|
+
name?: undefined;
|
|
10478
|
+
inviteId?: undefined;
|
|
10479
|
+
app?: undefined;
|
|
10480
|
+
attemptsLeft?: undefined;
|
|
10481
|
+
} | {
|
|
10482
|
+
status: string;
|
|
10483
|
+
sid: string;
|
|
10484
|
+
user: string;
|
|
10485
|
+
email: string;
|
|
10486
|
+
name: string;
|
|
10487
|
+
inviteId: string;
|
|
10488
|
+
app: string;
|
|
10489
|
+
message: string;
|
|
10490
|
+
lockedUntil?: undefined;
|
|
10491
|
+
secondsRemaining?: undefined;
|
|
10492
|
+
attemptsLeft?: undefined;
|
|
10493
|
+
} | {
|
|
10494
|
+
status: string;
|
|
10495
|
+
attemptsLeft: number;
|
|
10496
|
+
message: string;
|
|
10497
|
+
lockedUntil?: undefined;
|
|
10498
|
+
secondsRemaining?: undefined;
|
|
10499
|
+
sid?: undefined;
|
|
10500
|
+
user?: undefined;
|
|
10501
|
+
email?: undefined;
|
|
10502
|
+
name?: undefined;
|
|
10503
|
+
inviteId?: undefined;
|
|
10504
|
+
app?: undefined;
|
|
10505
|
+
}>;
|
|
10506
|
+
getInviteAccount: (inviteId: string) => Promise<{
|
|
10507
|
+
inviteId: string;
|
|
10508
|
+
email: string;
|
|
10509
|
+
app: string;
|
|
10510
|
+
role: string;
|
|
10511
|
+
invitedName: string;
|
|
10512
|
+
exists: boolean;
|
|
10513
|
+
name: string;
|
|
10514
|
+
}>;
|
|
10451
10515
|
};
|
|
10452
10516
|
|
|
10453
10517
|
declare function useVerificationControllerV2(): {
|
|
@@ -10463,6 +10527,8 @@ declare function useVerificationControllerV2(): {
|
|
|
10463
10527
|
verifyInviteCode: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
10464
10528
|
getOnboarding: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
10465
10529
|
updateOnboarding: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
10530
|
+
verifyInvitePassword: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
10531
|
+
getInviteAccount: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
10466
10532
|
};
|
|
10467
10533
|
|
|
10468
10534
|
/**
|