@xeplr/base-apis 2.0.4 → 2.0.6
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/README.md +2 -2
- package/lib/genericController.js +7 -6
- package/lib/remoteAuth.js +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,7 +120,7 @@ Why on by default: a service that forgot to configure auth used to boot clean, p
|
|
|
120
120
|
|---|---|
|
|
121
121
|
| path starts with a `publicPaths` entry | skipped |
|
|
122
122
|
| no `Bearer` token | 401 `No token provided` |
|
|
123
|
-
| auth answers `403` with `code` `DISABLED` or `
|
|
123
|
+
| auth answers `403` with `code` `DISABLED`, `HIDDEN` or `UNLICENSED` | 403 with that `code`: signed in, but not allowed this API (`UNLICENSED`: its module is not in the caller's licence) |
|
|
124
124
|
| auth answers 401 / other 403 | same status, `Invalid or expired token` |
|
|
125
125
|
| auth answers 200 **without** `state: 'enabled'` (an older auth, or an `endpoint` such as `/me` that only says who the caller is) | **503**: "did not say no" is not "said yes" |
|
|
126
126
|
| auth unreachable, times out (`timeoutMs`, 5000), answers anything else, or answers non-JSON | **503 `Authentication service unavailable` — never let through** |
|
|
@@ -203,7 +203,7 @@ Responses use `@xeplr/utils`' shape: `{ code, message, error, dataArray, updated
|
|
|
203
203
|
|
|
204
204
|
| error | status |
|
|
205
205
|
|---|---|
|
|
206
|
-
| `ValidationError` | 422 |
|
|
206
|
+
| `ValidationError` | 422. jsonSchema's answers `Validation failed` with `fields`; one a model hook throws with its own `type` (e.g. a licence limit) answers its own `message` |
|
|
207
207
|
| `UniqueViolationError`, `ForeignKeyViolationError` | 409 |
|
|
208
208
|
| `NotNullViolationError` (`<column> is required`), `CheckViolationError`, `DataError` | 400 |
|
|
209
209
|
| `NotFoundError` | 404 |
|
package/lib/genericController.js
CHANGED
|
@@ -7,7 +7,7 @@ var { generateId } = require('@xeplr/utils/lib/helpers');
|
|
|
7
7
|
* of a blanket 500. Matched by `err.name` (not instanceof) so it survives two
|
|
8
8
|
* copies of objection in a linked monorepo. Unknown errors still fall to 500.
|
|
9
9
|
*
|
|
10
|
-
* ValidationError → 422 { fields } (jsonSchema: required/format/…)
|
|
10
|
+
* ValidationError → 422 { fields } (jsonSchema: required/format/…); a hook's own type keeps its message
|
|
11
11
|
* UniqueViolationError → 409 already exists
|
|
12
12
|
* NotNullViolationError → 400 <column> is required
|
|
13
13
|
* ForeignKeyViolationError → 409 referenced record missing / in use
|
|
@@ -19,8 +19,12 @@ function sendError(req, res, err) {
|
|
|
19
19
|
|
|
20
20
|
switch (err && err.name) {
|
|
21
21
|
case 'ValidationError':
|
|
22
|
+
// A model's own check (a hook throwing ValidationError with a type of
|
|
23
|
+
// its own, e.g. a licence limit) carries a sentence for the person;
|
|
24
|
+
// jsonSchema's (ModelValidation) carries per-field detail instead.
|
|
22
25
|
return respond(res, HTTP.VALIDATION_ERROR, STATUS.VALIDATION_ERROR, 'validation_error', {
|
|
23
|
-
message:
|
|
26
|
+
message: err.type && err.type !== 'ModelValidation' && err.message ? err.message : 'Validation failed',
|
|
27
|
+
fields: err.data || {}
|
|
24
28
|
});
|
|
25
29
|
case 'UniqueViolationError':
|
|
26
30
|
return respond(res, HTTP.CONFLICT, STATUS.CONFLICT, 'conflict', {
|
|
@@ -66,7 +70,6 @@ function sendError(req, res, err) {
|
|
|
66
70
|
*/
|
|
67
71
|
async function save(req, res, hierarchy) {
|
|
68
72
|
var changeSet = req.body;
|
|
69
|
-
console.log('bruh: ', 1);
|
|
70
73
|
if (!Array.isArray(changeSet) || changeSet.length === 0) {
|
|
71
74
|
return respond(res, HTTP.BAD_REQUEST, STATUS.BAD_REQUEST, 'bad_request', {
|
|
72
75
|
message: 'Expected a non-empty changeset array'
|
|
@@ -102,7 +105,6 @@ console.log('bruh: ', 1);
|
|
|
102
105
|
var ids = await processEntry(changeSet[i], rootDef, trx, null, queryContext);
|
|
103
106
|
updatedIds = updatedIds.concat(ids);
|
|
104
107
|
}
|
|
105
|
-
console.log('bruh: ', 2);
|
|
106
108
|
|
|
107
109
|
await trx.commit();
|
|
108
110
|
|
|
@@ -114,7 +116,6 @@ console.log('bruh: ', 2);
|
|
|
114
116
|
else console.error('[genericController] afterCommit callback failed:', err.message);
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
|
-
console.log('bruh: ', 3);
|
|
118
119
|
|
|
119
120
|
respond(res, HTTP.OK, STATUS.UPDATED, 'updated', { updatedIds: updatedIds });
|
|
120
121
|
} catch (err) {
|
|
@@ -296,4 +297,4 @@ async function list(req, res, Model, graph) {
|
|
|
296
297
|
}
|
|
297
298
|
}
|
|
298
299
|
|
|
299
|
-
module.exports = { save, deleteByIds, getById, list };
|
|
300
|
+
module.exports = { save, deleteByIds, getById, list, sendError };
|
package/lib/remoteAuth.js
CHANGED
|
@@ -34,6 +34,11 @@ var DEFAULT_CACHE_SECONDS = 5;
|
|
|
34
34
|
// closed after 5s is bad; failing closed after forever is an outage.
|
|
35
35
|
var DEFAULT_TIMEOUT_MS = 5000;
|
|
36
36
|
|
|
37
|
+
// The 403 codes auth gives for a signed-in caller this API is refused to. Any
|
|
38
|
+
// other 403 is a token problem. UNLICENSED: the API's module is not in the
|
|
39
|
+
// caller's licence (@xeplr/auth's licence.use).
|
|
40
|
+
var REFUSALS = ['DISABLED', 'HIDDEN', 'UNLICENSED'];
|
|
41
|
+
|
|
37
42
|
/**
|
|
38
43
|
* @param {object} config
|
|
39
44
|
* @param {string} config.url - base URL of the auth service, e.g.
|
|
@@ -125,9 +130,10 @@ function remoteAuth(config) {
|
|
|
125
130
|
var body = null;
|
|
126
131
|
try { body = await response.json(); } catch (err) { body = null; }
|
|
127
132
|
|
|
128
|
-
if (response.status === 403 && body && (body.code
|
|
133
|
+
if (response.status === 403 && body && REFUSALS.indexOf(body.code) !== -1) {
|
|
129
134
|
// Signed in, but not allowed this API. The code says which, so a UI can
|
|
130
|
-
// grey a disabled item out rather than treat it as missing
|
|
135
|
+
// grey a disabled item out rather than treat it as missing, and tell
|
|
136
|
+
// "not in your licence" from "not for your role".
|
|
131
137
|
return { kind: 'refused', newToken: newToken, body: { error: body.error || 'Access denied', code: body.code } };
|
|
132
138
|
}
|
|
133
139
|
|