@clairejs/server 3.24.0 → 3.25.0
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 +4 -0
- package/dist/common/request/endpoint-metadata.d.ts +2 -0
- package/dist/http/common/dto.d.ts +2 -0
- package/dist/http/common/dto.js +10 -0
- package/dist/http/controller/AbstractHttpRequestHandler.js +2 -0
- package/dist/http/security/abstract-access-condition.d.ts +7 -0
- package/dist/http/security/abstract-access-condition.js +2 -0
- package/dist/http/security/access-condition-metadata.d.ts +7 -0
- package/dist/http/security/access-condition-metadata.js +49 -0
- package/dist/http/security/access-condition-value-type.d.ts +30 -0
- package/dist/http/security/access-condition-value-type.js +31 -0
- package/dist/http/security/access-conditions/filter-model-fields.d.ts +4 -0
- package/dist/http/security/access-conditions/filter-model-fields.js +31 -0
- package/dist/http/security/access-conditions/max-query-limit.d.ts +8 -0
- package/dist/http/security/access-conditions/max-query-limit.js +29 -0
- package/dist/http/security/access-conditions/socket-read-write.d.ts +13 -0
- package/dist/http/security/access-conditions/socket-read-write.js +50 -0
- package/dist/http/security/decorators.d.ts +7 -0
- package/dist/http/security/decorators.js +37 -1
- package/dist/http/utils.d.ts +1 -1
- package/dist/http/utils.js +8 -4
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type Constructor, type ObjectFieldMetadata } from "@clairejs/core";
|
|
2
2
|
import { type RequestDataSource } from "./types";
|
|
3
3
|
import { ApiInfo } from "../../http/common/dto";
|
|
4
|
+
import { AbstractAccessCondition } from "../../http/security/abstract-access-condition";
|
|
4
5
|
export interface EndpointMetadata extends ApiInfo, ObjectFieldMetadata {
|
|
5
6
|
controller: any;
|
|
7
|
+
accessConditionCls?: Constructor<AbstractAccessCondition<any>>[];
|
|
6
8
|
params?: {
|
|
7
9
|
[index: number]: {
|
|
8
10
|
source?: RequestDataSource;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HttpMethod, SocketMethod, DtoMetadata } from "@clairejs/core";
|
|
2
|
+
import { AccessConditionMetadata } from "../security/access-condition-metadata";
|
|
2
3
|
export declare class ApiInfo {
|
|
3
4
|
id: string;
|
|
4
5
|
apiGroup?: string;
|
|
@@ -15,6 +16,7 @@ export declare class ApiInfo {
|
|
|
15
16
|
downstreamMessageDtos?: DtoMetadata[];
|
|
16
17
|
publicAccess?: boolean;
|
|
17
18
|
tfaRequired?: boolean;
|
|
19
|
+
accessConditions?: AccessConditionMetadata[];
|
|
18
20
|
}
|
|
19
21
|
export declare class ApiInfoResponse {
|
|
20
22
|
apis: ApiInfo[];
|
package/dist/http/common/dto.js
CHANGED
|
@@ -8,6 +8,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
10
|
import { Data, Field, HttpMethod, Enum, getObjectMetadata, DataType } from "@clairejs/core";
|
|
11
|
+
import { AccessConditionMetadata } from "../security/access-condition-metadata";
|
|
11
12
|
let ApiInfo = class ApiInfo {
|
|
12
13
|
id;
|
|
13
14
|
apiGroup;
|
|
@@ -24,6 +25,7 @@ let ApiInfo = class ApiInfo {
|
|
|
24
25
|
downstreamMessageDtos;
|
|
25
26
|
publicAccess;
|
|
26
27
|
tfaRequired;
|
|
28
|
+
accessConditions;
|
|
27
29
|
};
|
|
28
30
|
__decorate([
|
|
29
31
|
Field({
|
|
@@ -121,6 +123,14 @@ __decorate([
|
|
|
121
123
|
}),
|
|
122
124
|
__metadata("design:type", Boolean)
|
|
123
125
|
], ApiInfo.prototype, "tfaRequired", void 0);
|
|
126
|
+
__decorate([
|
|
127
|
+
Field({
|
|
128
|
+
description: "The configurable access condition of this permission",
|
|
129
|
+
vectorProps: {},
|
|
130
|
+
elementDto: getObjectMetadata(AccessConditionMetadata),
|
|
131
|
+
}),
|
|
132
|
+
__metadata("design:type", Array)
|
|
133
|
+
], ApiInfo.prototype, "accessConditions", void 0);
|
|
124
134
|
ApiInfo = __decorate([
|
|
125
135
|
Data()
|
|
126
136
|
], ApiInfo);
|
|
@@ -53,9 +53,11 @@ export class AbstractHttpRequestHandler {
|
|
|
53
53
|
this.logger?.warn(`Implicit overriding endpoint: ${overridingEndpoint.method}:${overridingEndpoint.mount} of ${overridingEndpoint.controller?.constructor.name}:${overridingEndpoint.name}`, `Ignore ${endpointInfo.method}:${endpointInfo.mount} of ${endpointInfo.controller?.constructor.name}:${endpointInfo.name}`);
|
|
54
54
|
}
|
|
55
55
|
else {
|
|
56
|
+
endpointInfo.accessConditions = endpointInfo.accessConditionCls?.map((cls) => injector.resolve(cls).getConditionMetadata());
|
|
56
57
|
mountedEndpointInfo.push(endpointInfo);
|
|
57
58
|
}
|
|
58
59
|
}
|
|
60
|
+
await injector.initInstances();
|
|
59
61
|
this.mountedEndpointInfo = mountedEndpointInfo;
|
|
60
62
|
}
|
|
61
63
|
return this.mountedEndpointInfo;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HttpRequest } from "../common/HttpRequest";
|
|
2
|
+
import { AccessConditionMetadata } from "./access-condition-metadata";
|
|
3
|
+
export declare abstract class AbstractAccessCondition<T> {
|
|
4
|
+
abstract resolveConditionValue(req: HttpRequest): Promise<T>;
|
|
5
|
+
abstract validate(conditionValue: T, permittedConditionValue: unknown): Promise<boolean>;
|
|
6
|
+
abstract getConditionMetadata(): AccessConditionMetadata;
|
|
7
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Data, Enum, Field } from "@clairejs/core";
|
|
11
|
+
import { AccessConditionValueType } from "./access-condition-value-type";
|
|
12
|
+
let AccessConditionMetadata = class AccessConditionMetadata {
|
|
13
|
+
name;
|
|
14
|
+
valueType;
|
|
15
|
+
valueConstraint;
|
|
16
|
+
description;
|
|
17
|
+
};
|
|
18
|
+
__decorate([
|
|
19
|
+
Field({
|
|
20
|
+
description: "Distinguishable name of this condition type.",
|
|
21
|
+
isRequired: true,
|
|
22
|
+
}),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], AccessConditionMetadata.prototype, "name", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
Field({
|
|
27
|
+
description: "Type of condition value.",
|
|
28
|
+
isRequired: true,
|
|
29
|
+
...Enum(AccessConditionValueType),
|
|
30
|
+
}),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], AccessConditionMetadata.prototype, "valueType", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
Field({
|
|
35
|
+
description: "Constraint for the condition value.",
|
|
36
|
+
isRequired: false,
|
|
37
|
+
}),
|
|
38
|
+
__metadata("design:type", Object)
|
|
39
|
+
], AccessConditionMetadata.prototype, "valueConstraint", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
Field({
|
|
42
|
+
description: "Description of the condition.",
|
|
43
|
+
}),
|
|
44
|
+
__metadata("design:type", String)
|
|
45
|
+
], AccessConditionMetadata.prototype, "description", void 0);
|
|
46
|
+
AccessConditionMetadata = __decorate([
|
|
47
|
+
Data()
|
|
48
|
+
], AccessConditionMetadata);
|
|
49
|
+
export { AccessConditionMetadata };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare enum AccessConditionValueType {
|
|
2
|
+
/**
|
|
3
|
+
* Any string value. Constraint is a regex.
|
|
4
|
+
*/
|
|
5
|
+
STRING = "STRING",
|
|
6
|
+
/**
|
|
7
|
+
* Numerical value. Constraint is {from: number, to: number, integer: boolean} encoded into string.
|
|
8
|
+
*/
|
|
9
|
+
NUMBER = "NUMBER",
|
|
10
|
+
/**
|
|
11
|
+
* Yes or No. No constraint.
|
|
12
|
+
*/
|
|
13
|
+
BOOLEAN = "BOOLEAN",
|
|
14
|
+
/**
|
|
15
|
+
* An unlimited list of string values. Constraint is whether emptiness is allowed.
|
|
16
|
+
*/
|
|
17
|
+
LIST = "LIST",
|
|
18
|
+
/**
|
|
19
|
+
* A list of choices. Constraint is the list of choices.
|
|
20
|
+
*/
|
|
21
|
+
CHOICES = "CHOICES",
|
|
22
|
+
/**
|
|
23
|
+
* A list of mutual exclusive choices. Constraint is the list of choices.
|
|
24
|
+
*/
|
|
25
|
+
MUTEXCHOICES = "MUTEXCHOICES",
|
|
26
|
+
/**
|
|
27
|
+
* And DtoMetadata that validates an data object. Constraint is the information of dto fields.
|
|
28
|
+
*/
|
|
29
|
+
DTO = "DTO"
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export var AccessConditionValueType;
|
|
2
|
+
(function (AccessConditionValueType) {
|
|
3
|
+
/**
|
|
4
|
+
* Any string value. Constraint is a regex.
|
|
5
|
+
*/
|
|
6
|
+
AccessConditionValueType["STRING"] = "STRING";
|
|
7
|
+
/**
|
|
8
|
+
* Numerical value. Constraint is {from: number, to: number, integer: boolean} encoded into string.
|
|
9
|
+
*/
|
|
10
|
+
AccessConditionValueType["NUMBER"] = "NUMBER";
|
|
11
|
+
/**
|
|
12
|
+
* Yes or No. No constraint.
|
|
13
|
+
*/
|
|
14
|
+
AccessConditionValueType["BOOLEAN"] = "BOOLEAN";
|
|
15
|
+
/**
|
|
16
|
+
* An unlimited list of string values. Constraint is whether emptiness is allowed.
|
|
17
|
+
*/
|
|
18
|
+
AccessConditionValueType["LIST"] = "LIST";
|
|
19
|
+
/**
|
|
20
|
+
* A list of choices. Constraint is the list of choices.
|
|
21
|
+
*/
|
|
22
|
+
AccessConditionValueType["CHOICES"] = "CHOICES";
|
|
23
|
+
/**
|
|
24
|
+
* A list of mutual exclusive choices. Constraint is the list of choices.
|
|
25
|
+
*/
|
|
26
|
+
AccessConditionValueType["MUTEXCHOICES"] = "MUTEXCHOICES";
|
|
27
|
+
/**
|
|
28
|
+
* And DtoMetadata that validates an data object. Constraint is the information of dto fields.
|
|
29
|
+
*/
|
|
30
|
+
AccessConditionValueType["DTO"] = "DTO";
|
|
31
|
+
})(AccessConditionValueType || (AccessConditionValueType = {}));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Constructor } from "@clairejs/core";
|
|
2
|
+
import { HttpRequest } from "../../common/HttpRequest";
|
|
3
|
+
import { AbstractAccessCondition } from "../abstract-access-condition";
|
|
4
|
+
export declare const FilterModelFieldAccessCondition: <T extends Constructor<any>>(model: T, name: string, requestedConditionValueResolver: (context: HttpRequest) => string[] | undefined) => Constructor<AbstractAccessCondition<string[] | undefined>>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { getObjectMetadata, Register } from "@clairejs/core";
|
|
8
|
+
import { AbstractAccessCondition } from "../abstract-access-condition";
|
|
9
|
+
import { AccessConditionValueType } from "../access-condition-value-type";
|
|
10
|
+
export const FilterModelFieldAccessCondition = (model, name, requestedConditionValueResolver) => {
|
|
11
|
+
let _ = class _ extends AbstractAccessCondition {
|
|
12
|
+
async resolveConditionValue(context) {
|
|
13
|
+
return requestedConditionValueResolver(context);
|
|
14
|
+
}
|
|
15
|
+
getConditionMetadata() {
|
|
16
|
+
return {
|
|
17
|
+
name,
|
|
18
|
+
valueType: AccessConditionValueType.CHOICES,
|
|
19
|
+
valueConstraint: getObjectMetadata(model).fields.map((f) => f.name),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async validate(requestedConditionValue, permittedConditionValue) {
|
|
23
|
+
return (!!requestedConditionValue &&
|
|
24
|
+
requestedConditionValue.every((value) => permittedConditionValue.includes(value)));
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
_ = __decorate([
|
|
28
|
+
Register()
|
|
29
|
+
], _);
|
|
30
|
+
return _;
|
|
31
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HttpRequest } from "../../common/HttpRequest";
|
|
2
|
+
import { AbstractAccessCondition } from "../abstract-access-condition";
|
|
3
|
+
import { AccessConditionMetadata } from "../access-condition-metadata";
|
|
4
|
+
export declare class MaximumQueryLimit extends AbstractAccessCondition<number> {
|
|
5
|
+
resolveConditionValue(context: HttpRequest): Promise<number>;
|
|
6
|
+
validate(conditionValue: number, permittedConditionValue: number): Promise<boolean>;
|
|
7
|
+
getConditionMetadata(): AccessConditionMetadata;
|
|
8
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Register } from "@clairejs/core";
|
|
8
|
+
import { AbstractAccessCondition } from "../abstract-access-condition";
|
|
9
|
+
import { AccessConditionValueType } from "../access-condition-value-type";
|
|
10
|
+
let MaximumQueryLimit = class MaximumQueryLimit extends AbstractAccessCondition {
|
|
11
|
+
async resolveConditionValue(context) {
|
|
12
|
+
const queries = context.getQuery();
|
|
13
|
+
return queries.limit || 0;
|
|
14
|
+
}
|
|
15
|
+
async validate(conditionValue, permittedConditionValue) {
|
|
16
|
+
return conditionValue > 0 && conditionValue <= permittedConditionValue;
|
|
17
|
+
}
|
|
18
|
+
getConditionMetadata() {
|
|
19
|
+
return {
|
|
20
|
+
name: "maximum_query_limit",
|
|
21
|
+
valueType: AccessConditionValueType.NUMBER,
|
|
22
|
+
valueConstraint: JSON.stringify({ min: 1 }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
MaximumQueryLimit = __decorate([
|
|
27
|
+
Register()
|
|
28
|
+
], MaximumQueryLimit);
|
|
29
|
+
export { MaximumQueryLimit };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HttpRequest } from "../../common/HttpRequest";
|
|
2
|
+
import { AbstractAccessCondition } from "../abstract-access-condition";
|
|
3
|
+
import { AccessConditionMetadata } from "../access-condition-metadata";
|
|
4
|
+
export declare class SocketReadCondition extends AbstractAccessCondition<boolean> {
|
|
5
|
+
resolveConditionValue(request: HttpRequest): Promise<any>;
|
|
6
|
+
validate(conditionValue: any): Promise<boolean>;
|
|
7
|
+
getConditionMetadata(): AccessConditionMetadata;
|
|
8
|
+
}
|
|
9
|
+
export declare class SocketWriteCondition extends AbstractAccessCondition<boolean> {
|
|
10
|
+
resolveConditionValue(request: HttpRequest): Promise<any>;
|
|
11
|
+
validate(conditionValue: any): Promise<boolean>;
|
|
12
|
+
getConditionMetadata(): AccessConditionMetadata;
|
|
13
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Register } from "@clairejs/core";
|
|
8
|
+
import { AbstractAccessCondition } from "../abstract-access-condition";
|
|
9
|
+
import { AccessConditionValueType } from "../access-condition-value-type";
|
|
10
|
+
const SOCKET_ACTION_HEADER = "x-socket-action";
|
|
11
|
+
const SOCKET_ACTION_READ = "read";
|
|
12
|
+
const SOCKET_ACTION_WRITE = "write";
|
|
13
|
+
let SocketReadCondition = class SocketReadCondition extends AbstractAccessCondition {
|
|
14
|
+
async resolveConditionValue(request) {
|
|
15
|
+
return request.headers[SOCKET_ACTION_HEADER] === SOCKET_ACTION_READ;
|
|
16
|
+
}
|
|
17
|
+
async validate(conditionValue) {
|
|
18
|
+
return !!conditionValue;
|
|
19
|
+
}
|
|
20
|
+
getConditionMetadata() {
|
|
21
|
+
return {
|
|
22
|
+
name: "disable_write",
|
|
23
|
+
description: "Disable send message to channel",
|
|
24
|
+
valueType: AccessConditionValueType.BOOLEAN,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
SocketReadCondition = __decorate([
|
|
29
|
+
Register()
|
|
30
|
+
], SocketReadCondition);
|
|
31
|
+
export { SocketReadCondition };
|
|
32
|
+
let SocketWriteCondition = class SocketWriteCondition extends AbstractAccessCondition {
|
|
33
|
+
async resolveConditionValue(request) {
|
|
34
|
+
return request.headers[SOCKET_ACTION_HEADER] === SOCKET_ACTION_WRITE;
|
|
35
|
+
}
|
|
36
|
+
async validate(conditionValue) {
|
|
37
|
+
return !!conditionValue;
|
|
38
|
+
}
|
|
39
|
+
getConditionMetadata() {
|
|
40
|
+
return {
|
|
41
|
+
name: "disable_read",
|
|
42
|
+
description: "Disable receive message from channel",
|
|
43
|
+
valueType: AccessConditionValueType.BOOLEAN,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
SocketWriteCondition = __decorate([
|
|
48
|
+
Register()
|
|
49
|
+
], SocketWriteCondition);
|
|
50
|
+
export { SocketWriteCondition };
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { Constructor, Identifiable } from "@clairejs/core";
|
|
1
2
|
import { AbstractHttpController } from "../controller/AbstractHttpController";
|
|
3
|
+
import { CrudHttpController } from "../controller/CrudHttpController";
|
|
4
|
+
import { AbstractSocketController } from "../../socket/AbstractSocketController";
|
|
5
|
+
import { AbstractAccessCondition } from "./abstract-access-condition";
|
|
2
6
|
export declare const PublicAccess: () => (prototype: AbstractHttpController, propertyKey: string) => void;
|
|
3
7
|
export declare const TfaRequired: () => (prototype: AbstractHttpController, propertyKey: string) => void;
|
|
8
|
+
export declare const AccessCondition: (conditions: Constructor<AbstractAccessCondition<any>>[]) => <T extends AbstractHttpController | AbstractSocketController>(prototype: T, propertyKey: keyof T) => void;
|
|
9
|
+
export declare const DefaultHttpAccessConditions: <K extends Identifiable>(model: Constructor<K>) => <T extends CrudHttpController<K>>(constructor: Constructor<T>) => void;
|
|
10
|
+
export declare const DefaultSocketAccessConditions: <T extends AbstractSocketController>() => (constructor: Constructor<T>) => void;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { initFieldMetadata } from "@clairejs/core";
|
|
1
|
+
import { initFieldMetadata, leanData, uniqueReducer, } from "@clairejs/core";
|
|
2
|
+
import { FilterModelFieldAccessCondition } from "./access-conditions/filter-model-fields";
|
|
3
|
+
import { MaximumQueryLimit } from "./access-conditions/max-query-limit";
|
|
4
|
+
import { SocketReadCondition, SocketWriteCondition } from "./access-conditions/socket-read-write";
|
|
2
5
|
export const PublicAccess = () => (prototype, propertyKey) => {
|
|
3
6
|
const endpointMetadata = initFieldMetadata(prototype, propertyKey);
|
|
4
7
|
endpointMetadata.publicAccess = true;
|
|
@@ -7,3 +10,36 @@ export const TfaRequired = () => (prototype, propertyKey) => {
|
|
|
7
10
|
const endpointMetadata = initFieldMetadata(prototype, propertyKey);
|
|
8
11
|
endpointMetadata.tfaRequired = true;
|
|
9
12
|
};
|
|
13
|
+
export const AccessCondition = (conditions) => (prototype, propertyKey) => {
|
|
14
|
+
const endpointMetadata = initFieldMetadata(prototype, propertyKey);
|
|
15
|
+
endpointMetadata.accessConditionCls = [...(endpointMetadata.accessConditionCls || []), ...conditions];
|
|
16
|
+
};
|
|
17
|
+
export const DefaultHttpAccessConditions = (model) => (constructor) => {
|
|
18
|
+
//-- for getMany
|
|
19
|
+
AccessCondition([
|
|
20
|
+
FilterModelFieldAccessCondition(model, "model_projection", (request) => request.getQuery().projection),
|
|
21
|
+
MaximumQueryLimit,
|
|
22
|
+
])(constructor.prototype, "getMany");
|
|
23
|
+
//-- for update many
|
|
24
|
+
AccessCondition([
|
|
25
|
+
FilterModelFieldAccessCondition(model, "restrict_update_fields", (request) => {
|
|
26
|
+
const updateBody = request.getBody().update;
|
|
27
|
+
if (!updateBody) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return Object.keys(leanData(updateBody));
|
|
31
|
+
}),
|
|
32
|
+
])(constructor.prototype, "updateMany");
|
|
33
|
+
//-- for update records
|
|
34
|
+
AccessCondition([
|
|
35
|
+
FilterModelFieldAccessCondition(model, "restrict_update_fields", (request) => {
|
|
36
|
+
const updates = request.getBody();
|
|
37
|
+
return updates.records
|
|
38
|
+
.flatMap(({ id, ...update }) => Object.keys(leanData(update) || {}))
|
|
39
|
+
.reduce(uniqueReducer, []);
|
|
40
|
+
}),
|
|
41
|
+
])(constructor.prototype, "updateRecords");
|
|
42
|
+
};
|
|
43
|
+
export const DefaultSocketAccessConditions = () => (constructor) => {
|
|
44
|
+
AccessCondition([SocketReadCondition, SocketWriteCondition])(constructor.prototype, "getChannelName");
|
|
45
|
+
};
|
package/dist/http/utils.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiInfoResponse } from "./common/dto";
|
|
2
2
|
export declare const getApiInfo: () => Promise<ApiInfoResponse>;
|
package/dist/http/utils.js
CHANGED
|
@@ -6,9 +6,13 @@ export const getApiInfo = async () => {
|
|
|
6
6
|
const httpHandler = injector.resolveOptional(AbstractHttpRequestHandler);
|
|
7
7
|
const socketManager = injector.resolveOptional(AbstractServerSocketManager);
|
|
8
8
|
await injector.initInstances();
|
|
9
|
-
const httpInfo =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const [httpInfo, socketInfo] = await Promise.all([
|
|
10
|
+
httpHandler ? httpHandler.getMountedEndpointInfo() : Promise.resolve([]),
|
|
11
|
+
socketManager ? socketManager.getMountedEndpointInfo() : Promise.resolve([]),
|
|
12
|
+
]);
|
|
13
|
+
const result = {
|
|
14
|
+
apis: [...httpInfo, ...socketInfo].map(({ controller, params, injecteeSuperClass, accessConditionCls, ...api }) => api),
|
|
13
15
|
};
|
|
16
|
+
await injector.initInstances();
|
|
17
|
+
return result;
|
|
14
18
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ export * from "./http/controller/AbstractHttpRequestHandler";
|
|
|
15
15
|
export * from "./http/controller/AbstractHttpMiddleware";
|
|
16
16
|
export * from "./http/security/cors";
|
|
17
17
|
export * from "./http/security/decorators";
|
|
18
|
+
export * from "./http/security/access-conditions/filter-model-fields";
|
|
19
|
+
export * from "./http/security/access-conditions/max-query-limit";
|
|
20
|
+
export * from "./http/security/access-conditions/socket-read-write";
|
|
21
|
+
export * from "./http/security/abstract-access-condition";
|
|
22
|
+
export * from "./http/security/access-condition-metadata";
|
|
23
|
+
export * from "./http/security/access-condition-value-type";
|
|
18
24
|
export * from "./http/auth/AbstractHttpAuthorizer";
|
|
19
25
|
export * from "./http/repository/ModelRepository";
|
|
20
26
|
export * from "./http/repository/DtoRepository";
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,12 @@ export * from "./http/controller/AbstractHttpRequestHandler";
|
|
|
17
17
|
export * from "./http/controller/AbstractHttpMiddleware";
|
|
18
18
|
export * from "./http/security/cors";
|
|
19
19
|
export * from "./http/security/decorators";
|
|
20
|
+
export * from "./http/security/access-conditions/filter-model-fields";
|
|
21
|
+
export * from "./http/security/access-conditions/max-query-limit";
|
|
22
|
+
export * from "./http/security/access-conditions/socket-read-write";
|
|
23
|
+
export * from "./http/security/abstract-access-condition";
|
|
24
|
+
export * from "./http/security/access-condition-metadata";
|
|
25
|
+
export * from "./http/security/access-condition-value-type";
|
|
20
26
|
export * from "./http/auth/AbstractHttpAuthorizer";
|
|
21
27
|
export * from "./http/repository/ModelRepository";
|
|
22
28
|
export * from "./http/repository/DtoRepository";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clairejs/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0",
|
|
4
4
|
"description": "Claire server NodeJs framework written in Typescript.",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@clairejs/client": "^3.4.6",
|
|
37
|
-
"@clairejs/core": "^3.8.
|
|
38
|
-
"@clairejs/orm": "^3.16.
|
|
37
|
+
"@clairejs/core": "^3.8.13",
|
|
38
|
+
"@clairejs/orm": "^3.16.28"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/cookie-parser": "^1.4.3",
|