@clairejs/server 3.16.19 → 3.17.1
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 +5 -0
- package/dist/common/ControllerMetadata.d.ts +2 -2
- package/dist/common/request/endpoint-metadata.d.ts +12 -0
- package/dist/http/auth/AbstractHttpAuthorizer.d.ts +2 -2
- package/dist/http/common/HttpRequest.d.ts +1 -1
- package/dist/http/common/HttpRequest.js +7 -8
- package/dist/http/controller/AbstractHttpController.d.ts +2 -2
- package/dist/http/controller/AbstractHttpController.js +2 -2
- package/dist/http/controller/AbstractHttpMiddleware.d.ts +1 -1
- package/dist/http/controller/AbstractHttpRequestHandler.d.ts +8 -8
- package/dist/http/controller/AbstractHttpRequestHandler.js +14 -22
- package/dist/http/controller/CrudHttpController.d.ts +6 -6
- package/dist/http/controller/CrudHttpController.js +42 -84
- package/dist/http/controller/DefaultHttpRequestHandler.d.ts +2 -2
- package/dist/http/controller/DefaultHttpRequestHandler.js +9 -11
- package/dist/http/decorators.d.ts +5 -9
- package/dist/http/decorators.js +10 -22
- package/dist/http/repository/ICrudRepository.d.ts +3 -3
- package/dist/http/utils.d.ts +1 -3
- package/dist/http/utils.js +3 -20
- package/dist/index.d.ts +1 -6
- package/dist/index.js +1 -6
- package/dist/services/AbstractFileService.d.ts +2 -0
- package/dist/services/implementations/LocalFileService.d.ts +2 -0
- package/dist/services/implementations/LocalFileService.js +9 -0
- package/dist/services/implementations/S3FileService.d.ts +3 -1
- package/dist/services/implementations/S3FileService.js +22 -5
- package/dist/socket/AbstractServerSocketManager.d.ts +2 -2
- package/dist/socket/AbstractServerSocketManager.js +20 -70
- package/dist/socket/AbstractSocketController.d.ts +0 -1
- package/dist/socket/AbstractSocketController.js +0 -1
- package/dist/system/ClaireServer.d.ts +2 -3
- package/dist/system/ClaireServer.js +2 -10
- package/dist/system/ServerGlobalStore.d.ts +2 -2
- package/package.json +5 -5
- package/dist/common/request/EndpointMetadata.d.ts +0 -40
- package/dist/common/request/HttpEndpoint.d.ts +0 -7
- package/dist/common/request/HttpEndpoint.js +0 -1
- package/dist/common/request/MountedEndpointInfo.d.ts +0 -6
- package/dist/common/request/MountedEndpointInfo.js +0 -1
- package/dist/http/security/AbstractAccessCondition.d.ts +0 -7
- package/dist/http/security/AbstractAccessCondition.js +0 -2
- package/dist/http/security/access-conditions/FilterModelFieldAccessCondition.d.ts +0 -4
- package/dist/http/security/access-conditions/FilterModelFieldAccessCondition.js +0 -30
- package/dist/http/security/access-conditions/MaximumQueryLimit.d.ts +0 -8
- package/dist/http/security/access-conditions/MaximumQueryLimit.js +0 -31
- /package/dist/common/request/{EndpointMetadata.js → endpoint-metadata.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AbstractLogger, CreateManyRequestBody, CreateManyResponseBody, GetManyQueries, GetManyResponseBody, UpdateManyBody, UpdateManyQueries, UpdateManyResponse } from "@clairejs/core";
|
|
2
|
-
import { IQueryProvider, ITransaction, QueryCondition } from "@clairejs/orm";
|
|
3
|
-
import { IPrincipal } from "../../common/auth/IPrincipal";
|
|
1
|
+
import { type AbstractLogger, type CreateManyRequestBody, type CreateManyResponseBody, type GetManyQueries, type GetManyResponseBody, type UpdateManyBody, type UpdateManyQueries, type UpdateManyResponse } from "@clairejs/core";
|
|
2
|
+
import { type IQueryProvider, type ITransaction, type QueryCondition } from "@clairejs/orm";
|
|
3
|
+
import { type IPrincipal } from "../../common/auth/IPrincipal";
|
|
4
4
|
export interface ICrudRepository<T> {
|
|
5
5
|
createMany({ principal, body, tx, logger, }: {
|
|
6
6
|
body: CreateManyRequestBody<T>;
|
package/dist/http/utils.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import { ApiInfoResponse } from "@clairejs/core";
|
|
2
|
-
import { HttpEndpoint } from "../common/request/HttpEndpoint";
|
|
3
|
-
export declare const getEndpointId: (endpoint: HttpEndpoint) => string;
|
|
1
|
+
import { type ApiInfoResponse } from "@clairejs/core";
|
|
4
2
|
export declare const getApiInfo: () => Promise<ApiInfoResponse>;
|
package/dist/http/utils.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getServiceProvider, pickData, ApiInfo, getObjectMetadata } from "@clairejs/core";
|
|
2
2
|
import { AbstractHttpRequestHandler } from "./controller/AbstractHttpRequestHandler";
|
|
3
3
|
import { AbstractServerSocketManager } from "../socket/AbstractServerSocketManager";
|
|
4
|
-
|
|
5
|
-
return `${endpoint.httpMethod}:${endpoint.mount}`;
|
|
6
|
-
};
|
|
4
|
+
const fields = (getObjectMetadata(ApiInfo)?.fields || []).map((f) => f.name);
|
|
7
5
|
export const getApiInfo = async () => {
|
|
8
6
|
const injector = getServiceProvider().getInjector();
|
|
9
7
|
const httpHandler = injector.resolveOptional(AbstractHttpRequestHandler);
|
|
@@ -12,21 +10,6 @@ export const getApiInfo = async () => {
|
|
|
12
10
|
const httpInfo = httpHandler ? await httpHandler.getMountedEndpointInfo() : [];
|
|
13
11
|
const socketInfo = socketManager ? await socketManager.getMountedEndpointInfo() : [];
|
|
14
12
|
return {
|
|
15
|
-
|
|
16
|
-
id: getEndpointId(endpointInfo.endpoint),
|
|
17
|
-
description: endpointInfo.endpointMetadata.description,
|
|
18
|
-
name: endpointInfo.endpointMetadata.displayName || endpointInfo.endpointMetadata.name,
|
|
19
|
-
openAccess: !!endpointInfo.endpointMetadata.openAccess,
|
|
20
|
-
permissionGroup: endpointInfo.endpointMetadata.permissionGroup || "",
|
|
21
|
-
accessConditions: endpointInfo.endpointMetadata.accessConditions?.map((ac) => injector.resolve(ac).getConditionMetadata()) || [],
|
|
22
|
-
readOnly: endpointInfo.endpointMetadata.httpMethod === HttpMethod.GET,
|
|
23
|
-
tfaRequired: !!endpointInfo.endpointMetadata.tfaRequired,
|
|
24
|
-
method: endpointInfo.endpointMetadata.httpMethod,
|
|
25
|
-
mount: endpointInfo.endpoint.mount || "",
|
|
26
|
-
paramDto: endpointInfo.endpointMetadata.paramsValidationDto,
|
|
27
|
-
queryDto: endpointInfo.endpointMetadata.queriesValidationDto,
|
|
28
|
-
bodyDto: endpointInfo.endpointMetadata.bodyValidationDto,
|
|
29
|
-
responseDto: endpointInfo.endpointMetadata.responseValidationDto,
|
|
30
|
-
})),
|
|
13
|
+
apis: [...httpInfo, ...socketInfo].map((metadata) => pickData(metadata, fields)),
|
|
31
14
|
};
|
|
32
15
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export * from "./common/FileOperation";
|
|
2
2
|
export * from "./common/auth/AbstractPrincipalResolver";
|
|
3
3
|
export * from "./common/auth/IPrincipal";
|
|
4
|
-
export * from "./common/request/
|
|
5
|
-
export * from "./common/request/HttpEndpoint";
|
|
6
|
-
export * from "./common/request/EndpointMetadata";
|
|
4
|
+
export * from "./common/request/endpoint-metadata";
|
|
7
5
|
export * from "./common/request/RequestOptions";
|
|
8
6
|
export * from "./common/AbstractController";
|
|
9
7
|
export * from "./common/ControllerMetadata";
|
|
@@ -17,9 +15,6 @@ export * from "./http/controller/CrudHttpController";
|
|
|
17
15
|
export * from "./http/controller/AbstractHttpRequestHandler";
|
|
18
16
|
export * from "./http/controller/AbstractHttpMiddleware";
|
|
19
17
|
export * from "./http/security/cors";
|
|
20
|
-
export * from "./http/security/AbstractAccessCondition";
|
|
21
|
-
export * from "./http/security/access-conditions/FilterModelFieldAccessCondition";
|
|
22
|
-
export * from "./http/security/access-conditions/MaximumQueryLimit";
|
|
23
18
|
export * from "./http/auth/AbstractHttpAuthorizer";
|
|
24
19
|
export * from "./http/repository/ModelRepository";
|
|
25
20
|
export * from "./http/repository/DtoRepository";
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
export * from "./common/FileOperation";
|
|
3
3
|
export * from "./common/auth/AbstractPrincipalResolver";
|
|
4
4
|
export * from "./common/auth/IPrincipal";
|
|
5
|
-
export * from "./common/request/
|
|
6
|
-
export * from "./common/request/HttpEndpoint";
|
|
7
|
-
export * from "./common/request/EndpointMetadata";
|
|
5
|
+
export * from "./common/request/endpoint-metadata";
|
|
8
6
|
export * from "./common/request/RequestOptions";
|
|
9
7
|
export * from "./common/AbstractController";
|
|
10
8
|
export * from "./common/ControllerMetadata";
|
|
@@ -19,9 +17,6 @@ export * from "./http/controller/CrudHttpController";
|
|
|
19
17
|
export * from "./http/controller/AbstractHttpRequestHandler";
|
|
20
18
|
export * from "./http/controller/AbstractHttpMiddleware";
|
|
21
19
|
export * from "./http/security/cors";
|
|
22
|
-
export * from "./http/security/AbstractAccessCondition";
|
|
23
|
-
export * from "./http/security/access-conditions/FilterModelFieldAccessCondition";
|
|
24
|
-
export * from "./http/security/access-conditions/MaximumQueryLimit";
|
|
25
20
|
export * from "./http/auth/AbstractHttpAuthorizer";
|
|
26
21
|
export * from "./http/repository/ModelRepository";
|
|
27
22
|
export * from "./http/repository/DtoRepository";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { FileOperation } from "../common/FileOperation";
|
|
2
3
|
import { GetUploadUrlResponseBody } from "../controllers/dto/upload";
|
|
3
4
|
export declare abstract class AbstractFileService {
|
|
@@ -13,5 +14,6 @@ export declare abstract class AbstractFileService {
|
|
|
13
14
|
toURI: string;
|
|
14
15
|
}[]): Promise<void>;
|
|
15
16
|
abstract removeObject(uris: string[]): Promise<void>;
|
|
17
|
+
abstract putFile(uri: string, data: Buffer, headers?: Record<string, string>): Promise<void>;
|
|
16
18
|
getUploadUrlForTempUri(temporaryUri: string): Promise<GetUploadUrlResponseBody>;
|
|
17
19
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { FileOperation } from "../../common/FileOperation";
|
|
2
3
|
import { AbstractFileService } from "../AbstractFileService";
|
|
3
4
|
export declare class LocalFileService extends AbstractFileService {
|
|
@@ -6,6 +7,7 @@ export declare class LocalFileService extends AbstractFileService {
|
|
|
6
7
|
getFileSize(objectKeys: string[]): Promise<number[]>;
|
|
7
8
|
getAccessUrls(uris: (string | undefined)[], _isPublic: boolean): Promise<string[]>;
|
|
8
9
|
getPresignedUrl(operation: FileOperation, uris: string[]): Promise<string[]>;
|
|
10
|
+
putFile(uri: string, data: Buffer, headers?: Record<string, string>): Promise<void>;
|
|
9
11
|
moveObject(uris: {
|
|
10
12
|
fromURI: string;
|
|
11
13
|
toURI: string;
|
|
@@ -23,6 +23,15 @@ export class LocalFileService extends AbstractFileService {
|
|
|
23
23
|
}
|
|
24
24
|
return uris.map((uri) => `${this.fileServerUrl}/?objectKey="/${uri}"`);
|
|
25
25
|
}
|
|
26
|
+
async putFile(uri, data, headers) {
|
|
27
|
+
const [url] = await this.getPresignedUrl(FileOperation.PUT, [uri]);
|
|
28
|
+
await axios({
|
|
29
|
+
method: 'PUT',
|
|
30
|
+
url,
|
|
31
|
+
data,
|
|
32
|
+
headers,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
26
35
|
async moveObject(uris) {
|
|
27
36
|
await Promise.all(uris.map((uri) => axios.post(`${this.fileServerUrl}/`, {
|
|
28
37
|
from: uri.fromURI,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { AbstractLogger } from "@clairejs/core";
|
|
2
3
|
import { FileOperation } from "../../common/FileOperation";
|
|
3
4
|
import { AbstractFileService } from "../AbstractFileService";
|
|
@@ -13,8 +14,9 @@ export declare class S3FileService extends AbstractFileService {
|
|
|
13
14
|
protected readonly config: S3FileServiceConfig;
|
|
14
15
|
protected readonly logger: AbstractLogger;
|
|
15
16
|
private readonly s3Client;
|
|
16
|
-
private readonly cloudfrontSigner
|
|
17
|
+
private readonly cloudfrontSigner?;
|
|
17
18
|
constructor(config: S3FileServiceConfig, logger: AbstractLogger);
|
|
19
|
+
putFile(uri: string, data: Buffer, headers?: Record<string, string>): Promise<void>;
|
|
18
20
|
getFileSize(objectKeys: string[]): Promise<number[]>;
|
|
19
21
|
getAccessUrls(uris: (string | undefined)[], isPublic: boolean): Promise<string[]>;
|
|
20
22
|
getPresignedUrl(operation: FileOperation, uris: string[]): Promise<string[]>;
|
|
@@ -24,7 +24,17 @@ let S3FileService = class S3FileService extends AbstractFileService {
|
|
|
24
24
|
signatureVersion: "v4",
|
|
25
25
|
region: this.config.S3_BUCKET_REGION,
|
|
26
26
|
});
|
|
27
|
-
this.
|
|
27
|
+
if (this.config.CLOUD_FRONT_PUBLIC_DOMAIN && this.config.CLOUD_FRONT_PRIVATE_KEY && this.config.CLOUD_FRONT_PUBLIC_KEY_ID) {
|
|
28
|
+
this.cloudfrontSigner = new aws.CloudFront.Signer(this.config.CLOUD_FRONT_PUBLIC_KEY_ID, this.config.CLOUD_FRONT_PRIVATE_KEY);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async putFile(uri, data, headers) {
|
|
32
|
+
await this.s3Client.putObject({
|
|
33
|
+
Key: uri,
|
|
34
|
+
Bucket: this.config.S3_BUCKET_NAME,
|
|
35
|
+
Body: data,
|
|
36
|
+
Metadata: headers,
|
|
37
|
+
}).promise();
|
|
28
38
|
}
|
|
29
39
|
async getFileSize(objectKeys) {
|
|
30
40
|
return await Promise.all(objectKeys.map((uri) => this.getSingleFileSize(uri)));
|
|
@@ -51,10 +61,17 @@ let S3FileService = class S3FileService extends AbstractFileService {
|
|
|
51
61
|
.then((res) => res.ContentLength);
|
|
52
62
|
return size || 0;
|
|
53
63
|
}
|
|
54
|
-
getSinglePresignedUrl(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
getSinglePresignedUrl(operation, objectKey) {
|
|
65
|
+
if (this.cloudfrontSigner) {
|
|
66
|
+
return this.cloudfrontSigner.getSignedUrl({
|
|
67
|
+
url: `${this.config.CLOUD_FRONT_PUBLIC_DOMAIN}/${objectKey}`,
|
|
68
|
+
expires: Date.now() + this.config.PRESIGNED_URL_EXPIRATION_S * 1000,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return this.s3Client.getSignedUrl(operation, {
|
|
72
|
+
Bucket: this.config.S3_BUCKET_NAME,
|
|
73
|
+
Key: objectKey,
|
|
74
|
+
Expires: this.config.PRESIGNED_URL_EXPIRATION_S
|
|
58
75
|
});
|
|
59
76
|
}
|
|
60
77
|
async copySingleObject(fromObjectKey, toObjectKey) {
|
|
@@ -2,8 +2,8 @@ import { AbstractLogger, SocketMessage } from "@clairejs/core";
|
|
|
2
2
|
import Redis from "ioredis";
|
|
3
3
|
import { SocketData } from "../common/request/SocketData";
|
|
4
4
|
import { IPrincipal } from "../common/auth/IPrincipal";
|
|
5
|
+
import { EndpointMetadata } from "../common/request/endpoint-metadata";
|
|
5
6
|
import { AbstractPrincipalResolver } from "../common/auth/AbstractPrincipalResolver";
|
|
6
|
-
import { MountedEndpointInfo } from "../common/request/MountedEndpointInfo";
|
|
7
7
|
import { AbstractRequestAuthorizer } from "../http/auth/AbstractHttpAuthorizer";
|
|
8
8
|
import { AbstractSocketConnectionHandler } from "./AbstractSocketConnectionHandler";
|
|
9
9
|
import { AbstractServerSocket } from "./AbstractServerSocket";
|
|
@@ -42,5 +42,5 @@ export declare abstract class AbstractServerSocketManager {
|
|
|
42
42
|
removeSocket(socketId: string, _physicRemove?: boolean): Promise<void>;
|
|
43
43
|
abstract getById(socketId: string): Promise<AbstractServerSocket | undefined>;
|
|
44
44
|
handle(socketData: SocketData): Promise<void>;
|
|
45
|
-
getMountedEndpointInfo(): Promise<
|
|
45
|
+
getMountedEndpointInfo(): Promise<EndpointMetadata[]>;
|
|
46
46
|
}
|
|
@@ -1,53 +1,10 @@
|
|
|
1
|
-
|
|
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 { AccessConditionValueType, DataType, Errors, getObjectMetadata, getServiceProvider, MessageType, Register, SocketMethod, } from "@clairejs/core";
|
|
8
|
-
import { AbstractAccessCondition } from "../http/security/AbstractAccessCondition";
|
|
1
|
+
import { DataType, Errors, getServiceProvider, MessageType, SocketMethod, } from "@clairejs/core";
|
|
9
2
|
import { HttpRequest } from "../http/common/HttpRequest";
|
|
10
3
|
import { AbstractSocketConnectionHandler } from "./AbstractSocketConnectionHandler";
|
|
11
4
|
import { AbstractSocketController } from "./AbstractSocketController";
|
|
12
5
|
const SOCKET_ACTION_HEADER = "x-socket-action";
|
|
13
6
|
const SOCKET_ACTION_READ = "read";
|
|
14
7
|
const SOCKET_ACTION_WRITE = "write";
|
|
15
|
-
let SocketReadCondition = class SocketReadCondition extends AbstractAccessCondition {
|
|
16
|
-
async resolveConditionValue(request) {
|
|
17
|
-
return request.headers[SOCKET_ACTION_HEADER] === SOCKET_ACTION_READ;
|
|
18
|
-
}
|
|
19
|
-
async validate(conditionValue) {
|
|
20
|
-
return !!conditionValue;
|
|
21
|
-
}
|
|
22
|
-
getConditionMetadata() {
|
|
23
|
-
return {
|
|
24
|
-
name: "disable_write",
|
|
25
|
-
description: "Disable send message to channel",
|
|
26
|
-
valueType: AccessConditionValueType.BOOLEAN,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
SocketReadCondition = __decorate([
|
|
31
|
-
Register()
|
|
32
|
-
], SocketReadCondition);
|
|
33
|
-
let SocketWriteCondition = class SocketWriteCondition extends AbstractAccessCondition {
|
|
34
|
-
async resolveConditionValue(request) {
|
|
35
|
-
return request.headers[SOCKET_ACTION_HEADER] === SOCKET_ACTION_WRITE;
|
|
36
|
-
}
|
|
37
|
-
async validate(conditionValue) {
|
|
38
|
-
return !!conditionValue;
|
|
39
|
-
}
|
|
40
|
-
getConditionMetadata() {
|
|
41
|
-
return {
|
|
42
|
-
name: "disable_read",
|
|
43
|
-
description: "Disable receive message from channel",
|
|
44
|
-
valueType: AccessConditionValueType.BOOLEAN,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
SocketWriteCondition = __decorate([
|
|
49
|
-
Register()
|
|
50
|
-
], SocketWriteCondition);
|
|
51
8
|
export class AbstractServerSocketManager {
|
|
52
9
|
requireAuthentication;
|
|
53
10
|
logger;
|
|
@@ -157,9 +114,9 @@ export class AbstractServerSocketManager {
|
|
|
157
114
|
//-- notify all channels
|
|
158
115
|
this.logger.debug("Notify channels");
|
|
159
116
|
for (const channelInfo of socket.getChannelsInfo()) {
|
|
160
|
-
const currentEndpoint = mountedEndpoints.find((e) => e.
|
|
117
|
+
const currentEndpoint = mountedEndpoints.find((e) => e.mount === channelInfo.name);
|
|
161
118
|
if (currentEndpoint) {
|
|
162
|
-
currentEndpoint.
|
|
119
|
+
currentEndpoint.controller.onChannelLeave(socket);
|
|
163
120
|
}
|
|
164
121
|
}
|
|
165
122
|
this.logger.debug("Calling disconnection handler");
|
|
@@ -206,7 +163,7 @@ export class AbstractServerSocketManager {
|
|
|
206
163
|
let canSend = false;
|
|
207
164
|
let canReceive = false;
|
|
208
165
|
const mountedEndpoints = await this.getMountedEndpointInfo();
|
|
209
|
-
const currentEndpoint = mountedEndpoints.find((e) => e.
|
|
166
|
+
const currentEndpoint = mountedEndpoints.find((e) => e.mount === channel);
|
|
210
167
|
if (!currentEndpoint) {
|
|
211
168
|
continue;
|
|
212
169
|
}
|
|
@@ -215,7 +172,7 @@ export class AbstractServerSocketManager {
|
|
|
215
172
|
method: SocketMethod.MESSAGE,
|
|
216
173
|
pathName: channel,
|
|
217
174
|
headers: { [SOCKET_ACTION_HEADER]: SOCKET_ACTION_READ },
|
|
218
|
-
}, currentEndpoint
|
|
175
|
+
}, currentEndpoint);
|
|
219
176
|
request.setAuthInfo(clientSocket.getAuthInfo());
|
|
220
177
|
await this.requestAuthorizer.authorize(request, currentEndpoint);
|
|
221
178
|
canReceive = true;
|
|
@@ -228,7 +185,7 @@ export class AbstractServerSocketManager {
|
|
|
228
185
|
method: SocketMethod.MESSAGE,
|
|
229
186
|
pathName: channel,
|
|
230
187
|
headers: { [SOCKET_ACTION_HEADER]: SOCKET_ACTION_WRITE },
|
|
231
|
-
}, currentEndpoint
|
|
188
|
+
}, currentEndpoint);
|
|
232
189
|
request.setAuthInfo(clientSocket.getAuthInfo());
|
|
233
190
|
await this.requestAuthorizer.authorize(request, currentEndpoint);
|
|
234
191
|
canSend = true;
|
|
@@ -258,7 +215,7 @@ export class AbstractServerSocketManager {
|
|
|
258
215
|
type: MessageType.CHANNEL_JOIN,
|
|
259
216
|
data: channelsInfo.map((c) => c.name),
|
|
260
217
|
}),
|
|
261
|
-
...endpoints.map((endpoint) => endpoint.
|
|
218
|
+
...endpoints.map((endpoint) => endpoint.controller.onChannelJoin(clientSocket)),
|
|
262
219
|
]);
|
|
263
220
|
}
|
|
264
221
|
}
|
|
@@ -269,11 +226,11 @@ export class AbstractServerSocketManager {
|
|
|
269
226
|
//-- remove channels from socket
|
|
270
227
|
const mountedEndpoints = await this.getMountedEndpointInfo();
|
|
271
228
|
Promise.all(channels.map((channel) => () => {
|
|
272
|
-
const currentEndpoint = mountedEndpoints.find((e) => e.
|
|
229
|
+
const currentEndpoint = mountedEndpoints.find((e) => e.mount === channel);
|
|
273
230
|
if (!currentEndpoint) {
|
|
274
231
|
return;
|
|
275
232
|
}
|
|
276
|
-
return currentEndpoint.
|
|
233
|
+
return currentEndpoint.controller.onChannelLeave(clientSocket);
|
|
277
234
|
}));
|
|
278
235
|
//-- remove socket from channels
|
|
279
236
|
await this.removeSocketFromChannel(clientSocket.getId(), channels);
|
|
@@ -291,9 +248,9 @@ export class AbstractServerSocketManager {
|
|
|
291
248
|
.find((info) => info.name === channel && info.clientToServerAllowed);
|
|
292
249
|
if (allowed) {
|
|
293
250
|
const mountedEndpoints = await this.getMountedEndpointInfo();
|
|
294
|
-
const currentEndpoint = mountedEndpoints.find((e) => e.
|
|
251
|
+
const currentEndpoint = mountedEndpoints.find((e) => e.mount === channel);
|
|
295
252
|
if (currentEndpoint) {
|
|
296
|
-
const result = await currentEndpoint.
|
|
253
|
+
const result = await currentEndpoint.controller.onMessage(clientSocket, data);
|
|
297
254
|
if (result !== false) {
|
|
298
255
|
//-- broadcast
|
|
299
256
|
this.logger.debug("broadcasting to channel", channel, data);
|
|
@@ -325,23 +282,16 @@ export class AbstractServerSocketManager {
|
|
|
325
282
|
const socketController = injector.resolveMultiple(AbstractSocketController);
|
|
326
283
|
await injector.initInstances();
|
|
327
284
|
this.mountedEndpointInfo = socketController.map((controller) => {
|
|
328
|
-
const controllerMetadata = getObjectMetadata(controller.constructor);
|
|
329
285
|
return {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
permissionGroup: controllerMetadata.permissionGroup,
|
|
340
|
-
dataType: DataType.OBJECT,
|
|
341
|
-
url: controller.getChannelName(),
|
|
342
|
-
name: controller.getChannelName(),
|
|
343
|
-
accessConditions: [SocketReadCondition, SocketWriteCondition],
|
|
344
|
-
},
|
|
286
|
+
id: `${SocketMethod.MESSAGE}:${controller.getChannelName()}`,
|
|
287
|
+
readOnly: false,
|
|
288
|
+
controller: socketController,
|
|
289
|
+
method: SocketMethod.MESSAGE,
|
|
290
|
+
mount: controller.getChannelName(),
|
|
291
|
+
handlerFunctionName: controller.onMessage.name,
|
|
292
|
+
description: "Send / Receive message to / from channel",
|
|
293
|
+
name: controller.getChannelName(),
|
|
294
|
+
dataType: DataType.OBJECT,
|
|
345
295
|
};
|
|
346
296
|
});
|
|
347
297
|
}
|
|
@@ -7,7 +7,6 @@ export declare abstract class AbstractSocketController extends AbstractControlle
|
|
|
7
7
|
/**
|
|
8
8
|
* Handle the message sent to this channel
|
|
9
9
|
* @param socket the socket sending message
|
|
10
|
-
* @param data the data payload being sent
|
|
11
10
|
* @returns return false to prevent message broadcast
|
|
12
11
|
*/
|
|
13
12
|
onMessage(_socket: IServerSocket, _message: any): Promise<boolean | void>;
|
|
@@ -5,7 +5,6 @@ export class AbstractSocketController extends AbstractController {
|
|
|
5
5
|
/**
|
|
6
6
|
* Handle the message sent to this channel
|
|
7
7
|
* @param socket the socket sending message
|
|
8
|
-
* @param data the data payload being sent
|
|
9
8
|
* @returns return false to prevent message broadcast
|
|
10
9
|
*/
|
|
11
10
|
async onMessage(_socket, _message) { }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbstractLogger, ClaireApp } from "@clairejs/core";
|
|
2
|
-
import { AbstractHttpRequestHandler } from "../http/controller/AbstractHttpRequestHandler";
|
|
3
|
-
import { AbstractServerSocketManager } from "../socket/AbstractServerSocketManager";
|
|
2
|
+
import { type AbstractHttpRequestHandler } from "../http/controller/AbstractHttpRequestHandler";
|
|
3
|
+
import { type AbstractServerSocketManager } from "../socket/AbstractServerSocketManager";
|
|
4
4
|
export declare class ClaireServer extends ClaireApp {
|
|
5
5
|
protected readonly logger: AbstractLogger;
|
|
6
6
|
protected readonly httpRequestHandler?: AbstractHttpRequestHandler | undefined;
|
|
@@ -8,6 +8,5 @@ export declare class ClaireServer extends ClaireApp {
|
|
|
8
8
|
private booted;
|
|
9
9
|
constructor(logger: AbstractLogger, httpRequestHandler?: AbstractHttpRequestHandler | undefined, socketManager?: AbstractServerSocketManager | undefined);
|
|
10
10
|
init(): Promise<void>;
|
|
11
|
-
exit(): void;
|
|
12
11
|
private stop;
|
|
13
12
|
}
|
|
@@ -9,9 +9,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import { AbstractLogger, ClaireApp, LogContext, getGlobalStore } from "@clairejs/core";
|
|
11
11
|
import { ExitCode } from "../common/constants";
|
|
12
|
-
import { AbstractHttpRequestHandler } from "../http/controller/AbstractHttpRequestHandler";
|
|
13
|
-
import { AbstractServerSocketManager } from "../socket/AbstractServerSocketManager";
|
|
14
|
-
import { getEndpointId } from "../http/utils";
|
|
15
12
|
let ClaireServer = class ClaireServer extends ClaireApp {
|
|
16
13
|
logger;
|
|
17
14
|
httpRequestHandler;
|
|
@@ -38,7 +35,7 @@ let ClaireServer = class ClaireServer extends ClaireApp {
|
|
|
38
35
|
}
|
|
39
36
|
//-- save mounted endpoint info in server store to prevent circular dependency when resolving http request handler in controller
|
|
40
37
|
for (const endpoint of mountedEndpointInfo) {
|
|
41
|
-
this.logger.info(`Mounting: ${
|
|
38
|
+
this.logger.info(`Mounting: ${endpoint.method}:${endpoint.mount}`);
|
|
42
39
|
}
|
|
43
40
|
getGlobalStore().mountedEndpointInfo = mountedEndpointInfo;
|
|
44
41
|
this.logger.debug("Claire server initing");
|
|
@@ -60,9 +57,6 @@ let ClaireServer = class ClaireServer extends ClaireApp {
|
|
|
60
57
|
});
|
|
61
58
|
this.booted = true;
|
|
62
59
|
}
|
|
63
|
-
exit() {
|
|
64
|
-
super.exit();
|
|
65
|
-
}
|
|
66
60
|
stop(code) {
|
|
67
61
|
this.logger.debug("Server is shutting down");
|
|
68
62
|
this.exit();
|
|
@@ -71,8 +65,6 @@ let ClaireServer = class ClaireServer extends ClaireApp {
|
|
|
71
65
|
};
|
|
72
66
|
ClaireServer = __decorate([
|
|
73
67
|
LogContext(),
|
|
74
|
-
__metadata("design:paramtypes", [AbstractLogger,
|
|
75
|
-
AbstractHttpRequestHandler,
|
|
76
|
-
AbstractServerSocketManager])
|
|
68
|
+
__metadata("design:paramtypes", [AbstractLogger, Function, Function])
|
|
77
69
|
], ClaireServer);
|
|
78
70
|
export { ClaireServer };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CoreGlobalStore } from "@clairejs/core";
|
|
2
|
-
import {
|
|
2
|
+
import { EndpointMetadata } from "../common/request/endpoint-metadata";
|
|
3
3
|
export interface ServerGlobalStore extends CoreGlobalStore {
|
|
4
|
-
mountedEndpointInfo?:
|
|
4
|
+
mountedEndpointInfo?: EndpointMetadata[];
|
|
5
5
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clairejs/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.1",
|
|
4
4
|
"description": "Claire server NodeJs framework written in Typescript.",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,10 +16,12 @@
|
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"aws-sdk": "^2.841.0",
|
|
19
|
+
"axios": "^0.21.4",
|
|
19
20
|
"cookie-parser": "^1.4.6",
|
|
20
21
|
"cors": "^2.8.5",
|
|
21
22
|
"express": "^4.17.1",
|
|
22
23
|
"express-fileupload": "^1.2.1",
|
|
24
|
+
"ioredis": "^5.2.0",
|
|
23
25
|
"node-cron": "^3.0.1",
|
|
24
26
|
"node-schedule": "^2.1.0",
|
|
25
27
|
"parseurl": "^1.3.3",
|
|
@@ -28,12 +30,10 @@
|
|
|
28
30
|
"randomstring": "^1.2.2",
|
|
29
31
|
"redlock": "^5.0.0-beta.2",
|
|
30
32
|
"reflect-metadata": "^0.1.13",
|
|
31
|
-
"ws": "^7.5.5"
|
|
32
|
-
"ioredis": "^5.2.0",
|
|
33
|
-
"axios": "^0.21.4"
|
|
33
|
+
"ws": "^7.5.5"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@clairejs/core": "^3.
|
|
36
|
+
"@clairejs/core": "^3.7.1",
|
|
37
37
|
"@clairejs/orm": "^3.11.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Constructor, DtoMetadata, HttpMethod, SocketMethod, ObjectFieldMetadata } from "@clairejs/core";
|
|
2
|
-
import { RequestDataSource } from "./types";
|
|
3
|
-
import { AbstractAccessCondition } from "../../http/security/AbstractAccessCondition";
|
|
4
|
-
export interface EndpointMetadata extends ObjectFieldMetadata {
|
|
5
|
-
/**
|
|
6
|
-
* Basic HTTP information, name property is handler function name.
|
|
7
|
-
*/
|
|
8
|
-
httpMethod: HttpMethod | SocketMethod;
|
|
9
|
-
url: string;
|
|
10
|
-
/**
|
|
11
|
-
* User-friendly display name of endpoint.
|
|
12
|
-
*/
|
|
13
|
-
displayName?: string;
|
|
14
|
-
bodyValidationDto?: DtoMetadata;
|
|
15
|
-
queriesValidationDto?: DtoMetadata;
|
|
16
|
-
paramsValidationDto?: DtoMetadata;
|
|
17
|
-
responseValidationDto?: DtoMetadata;
|
|
18
|
-
params?: {
|
|
19
|
-
[index: number]: {
|
|
20
|
-
source?: RequestDataSource;
|
|
21
|
-
diClass?: Constructor<any>;
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* This endpoint requires tfa
|
|
26
|
-
*/
|
|
27
|
-
tfaRequired?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Allow public access to this endpoint.
|
|
30
|
-
*/
|
|
31
|
-
openAccess?: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Metadata of access condition to allow a conditional access to the endpoint.
|
|
34
|
-
*/
|
|
35
|
-
accessConditions?: Constructor<AbstractAccessCondition>[];
|
|
36
|
-
/**
|
|
37
|
-
* Group of permission of this endpoint.
|
|
38
|
-
*/
|
|
39
|
-
permissionGroup?: string;
|
|
40
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { AccessConditionMetadata } from "@clairejs/core";
|
|
2
|
-
import { HttpRequest } from "../common/HttpRequest";
|
|
3
|
-
export declare abstract class AbstractAccessCondition<T = any> {
|
|
4
|
-
abstract resolveConditionValue(request: HttpRequest): Promise<T>;
|
|
5
|
-
abstract validate(conditionValue: T, permittedConditionValue: any): Promise<boolean>;
|
|
6
|
-
abstract getConditionMetadata(): AccessConditionMetadata;
|
|
7
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { Constructor } from "@clairejs/core";
|
|
2
|
-
import { HttpRequest } from "../../common/HttpRequest";
|
|
3
|
-
import { AbstractAccessCondition } from "../AbstractAccessCondition";
|
|
4
|
-
export declare const FilterModelFieldAccessCondition: <T extends Constructor<any>>(model: T, name: string, requestedConditionValueResolver: (request: HttpRequest) => string[] | undefined) => Constructor<AbstractAccessCondition<string[] | undefined>>;
|
|
@@ -1,30 +0,0 @@
|
|
|
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 { AccessConditionValueType, getObjectMetadata, Register, } from "@clairejs/core";
|
|
8
|
-
import { AbstractAccessCondition } from "../AbstractAccessCondition";
|
|
9
|
-
export const FilterModelFieldAccessCondition = (model, name, requestedConditionValueResolver) => {
|
|
10
|
-
let _ = class _ extends AbstractAccessCondition {
|
|
11
|
-
async resolveConditionValue(request) {
|
|
12
|
-
return requestedConditionValueResolver(request);
|
|
13
|
-
}
|
|
14
|
-
getConditionMetadata() {
|
|
15
|
-
return {
|
|
16
|
-
name,
|
|
17
|
-
valueType: AccessConditionValueType.CHOICES,
|
|
18
|
-
valueConstraint: getObjectMetadata(model).fields.map((f) => f.name),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
async validate(requestedConditionValue, permittedConditionValue) {
|
|
22
|
-
return (!!requestedConditionValue &&
|
|
23
|
-
requestedConditionValue.every((value) => permittedConditionValue.includes(value)));
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
_ = __decorate([
|
|
27
|
-
Register()
|
|
28
|
-
], _);
|
|
29
|
-
return _;
|
|
30
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { AccessConditionMetadata } from "@clairejs/core";
|
|
2
|
-
import { HttpRequest } from "../../common/HttpRequest";
|
|
3
|
-
import { AbstractAccessCondition } from "../AbstractAccessCondition";
|
|
4
|
-
export declare class MaximumQueryLimit extends AbstractAccessCondition {
|
|
5
|
-
resolveConditionValue(request: HttpRequest): Promise<any>;
|
|
6
|
-
validate(conditionValue: number, permittedConditionValue: number): Promise<boolean>;
|
|
7
|
-
getConditionMetadata(): AccessConditionMetadata;
|
|
8
|
-
}
|