@7365admin1/core 3.48.1-staging.155 → 3.48.1-staging.157
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/.changeset/site-entrypass-settings-scope.md +53 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +59 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/harness.mjs +42 -0
- package/test/e2e/manpower-remarks-scope.e2e.test.mjs +504 -0
- package/test/e2e/site-entrypass-settings-scope.e2e.test.mjs +535 -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.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope the entry pass settings routes to their site, and take the writer's
|
|
6
|
+
identity from the session.
|
|
7
|
+
|
|
8
|
+
These rows decide how a site issues visitor passes: whether passes are on at
|
|
9
|
+
all, whether a physical or NFC pass is used, which USB printer model the
|
|
10
|
+
gatehouse drives, and the header, disclaimer and URL printed on the pass a
|
|
11
|
+
visitor is handed at the gate. All seven routes on
|
|
12
|
+
`/api/site-entrypass-settings` carried `requireAuth` and nothing more — the
|
|
13
|
+
controller held no authorization identifier of any kind.
|
|
14
|
+
|
|
15
|
+
Two defects were fixed, not one.
|
|
16
|
+
|
|
17
|
+
**No scope.** `GET /` returned every row on the platform: it accepts `org` and
|
|
18
|
+
`site` query parameters and the repository never applies them, so a filter that
|
|
19
|
+
looked like scoping was not one. The record routes took an id and no site.
|
|
20
|
+
`GET|PUT /site/:site` took a site straight off the URL. All seven now go through
|
|
21
|
+
`requireSiteReach`, the rule `/api/access-management`,
|
|
22
|
+
`/api/manpower-monitoring`, `/api/attendances`, `/api/vehicles`,
|
|
23
|
+
`/api/documents` and `/api/incident-reports` already use:
|
|
24
|
+
|
|
25
|
+
- `POST /` and `GET|PUT /site/:site` name a site in the request; it is checked
|
|
26
|
+
before it is used.
|
|
27
|
+
- `GET|PUT|DELETE /:id` name only a record, so the site is read off the
|
|
28
|
+
**stored** row — a `site` in the caller's own body cannot stand in for it.
|
|
29
|
+
- `PUT /:id` and `PUT /site/:site` can also **move** a row, because the body's
|
|
30
|
+
`site` is `$set`, so the destination is checked as well as the origin.
|
|
31
|
+
- `GET /` is narrowed after the read. It cannot be narrowed in the repository:
|
|
32
|
+
the page is cached under a key built only from page/limit/status/sort, so a
|
|
33
|
+
per-caller filter there would be served to the next caller. The count in the
|
|
34
|
+
envelope stays the unfiltered one, as it does on the sibling lists.
|
|
35
|
+
|
|
36
|
+
**The writer's identity came from a cookie the caller writes.** `add`,
|
|
37
|
+
`updateEntryPassSettingsById` and `updateEntryPassSettingsBySiteId` each parsed
|
|
38
|
+
the raw `Cookie` header for a `user` value and stored it as `createdBy` /
|
|
39
|
+
`updatedBy` without ever comparing it to the session, so the audit trail on
|
|
40
|
+
these rows was whatever the caller typed. It now comes from `callerId(req)`.
|
|
41
|
+
That also removes a latent crash: `cookies?.["user"].toString()` short-circuits
|
|
42
|
+
only on `cookies` being nullish, so any request carrying cookies but no `user`
|
|
43
|
+
cookie called `.toString()` on `undefined` and threw.
|
|
44
|
+
|
|
45
|
+
`requireSiteReach` matters here because the contracted agency that runs the
|
|
46
|
+
gatehouse holds no membership in the estate's organisation and reaches its own
|
|
47
|
+
site through `customer.sites`.
|
|
48
|
+
|
|
49
|
+
Nothing on this mount has a live caller: `layer-common`'s
|
|
50
|
+
`useSiteEntryPassSettings` binds only `GET /:id` and no component calls it, and
|
|
51
|
+
the entry-pass screens read and write `/api/access-management/settings`, a
|
|
52
|
+
different mount over a different collection. The routes are guarded rather than
|
|
53
|
+
removed; whether this mount should exist at all is a product decision.
|
package/dist/index.d.ts
CHANGED
|
@@ -6954,6 +6954,7 @@ declare function MEntryPassSettings(value: TEntryPassSettings): {
|
|
|
6954
6954
|
};
|
|
6955
6955
|
|
|
6956
6956
|
declare function useEntryPassSettingsRepo(): {
|
|
6957
|
+
getRawEntryPassSettingsById: (_id: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
6957
6958
|
add: (value: TEntryPassSettings, session?: ClientSession) => Promise<ObjectId>;
|
|
6958
6959
|
getAll: ({ search, page, limit, sort, status, org, site, }: {
|
|
6959
6960
|
search?: string | undefined;
|
|
@@ -6976,6 +6977,51 @@ declare function useEntryPassSettingsRepo(): {
|
|
|
6976
6977
|
updateEntryPassSettingsBySiteId: (site: string | ObjectId, value: TEntryPassSettings) => Promise<number>;
|
|
6977
6978
|
};
|
|
6978
6979
|
|
|
6980
|
+
/**
|
|
6981
|
+
* Who may see, or change, a site's entry-pass settings.
|
|
6982
|
+
*
|
|
6983
|
+
* These rows decide how a site issues visitor passes: whether passes are on at
|
|
6984
|
+
* all, whether a physical or NFC pass is used, which USB printer model the
|
|
6985
|
+
* gatehouse drives, and the header, disclaimer and URL printed on the pass
|
|
6986
|
+
* itself. All seven routes carried `requireAuth` and nothing more - the
|
|
6987
|
+
* controller held no authorization identifier of any kind - so being signed in
|
|
6988
|
+
* anywhere on the platform was enough to read every client's configuration, to
|
|
6989
|
+
* turn another estate's passes off, or to rewrite the text and URL printed on a
|
|
6990
|
+
* pass a visitor is handed at the gate.
|
|
6991
|
+
*
|
|
6992
|
+
* Two defects, not one:
|
|
6993
|
+
*
|
|
6994
|
+
* 1. **No scope.** `GET /` returns every row on the platform: it accepts `org`
|
|
6995
|
+
* and `site` query parameters and the repository never applies them, so a
|
|
6996
|
+
* filter that looks like scoping is not one. The record routes take an id
|
|
6997
|
+
* and no site. `GET|PUT /site/:site` take a site straight off the URL.
|
|
6998
|
+
* 2. **The writer's identity came from a cookie the caller writes.** `add`,
|
|
6999
|
+
* `updateEntryPassSettingsById` and `updateEntryPassSettingsBySiteId` each
|
|
7000
|
+
* parsed the raw `Cookie` header for a `user` value and stored it as
|
|
7001
|
+
* `createdBy` / `updatedBy` without ever comparing it to the session, so
|
|
7002
|
+
* the audit trail on these rows was whatever the caller typed. It now comes
|
|
7003
|
+
* from `callerId(req)`, the session, as the rest of the platform does. That
|
|
7004
|
+
* also removes a latent crash: `cookies?.["user"].toString()` threw a
|
|
7005
|
+
* TypeError on any request that carried cookies but no `user` cookie.
|
|
7006
|
+
*
|
|
7007
|
+
* The estate is the scope. `requireSiteReach` is the rule
|
|
7008
|
+
* `/api/access-management`, `/api/manpower-monitoring`, `/api/attendances`,
|
|
7009
|
+
* `/api/vehicles`, `/api/documents` and `/api/incident-reports` already use, so
|
|
7010
|
+
* the contracted agency that runs the gatehouse reaches its own site through
|
|
7011
|
+
* `customer.sites` and needs no membership in the estate's own organisation.
|
|
7012
|
+
*
|
|
7013
|
+
* Where a write can also MOVE a row - the body carries `site`, and the
|
|
7014
|
+
* repository `$set`s it - the destination is checked as well as the origin, so
|
|
7015
|
+
* a row cannot be re-parented into an estate the caller cannot reach.
|
|
7016
|
+
*
|
|
7017
|
+
* Nothing on this mount has a live caller. `layer-common`'s
|
|
7018
|
+
* `useSiteEntryPassSettings` binds only `GET /:id`, and no component calls it;
|
|
7019
|
+
* the entry-pass screens read and write `/api/access-management/settings`,
|
|
7020
|
+
* which is a different mount over a different collection
|
|
7021
|
+
* (`entrypass-settings`, not `site.entrypass-settings`). The routes are guarded
|
|
7022
|
+
* rather than removed - whether this mount should exist at all is a product
|
|
7023
|
+
* decision, not one to take inside an authorization fix.
|
|
7024
|
+
*/
|
|
6979
7025
|
declare function useEntryPassSettingsController(): {
|
|
6980
7026
|
add: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
6981
7027
|
getAll: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -8369,11 +8415,45 @@ declare function useManpowerRemarksRepo(): {
|
|
|
8369
8415
|
pageRange: string;
|
|
8370
8416
|
}>;
|
|
8371
8417
|
getManpowerRemarksBySiteId: (_id: string | ObjectId, date: string, serviceProviderId?: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
8418
|
+
getManpowerRemarksById: (_id: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
8372
8419
|
updateManpowerRemarks: (_id: string | ObjectId, value: TManpowerRemarksUpdate) => Promise<number>;
|
|
8373
8420
|
updateRemarksStatus: (_id: string | ObjectId, value: TManpowerRemarksStatusUpdate) => Promise<number>;
|
|
8374
8421
|
createIndexes: () => Promise<string>;
|
|
8375
8422
|
};
|
|
8376
8423
|
|
|
8424
|
+
/**
|
|
8425
|
+
* Who may see, or change, a site's manpower remarks.
|
|
8426
|
+
*
|
|
8427
|
+
* A remarks row is the shift-attendance exception record for one site on one
|
|
8428
|
+
* day: which named guards were late or absent, and whether the estate has
|
|
8429
|
+
* acknowledged it. Every route on this mount carried `requireAuth` and NOTHING
|
|
8430
|
+
* else — this controller held no authorization identifier of any kind — so
|
|
8431
|
+
* being signed in anywhere on the platform was enough to read another client's
|
|
8432
|
+
* daily manning failures, to write an acknowledgement into their record in
|
|
8433
|
+
* somebody else's name, or to switch a row to `inactive` so the estate stops
|
|
8434
|
+
* seeing it.
|
|
8435
|
+
*
|
|
8436
|
+
* The estate is the scope, the same rule `/api/manpower-monitoring`,
|
|
8437
|
+
* `/api/attendances`, `/api/vehicles`, `/api/documents` and
|
|
8438
|
+
* `/api/incident-reports` already use, so the contracted agency that actually
|
|
8439
|
+
* runs these shifts reaches its own sites through `customer.sites` and needs no
|
|
8440
|
+
* membership in the estate's own organisation.
|
|
8441
|
+
*
|
|
8442
|
+
* Three shapes, because the routes ask three different questions:
|
|
8443
|
+
* - `GET /:id/:serviceProviderId` names the site in the URL, so it is checked
|
|
8444
|
+
* BEFORE the read.
|
|
8445
|
+
* - `PUT /:id` and `PATCH /:id` name only a record, so the site is read off
|
|
8446
|
+
* the STORED row (`requireRemarkReach`) and a `siteId` in the body cannot
|
|
8447
|
+
* stand in for it.
|
|
8448
|
+
* - `GET /` names no site at all — its only filter is a `serviceProviderId`
|
|
8449
|
+
* the caller supplies — so the page has to be narrowed AFTER the read, the
|
|
8450
|
+
* way `/api/manpower-monitoring`'s own `GET /search` is.
|
|
8451
|
+
*
|
|
8452
|
+
* `POST /` writes a row for whatever `siteId` the body carries. It has no
|
|
8453
|
+
* caller in any web app or mobile app; the rows are written internally by
|
|
8454
|
+
* `manpower-monitoring.service.ts` when a site's monitoring settings are
|
|
8455
|
+
* created. It is guarded all the same rather than left open.
|
|
8456
|
+
*/
|
|
8377
8457
|
declare function useManpowerRemarkCtrl(): {
|
|
8378
8458
|
createManpowerRemark: (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
8379
8459
|
getManpowerRemarksAllSite: (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -68316,6 +68316,14 @@ function useEntryPassSettingsRepo() {
|
|
|
68316
68316
|
throw error;
|
|
68317
68317
|
}
|
|
68318
68318
|
}
|
|
68319
|
+
async function getRawEntryPassSettingsById(_id) {
|
|
68320
|
+
try {
|
|
68321
|
+
_id = new import_mongodb129.ObjectId(_id);
|
|
68322
|
+
} catch (error) {
|
|
68323
|
+
throw new import_node_server_utils203.BadRequestError("Invalid entry pass settings ID format.");
|
|
68324
|
+
}
|
|
68325
|
+
return await collection.findOne({ _id });
|
|
68326
|
+
}
|
|
68319
68327
|
async function updateEntryPassSettingsById(_id, value) {
|
|
68320
68328
|
try {
|
|
68321
68329
|
_id = new import_mongodb129.ObjectId(_id);
|
|
@@ -68473,6 +68481,7 @@ function useEntryPassSettingsRepo() {
|
|
|
68473
68481
|
}
|
|
68474
68482
|
}
|
|
68475
68483
|
return {
|
|
68484
|
+
getRawEntryPassSettingsById,
|
|
68476
68485
|
add,
|
|
68477
68486
|
getAll,
|
|
68478
68487
|
getEntryPassSettingsById,
|
|
@@ -68492,17 +68501,18 @@ function useEntryPassSettingsController() {
|
|
|
68492
68501
|
add: _add,
|
|
68493
68502
|
getAll: _getAll,
|
|
68494
68503
|
getEntryPassSettingsById: _getEntryPassSettingsById,
|
|
68504
|
+
getRawEntryPassSettingsById: _getRawEntryPassSettingsById,
|
|
68495
68505
|
updateEntryPassSettingsById: _updateEntryPassSettingsById,
|
|
68496
68506
|
deleteEntryPassSettingsById: _deleteEntryPassSettingsById,
|
|
68497
68507
|
getEntryPassSettingsBySiteId: _getEntryPassSettingsBySiteId,
|
|
68498
68508
|
updateEntryPassSettingsBySiteId: _updateEntryPassSettingsBySiteId
|
|
68499
68509
|
} = useEntryPassSettingsRepo();
|
|
68510
|
+
async function requireEntryPassReach(req, _id) {
|
|
68511
|
+
const row = await _getRawEntryPassSettingsById(_id);
|
|
68512
|
+
await requireSiteReach(req, row?.site);
|
|
68513
|
+
}
|
|
68500
68514
|
async function add(req, res, next) {
|
|
68501
|
-
const
|
|
68502
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
68503
|
-
{}
|
|
68504
|
-
);
|
|
68505
|
-
const createdBy = cookies?.["user"].toString() ?? "";
|
|
68515
|
+
const createdBy = callerId(req);
|
|
68506
68516
|
const payload = { ...req.body, createdBy };
|
|
68507
68517
|
const { error } = schemaEntryPassSettings.validate(payload, {
|
|
68508
68518
|
abortEarly: false
|
|
@@ -68514,6 +68524,7 @@ function useEntryPassSettingsController() {
|
|
|
68514
68524
|
return;
|
|
68515
68525
|
}
|
|
68516
68526
|
try {
|
|
68527
|
+
await requireSiteReach(req, payload.site);
|
|
68517
68528
|
const data = await _add(payload);
|
|
68518
68529
|
res.status(201).json({ message: data });
|
|
68519
68530
|
return;
|
|
@@ -68548,7 +68559,9 @@ function useEntryPassSettingsController() {
|
|
|
68548
68559
|
const site = req.query.site ?? "";
|
|
68549
68560
|
try {
|
|
68550
68561
|
const data = await _getAll({ search, page, limit, status, org, site });
|
|
68551
|
-
|
|
68562
|
+
const { only } = await siteReachOf(req);
|
|
68563
|
+
const items = await only(data?.items ?? []);
|
|
68564
|
+
res.json({ ...data, items });
|
|
68552
68565
|
return;
|
|
68553
68566
|
} catch (error2) {
|
|
68554
68567
|
import_node_server_utils204.logger.log({ level: "error", message: error2.message });
|
|
@@ -68566,6 +68579,7 @@ function useEntryPassSettingsController() {
|
|
|
68566
68579
|
return;
|
|
68567
68580
|
}
|
|
68568
68581
|
try {
|
|
68582
|
+
await requireEntryPassReach(req, _id);
|
|
68569
68583
|
const data = await _getEntryPassSettingsById(_id);
|
|
68570
68584
|
res.json(data);
|
|
68571
68585
|
return;
|
|
@@ -68593,11 +68607,7 @@ function useEntryPassSettingsController() {
|
|
|
68593
68607
|
status: import_joi106.default.string().optional().allow("", null),
|
|
68594
68608
|
updatedBy: import_joi106.default.string().hex().optional().allow("", null)
|
|
68595
68609
|
});
|
|
68596
|
-
const
|
|
68597
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
68598
|
-
{}
|
|
68599
|
-
);
|
|
68600
|
-
const updatedBy = cookies?.["user"].toString() ?? "";
|
|
68610
|
+
const updatedBy = callerId(req);
|
|
68601
68611
|
const _id = req.params.id;
|
|
68602
68612
|
const payload = { ...req.body, updatedBy };
|
|
68603
68613
|
const { error } = validation.validate({ _id, ...payload });
|
|
@@ -68607,6 +68617,9 @@ function useEntryPassSettingsController() {
|
|
|
68607
68617
|
return;
|
|
68608
68618
|
}
|
|
68609
68619
|
try {
|
|
68620
|
+
await requireEntryPassReach(req, _id);
|
|
68621
|
+
if (payload.site)
|
|
68622
|
+
await requireSiteReach(req, payload.site);
|
|
68610
68623
|
await _updateEntryPassSettingsById(_id, payload);
|
|
68611
68624
|
res.json({ message: "Successfully updated entry pass settings." });
|
|
68612
68625
|
return;
|
|
@@ -68626,6 +68639,7 @@ function useEntryPassSettingsController() {
|
|
|
68626
68639
|
return;
|
|
68627
68640
|
}
|
|
68628
68641
|
try {
|
|
68642
|
+
await requireEntryPassReach(req, _id);
|
|
68629
68643
|
await _deleteEntryPassSettingsById(_id);
|
|
68630
68644
|
res.json({ message: "Successfully deleted entry pass settings." });
|
|
68631
68645
|
return;
|
|
@@ -68645,6 +68659,7 @@ function useEntryPassSettingsController() {
|
|
|
68645
68659
|
return;
|
|
68646
68660
|
}
|
|
68647
68661
|
try {
|
|
68662
|
+
await requireSiteReach(req, _id);
|
|
68648
68663
|
const data = await _getEntryPassSettingsBySiteId(_id);
|
|
68649
68664
|
res.json(data);
|
|
68650
68665
|
return;
|
|
@@ -68671,11 +68686,7 @@ function useEntryPassSettingsController() {
|
|
|
68671
68686
|
status: import_joi106.default.string().optional().allow("", null),
|
|
68672
68687
|
updatedBy: import_joi106.default.string().hex().optional().allow("", null)
|
|
68673
68688
|
});
|
|
68674
|
-
const
|
|
68675
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
68676
|
-
{}
|
|
68677
|
-
);
|
|
68678
|
-
const updatedBy = cookies?.["user"].toString() ?? "";
|
|
68689
|
+
const updatedBy = callerId(req);
|
|
68679
68690
|
const _id = req.params.site;
|
|
68680
68691
|
const payload = { ...req.body, updatedBy };
|
|
68681
68692
|
const { error } = validation.validate({ ...payload });
|
|
@@ -68685,6 +68696,9 @@ function useEntryPassSettingsController() {
|
|
|
68685
68696
|
return;
|
|
68686
68697
|
}
|
|
68687
68698
|
try {
|
|
68699
|
+
await requireSiteReach(req, _id);
|
|
68700
|
+
if (payload.site)
|
|
68701
|
+
await requireSiteReach(req, payload.site);
|
|
68688
68702
|
await _updateEntryPassSettingsBySiteId(_id, payload);
|
|
68689
68703
|
res.json({ message: "Successfully updated entry pass settings." });
|
|
68690
68704
|
return;
|
|
@@ -75335,6 +75349,14 @@ function useManpowerRemarksRepo() {
|
|
|
75335
75349
|
throw error;
|
|
75336
75350
|
}
|
|
75337
75351
|
}
|
|
75352
|
+
async function getManpowerRemarksById(_id) {
|
|
75353
|
+
try {
|
|
75354
|
+
_id = new import_mongodb146.ObjectId(_id);
|
|
75355
|
+
} catch (error) {
|
|
75356
|
+
throw new import_node_server_utils231.BadRequestError("Invalid ID format.");
|
|
75357
|
+
}
|
|
75358
|
+
return await collection.findOne({ _id });
|
|
75359
|
+
}
|
|
75338
75360
|
async function updateManpowerRemarks(_id, value) {
|
|
75339
75361
|
try {
|
|
75340
75362
|
_id = new import_mongodb146.ObjectId(_id);
|
|
@@ -75382,6 +75404,7 @@ function useManpowerRemarksRepo() {
|
|
|
75382
75404
|
createManpowerRemarks,
|
|
75383
75405
|
getManpowerRemarksAllSite,
|
|
75384
75406
|
getManpowerRemarksBySiteId,
|
|
75407
|
+
getManpowerRemarksById,
|
|
75385
75408
|
updateManpowerRemarks,
|
|
75386
75409
|
updateRemarksStatus,
|
|
75387
75410
|
createIndexes
|
|
@@ -77349,8 +77372,13 @@ function useManpowerRemarkCtrl() {
|
|
|
77349
77372
|
getManpowerRemarksAllSite: _getManpowerRemarksAllSite,
|
|
77350
77373
|
updateRemarksStatus: _updateRemarksStatus,
|
|
77351
77374
|
getManpowerRemarksBySiteId: _getManpowerRemarksBySiteId,
|
|
77375
|
+
getManpowerRemarksById: _getManpowerRemarksById,
|
|
77352
77376
|
updateManpowerRemarks: _updateManpowerRemarks
|
|
77353
77377
|
} = useManpowerRemarksRepo();
|
|
77378
|
+
async function requireRemarkReach(req, _id) {
|
|
77379
|
+
const remark = await _getManpowerRemarksById(_id);
|
|
77380
|
+
await requireSiteReach(req, remark?.siteId);
|
|
77381
|
+
}
|
|
77354
77382
|
async function createManpowerRemark(req, res, next) {
|
|
77355
77383
|
try {
|
|
77356
77384
|
const payload = { ...req.body };
|
|
@@ -77359,6 +77387,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77359
77387
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77360
77388
|
return;
|
|
77361
77389
|
}
|
|
77390
|
+
await requireSiteReach(req, payload.siteId);
|
|
77362
77391
|
const result = await _createManpowerRemarks(payload);
|
|
77363
77392
|
return res.json(result);
|
|
77364
77393
|
} catch (error) {
|
|
@@ -77398,7 +77427,17 @@ function useManpowerRemarkCtrl() {
|
|
|
77398
77427
|
status: status?.toString() || "",
|
|
77399
77428
|
date: date?.toString() || ""
|
|
77400
77429
|
});
|
|
77401
|
-
|
|
77430
|
+
const { only } = await siteReachOf(req);
|
|
77431
|
+
const items = await only(
|
|
77432
|
+
(result?.items ?? []).map((row) => ({
|
|
77433
|
+
row,
|
|
77434
|
+
site: row?.siteId
|
|
77435
|
+
}))
|
|
77436
|
+
);
|
|
77437
|
+
return res.json({
|
|
77438
|
+
...result,
|
|
77439
|
+
items: items.map((entry) => entry.row)
|
|
77440
|
+
});
|
|
77402
77441
|
} catch (error) {
|
|
77403
77442
|
import_node_server_utils244.logger.log({ level: "error", message: error.message });
|
|
77404
77443
|
next(error);
|
|
@@ -77423,6 +77462,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77423
77462
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77424
77463
|
return;
|
|
77425
77464
|
}
|
|
77465
|
+
await requireSiteReach(req, id);
|
|
77426
77466
|
const result = await _getManpowerRemarksBySiteId(
|
|
77427
77467
|
id,
|
|
77428
77468
|
date,
|
|
@@ -77450,6 +77490,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77450
77490
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77451
77491
|
return;
|
|
77452
77492
|
}
|
|
77493
|
+
await requireRemarkReach(req, _id);
|
|
77453
77494
|
const result = await _updateManpowerRemarks(_id, payload);
|
|
77454
77495
|
return res.json(result);
|
|
77455
77496
|
} catch (error) {
|
|
@@ -77471,6 +77512,7 @@ function useManpowerRemarkCtrl() {
|
|
|
77471
77512
|
next(new import_node_server_utils244.BadRequestError(error.message));
|
|
77472
77513
|
return;
|
|
77473
77514
|
}
|
|
77515
|
+
await requireRemarkReach(req, _id);
|
|
77474
77516
|
const result = await _updateRemarksStatus(_id, payload);
|
|
77475
77517
|
return res.json(result);
|
|
77476
77518
|
} catch (error) {
|