@7365admin1/core 3.48.1-staging.155 → 3.48.1-staging.156
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/manpower-remark-site-scope.md +41 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/harness.mjs +19 -0
- package/test/e2e/manpower-remarks-scope.e2e.test.mjs +504 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope the manpower remarks routes to the site the remarks belong to.
|
|
6
|
+
|
|
7
|
+
A remarks row is the shift-attendance exception record for one site on one day:
|
|
8
|
+
which named guards were late or absent, and whether the estate has acknowledged
|
|
9
|
+
it. Every route on `/api/remarks` carried `requireAuth` and nothing more — the
|
|
10
|
+
controller held no authorization identifier of any kind — so being signed in
|
|
11
|
+
anywhere on the platform was enough to read another client's daily manning
|
|
12
|
+
failures, to write an acknowledgement into their record in a name of the
|
|
13
|
+
caller's choosing, or to switch a row to `inactive` so the estate's own console
|
|
14
|
+
stops listing it.
|
|
15
|
+
|
|
16
|
+
All five routes now go through `requireSiteReach`, the rule
|
|
17
|
+
`/api/manpower-monitoring`, `/api/attendances`, `/api/vehicles`,
|
|
18
|
+
`/api/documents` and `/api/incident-reports` already use:
|
|
19
|
+
|
|
20
|
+
- `GET /:id/:serviceProviderId` names the site in the URL, so it is checked
|
|
21
|
+
before the read.
|
|
22
|
+
- `PUT /:id` and `PATCH /:id` name only a record, so the site is read off the
|
|
23
|
+
**stored** row — a `siteId` in the caller's own body cannot stand in for it.
|
|
24
|
+
- `GET /` names no site at all. Its only filter is a `serviceProviderId` the
|
|
25
|
+
caller supplies, which is not a claim about the caller, and one agency works
|
|
26
|
+
for several clients — so the page came back holding every one of those
|
|
27
|
+
clients' rows. It is narrowed after the read, the way
|
|
28
|
+
`/api/manpower-monitoring`'s own `GET /search` is. The count in the envelope
|
|
29
|
+
stays the unfiltered one, as it does there; both callers read it only for the
|
|
30
|
+
pager.
|
|
31
|
+
- `POST /` writes a row for whatever `siteId` the body carries. It has no caller
|
|
32
|
+
in any web app or mobile app — the rows are written internally by
|
|
33
|
+
`manpower-monitoring.service.ts` when a site's monitoring settings are created
|
|
34
|
+
— and it is guarded all the same rather than left open.
|
|
35
|
+
|
|
36
|
+
`requireSiteReach` matters here because the contracted agency that actually runs
|
|
37
|
+
these shifts holds no membership in the estate's organisation and reaches its
|
|
38
|
+
own site through `customer.sites`.
|
|
39
|
+
|
|
40
|
+
A row the caller cannot reach answers exactly as one that does not exist, so
|
|
41
|
+
site ids cannot be enumerated by watching the difference.
|
package/dist/index.d.ts
CHANGED
|
@@ -8369,11 +8369,45 @@ declare function useManpowerRemarksRepo(): {
|
|
|
8369
8369
|
pageRange: string;
|
|
8370
8370
|
}>;
|
|
8371
8371
|
getManpowerRemarksBySiteId: (_id: string | ObjectId, date: string, serviceProviderId?: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
8372
|
+
getManpowerRemarksById: (_id: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
8372
8373
|
updateManpowerRemarks: (_id: string | ObjectId, value: TManpowerRemarksUpdate) => Promise<number>;
|
|
8373
8374
|
updateRemarksStatus: (_id: string | ObjectId, value: TManpowerRemarksStatusUpdate) => Promise<number>;
|
|
8374
8375
|
createIndexes: () => Promise<string>;
|
|
8375
8376
|
};
|
|
8376
8377
|
|
|
8378
|
+
/**
|
|
8379
|
+
* Who may see, or change, a site's manpower remarks.
|
|
8380
|
+
*
|
|
8381
|
+
* A remarks row is the shift-attendance exception record for one site on one
|
|
8382
|
+
* day: which named guards were late or absent, and whether the estate has
|
|
8383
|
+
* acknowledged it. Every route on this mount carried `requireAuth` and NOTHING
|
|
8384
|
+
* else — this controller held no authorization identifier of any kind — so
|
|
8385
|
+
* being signed in anywhere on the platform was enough to read another client's
|
|
8386
|
+
* daily manning failures, to write an acknowledgement into their record in
|
|
8387
|
+
* somebody else's name, or to switch a row to `inactive` so the estate stops
|
|
8388
|
+
* seeing it.
|
|
8389
|
+
*
|
|
8390
|
+
* The estate is the scope, the same rule `/api/manpower-monitoring`,
|
|
8391
|
+
* `/api/attendances`, `/api/vehicles`, `/api/documents` and
|
|
8392
|
+
* `/api/incident-reports` already use, so the contracted agency that actually
|
|
8393
|
+
* runs these shifts reaches its own sites through `customer.sites` and needs no
|
|
8394
|
+
* membership in the estate's own organisation.
|
|
8395
|
+
*
|
|
8396
|
+
* Three shapes, because the routes ask three different questions:
|
|
8397
|
+
* - `GET /:id/:serviceProviderId` names the site in the URL, so it is checked
|
|
8398
|
+
* BEFORE the read.
|
|
8399
|
+
* - `PUT /:id` and `PATCH /:id` name only a record, so the site is read off
|
|
8400
|
+
* the STORED row (`requireRemarkReach`) and a `siteId` in the body cannot
|
|
8401
|
+
* stand in for it.
|
|
8402
|
+
* - `GET /` names no site at all — its only filter is a `serviceProviderId`
|
|
8403
|
+
* the caller supplies — so the page has to be narrowed AFTER the read, the
|
|
8404
|
+
* way `/api/manpower-monitoring`'s own `GET /search` is.
|
|
8405
|
+
*
|
|
8406
|
+
* `POST /` writes a row for whatever `siteId` the body carries. It has no
|
|
8407
|
+
* caller in any web app or mobile app; the rows are written internally by
|
|
8408
|
+
* `manpower-monitoring.service.ts` when a site's monitoring settings are
|
|
8409
|
+
* created. It is guarded all the same rather than left open.
|
|
8410
|
+
*/
|
|
8377
8411
|
declare function useManpowerRemarkCtrl(): {
|
|
8378
8412
|
createManpowerRemark: (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
8379
8413
|
getManpowerRemarksAllSite: (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -75335,6 +75335,14 @@ function useManpowerRemarksRepo() {
|
|
|
75335
75335
|
throw error;
|
|
75336
75336
|
}
|
|
75337
75337
|
}
|
|
75338
|
+
async function getManpowerRemarksById(_id) {
|
|
75339
|
+
try {
|
|
75340
|
+
_id = new import_mongodb146.ObjectId(_id);
|
|
75341
|
+
} catch (error) {
|
|
75342
|
+
throw new import_node_server_utils231.BadRequestError("Invalid ID format.");
|
|
75343
|
+
}
|
|
75344
|
+
return await collection.findOne({ _id });
|
|
75345
|
+
}
|
|
75338
75346
|
async function updateManpowerRemarks(_id, value) {
|
|
75339
75347
|
try {
|
|
75340
75348
|
_id = new import_mongodb146.ObjectId(_id);
|
|
@@ -75382,6 +75390,7 @@ function useManpowerRemarksRepo() {
|
|
|
75382
75390
|
createManpowerRemarks,
|
|
75383
75391
|
getManpowerRemarksAllSite,
|
|
75384
75392
|
getManpowerRemarksBySiteId,
|
|
75393
|
+
getManpowerRemarksById,
|
|
75385
75394
|
updateManpowerRemarks,
|
|
75386
75395
|
updateRemarksStatus,
|
|
75387
75396
|
createIndexes
|
|
@@ -77349,8 +77358,13 @@ function useManpowerRemarkCtrl() {
|
|
|
77349
77358
|
getManpowerRemarksAllSite: _getManpowerRemarksAllSite,
|
|
77350
77359
|
updateRemarksStatus: _updateRemarksStatus,
|
|
77351
77360
|
getManpowerRemarksBySiteId: _getManpowerRemarksBySiteId,
|
|
77361
|
+
getManpowerRemarksById: _getManpowerRemarksById,
|
|
77352
77362
|
updateManpowerRemarks: _updateManpowerRemarks
|
|
77353
77363
|
} = useManpowerRemarksRepo();
|
|
77364
|
+
async function requireRemarkReach(req, _id) {
|
|
77365
|
+
const remark = await _getManpowerRemarksById(_id);
|
|
77366
|
+
await requireSiteReach(req, remark?.siteId);
|
|
77367
|
+
}
|
|
77354
77368
|
async function createManpowerRemark(req, res, next) {
|
|
77355
77369
|
try {
|
|
77356
77370
|
const payload = { ...req.body };
|
|
@@ -77359,6 +77373,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77359
77373
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77360
77374
|
return;
|
|
77361
77375
|
}
|
|
77376
|
+
await requireSiteReach(req, payload.siteId);
|
|
77362
77377
|
const result = await _createManpowerRemarks(payload);
|
|
77363
77378
|
return res.json(result);
|
|
77364
77379
|
} catch (error) {
|
|
@@ -77398,7 +77413,17 @@ function useManpowerRemarkCtrl() {
|
|
|
77398
77413
|
status: status?.toString() || "",
|
|
77399
77414
|
date: date?.toString() || ""
|
|
77400
77415
|
});
|
|
77401
|
-
|
|
77416
|
+
const { only } = await siteReachOf(req);
|
|
77417
|
+
const items = await only(
|
|
77418
|
+
(result?.items ?? []).map((row) => ({
|
|
77419
|
+
row,
|
|
77420
|
+
site: row?.siteId
|
|
77421
|
+
}))
|
|
77422
|
+
);
|
|
77423
|
+
return res.json({
|
|
77424
|
+
...result,
|
|
77425
|
+
items: items.map((entry) => entry.row)
|
|
77426
|
+
});
|
|
77402
77427
|
} catch (error) {
|
|
77403
77428
|
import_node_server_utils244.logger.log({ level: "error", message: error.message });
|
|
77404
77429
|
next(error);
|
|
@@ -77423,6 +77448,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77423
77448
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77424
77449
|
return;
|
|
77425
77450
|
}
|
|
77451
|
+
await requireSiteReach(req, id);
|
|
77426
77452
|
const result = await _getManpowerRemarksBySiteId(
|
|
77427
77453
|
id,
|
|
77428
77454
|
date,
|
|
@@ -77450,6 +77476,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77450
77476
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77451
77477
|
return;
|
|
77452
77478
|
}
|
|
77479
|
+
await requireRemarkReach(req, _id);
|
|
77453
77480
|
const result = await _updateManpowerRemarks(_id, payload);
|
|
77454
77481
|
return res.json(result);
|
|
77455
77482
|
} catch (error) {
|
|
@@ -77471,6 +77498,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77471
77498
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77472
77499
|
return;
|
|
77473
77500
|
}
|
|
77501
|
+
await requireRemarkReach(req, _id);
|
|
77474
77502
|
const result = await _updateRemarksStatus(_id, payload);
|
|
77475
77503
|
return res.json(result);
|
|
77476
77504
|
} catch (error) {
|