@7365admin1/core 3.48.1-staging.188 → 3.48.1-staging.189
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/invoice-subscription-owner-scope.md +23 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +161 -147
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/harness.mjs +9 -0
- package/test/e2e/invoice-scope.e2e.test.mjs +262 -0
- package/test/staff-console-authz.test.mjs +7 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope a subscription's invoices to the subscription's owner.
|
|
6
|
+
|
|
7
|
+
`GET /api/invoices/subscription/:id` carried `requireAuth` and nothing more, and
|
|
8
|
+
`invoice.controller.ts` held no authorization identifier of any kind: the
|
|
9
|
+
subscription id came off the URL and went straight into the query. Being signed
|
|
10
|
+
in anywhere on the platform was therefore enough to page through another
|
|
11
|
+
organisation's billing history — invoice numbers, amounts, line-item
|
|
12
|
+
descriptions, due dates and payment status.
|
|
13
|
+
|
|
14
|
+
A new module-named `requireInvoiceReach` takes the verdict off the STORED
|
|
15
|
+
subscription, never from anything the caller supplied. A subscription is owned
|
|
16
|
+
by an organisation OR by a single user, so both are checked: `siteReachOf`'s
|
|
17
|
+
`canReach` answers the organisation half, and the personal half is the caller
|
|
18
|
+
being that user. A subscription that names neither is refused. "Not yours",
|
|
19
|
+
"does not exist" and "not a valid id" all answer 404 identically, so
|
|
20
|
+
subscription ids cannot be enumerated.
|
|
21
|
+
|
|
22
|
+
Read access to invoice records only — no card handling, no payment gateway and
|
|
23
|
+
no money movement is touched.
|
package/dist/index.js
CHANGED
|
@@ -31022,6 +31022,15 @@ var import_node_server_utils82 = require("@7365admin1/node-server-utils");
|
|
|
31022
31022
|
var import_joi39 = __toESM(require("joi"));
|
|
31023
31023
|
function useInvoiceController() {
|
|
31024
31024
|
const { getBySubscriptionId: _getBySubscriptionId } = useInvoiceRepo();
|
|
31025
|
+
const { getById: _getSubscriptionById } = useSubscriptionRepo();
|
|
31026
|
+
async function requireInvoiceReach(req, id) {
|
|
31027
|
+
const subscription = await _getSubscriptionById(id).catch(() => null);
|
|
31028
|
+
const { actor, canReach } = await siteReachOf(req);
|
|
31029
|
+
const owned = await canReach(subscription) || Boolean(actor.id) && Boolean(subscription?.user) && subscription?.user?.toString() === actor.id;
|
|
31030
|
+
if (!owned) {
|
|
31031
|
+
throw new import_node_server_utils82.NotFoundError("Subscription not found.");
|
|
31032
|
+
}
|
|
31033
|
+
}
|
|
31025
31034
|
async function getBySubscriptionId(req, res, next) {
|
|
31026
31035
|
const validation = import_joi39.default.object({
|
|
31027
31036
|
id: import_joi39.default.string().required(),
|
|
@@ -31044,6 +31053,7 @@ function useInvoiceController() {
|
|
|
31044
31053
|
const page = parseInt(req.query.page ?? "1");
|
|
31045
31054
|
const limit = parseInt(req.query.limit ?? "10");
|
|
31046
31055
|
try {
|
|
31056
|
+
await requireInvoiceReach(req, id);
|
|
31047
31057
|
const data = await _getBySubscriptionId({
|
|
31048
31058
|
id,
|
|
31049
31059
|
search,
|