@7365admin1/core 3.48.1-staging.184 → 3.48.1-staging.186
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/bulletin-board-site-scope.md +19 -0
- package/.changeset/event-management-site-scope.md +16 -0
- package/dist/index.js +34 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/bulletin-board-scope.e2e.test.mjs +442 -0
- package/test/e2e/event-management-scope.e2e.test.mjs +411 -0
- package/test/e2e/harness.mjs +40 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope the bulletin-board routes to the caller's own estate.
|
|
6
|
+
|
|
7
|
+
All five `/api/bulletin-boards` routes carried `requireAuth` and nothing more,
|
|
8
|
+
and the controller held no authorization identifier of any kind, so any
|
|
9
|
+
signed-in account in any organisation could publish an announcement into another
|
|
10
|
+
client's estate — which also fans out as a notification to every recipient group
|
|
11
|
+
at that site — read that board, and read, rewrite or delete any single bulletin
|
|
12
|
+
reached by id alone.
|
|
13
|
+
|
|
14
|
+
`add` and `getAll` now authorise the site named in the request with
|
|
15
|
+
`requireSiteReach`; `site` is optional on the add schema, so the org-wide case is
|
|
16
|
+
asked about separately rather than an absent site leaving the write unscoped. The
|
|
17
|
+
three by-id handlers take the verdict off the STORED row with a new module-named
|
|
18
|
+
`requireBulletinReach`, which answers "not yours" and "does not exist"
|
|
19
|
+
identically so bulletin ids cannot be enumerated.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope the event-management routes to the caller's own estate.
|
|
6
|
+
|
|
7
|
+
All five `/api/event-management` routes carried `requireAuth` and nothing more,
|
|
8
|
+
and the controller held no authorization identifier of any kind, so any
|
|
9
|
+
signed-in account in any organisation could file an event into another client's
|
|
10
|
+
calendar, read that calendar, and read, rewrite or delete any single event
|
|
11
|
+
reached by id alone.
|
|
12
|
+
|
|
13
|
+
`add` and `getAll` now authorise the site named in the request with
|
|
14
|
+
`requireSiteReach`; the three by-id handlers take the verdict off the STORED row
|
|
15
|
+
with a new module-named `requireEventReach`, which answers "not yours" and "does
|
|
16
|
+
not exist" identically so event ids cannot be enumerated.
|
package/dist/index.js
CHANGED
|
@@ -57728,6 +57728,15 @@ function useBulletinBoardController() {
|
|
|
57728
57728
|
deleteBulletinBoardById: _deleteBulletinBoardById
|
|
57729
57729
|
} = useBulletinBoardService();
|
|
57730
57730
|
const { getAll: _getAll, getBulletinBoardById: _getBulletinBoardById } = useBulletinBoardRepo();
|
|
57731
|
+
const scopeOf = (row) => ({ site: row?.site, org: row?.orgId });
|
|
57732
|
+
async function requireBulletinReach(req, id) {
|
|
57733
|
+
const bulletin = await _getBulletinBoardById(id);
|
|
57734
|
+
const { canReach } = await siteReachOf(req);
|
|
57735
|
+
if (!await canReach(scopeOf(bulletin))) {
|
|
57736
|
+
throw new import_node_server_utils174.NotFoundError("Bulletin board not found.");
|
|
57737
|
+
}
|
|
57738
|
+
return bulletin;
|
|
57739
|
+
}
|
|
57731
57740
|
async function add(req, res, next) {
|
|
57732
57741
|
const { error, value } = schemaBulletinBoard.validate(req.body, {
|
|
57733
57742
|
abortEarly: false
|
|
@@ -57739,6 +57748,14 @@ function useBulletinBoardController() {
|
|
|
57739
57748
|
return;
|
|
57740
57749
|
}
|
|
57741
57750
|
try {
|
|
57751
|
+
if (value.site) {
|
|
57752
|
+
await requireSiteReach(req, value.site);
|
|
57753
|
+
} else {
|
|
57754
|
+
const { canReach } = await siteReachOf(req);
|
|
57755
|
+
if (!await canReach(scopeOf(value))) {
|
|
57756
|
+
throw new import_node_server_utils174.UnauthorizedError("Not authorized.");
|
|
57757
|
+
}
|
|
57758
|
+
}
|
|
57742
57759
|
const data = await _add(value);
|
|
57743
57760
|
res.status(201).json(data);
|
|
57744
57761
|
return;
|
|
@@ -57811,6 +57828,7 @@ function useBulletinBoardController() {
|
|
|
57811
57828
|
[sort ? sort : "_id" /* ID */]: order === "asc" /* ASC */ ? 1 : -1
|
|
57812
57829
|
};
|
|
57813
57830
|
try {
|
|
57831
|
+
await requireSiteReach(req, site);
|
|
57814
57832
|
const data = await _getAll({
|
|
57815
57833
|
search,
|
|
57816
57834
|
page,
|
|
@@ -57841,7 +57859,7 @@ function useBulletinBoardController() {
|
|
|
57841
57859
|
return;
|
|
57842
57860
|
}
|
|
57843
57861
|
const { _id } = value;
|
|
57844
|
-
const data = await
|
|
57862
|
+
const data = await requireBulletinReach(req, _id);
|
|
57845
57863
|
res.status(200).json(data);
|
|
57846
57864
|
return;
|
|
57847
57865
|
} catch (error) {
|
|
@@ -57863,6 +57881,7 @@ function useBulletinBoardController() {
|
|
|
57863
57881
|
return;
|
|
57864
57882
|
}
|
|
57865
57883
|
try {
|
|
57884
|
+
await requireBulletinReach(req, _id);
|
|
57866
57885
|
const result = await _updateBulletinBoardById(_id, req.body);
|
|
57867
57886
|
res.status(200).json({ message: result });
|
|
57868
57887
|
return;
|
|
@@ -57884,6 +57903,7 @@ function useBulletinBoardController() {
|
|
|
57884
57903
|
}
|
|
57885
57904
|
const { _id } = value;
|
|
57886
57905
|
try {
|
|
57906
|
+
await requireBulletinReach(req, _id);
|
|
57887
57907
|
await _deleteBulletinBoardById(_id);
|
|
57888
57908
|
res.status(200).json({ message: "Successfully deleted bulletin board." });
|
|
57889
57909
|
return;
|
|
@@ -59647,6 +59667,14 @@ function useEventManagementController() {
|
|
|
59647
59667
|
getEventManagementById: _getEventManagementById,
|
|
59648
59668
|
deleteEventManagementById: _deleteEventManagementById
|
|
59649
59669
|
} = useEventManagementRepo();
|
|
59670
|
+
async function requireEventReach(req, id) {
|
|
59671
|
+
const event = await _getEventManagementById(id);
|
|
59672
|
+
const { canReach } = await siteReachOf(req);
|
|
59673
|
+
if (!await canReach(event)) {
|
|
59674
|
+
throw new import_node_server_utils185.NotFoundError("Event not found.");
|
|
59675
|
+
}
|
|
59676
|
+
return event;
|
|
59677
|
+
}
|
|
59650
59678
|
async function add(req, res, next) {
|
|
59651
59679
|
try {
|
|
59652
59680
|
const { error, value } = schemaEventManagement.validate(req.body, {
|
|
@@ -59658,6 +59686,7 @@ function useEventManagementController() {
|
|
|
59658
59686
|
next(new import_node_server_utils185.BadRequestError(messages));
|
|
59659
59687
|
return;
|
|
59660
59688
|
}
|
|
59689
|
+
await requireSiteReach(req, value.site);
|
|
59661
59690
|
const data = await _add(value);
|
|
59662
59691
|
res.status(201).json(data);
|
|
59663
59692
|
return;
|
|
@@ -59691,6 +59720,7 @@ function useEventManagementController() {
|
|
|
59691
59720
|
return;
|
|
59692
59721
|
}
|
|
59693
59722
|
const { search, page, limit, site, status, type, startDate, endDate, sort, order } = value;
|
|
59723
|
+
await requireSiteReach(req, site);
|
|
59694
59724
|
const sortObj = {
|
|
59695
59725
|
[sort ?? "_id" /* ID */]: order === "asc" /* ASC */ ? 1 : -1
|
|
59696
59726
|
};
|
|
@@ -59725,7 +59755,7 @@ function useEventManagementController() {
|
|
|
59725
59755
|
return;
|
|
59726
59756
|
}
|
|
59727
59757
|
const { _id } = value;
|
|
59728
|
-
const data = await
|
|
59758
|
+
const data = await requireEventReach(req, _id);
|
|
59729
59759
|
res.status(200).json(data);
|
|
59730
59760
|
return;
|
|
59731
59761
|
} catch (error) {
|
|
@@ -59747,6 +59777,7 @@ function useEventManagementController() {
|
|
|
59747
59777
|
}
|
|
59748
59778
|
const { _id, ...rest } = value;
|
|
59749
59779
|
try {
|
|
59780
|
+
await requireEventReach(req, _id);
|
|
59750
59781
|
const result = await _updateEventManagementById(_id, rest);
|
|
59751
59782
|
res.status(200).json({ message: result });
|
|
59752
59783
|
return;
|
|
@@ -59768,6 +59799,7 @@ function useEventManagementController() {
|
|
|
59768
59799
|
return;
|
|
59769
59800
|
}
|
|
59770
59801
|
const { _id } = value;
|
|
59802
|
+
await requireEventReach(req, _id);
|
|
59771
59803
|
await _deleteEventManagementById(_id);
|
|
59772
59804
|
res.status(200).json({ message: "Successfully deleted event." });
|
|
59773
59805
|
return;
|