@7365admin1/core 3.47.1-staging.140 → 3.47.1-staging.141

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.
@@ -0,0 +1,44 @@
1
+ ---
2
+ "@7365admin1/core": minor
3
+ ---
4
+
5
+ Scope the organisation lookups so they stop mapping one client to another.
6
+
7
+ Four reads on `/api/organizations` carried `requireAuth` and nothing more, and
8
+ every one took its key straight from the URL:
9
+
10
+ - `GET /api/organizations/user/:user` — which organisations ANY person belongs to
11
+ - `GET /api/organizations/orgs/:email` — the same, keyed on ANY email address
12
+ - `GET /api/organizations/name/:name` — any organisation, by name
13
+ - `GET /api/organizations/email/:email` — any organisation, by email address
14
+
15
+ Together those are a cross-client directory and an account-enumeration oracle: a
16
+ resident of one estate could map which clients an address or a user id belongs
17
+ to across the whole platform.
18
+
19
+ Each is now decided from the session:
20
+
21
+ - `user/:user` — the caller's own id, or Seven365 staff. Every live caller asks
22
+ about itself: the seven service-provider app layouts, the org app, and the
23
+ resident mobile app all pass the signed-in user's own id.
24
+ - `orgs/:email` — the caller's own address, compared case-insensitively after
25
+ being resolved from the session, or Seven365 staff. All three live callers
26
+ pass the signed-in user's own address.
27
+ - `name/:name` — Seven365 staff. Its only caller is the staff console's client
28
+ list.
29
+ - `email/:email` — Seven365 staff. No caller exists in any repository in the
30
+ organisation.
31
+
32
+ A key that does not exist is refused exactly as one that does, so the refusal
33
+ itself is not an oracle.
34
+
35
+ `GET /api/organizations/id/:id` is deliberately NOT guarded here: the same
36
+ controller function is mounted a second time, unauthenticated, at
37
+ `/api/organizations/org/id/:id`, which the sign-up-invite screens call before an
38
+ account exists. Guarding the handler would guard both mounts and break
39
+ registration. That one needs the alias split first.
40
+
41
+ `GET /api/organizations/` (the full client list) is also unchanged and is
42
+ recorded as a decision for the leads: it is reached from a live signup path that
43
+ must move onto the organisation `POST /api/organizations/onboarding` already
44
+ returns before the list can be staff-gated.
package/dist/index.js CHANGED
@@ -21171,6 +21171,7 @@ async function recordConsoleAction(entry) {
21171
21171
  // src/controllers/organization.controller.ts
21172
21172
  function useOrgController() {
21173
21173
  const { getOrgsByMembership } = useMemberRepo();
21174
+ const { getUserById: _getUserById } = useUserRepo();
21174
21175
  const {
21175
21176
  getByName: _getByName,
21176
21177
  getById: _getById,
@@ -21298,6 +21299,9 @@ function useOrgController() {
21298
21299
  const user = req.params.user;
21299
21300
  const type = req.query.type ?? "";
21300
21301
  try {
21302
+ if (user !== callerId(req)) {
21303
+ await requirePlatformStaff(req);
21304
+ }
21301
21305
  const data = await getOrgsByMembership({
21302
21306
  search,
21303
21307
  page,
@@ -21323,6 +21327,7 @@ function useOrgController() {
21323
21327
  return;
21324
21328
  }
21325
21329
  try {
21330
+ await requirePlatformStaff(req);
21326
21331
  const data = await _getByName(name);
21327
21332
  res.json(data);
21328
21333
  return;
@@ -21360,6 +21365,7 @@ function useOrgController() {
21360
21365
  return;
21361
21366
  }
21362
21367
  try {
21368
+ await requirePlatformStaff(req);
21363
21369
  const data = await _getByEmail(email);
21364
21370
  if (!data) {
21365
21371
  next(new import_node_server_utils54.NotFoundError("Organization not found."));
@@ -21387,6 +21393,10 @@ function useOrgController() {
21387
21393
  }
21388
21394
  const email = req.params.email;
21389
21395
  try {
21396
+ const self = await _getUserById(callerId(req)).catch(() => null);
21397
+ if (!self?.email || self.email.toLowerCase() !== email.toLowerCase()) {
21398
+ await requirePlatformStaff(req);
21399
+ }
21390
21400
  const data = await _getOrgsByEmail(email);
21391
21401
  res.json(data);
21392
21402
  return;