@seidor-cloud-produtos/orbit-backend-lib 0.0.9 → 0.0.11
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/clean-arch/application/queue/handler.js +2 -0
- package/dist/clean-arch/application/queue/messages-in-memory.d.ts +1 -1
- package/dist/clean-arch/application/queue/messages-in-memory.js +2 -0
- package/dist/clean-arch/application/queue/queue-connection.js +2 -0
- package/dist/clean-arch/application/queue/queue.d.ts +1 -1
- package/dist/clean-arch/application/queue/queue.js +2 -0
- package/dist/clean-arch/domain/entities/aggregate-root.js +19 -0
- package/dist/clean-arch/domain/entities/common-dto.js +2 -0
- package/dist/clean-arch/domain/entities/entity.js +26 -0
- package/dist/clean-arch/domain/entities/unique-entity-id.js +19 -0
- package/dist/clean-arch/domain/entities/value-object.js +9 -0
- package/dist/clean-arch/domain/entities/watched-list.js +88 -0
- package/dist/clean-arch/domain/entities/watched-list.spec.js +49 -0
- package/dist/clean-arch/domain/errors/application-error.js +9 -0
- package/dist/clean-arch/domain/errors/domain-error.js +9 -0
- package/dist/clean-arch/domain/errors/validation-error.js +11 -0
- package/dist/clean-arch/domain/events/domain-event.js +2 -0
- package/dist/clean-arch/domain/types/optional.js +2 -0
- package/dist/clean-arch/infra/adapters/express-adapter.js +43 -0
- package/dist/clean-arch/infra/adapters/fastify-adapter.js +51 -0
- package/dist/clean-arch/infra/authorizations/authorization.d.ts +4 -4
- package/dist/clean-arch/infra/authorizations/authorization.js +29 -0
- package/dist/clean-arch/infra/authorizations/authorizer.d.ts +1 -1
- package/dist/clean-arch/infra/authorizations/authorizer.js +18 -0
- package/dist/clean-arch/infra/authorizations/authorizer.spec.js +145 -0
- package/dist/clean-arch/infra/authorizations/not-allowed.d.ts +2 -2
- package/dist/clean-arch/infra/authorizations/not-allowed.js +9 -0
- package/dist/clean-arch/infra/errors/infra-error.js +9 -0
- package/dist/clean-arch/infra/http/controller.js +70 -0
- package/dist/clean-arch/infra/http/handle-bool-filter.js +9 -0
- package/dist/clean-arch/infra/http/handle-is-active-query.js +9 -0
- package/dist/clean-arch/infra/http/handle-sort-param-query.js +16 -0
- package/dist/clean-arch/infra/http/handle-user-headers.js +12 -0
- package/dist/clean-arch/infra/http/health-connections.js +12 -0
- package/dist/clean-arch/infra/http/http.js +2 -0
- package/dist/clean-arch/shared/pagination/dto-response.js +2 -0
- package/dist/clean-arch/shared/pagination/get-take-and-skip.js +9 -0
- package/dist/clean-arch/shared/pagination/pagination.js +2 -0
- package/dist/frameworks/express/authorizations/authorization-express.d.ts +4 -4
- package/dist/frameworks/express/authorizations/authorization-express.js +32 -0
- package/dist/frameworks/express/authorizations/authorization-express.spec.js +75 -0
- package/dist/frameworks/express/authorizations/midleware-express.d.ts +1 -1
- package/dist/frameworks/express/authorizations/midleware-express.js +16 -0
- package/dist/frameworks/nest/authorizations/guard-nest.d.ts +1 -1
- package/dist/frameworks/nest/authorizations/guard-nest.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/infra/authorizations/auth-matcher.js +54 -0
- package/dist/infra/authorizations/auth-matcher.spec.js +101 -0
- package/dist/infra/authorizations/validator/api/api-validator.d.ts +3 -3
- package/dist/infra/authorizations/validator/api/api-validator.js +24 -0
- package/dist/infra/authorizations/validator/api/factories/unauthorized-response-factory.d.ts +3 -3
- package/dist/infra/authorizations/validator/api/factories/unauthorized-response-factory.js +41 -0
- package/dist/infra/authorizations/validator/api/factories/unauthorized-response-factory.spec.js +111 -0
- package/dist/infra/authorizations/validator/auth-validator.js +22 -0
- package/dist/infra/authorizations/validator/auth-validator.spec.js +67 -0
- package/dist/infra/http/errors/api-common-error.js +2 -0
- package/dist/infra/http/errors/api-error.js +11 -0
- package/dist/infra/http/errors/unauthorized-response.js +2 -0
- package/lib/clean-arch/application/queue/handler.ts +3 -0
- package/lib/clean-arch/application/queue/messages-in-memory.ts +7 -0
- package/lib/clean-arch/application/queue/queue-connection.ts +7 -0
- package/lib/clean-arch/application/queue/queue.ts +11 -0
- package/lib/clean-arch/domain/entities/aggregate-root.ts +22 -0
- package/lib/clean-arch/domain/entities/common-dto.ts +16 -0
- package/lib/clean-arch/domain/entities/entity.ts +31 -0
- package/lib/clean-arch/domain/entities/unique-entity-id.ts +21 -0
- package/lib/clean-arch/domain/entities/value-object.ts +7 -0
- package/lib/clean-arch/domain/entities/watched-list.spec.ts +65 -0
- package/lib/clean-arch/domain/entities/watched-list.ts +130 -0
- package/lib/clean-arch/domain/errors/application-error.ts +8 -0
- package/lib/clean-arch/domain/errors/domain-error.ts +8 -0
- package/lib/clean-arch/domain/errors/validation-error.ts +17 -0
- package/lib/clean-arch/domain/events/domain-event.ts +4 -0
- package/lib/clean-arch/domain/types/optional.ts +1 -0
- package/lib/clean-arch/infra/adapters/express-adapter.ts +49 -0
- package/lib/clean-arch/infra/adapters/fastify-adapter.ts +66 -0
- package/lib/clean-arch/infra/authorizations/authorization.ts +47 -0
- package/lib/clean-arch/infra/authorizations/authorizer.spec.ts +156 -0
- package/lib/clean-arch/infra/authorizations/authorizer.ts +22 -0
- package/lib/clean-arch/infra/authorizations/not-allowed.ts +8 -0
- package/lib/clean-arch/infra/errors/infra-error.ts +8 -0
- package/lib/clean-arch/infra/http/controller.ts +93 -0
- package/lib/clean-arch/infra/http/handle-bool-filter.ts +7 -0
- package/lib/clean-arch/infra/http/handle-is-active-query.ts +7 -0
- package/lib/clean-arch/infra/http/handle-sort-param-query.ts +12 -0
- package/lib/clean-arch/infra/http/handle-user-headers.ts +13 -0
- package/lib/clean-arch/infra/http/health-connections.ts +21 -0
- package/lib/clean-arch/infra/http/http.ts +7 -0
- package/lib/clean-arch/shared/pagination/dto-response.ts +5 -0
- package/lib/clean-arch/shared/pagination/get-take-and-skip.ts +6 -0
- package/lib/clean-arch/shared/pagination/pagination.ts +8 -0
- package/lib/frameworks/express/authorizations/authorization-express.spec.ts +107 -0
- package/lib/frameworks/express/authorizations/authorization-express.ts +54 -0
- package/lib/frameworks/express/authorizations/midleware-express.ts +16 -0
- package/lib/frameworks/nest/authorizations/guard-nest.ts +24 -0
- package/lib/index.ts +1 -0
- package/lib/infra/authorizations/auth-matcher.spec.ts +130 -0
- package/lib/infra/authorizations/auth-matcher.ts +76 -0
- package/lib/infra/authorizations/validator/api/api-validator.ts +37 -0
- package/lib/infra/authorizations/validator/api/factories/unauthorized-response-factory.spec.ts +126 -0
- package/lib/infra/authorizations/validator/api/factories/unauthorized-response-factory.ts +51 -0
- package/lib/infra/authorizations/validator/auth-validator.spec.ts +82 -0
- package/lib/infra/authorizations/validator/auth-validator.ts +35 -0
- package/lib/infra/http/errors/api-common-error.ts +25 -0
- package/lib/infra/http/errors/api-error.ts +13 -0
- package/lib/infra/http/errors/unauthorized-response.ts +7 -0
- package/lib/node_modules/.vitest/results.json +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateRoot = void 0;
|
|
4
|
+
const entity_1 = require("./entity");
|
|
5
|
+
class AggregateRoot extends entity_1.Entity {
|
|
6
|
+
get createdAt() {
|
|
7
|
+
return this.props.createdAt;
|
|
8
|
+
}
|
|
9
|
+
set createdAt(date) {
|
|
10
|
+
this.props.createdAt = date;
|
|
11
|
+
}
|
|
12
|
+
get updatedAt() {
|
|
13
|
+
return this.props.updatedAt;
|
|
14
|
+
}
|
|
15
|
+
touch() {
|
|
16
|
+
this.props.updatedAt = new Date();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.AggregateRoot = AggregateRoot;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Entity = void 0;
|
|
4
|
+
const unique_entity_id_1 = require("./unique-entity-id");
|
|
5
|
+
class Entity {
|
|
6
|
+
get id() {
|
|
7
|
+
return this._id;
|
|
8
|
+
}
|
|
9
|
+
set id(id) {
|
|
10
|
+
this._id = id;
|
|
11
|
+
}
|
|
12
|
+
constructor(props, id) {
|
|
13
|
+
this._id = id ?? new unique_entity_id_1.UniqueEntityId(id);
|
|
14
|
+
this.props = props;
|
|
15
|
+
}
|
|
16
|
+
equals(entity) {
|
|
17
|
+
if (entity === this) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (entity.id === this._id) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.Entity = Entity;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UniqueEntityId = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
class UniqueEntityId {
|
|
6
|
+
constructor(value) {
|
|
7
|
+
this.value = value ?? (0, node_crypto_1.randomUUID)();
|
|
8
|
+
}
|
|
9
|
+
toString() {
|
|
10
|
+
return this.value;
|
|
11
|
+
}
|
|
12
|
+
toValue() {
|
|
13
|
+
return this.value;
|
|
14
|
+
}
|
|
15
|
+
equals(id) {
|
|
16
|
+
return id.toValue() === this.toValue();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.UniqueEntityId = UniqueEntityId;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WatchedList = void 0;
|
|
4
|
+
class WatchedList {
|
|
5
|
+
constructor(initialItems) {
|
|
6
|
+
this.currentItems = initialItems || [];
|
|
7
|
+
this.initial = initialItems || [];
|
|
8
|
+
this.new = [];
|
|
9
|
+
this.removed = [];
|
|
10
|
+
this.updated = [];
|
|
11
|
+
}
|
|
12
|
+
getItems() {
|
|
13
|
+
return this.currentItems;
|
|
14
|
+
}
|
|
15
|
+
getNewItems() {
|
|
16
|
+
return this.new;
|
|
17
|
+
}
|
|
18
|
+
getRemovedItems() {
|
|
19
|
+
return this.removed;
|
|
20
|
+
}
|
|
21
|
+
getUpdatedItems() {
|
|
22
|
+
return this.updated;
|
|
23
|
+
}
|
|
24
|
+
addUpdatedItem(item) {
|
|
25
|
+
return this.updated.push(item);
|
|
26
|
+
}
|
|
27
|
+
isCurrentItem(item) {
|
|
28
|
+
return (this.currentItems.filter((v) => this.compareItems(item, v)).length !==
|
|
29
|
+
0);
|
|
30
|
+
}
|
|
31
|
+
isNewItem(item) {
|
|
32
|
+
return this.new.filter((v) => this.compareItems(item, v)).length !== 0;
|
|
33
|
+
}
|
|
34
|
+
isRemovedItem(item) {
|
|
35
|
+
return (this.removed.filter((v) => this.compareItems(item, v)).length !== 0);
|
|
36
|
+
}
|
|
37
|
+
removeFromNew(item) {
|
|
38
|
+
this.new = this.new.filter(v => !this.compareItems(v, item));
|
|
39
|
+
}
|
|
40
|
+
removeFromCurrent(item) {
|
|
41
|
+
this.currentItems = this.currentItems.filter(v => !this.compareItems(item, v));
|
|
42
|
+
}
|
|
43
|
+
removeFromRemoved(item) {
|
|
44
|
+
this.removed = this.removed.filter(v => !this.compareItems(item, v));
|
|
45
|
+
}
|
|
46
|
+
wasAddedInitially(item) {
|
|
47
|
+
return (this.initial.filter((v) => this.compareItems(item, v)).length !== 0);
|
|
48
|
+
}
|
|
49
|
+
exists(item) {
|
|
50
|
+
return this.isCurrentItem(item);
|
|
51
|
+
}
|
|
52
|
+
add(item) {
|
|
53
|
+
if (this.isRemovedItem(item)) {
|
|
54
|
+
this.removeFromRemoved(item);
|
|
55
|
+
}
|
|
56
|
+
if (!this.isNewItem(item) && !this.wasAddedInitially(item)) {
|
|
57
|
+
this.new.push(item);
|
|
58
|
+
}
|
|
59
|
+
if (!this.isCurrentItem(item)) {
|
|
60
|
+
this.currentItems.push(item);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
remove(item) {
|
|
64
|
+
this.removeFromCurrent(item);
|
|
65
|
+
if (this.isNewItem(item)) {
|
|
66
|
+
this.removeFromNew(item);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!this.isRemovedItem(item)) {
|
|
70
|
+
this.removed.push(item);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
update(items) {
|
|
74
|
+
const newItems = items.filter(a => {
|
|
75
|
+
return !this.getItems().some(b => this.compareItems(a, b));
|
|
76
|
+
});
|
|
77
|
+
const removedItems = this.getItems().filter(a => {
|
|
78
|
+
return !items.some(b => this.compareItems(a, b));
|
|
79
|
+
});
|
|
80
|
+
const updatedItems = items.filter(item => !newItems.some(a => this.compareItems(item, a) &&
|
|
81
|
+
!removedItems.some(b => this.compareItems(item, b))));
|
|
82
|
+
this.currentItems = items;
|
|
83
|
+
this.new = newItems;
|
|
84
|
+
this.removed = removedItems;
|
|
85
|
+
this.updated = updatedItems;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.WatchedList = WatchedList;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const watched_list_1 = require("./watched-list");
|
|
4
|
+
class NumberWatchedList extends watched_list_1.WatchedList {
|
|
5
|
+
compareItems(a, b) {
|
|
6
|
+
return a === b;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
describe('Watched List', () => {
|
|
10
|
+
it('should be able to create a watched list with initial items', () => {
|
|
11
|
+
const list = new NumberWatchedList([1, 2, 3]);
|
|
12
|
+
expect(list.currentItems).toHaveLength(3);
|
|
13
|
+
});
|
|
14
|
+
it('should be able to add new items to the list', () => {
|
|
15
|
+
const list = new NumberWatchedList([1, 2, 3]);
|
|
16
|
+
list.add(4);
|
|
17
|
+
expect(list.currentItems).toHaveLength(4);
|
|
18
|
+
expect(list.getNewItems()).toEqual([4]);
|
|
19
|
+
});
|
|
20
|
+
it('should be able to add remove items from the list', () => {
|
|
21
|
+
const list = new NumberWatchedList([1, 2, 3]);
|
|
22
|
+
list.remove(2);
|
|
23
|
+
expect(list.currentItems).toHaveLength(2);
|
|
24
|
+
expect(list.getRemovedItems()).toEqual([2]);
|
|
25
|
+
});
|
|
26
|
+
it('should be able to add an item even if it was removed before', () => {
|
|
27
|
+
const list = new NumberWatchedList([1, 2, 3]);
|
|
28
|
+
list.remove(2);
|
|
29
|
+
list.add(2);
|
|
30
|
+
expect(list.currentItems).toHaveLength(3);
|
|
31
|
+
expect(list.getRemovedItems()).toEqual([]);
|
|
32
|
+
expect(list.getNewItems()).toEqual([]);
|
|
33
|
+
});
|
|
34
|
+
it('should be able to remove an item even if it was added before', () => {
|
|
35
|
+
const list = new NumberWatchedList([1, 2, 3]);
|
|
36
|
+
list.add(4);
|
|
37
|
+
list.remove(4);
|
|
38
|
+
expect(list.currentItems).toHaveLength(3);
|
|
39
|
+
expect(list.getRemovedItems()).toEqual([]);
|
|
40
|
+
expect(list.getNewItems()).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
it('should be able to update watched list items', () => {
|
|
43
|
+
const list = new NumberWatchedList([1, 2, 3]);
|
|
44
|
+
list.update([1, 3, 5]);
|
|
45
|
+
expect(list.getRemovedItems()).toEqual([2]);
|
|
46
|
+
expect(list.getNewItems()).toEqual([5]);
|
|
47
|
+
expect(list.getUpdatedItems()).toEqual([1, 3]);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class ValidationError extends Error {
|
|
4
|
+
constructor(errors) {
|
|
5
|
+
super('Validation Error');
|
|
6
|
+
this.code = 400;
|
|
7
|
+
this.name = 'Validation Error';
|
|
8
|
+
this.errors = errors;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.default = ValidationError;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const cors_1 = tslib_1.__importDefault(require("cors"));
|
|
5
|
+
const express_1 = tslib_1.__importDefault(require("express"));
|
|
6
|
+
class ExpressAdapter {
|
|
7
|
+
constructor(envs) {
|
|
8
|
+
this.envs = envs;
|
|
9
|
+
this.instance = (0, express_1.default)();
|
|
10
|
+
this.instance.use((0, cors_1.default)());
|
|
11
|
+
this.instance.use(express_1.default.json({ limit: '10mb' }));
|
|
12
|
+
this.instance.use(express_1.default.urlencoded({ limit: '10mb', extended: false }));
|
|
13
|
+
}
|
|
14
|
+
on(method, url, callback) {
|
|
15
|
+
this.instance[method](url, async (request, response) => {
|
|
16
|
+
try {
|
|
17
|
+
const requestData = {
|
|
18
|
+
body: request.body,
|
|
19
|
+
params: request.params,
|
|
20
|
+
headers: request.headers,
|
|
21
|
+
query: request.query,
|
|
22
|
+
};
|
|
23
|
+
const output = await callback.handle(requestData);
|
|
24
|
+
return response.status(output.code || 200).json(output.data || {});
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const error = callback.throw(err);
|
|
28
|
+
return response.status(error.code).json(error.data || {});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async listen(port) {
|
|
33
|
+
this.server = this.instance.listen(port, () => {
|
|
34
|
+
if (this.envs.NODE_ENV !== 'test') {
|
|
35
|
+
console.log(`🚀 Server is running on PORT ${port}`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async close() {
|
|
40
|
+
await this.server.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = ExpressAdapter;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const cors_1 = tslib_1.__importDefault(require("@fastify/cors"));
|
|
5
|
+
const fastify_1 = tslib_1.__importDefault(require("fastify"));
|
|
6
|
+
const qs_1 = tslib_1.__importDefault(require("qs"));
|
|
7
|
+
class FastifyAdapter {
|
|
8
|
+
constructor(envs) {
|
|
9
|
+
this.envs = envs;
|
|
10
|
+
this.instance = (0, fastify_1.default)({
|
|
11
|
+
bodyLimit: 10 * 1024 * 1024,
|
|
12
|
+
querystringParser: str => qs_1.default.parse(str),
|
|
13
|
+
});
|
|
14
|
+
this.instance.register(cors_1.default);
|
|
15
|
+
}
|
|
16
|
+
on(method, url, callback) {
|
|
17
|
+
this.instance[method](url, async (request, reply) => {
|
|
18
|
+
try {
|
|
19
|
+
const requestData = {
|
|
20
|
+
body: request.body,
|
|
21
|
+
params: request.params,
|
|
22
|
+
headers: request.headers,
|
|
23
|
+
query: request.query,
|
|
24
|
+
};
|
|
25
|
+
const output = await callback.handle(requestData);
|
|
26
|
+
return reply.status(output.code || 200).send(output.data || {});
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const error = callback.throw(err);
|
|
30
|
+
return reply.status(error.code || 200).send(error.data || {});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async listen(port) {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
36
|
+
this.instance.listen({ port }, async (err, _) => {
|
|
37
|
+
if (err) {
|
|
38
|
+
console.error(err);
|
|
39
|
+
process.exit();
|
|
40
|
+
}
|
|
41
|
+
await this.instance?.ready();
|
|
42
|
+
if (this.envs.NODE_ENV !== 'test') {
|
|
43
|
+
console.log(`🚀 Server is running on PORT ${port}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async close() {
|
|
48
|
+
await this.instance.close();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.default = FastifyAdapter;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AuthParams } from '
|
|
2
|
-
import { APIAuthValidator } from '
|
|
3
|
-
import AuthValidator from '
|
|
4
|
-
import { UnauthorizedResponse } from '
|
|
1
|
+
import { AuthParams } from '../../../infra/authorizations/auth-matcher';
|
|
2
|
+
import { APIAuthValidator } from '../../../infra/authorizations/validator/api/api-validator';
|
|
3
|
+
import AuthValidator from '../../../infra/authorizations/validator/auth-validator';
|
|
4
|
+
import { UnauthorizedResponse } from '../../../infra/http/errors/unauthorized-response';
|
|
5
5
|
import { Request, Response } from '../http/controller';
|
|
6
6
|
type AuthorizationMetaData = {
|
|
7
7
|
handle(input: Request): Promise<Response>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const api_validator_1 = require("../../../infra/authorizations/validator/api/api-validator");
|
|
5
|
+
const not_allowed_1 = tslib_1.__importDefault(require("./not-allowed"));
|
|
6
|
+
class Authorization extends api_validator_1.APIAuthValidator {
|
|
7
|
+
static async create(query, controllerMetaData) {
|
|
8
|
+
const instance = new Authorization(query, controllerMetaData);
|
|
9
|
+
return await instance.setup();
|
|
10
|
+
}
|
|
11
|
+
unauthorize(response) {
|
|
12
|
+
throw new not_allowed_1.default(response);
|
|
13
|
+
}
|
|
14
|
+
getRequestId() {
|
|
15
|
+
return this.controller.request.headers['X-Amzn-Requestid'];
|
|
16
|
+
}
|
|
17
|
+
async getAuthorizations() {
|
|
18
|
+
const authorizations = this.controller.request.headers
|
|
19
|
+
.authorizations;
|
|
20
|
+
if (typeof authorizations === 'string') {
|
|
21
|
+
return JSON.parse(authorizations);
|
|
22
|
+
}
|
|
23
|
+
return authorizations;
|
|
24
|
+
}
|
|
25
|
+
handleAuthorized() {
|
|
26
|
+
return this.controller.handle(this.controller.request);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.default = Authorization;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthParams } from '
|
|
1
|
+
import { AuthParams } from '../../../infra/authorizations/auth-matcher';
|
|
2
2
|
import { Request, Response } from '../http/controller';
|
|
3
3
|
export default function Authorizer(props: AuthParams): <T extends new (..._: any[]) => {
|
|
4
4
|
handle(request: Request): Promise<Response>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const authorization_1 = tslib_1.__importDefault(require("./authorization"));
|
|
5
|
+
function Authorizer(props) {
|
|
6
|
+
return function (constructor) {
|
|
7
|
+
return class extends constructor {
|
|
8
|
+
async handle(request) {
|
|
9
|
+
const authorization = await authorization_1.default.create(props, {
|
|
10
|
+
handle: super.handle,
|
|
11
|
+
request,
|
|
12
|
+
});
|
|
13
|
+
return authorization.validate();
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
exports.default = Authorizer;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
5
|
+
const authorizer_1 = tslib_1.__importDefault(require("./authorizer"));
|
|
6
|
+
describe('Authorizer', () => {
|
|
7
|
+
it('should be able to validate authorizations (AND)', async () => {
|
|
8
|
+
let Test = class Test {
|
|
9
|
+
async handle(_) {
|
|
10
|
+
return {
|
|
11
|
+
data: { message: 'ok' },
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
Test = tslib_1.__decorate([
|
|
16
|
+
(0, authorizer_1.default)({ $and: ['arch.user.create'] })
|
|
17
|
+
], Test);
|
|
18
|
+
const controller = new Test();
|
|
19
|
+
const response = await controller.handle({
|
|
20
|
+
headers: {
|
|
21
|
+
authorizations: [
|
|
22
|
+
'arch.user.create',
|
|
23
|
+
'arch.user.update',
|
|
24
|
+
'arch.user.list',
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
body: {},
|
|
28
|
+
params: {},
|
|
29
|
+
query: {},
|
|
30
|
+
});
|
|
31
|
+
expect(response.data).toEqual({ message: 'ok' });
|
|
32
|
+
});
|
|
33
|
+
it('should be able to validate authorizations (OR)', async () => {
|
|
34
|
+
let Test = class Test {
|
|
35
|
+
async handle(_) {
|
|
36
|
+
return {
|
|
37
|
+
data: { message: 'ok' },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
Test = tslib_1.__decorate([
|
|
42
|
+
(0, authorizer_1.default)({ $or: ['arch.user.list', 'arch.user.update'] })
|
|
43
|
+
], Test);
|
|
44
|
+
const controller = new Test();
|
|
45
|
+
const response = await controller.handle({
|
|
46
|
+
headers: {
|
|
47
|
+
authorizations: ['arch.user.create', 'arch.user.list'],
|
|
48
|
+
},
|
|
49
|
+
body: {},
|
|
50
|
+
params: {},
|
|
51
|
+
query: {},
|
|
52
|
+
});
|
|
53
|
+
expect(response.data).toEqual({ message: 'ok' });
|
|
54
|
+
});
|
|
55
|
+
it('should be able to validate authorizations (THROW)', async () => {
|
|
56
|
+
let Test = class Test {
|
|
57
|
+
async handle(_) {
|
|
58
|
+
return {
|
|
59
|
+
data: { message: 'ok' },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
Test = tslib_1.__decorate([
|
|
64
|
+
(0, authorizer_1.default)({ $or: ['arch.user.list', 'arch.user.create'] })
|
|
65
|
+
], Test);
|
|
66
|
+
const controller = new Test();
|
|
67
|
+
await expect(() => controller.handle({
|
|
68
|
+
headers: {
|
|
69
|
+
authorizations: ['arch.user.update'],
|
|
70
|
+
},
|
|
71
|
+
body: {},
|
|
72
|
+
params: {},
|
|
73
|
+
query: {},
|
|
74
|
+
})).rejects.toBeInstanceOf(Error);
|
|
75
|
+
});
|
|
76
|
+
it('should be able to call controller when authorization is not required', async () => {
|
|
77
|
+
let Test = class Test {
|
|
78
|
+
async handle(_) {
|
|
79
|
+
return {
|
|
80
|
+
data: { message: 'ok' },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
Test = tslib_1.__decorate([
|
|
85
|
+
(0, authorizer_1.default)({})
|
|
86
|
+
], Test);
|
|
87
|
+
const controller = new Test();
|
|
88
|
+
const response = await controller.handle({
|
|
89
|
+
headers: {
|
|
90
|
+
authorizations: [
|
|
91
|
+
'arch.user.create',
|
|
92
|
+
'arch.user.update',
|
|
93
|
+
'arch.user.list',
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
body: {},
|
|
97
|
+
params: {},
|
|
98
|
+
query: {},
|
|
99
|
+
});
|
|
100
|
+
expect(response.data).toEqual({ message: 'ok' });
|
|
101
|
+
});
|
|
102
|
+
it('should be able to return error when not have authorizations on request', async () => {
|
|
103
|
+
let Test = class Test {
|
|
104
|
+
async handle(_) {
|
|
105
|
+
return {
|
|
106
|
+
data: { message: 'ok' },
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
Test = tslib_1.__decorate([
|
|
111
|
+
(0, authorizer_1.default)({ $and: ['arch.user.list', 'arch.user.create'] })
|
|
112
|
+
], Test);
|
|
113
|
+
const controller = new Test();
|
|
114
|
+
await expect(() => controller.handle({
|
|
115
|
+
headers: {
|
|
116
|
+
authorizations: [],
|
|
117
|
+
},
|
|
118
|
+
body: {},
|
|
119
|
+
params: {},
|
|
120
|
+
query: {},
|
|
121
|
+
})).rejects.toBeInstanceOf(Error);
|
|
122
|
+
});
|
|
123
|
+
it('should be able to convert authorizations string to object JS', async () => {
|
|
124
|
+
let Test = class Test {
|
|
125
|
+
async handle(_) {
|
|
126
|
+
return {
|
|
127
|
+
data: { message: 'ok' },
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
Test = tslib_1.__decorate([
|
|
132
|
+
(0, authorizer_1.default)({ $and: ['arch.user.create'] })
|
|
133
|
+
], Test);
|
|
134
|
+
const controller = new Test();
|
|
135
|
+
const response = await controller.handle({
|
|
136
|
+
headers: {
|
|
137
|
+
authorizations: JSON.stringify(['arch.user.create']),
|
|
138
|
+
},
|
|
139
|
+
body: {},
|
|
140
|
+
params: {},
|
|
141
|
+
query: {},
|
|
142
|
+
});
|
|
143
|
+
expect(response.data).toEqual({ message: 'ok' });
|
|
144
|
+
});
|
|
145
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ApiError } from '
|
|
2
|
-
import { UnauthorizedResponse } from '
|
|
1
|
+
import { ApiError } from '../../../infra/http/errors/api-error';
|
|
2
|
+
import { UnauthorizedResponse } from '../../../infra/http/errors/unauthorized-response';
|
|
3
3
|
export default class NotAllowedError extends ApiError {
|
|
4
4
|
constructor(input: UnauthorizedResponse);
|
|
5
5
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const api_error_1 = require("../../../infra/http/errors/api-error");
|
|
4
|
+
class NotAllowedError extends api_error_1.ApiError {
|
|
5
|
+
constructor(input) {
|
|
6
|
+
super(input);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.default = NotAllowedError;
|