@aeriajs/security 0.0.277 → 0.0.279
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/dist/define.js +1 -5
- package/dist/index.js +5 -21
- package/dist/middleware/applyReadMiddlewares.js +3 -7
- package/dist/middleware/applyWriteMiddlewares.js +3 -7
- package/dist/middleware/define.js +1 -5
- package/dist/middleware/index.js +4 -20
- package/dist/middleware/iterableMiddlewares.js +1 -5
- package/dist/middlewares/immutability.js +16 -21
- package/dist/middlewares/index.js +3 -19
- package/dist/middlewares/ownership.js +6 -11
- package/dist/middlewares/pagination.js +5 -9
- package/dist/rateLimiting.js +9 -14
- package/dist/types.js +1 -2
- package/dist/use.js +16 -20
- package/package.json +7 -11
- package/dist/define.mjs +0 -4
- package/dist/index.mjs +0 -6
- package/dist/middleware/applyReadMiddlewares.mjs +0 -19
- package/dist/middleware/applyWriteMiddlewares.mjs +0 -19
- package/dist/middleware/define.mjs +0 -4
- package/dist/middleware/index.mjs +0 -5
- package/dist/middleware/iterableMiddlewares.mjs +0 -13
- package/dist/middlewares/immutability.mjs +0 -47
- package/dist/middlewares/index.mjs +0 -4
- package/dist/middlewares/ownership.mjs +0 -33
- package/dist/middlewares/pagination.mjs +0 -22
- package/dist/rateLimiting.mjs +0 -75
- package/dist/types.mjs +0 -1
- package/dist/use.mjs +0 -46
package/dist/define.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defineSecurityPolicy = void 0;
|
|
4
|
-
const defineSecurityPolicy = (policy) => {
|
|
1
|
+
export const defineSecurityPolicy = (policy) => {
|
|
5
2
|
return policy;
|
|
6
3
|
};
|
|
7
|
-
exports.defineSecurityPolicy = defineSecurityPolicy;
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./define.js"), exports);
|
|
18
|
-
__exportStar(require("./middleware/index.js"), exports);
|
|
19
|
-
__exportStar(require("./middlewares/index.js"), exports);
|
|
20
|
-
__exportStar(require("./rateLimiting.js"), exports);
|
|
21
|
-
__exportStar(require("./use.js"), exports);
|
|
1
|
+
export * from './define.js';
|
|
2
|
+
export * from './middleware/index.js';
|
|
3
|
+
export * from './middlewares/index.js';
|
|
4
|
+
export * from './rateLimiting.js';
|
|
5
|
+
export * from './use.js';
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.applyReadMiddlewares = void 0;
|
|
4
|
-
const iterableMiddlewares_js_1 = require("./iterableMiddlewares.js");
|
|
5
|
-
const applyReadMiddlewares = (payload, context, fn) => {
|
|
1
|
+
import { iterableMiddlewares } from './iterableMiddlewares.js';
|
|
2
|
+
export const applyReadMiddlewares = (payload, context, fn) => {
|
|
6
3
|
const { middlewares } = context.collection;
|
|
7
4
|
if (middlewares) {
|
|
8
5
|
if (Array.isArray(middlewares)) {
|
|
9
6
|
const readMiddlewares = middlewares.map((middleware) => middleware.beforeRead).filter((fn) => !!fn);
|
|
10
|
-
const start =
|
|
7
|
+
const start = iterableMiddlewares(readMiddlewares, fn);
|
|
11
8
|
return start(payload, context);
|
|
12
9
|
}
|
|
13
10
|
if (middlewares.beforeRead) {
|
|
@@ -16,4 +13,3 @@ const applyReadMiddlewares = (payload, context, fn) => {
|
|
|
16
13
|
}
|
|
17
14
|
return fn(payload, context);
|
|
18
15
|
};
|
|
19
|
-
exports.applyReadMiddlewares = applyReadMiddlewares;
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.applyWriteMiddlewares = void 0;
|
|
4
|
-
const iterableMiddlewares_js_1 = require("./iterableMiddlewares.js");
|
|
5
|
-
const applyWriteMiddlewares = (payload, context, fn) => {
|
|
1
|
+
import { iterableMiddlewares } from './iterableMiddlewares.js';
|
|
2
|
+
export const applyWriteMiddlewares = (payload, context, fn) => {
|
|
6
3
|
const { middlewares } = context.collection;
|
|
7
4
|
if (middlewares) {
|
|
8
5
|
if (Array.isArray(middlewares)) {
|
|
9
6
|
const writeMiddlewares = middlewares.map((middleware) => middleware.beforeWrite).filter((fn) => !!fn);
|
|
10
|
-
const start =
|
|
7
|
+
const start = iterableMiddlewares(writeMiddlewares, fn);
|
|
11
8
|
return start(payload, context);
|
|
12
9
|
}
|
|
13
10
|
if (middlewares.beforeWrite) {
|
|
@@ -16,4 +13,3 @@ const applyWriteMiddlewares = (payload, context, fn) => {
|
|
|
16
13
|
}
|
|
17
14
|
return fn(payload, context);
|
|
18
15
|
};
|
|
19
|
-
exports.applyWriteMiddlewares = applyWriteMiddlewares;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defineCollectionMiddleware = void 0;
|
|
4
|
-
const defineCollectionMiddleware = (middleware) => {
|
|
1
|
+
export const defineCollectionMiddleware = (middleware) => {
|
|
5
2
|
return middleware;
|
|
6
3
|
};
|
|
7
|
-
exports.defineCollectionMiddleware = defineCollectionMiddleware;
|
package/dist/middleware/index.js
CHANGED
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./define.js"), exports);
|
|
18
|
-
__exportStar(require("./iterableMiddlewares.js"), exports);
|
|
19
|
-
__exportStar(require("./applyReadMiddlewares.js"), exports);
|
|
20
|
-
__exportStar(require("./applyWriteMiddlewares.js"), exports);
|
|
1
|
+
export * from './define.js';
|
|
2
|
+
export * from './iterableMiddlewares.js';
|
|
3
|
+
export * from './applyReadMiddlewares.js';
|
|
4
|
+
export * from './applyWriteMiddlewares.js';
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.iterableMiddlewares = void 0;
|
|
4
|
-
const iterableMiddlewares = function (middlewares, end = (payload, _context) => payload) {
|
|
1
|
+
export const iterableMiddlewares = function (middlewares, end = (payload, _context) => payload) {
|
|
5
2
|
const run = (payload, context, index) => {
|
|
6
3
|
if (index === middlewares.length) {
|
|
7
4
|
return end(payload, context);
|
|
@@ -13,4 +10,3 @@ const iterableMiddlewares = function (middlewares, end = (payload, _context) =>
|
|
|
13
10
|
return run(payload, context, 0);
|
|
14
11
|
};
|
|
15
12
|
};
|
|
16
|
-
exports.iterableMiddlewares = iterableMiddlewares;
|
|
@@ -1,53 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.checkImmutabilityWrite = exports.checkImmutabilityRead = void 0;
|
|
4
|
-
const mongodb_1 = require("mongodb");
|
|
5
|
-
const types_1 = require("@aeriajs/types");
|
|
1
|
+
import { ObjectId } from 'mongodb';
|
|
2
|
+
import { Result, ACError } from '@aeriajs/types';
|
|
6
3
|
const checkImmutability = async (docId, props, context) => {
|
|
7
4
|
if (!context.description.immutable) {
|
|
8
|
-
return
|
|
5
|
+
return Result.result(props.payload);
|
|
9
6
|
}
|
|
10
7
|
if (docId) {
|
|
11
8
|
if (typeof context.description.immutable === 'function') {
|
|
12
9
|
const doc = await context.collection.model.findOne({
|
|
13
|
-
_id: new
|
|
10
|
+
_id: new ObjectId(docId),
|
|
14
11
|
});
|
|
15
12
|
if (!doc) {
|
|
16
|
-
return
|
|
13
|
+
return Result.error(ACError.ResourceNotFound);
|
|
17
14
|
}
|
|
18
15
|
const isImmutable = await context.description.immutable(doc);
|
|
19
16
|
return isImmutable
|
|
20
|
-
?
|
|
21
|
-
:
|
|
17
|
+
? Result.error(ACError.TargetImmutable)
|
|
18
|
+
: Result.result(props.payload);
|
|
22
19
|
}
|
|
23
|
-
return
|
|
20
|
+
return Result.error(ACError.TargetImmutable);
|
|
24
21
|
}
|
|
25
|
-
return
|
|
22
|
+
return Result.result(props.payload);
|
|
26
23
|
};
|
|
27
|
-
const checkImmutabilityRead = async (props, context, next) => {
|
|
24
|
+
export const checkImmutabilityRead = async (props, context, next) => {
|
|
28
25
|
const { payload: originalPayload } = props.result;
|
|
29
|
-
if (!(originalPayload.filters._id instanceof
|
|
26
|
+
if (!(originalPayload.filters._id instanceof ObjectId)) {
|
|
30
27
|
throw new Error;
|
|
31
28
|
}
|
|
32
29
|
const { result: payload, error } = await checkImmutability(originalPayload.filters._id, props.result, context);
|
|
33
30
|
if (error) {
|
|
34
|
-
return
|
|
31
|
+
return Result.error(error);
|
|
35
32
|
}
|
|
36
|
-
return next(
|
|
33
|
+
return next(Result.result({
|
|
37
34
|
...props.result,
|
|
38
35
|
payload,
|
|
39
36
|
}), context);
|
|
40
37
|
};
|
|
41
|
-
|
|
42
|
-
const checkImmutabilityWrite = async (props, context, next) => {
|
|
38
|
+
export const checkImmutabilityWrite = async (props, context, next) => {
|
|
43
39
|
const { payload: originalPayload } = props.result;
|
|
44
40
|
const { result: payload, error } = await checkImmutability(originalPayload.what._id, props.result, context);
|
|
45
41
|
if (error) {
|
|
46
|
-
return
|
|
42
|
+
return Result.error(error);
|
|
47
43
|
}
|
|
48
|
-
return next(
|
|
44
|
+
return next(Result.result({
|
|
49
45
|
...props.result,
|
|
50
46
|
payload,
|
|
51
47
|
}), context);
|
|
52
48
|
};
|
|
53
|
-
exports.checkImmutabilityWrite = checkImmutabilityWrite;
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./immutability.js"), exports);
|
|
18
|
-
__exportStar(require("./ownership.js"), exports);
|
|
19
|
-
__exportStar(require("./pagination.js"), exports);
|
|
1
|
+
export * from './immutability.js';
|
|
2
|
+
export * from './ownership.js';
|
|
3
|
+
export * from './pagination.js';
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.checkOwnershipWrite = exports.checkOwnershipRead = void 0;
|
|
4
|
-
const types_1 = require("@aeriajs/types");
|
|
5
|
-
const checkOwnershipRead = async (props, context, next) => {
|
|
1
|
+
import { Result, ACError } from '@aeriajs/types';
|
|
2
|
+
export const checkOwnershipRead = async (props, context, next) => {
|
|
6
3
|
const { token, description } = context;
|
|
7
4
|
const { payload } = props.result;
|
|
8
5
|
if (token.authenticated && description.owned && description.owned !== 'on-write') {
|
|
@@ -10,13 +7,12 @@ const checkOwnershipRead = async (props, context, next) => {
|
|
|
10
7
|
payload.filters.owner = token.sub;
|
|
11
8
|
}
|
|
12
9
|
}
|
|
13
|
-
return next(
|
|
10
|
+
return next(Result.result({
|
|
14
11
|
...props.result,
|
|
15
12
|
payload,
|
|
16
13
|
}), context);
|
|
17
14
|
};
|
|
18
|
-
|
|
19
|
-
const checkOwnershipWrite = async (props, context, next) => {
|
|
15
|
+
export const checkOwnershipWrite = async (props, context, next) => {
|
|
20
16
|
const { token, description } = context;
|
|
21
17
|
const { payload, parentId } = props.result;
|
|
22
18
|
if (token.authenticated && description.owned) {
|
|
@@ -28,11 +24,10 @@ const checkOwnershipWrite = async (props, context, next) => {
|
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
26
|
if ((!payload.what.owner && !parentId) && context.description.owned) {
|
|
31
|
-
return
|
|
27
|
+
return Result.error(ACError.OwnershipError);
|
|
32
28
|
}
|
|
33
|
-
return next(
|
|
29
|
+
return next(Result.result({
|
|
34
30
|
...props.result,
|
|
35
31
|
payload,
|
|
36
32
|
}), context);
|
|
37
33
|
};
|
|
38
|
-
exports.checkOwnershipWrite = checkOwnershipWrite;
|
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.checkPagination = void 0;
|
|
4
|
-
const types_1 = require("@aeriajs/types");
|
|
5
|
-
const checkPagination = async (props, context, next) => {
|
|
1
|
+
import { Result, ACError } from '@aeriajs/types';
|
|
2
|
+
export const checkPagination = async (props, context, next) => {
|
|
6
3
|
const { payload } = props.result;
|
|
7
4
|
switch (typeof payload.limit) {
|
|
8
5
|
case 'undefined': break;
|
|
9
6
|
case 'number': {
|
|
10
7
|
if (payload.limit <= 0) {
|
|
11
|
-
return
|
|
8
|
+
return Result.error(ACError.InvalidLimit);
|
|
12
9
|
}
|
|
13
10
|
if (context.config.security.paginationLimit && payload.limit > context.config.security.paginationLimit) {
|
|
14
|
-
return
|
|
11
|
+
return Result.error(ACError.InvalidLimit);
|
|
15
12
|
}
|
|
16
13
|
break;
|
|
17
14
|
}
|
|
18
15
|
default: {
|
|
19
|
-
return
|
|
16
|
+
return Result.error(ACError.InvalidLimit);
|
|
20
17
|
}
|
|
21
18
|
}
|
|
22
19
|
return next(props, context);
|
|
23
20
|
};
|
|
24
|
-
exports.checkPagination = checkPagination;
|
package/dist/rateLimiting.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.limitRate = exports.getOrCreateUsageEntry = void 0;
|
|
4
|
-
const types_1 = require("@aeriajs/types");
|
|
1
|
+
import { Result, HTTPStatus, RateLimitingError } from '@aeriajs/types';
|
|
5
2
|
const buildEntryFilter = (params, context) => {
|
|
6
3
|
if (params.strategy === 'ip') {
|
|
7
4
|
const address = context.response.socket.remoteAddress;
|
|
@@ -16,7 +13,7 @@ const buildEntryFilter = (params, context) => {
|
|
|
16
13
|
user: context.token.sub,
|
|
17
14
|
};
|
|
18
15
|
};
|
|
19
|
-
const getOrCreateUsageEntry = async (params, context) => {
|
|
16
|
+
export const getOrCreateUsageEntry = async (params, context) => {
|
|
20
17
|
const filters = buildEntryFilter(params, context);
|
|
21
18
|
return context.collections.resourceUsage.model.findOneAndUpdate(filters, {
|
|
22
19
|
$setOnInsert: {
|
|
@@ -27,13 +24,12 @@ const getOrCreateUsageEntry = async (params, context) => {
|
|
|
27
24
|
returnDocument: 'after',
|
|
28
25
|
});
|
|
29
26
|
};
|
|
30
|
-
|
|
31
|
-
const limitRate = async (params, context) => {
|
|
27
|
+
export const limitRate = async (params, context) => {
|
|
32
28
|
const { increment = 1 } = params;
|
|
33
|
-
const entry = await
|
|
29
|
+
const entry = await getOrCreateUsageEntry(params, context);
|
|
34
30
|
if (!entry) {
|
|
35
|
-
return context.error(
|
|
36
|
-
code:
|
|
31
|
+
return context.error(HTTPStatus.InternalServerError, {
|
|
32
|
+
code: RateLimitingError.Unauthenticated,
|
|
37
33
|
});
|
|
38
34
|
}
|
|
39
35
|
const pathname = context.request.url.replace(new RegExp(`^${context.config.baseUrl}`), '');
|
|
@@ -43,8 +39,8 @@ const limitRate = async (params, context) => {
|
|
|
43
39
|
if ('scale' in params) {
|
|
44
40
|
const now = new Date();
|
|
45
41
|
if (params.scale > now.getTime() / 1000 - resource.last_reach.getTime() / 1000) {
|
|
46
|
-
return context.error(
|
|
47
|
-
code:
|
|
42
|
+
return context.error(HTTPStatus.TooManyRequests, {
|
|
43
|
+
code: RateLimitingError.LimitReached,
|
|
48
44
|
});
|
|
49
45
|
}
|
|
50
46
|
}
|
|
@@ -66,6 +62,5 @@ const limitRate = async (params, context) => {
|
|
|
66
62
|
if (!newEntry || !newEntry.usage[resourceName]) {
|
|
67
63
|
throw new Error();
|
|
68
64
|
}
|
|
69
|
-
return
|
|
65
|
+
return Result.result(newEntry.usage[resourceName]);
|
|
70
66
|
};
|
|
71
|
-
exports.limitRate = limitRate;
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/dist/use.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const index_js_1 = require("./middleware/index.js");
|
|
6
|
-
const index_js_2 = require("./middlewares/index.js");
|
|
7
|
-
const useSecurity = (context) => {
|
|
1
|
+
import { Result } from '@aeriajs/types';
|
|
2
|
+
import { iterableMiddlewares } from './middleware/index.js';
|
|
3
|
+
import { checkImmutabilityWrite, checkOwnershipRead, checkOwnershipWrite, checkPagination, } from './middlewares/index.js';
|
|
4
|
+
export const useSecurity = (context) => {
|
|
8
5
|
const secureReadPayload = async (payload) => {
|
|
9
6
|
const props = {
|
|
10
7
|
payload: {
|
|
@@ -12,33 +9,32 @@ const useSecurity = (context) => {
|
|
|
12
9
|
...payload,
|
|
13
10
|
},
|
|
14
11
|
};
|
|
15
|
-
const start =
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
const start = iterableMiddlewares([
|
|
13
|
+
checkPagination,
|
|
14
|
+
checkOwnershipRead,
|
|
18
15
|
]);
|
|
19
|
-
const { error, result } = await start(
|
|
16
|
+
const { error, result } = await start(Result.result(props), context);
|
|
20
17
|
if (error) {
|
|
21
|
-
return
|
|
18
|
+
return Result.error(error);
|
|
22
19
|
}
|
|
23
|
-
return
|
|
20
|
+
return Result.result(result.payload);
|
|
24
21
|
};
|
|
25
22
|
const secureWritePayload = async (payload) => {
|
|
26
23
|
const props = {
|
|
27
24
|
payload,
|
|
28
25
|
};
|
|
29
|
-
const start =
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
const start = iterableMiddlewares([
|
|
27
|
+
checkOwnershipWrite,
|
|
28
|
+
checkImmutabilityWrite,
|
|
32
29
|
]);
|
|
33
|
-
const { error, result } = await start(
|
|
30
|
+
const { error, result } = await start(Result.result(props), context);
|
|
34
31
|
if (error) {
|
|
35
|
-
return
|
|
32
|
+
return Result.error(error);
|
|
36
33
|
}
|
|
37
|
-
return
|
|
34
|
+
return Result.result(result.payload);
|
|
38
35
|
};
|
|
39
36
|
return {
|
|
40
37
|
secureReadPayload,
|
|
41
38
|
secureWritePayload,
|
|
42
39
|
};
|
|
43
40
|
};
|
|
44
|
-
exports.useSecurity = useSecurity;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aeriajs/security",
|
|
3
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.279",
|
|
4
5
|
"description": "",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "public"
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
16
|
"types": "./dist/index.d.ts",
|
|
17
|
-
"
|
|
18
|
-
"require": "./dist/index.js"
|
|
17
|
+
"default": "./dist/index.js"
|
|
19
18
|
}
|
|
20
19
|
},
|
|
21
20
|
"files": [
|
|
@@ -28,9 +27,9 @@
|
|
|
28
27
|
"mongodb": "^6.17.0"
|
|
29
28
|
},
|
|
30
29
|
"peerDependencies": {
|
|
31
|
-
"@aeriajs/core": "^0.0.
|
|
32
|
-
"@aeriajs/common": "^0.0.
|
|
33
|
-
"@aeriajs/types": "^0.0.
|
|
30
|
+
"@aeriajs/core": "^0.0.279",
|
|
31
|
+
"@aeriajs/common": "^0.0.158",
|
|
32
|
+
"@aeriajs/types": "^0.0.136",
|
|
34
33
|
"mongodb": "^6.17.0"
|
|
35
34
|
},
|
|
36
35
|
"scripts": {
|
|
@@ -38,9 +37,6 @@
|
|
|
38
37
|
"test:typecheck": "tsc -p tsconfig.test.json",
|
|
39
38
|
"lint": "eslint .",
|
|
40
39
|
"lint:fix": "eslint . --fix",
|
|
41
|
-
"build": "
|
|
42
|
-
"build:cjs": "tsc",
|
|
43
|
-
"build:esm": "esbuild './src/**/*.ts' --outdir=dist --out-extension:.js=.mjs && pnpm build:esm-transform",
|
|
44
|
-
"build:esm-transform": "pnpm -w esm-transform $PWD/dist"
|
|
40
|
+
"build": "tsc"
|
|
45
41
|
}
|
|
46
42
|
}
|
package/dist/define.mjs
DELETED
package/dist/index.mjs
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { iterableMiddlewares } from "./iterableMiddlewares.mjs";
|
|
3
|
-
export const applyReadMiddlewares = (payload, context, fn) => {
|
|
4
|
-
const { middlewares } = context.collection;
|
|
5
|
-
if (middlewares) {
|
|
6
|
-
if (Array.isArray(middlewares)) {
|
|
7
|
-
const readMiddlewares = middlewares.map((middleware) => middleware.beforeRead).filter((fn2) => !!fn2);
|
|
8
|
-
const start = iterableMiddlewares(
|
|
9
|
-
readMiddlewares,
|
|
10
|
-
fn
|
|
11
|
-
);
|
|
12
|
-
return start(payload, context);
|
|
13
|
-
}
|
|
14
|
-
if (middlewares.beforeRead) {
|
|
15
|
-
return middlewares.beforeRead(payload, context, fn);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return fn(payload, context);
|
|
19
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { iterableMiddlewares } from "./iterableMiddlewares.mjs";
|
|
3
|
-
export const applyWriteMiddlewares = (payload, context, fn) => {
|
|
4
|
-
const { middlewares } = context.collection;
|
|
5
|
-
if (middlewares) {
|
|
6
|
-
if (Array.isArray(middlewares)) {
|
|
7
|
-
const writeMiddlewares = middlewares.map((middleware) => middleware.beforeWrite).filter((fn2) => !!fn2);
|
|
8
|
-
const start = iterableMiddlewares(
|
|
9
|
-
writeMiddlewares,
|
|
10
|
-
fn
|
|
11
|
-
);
|
|
12
|
-
return start(payload, context);
|
|
13
|
-
}
|
|
14
|
-
if (middlewares.beforeWrite) {
|
|
15
|
-
return middlewares.beforeWrite(payload, context, fn);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return fn(payload, context);
|
|
19
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
export const iterableMiddlewares = function(middlewares, end = (payload, _context) => payload) {
|
|
3
|
-
const run = (payload, context, index) => {
|
|
4
|
-
if (index === middlewares.length) {
|
|
5
|
-
return end(payload, context);
|
|
6
|
-
}
|
|
7
|
-
const middleware = middlewares[index];
|
|
8
|
-
return middleware(payload, context, (payload2, context2) => run(payload2, context2, index + 1));
|
|
9
|
-
};
|
|
10
|
-
return (payload, context) => {
|
|
11
|
-
return run(payload, context, 0);
|
|
12
|
-
};
|
|
13
|
-
};
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { ObjectId } from "mongodb";
|
|
3
|
-
import { Result, ACError } from "@aeriajs/types";
|
|
4
|
-
const checkImmutability = async (docId, props, context) => {
|
|
5
|
-
if (!context.description.immutable) {
|
|
6
|
-
return Result.result(props.payload);
|
|
7
|
-
}
|
|
8
|
-
if (docId) {
|
|
9
|
-
if (typeof context.description.immutable === "function") {
|
|
10
|
-
const doc = await context.collection.model.findOne({
|
|
11
|
-
_id: new ObjectId(docId)
|
|
12
|
-
});
|
|
13
|
-
if (!doc) {
|
|
14
|
-
return Result.error(ACError.ResourceNotFound);
|
|
15
|
-
}
|
|
16
|
-
const isImmutable = await context.description.immutable(doc);
|
|
17
|
-
return isImmutable ? Result.error(ACError.TargetImmutable) : Result.result(props.payload);
|
|
18
|
-
}
|
|
19
|
-
return Result.error(ACError.TargetImmutable);
|
|
20
|
-
}
|
|
21
|
-
return Result.result(props.payload);
|
|
22
|
-
};
|
|
23
|
-
export const checkImmutabilityRead = async (props, context, next) => {
|
|
24
|
-
const { payload: originalPayload } = props.result;
|
|
25
|
-
if (!(originalPayload.filters._id instanceof ObjectId)) {
|
|
26
|
-
throw new Error();
|
|
27
|
-
}
|
|
28
|
-
const { result: payload, error } = await checkImmutability(originalPayload.filters._id, props.result, context);
|
|
29
|
-
if (error) {
|
|
30
|
-
return Result.error(error);
|
|
31
|
-
}
|
|
32
|
-
return next(Result.result({
|
|
33
|
-
...props.result,
|
|
34
|
-
payload
|
|
35
|
-
}), context);
|
|
36
|
-
};
|
|
37
|
-
export const checkImmutabilityWrite = async (props, context, next) => {
|
|
38
|
-
const { payload: originalPayload } = props.result;
|
|
39
|
-
const { result: payload, error } = await checkImmutability(originalPayload.what._id, props.result, context);
|
|
40
|
-
if (error) {
|
|
41
|
-
return Result.error(error);
|
|
42
|
-
}
|
|
43
|
-
return next(Result.result({
|
|
44
|
-
...props.result,
|
|
45
|
-
payload
|
|
46
|
-
}), context);
|
|
47
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Result, ACError } from "@aeriajs/types";
|
|
3
|
-
export const checkOwnershipRead = async (props, context, next) => {
|
|
4
|
-
const { token, description } = context;
|
|
5
|
-
const { payload } = props.result;
|
|
6
|
-
if (token.authenticated && description.owned && description.owned !== "on-write") {
|
|
7
|
-
if (!token.roles.includes("root")) {
|
|
8
|
-
payload.filters.owner = token.sub;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return next(Result.result({
|
|
12
|
-
...props.result,
|
|
13
|
-
payload
|
|
14
|
-
}), context);
|
|
15
|
-
};
|
|
16
|
-
export const checkOwnershipWrite = async (props, context, next) => {
|
|
17
|
-
const { token, description } = context;
|
|
18
|
-
const { payload, parentId } = props.result;
|
|
19
|
-
if (token.authenticated && description.owned) {
|
|
20
|
-
if (!payload.what._id || description.owned === "always") {
|
|
21
|
-
payload.what.owner = token.sub;
|
|
22
|
-
} else {
|
|
23
|
-
return next(props, context);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (!payload.what.owner && !parentId && context.description.owned) {
|
|
27
|
-
return Result.error(ACError.OwnershipError);
|
|
28
|
-
}
|
|
29
|
-
return next(Result.result({
|
|
30
|
-
...props.result,
|
|
31
|
-
payload
|
|
32
|
-
}), context);
|
|
33
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Result, ACError } from "@aeriajs/types";
|
|
3
|
-
export const checkPagination = async (props, context, next) => {
|
|
4
|
-
const { payload } = props.result;
|
|
5
|
-
switch (typeof payload.limit) {
|
|
6
|
-
case "undefined":
|
|
7
|
-
break;
|
|
8
|
-
case "number": {
|
|
9
|
-
if (payload.limit <= 0) {
|
|
10
|
-
return Result.error(ACError.InvalidLimit);
|
|
11
|
-
}
|
|
12
|
-
if (context.config.security.paginationLimit && payload.limit > context.config.security.paginationLimit) {
|
|
13
|
-
return Result.error(ACError.InvalidLimit);
|
|
14
|
-
}
|
|
15
|
-
break;
|
|
16
|
-
}
|
|
17
|
-
default: {
|
|
18
|
-
return Result.error(ACError.InvalidLimit);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return next(props, context);
|
|
22
|
-
};
|
package/dist/rateLimiting.mjs
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Result, HTTPStatus, RateLimitingError } from "@aeriajs/types";
|
|
3
|
-
const buildEntryFilter = (params, context) => {
|
|
4
|
-
if (params.strategy === "ip") {
|
|
5
|
-
const address = context.response.socket.remoteAddress;
|
|
6
|
-
return {
|
|
7
|
-
address
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
if (!context.token.sub) {
|
|
11
|
-
throw new Error("user is not authenticated");
|
|
12
|
-
}
|
|
13
|
-
return {
|
|
14
|
-
user: context.token.sub
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
export const getOrCreateUsageEntry = async (params, context) => {
|
|
18
|
-
const filters = buildEntryFilter(params, context);
|
|
19
|
-
return context.collections.resourceUsage.model.findOneAndUpdate(
|
|
20
|
-
filters,
|
|
21
|
-
{
|
|
22
|
-
$setOnInsert: {
|
|
23
|
-
usage: {}
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
upsert: true,
|
|
28
|
-
returnDocument: "after"
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
};
|
|
32
|
-
export const limitRate = async (params, context) => {
|
|
33
|
-
const { increment = 1 } = params;
|
|
34
|
-
const entry = await getOrCreateUsageEntry(params, context);
|
|
35
|
-
if (!entry) {
|
|
36
|
-
return context.error(HTTPStatus.InternalServerError, {
|
|
37
|
-
code: RateLimitingError.Unauthenticated
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
const pathname = context.request.url.replace(new RegExp(`^${context.config.baseUrl}`), "");
|
|
41
|
-
const resourceName = new URL(`http://0.com${pathname}`).pathname;
|
|
42
|
-
const resource = entry.usage[resourceName];
|
|
43
|
-
if (resource) {
|
|
44
|
-
if ("scale" in params) {
|
|
45
|
-
const now = /* @__PURE__ */ new Date();
|
|
46
|
-
if (params.scale > now.getTime() / 1e3 - resource.last_reach.getTime() / 1e3) {
|
|
47
|
-
return context.error(HTTPStatus.TooManyRequests, {
|
|
48
|
-
code: RateLimitingError.LimitReached
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const newEntry = await context.collections.resourceUsage.model.findOneAndUpdate(
|
|
54
|
-
{
|
|
55
|
-
_id: entry._id
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
$inc: {
|
|
59
|
-
[`usage.${resourceName}.hits`]: 1,
|
|
60
|
-
[`usage.${resourceName}.points`]: increment
|
|
61
|
-
},
|
|
62
|
-
$set: {
|
|
63
|
-
[`usage.${resourceName}.last_reach`]: /* @__PURE__ */ new Date(),
|
|
64
|
-
[`usage.${resourceName}.last_maximum_reach`]: /* @__PURE__ */ new Date()
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
returnDocument: "after"
|
|
69
|
-
}
|
|
70
|
-
);
|
|
71
|
-
if (!newEntry || !newEntry.usage[resourceName]) {
|
|
72
|
-
throw new Error();
|
|
73
|
-
}
|
|
74
|
-
return Result.result(newEntry.usage[resourceName]);
|
|
75
|
-
};
|
package/dist/types.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
package/dist/use.mjs
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Result } from "@aeriajs/types";
|
|
3
|
-
import { iterableMiddlewares } from "./middleware/index.mjs";
|
|
4
|
-
import {
|
|
5
|
-
checkImmutabilityWrite,
|
|
6
|
-
checkOwnershipRead,
|
|
7
|
-
checkOwnershipWrite,
|
|
8
|
-
checkPagination
|
|
9
|
-
} from "./middlewares/index.mjs";
|
|
10
|
-
export const useSecurity = (context) => {
|
|
11
|
-
const secureReadPayload = async (payload) => {
|
|
12
|
-
const props = {
|
|
13
|
-
payload: {
|
|
14
|
-
filters: {},
|
|
15
|
-
...payload
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
const start = iterableMiddlewares([
|
|
19
|
-
checkPagination,
|
|
20
|
-
checkOwnershipRead
|
|
21
|
-
]);
|
|
22
|
-
const { error, result } = await start(Result.result(props), context);
|
|
23
|
-
if (error) {
|
|
24
|
-
return Result.error(error);
|
|
25
|
-
}
|
|
26
|
-
return Result.result(result.payload);
|
|
27
|
-
};
|
|
28
|
-
const secureWritePayload = async (payload) => {
|
|
29
|
-
const props = {
|
|
30
|
-
payload
|
|
31
|
-
};
|
|
32
|
-
const start = iterableMiddlewares([
|
|
33
|
-
checkOwnershipWrite,
|
|
34
|
-
checkImmutabilityWrite
|
|
35
|
-
]);
|
|
36
|
-
const { error, result } = await start(Result.result(props), context);
|
|
37
|
-
if (error) {
|
|
38
|
-
return Result.error(error);
|
|
39
|
-
}
|
|
40
|
-
return Result.result(result.payload);
|
|
41
|
-
};
|
|
42
|
-
return {
|
|
43
|
-
secureReadPayload,
|
|
44
|
-
secureWritePayload
|
|
45
|
-
};
|
|
46
|
-
};
|