@ruiapp/rapid-core 0.1.41 → 0.1.43
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/dataAccess/dataAccessTypes.d.ts +63 -0
- package/dist/dataAccess/dataAccessor.d.ts +5 -4
- package/dist/dataAccess/entityMapper.d.ts +7 -2
- package/dist/dataAccess/metaHelper.d.ts +6 -0
- package/dist/index.js +576 -324
- package/dist/plugins/sequence/SequencePluginTypes.d.ts +1 -0
- package/dist/queryBuilder/queryBuilder.d.ts +12 -22
- package/dist/types.d.ts +34 -5
- package/dist/utilities/errorUtility.d.ts +3 -0
- package/package.json +1 -1
- package/rollup.config.js +13 -17
- package/src/bootstrapApplicationConfig.ts +25 -4
- package/src/core/actionHandler.ts +2 -5
- package/src/core/eventManager.ts +1 -4
- package/src/core/facility.ts +1 -1
- package/src/core/http/formDataParser.ts +31 -43
- package/src/core/pluginManager.ts +13 -39
- package/src/core/providers/runtimeProvider.ts +1 -1
- package/src/core/request.ts +3 -3
- package/src/core/response.ts +2 -7
- package/src/core/routeContext.ts +2 -6
- package/src/core/routesBuilder.ts +46 -55
- package/src/core/server.ts +8 -34
- package/src/dataAccess/dataAccessTypes.ts +86 -0
- package/src/dataAccess/dataAccessor.ts +46 -24
- package/src/dataAccess/entityManager.ts +294 -245
- package/src/dataAccess/entityMapper.ts +32 -15
- package/src/dataAccess/filterHelper.ts +1 -3
- package/src/dataAccess/metaHelper.ts +45 -0
- package/src/dataAccess/propertyMapper.ts +3 -3
- package/src/deno-std/datetime/to_imf.ts +2 -17
- package/src/deno-std/encoding/base64.ts +1 -5
- package/src/deno-std/http/cookie.ts +26 -59
- package/src/facilities/log/LogFacility.ts +0 -1
- package/src/helpers/entityHelpers.ts +1 -4
- package/src/helpers/runCollectionEntityActionHandler.ts +2 -10
- package/src/plugins/auth/AuthPlugin.ts +2 -5
- package/src/plugins/auth/actionHandlers/changePassword.ts +6 -10
- package/src/plugins/auth/actionHandlers/createSession.ts +14 -15
- package/src/plugins/auth/actionHandlers/deleteSession.ts +1 -5
- package/src/plugins/auth/actionHandlers/getMyProfile.ts +5 -9
- package/src/plugins/auth/actionHandlers/index.ts +1 -7
- package/src/plugins/auth/actionHandlers/resetPassword.ts +3 -7
- package/src/plugins/auth/models/AccessToken.ts +2 -2
- package/src/plugins/auth/models/index.ts +1 -3
- package/src/plugins/auth/routes/changePassword.ts +1 -1
- package/src/plugins/auth/routes/getMyProfile.ts +1 -1
- package/src/plugins/auth/routes/index.ts +1 -7
- package/src/plugins/auth/routes/resetPassword.ts +1 -1
- package/src/plugins/auth/routes/signin.ts +1 -1
- package/src/plugins/auth/routes/signout.ts +1 -1
- package/src/plugins/cronJob/CronJobPlugin.ts +12 -21
- package/src/plugins/cronJob/CronJobPluginTypes.ts +9 -9
- package/src/plugins/cronJob/actionHandlers/index.ts +1 -3
- package/src/plugins/cronJob/actionHandlers/runCronJob.ts +3 -8
- package/src/plugins/cronJob/routes/index.ts +1 -3
- package/src/plugins/cronJob/routes/runCronJob.ts +1 -1
- package/src/plugins/dataManage/DataManagePlugin.ts +5 -11
- package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +5 -14
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +8 -9
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +7 -8
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +15 -24
- package/src/plugins/dataManage/actionHandlers/findCollectionEntityById.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/queryDatabase.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +1 -5
- package/src/plugins/entityAccessControl/EntityAccessControlPlugin.ts +5 -6
- package/src/plugins/entityWatch/EntityWatchPlugin.ts +18 -17
- package/src/plugins/entityWatch/EntityWatchPluginTypes.ts +3 -10
- package/src/plugins/fileManage/FileManagePlugin.ts +1 -3
- package/src/plugins/fileManage/actionHandlers/downloadDocument.ts +2 -6
- package/src/plugins/fileManage/actionHandlers/downloadFile.ts +2 -6
- package/src/plugins/fileManage/actionHandlers/uploadFile.ts +3 -7
- package/src/plugins/fileManage/routes/downloadDocument.ts +1 -1
- package/src/plugins/fileManage/routes/downloadFile.ts +1 -1
- package/src/plugins/fileManage/routes/index.ts +1 -5
- package/src/plugins/fileManage/routes/uploadFile.ts +1 -1
- package/src/plugins/metaManage/MetaManagePlugin.ts +45 -92
- package/src/plugins/metaManage/actionHandlers/getMetaModelDetail.ts +1 -5
- package/src/plugins/metaManage/actionHandlers/listMetaModels.ts +1 -5
- package/src/plugins/metaManage/actionHandlers/listMetaRoutes.ts +1 -5
- package/src/plugins/routeManage/RouteManagePlugin.ts +2 -7
- package/src/plugins/routeManage/actionHandlers/httpProxy.ts +1 -5
- package/src/plugins/sequence/SequencePlugin.ts +14 -16
- package/src/plugins/sequence/SequencePluginTypes.ts +20 -29
- package/src/plugins/sequence/SequenceService.ts +16 -15
- package/src/plugins/sequence/actionHandlers/generateSn.ts +2 -7
- package/src/plugins/sequence/actionHandlers/index.ts +1 -3
- package/src/plugins/sequence/models/SequenceAutoIncrementRecord.ts +2 -2
- package/src/plugins/sequence/models/SequenceRule.ts +2 -2
- package/src/plugins/sequence/models/index.ts +1 -4
- package/src/plugins/sequence/routes/generateSn.ts +1 -1
- package/src/plugins/sequence/routes/index.ts +1 -3
- package/src/plugins/sequence/segment-utility.ts +1 -1
- package/src/plugins/sequence/segments/autoIncrement.ts +4 -8
- package/src/plugins/sequence/segments/dayOfMonth.ts +3 -7
- package/src/plugins/sequence/segments/index.ts +1 -8
- package/src/plugins/sequence/segments/literal.ts +1 -1
- package/src/plugins/sequence/segments/month.ts +3 -7
- package/src/plugins/sequence/segments/parameter.ts +3 -7
- package/src/plugins/sequence/segments/year.ts +3 -7
- package/src/plugins/serverOperation/ServerOperationPlugin.ts +12 -22
- package/src/plugins/serverOperation/ServerOperationPluginTypes.ts +1 -1
- package/src/plugins/serverOperation/actionHandlers/index.ts +1 -3
- package/src/plugins/stateMachine/StateMachinePlugin.ts +19 -22
- package/src/plugins/stateMachine/StateMachinePluginTypes.ts +6 -7
- package/src/plugins/stateMachine/actionHandlers/index.ts +1 -3
- package/src/plugins/stateMachine/actionHandlers/sendStateMachineEvent.ts +3 -7
- package/src/plugins/stateMachine/models/StateMachine.ts +2 -2
- package/src/plugins/stateMachine/models/index.ts +1 -3
- package/src/plugins/stateMachine/routes/index.ts +1 -3
- package/src/plugins/stateMachine/routes/sendStateMachineEvent.ts +1 -1
- package/src/plugins/webhooks/WebhooksPlugin.ts +9 -41
- package/src/polyfill.ts +1 -1
- package/src/proxy/mod.ts +4 -13
- package/src/queryBuilder/queryBuilder.ts +149 -106
- package/src/server.ts +19 -44
- package/src/types.ts +54 -79
- package/src/utilities/accessControlUtility.ts +4 -4
- package/src/utilities/errorUtility.ts +17 -0
- package/src/utilities/fsUtility.ts +12 -13
- package/src/utilities/httpUtility.ts +1 -5
- package/src/utilities/jwtUtility.ts +6 -10
- package/tsconfig.json +1 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { IRpdServer } from "~/core/server";
|
|
1
2
|
import { RpdDataModel } from "~/types";
|
|
2
3
|
import { isRelationProperty } from "~/utilities/rapidUtility";
|
|
4
|
+
import { getEntityProperty, getEntityPropertyByCode } from "./metaHelper";
|
|
3
5
|
|
|
4
6
|
// TODO Generate mapper and cache it.
|
|
5
7
|
|
|
6
|
-
export function mapDbRowToEntity(model: RpdDataModel, row: any, keepNonPropertyFields: boolean) {
|
|
8
|
+
export function mapDbRowToEntity(server: IRpdServer, model: RpdDataModel, row: any, keepNonPropertyFields: boolean) {
|
|
7
9
|
if (!row) {
|
|
8
10
|
return null;
|
|
9
11
|
}
|
|
@@ -14,14 +16,15 @@ export function mapDbRowToEntity(model: RpdDataModel, row: any, keepNonPropertyF
|
|
|
14
16
|
|
|
15
17
|
const result: Record<string, any> = {};
|
|
16
18
|
const columnNames = Object.keys(row);
|
|
17
|
-
|
|
19
|
+
// TODO: Improve performance.
|
|
20
|
+
columnNames.forEach((columnName) => {
|
|
18
21
|
let isRelationProp = false;
|
|
19
22
|
let propertyName = columnName;
|
|
20
|
-
let property = model
|
|
23
|
+
let property = getEntityProperty(server, model, (item) => item.columnName === columnName);
|
|
21
24
|
if (property) {
|
|
22
25
|
propertyName = property.code;
|
|
23
26
|
} else {
|
|
24
|
-
property = model
|
|
27
|
+
property = getEntityProperty(server, model, (item) => item.relation === "one" && item.targetIdColumnName === columnName);
|
|
25
28
|
if (property) {
|
|
26
29
|
isRelationProp = true;
|
|
27
30
|
propertyName = property.code;
|
|
@@ -48,33 +51,47 @@ export function mapDbRowToEntity(model: RpdDataModel, row: any, keepNonPropertyF
|
|
|
48
51
|
return result;
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
export type DbRowWithBaseRow = {
|
|
55
|
+
row?: Record<string, any>;
|
|
56
|
+
baseRow?: Record<string, any>;
|
|
57
|
+
}
|
|
51
58
|
|
|
52
|
-
export function mapEntityToDbRow(model: RpdDataModel, entity: any) {
|
|
59
|
+
export function mapEntityToDbRow(server: IRpdServer, model: RpdDataModel, entity: any): DbRowWithBaseRow {
|
|
60
|
+
let result: DbRowWithBaseRow = {};
|
|
53
61
|
if (!entity) {
|
|
54
|
-
return
|
|
62
|
+
return result;
|
|
55
63
|
}
|
|
56
64
|
|
|
65
|
+
const row = result.row = {};
|
|
66
|
+
const baseRow = result.baseRow = {};
|
|
57
67
|
if (!model.properties || !model.properties.length) {
|
|
58
|
-
return
|
|
68
|
+
return result;
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
const result: Record<string, any> = {};
|
|
62
71
|
const propertyNames = Object.keys(entity);
|
|
63
|
-
propertyNames.forEach(propertyName => {
|
|
72
|
+
propertyNames.forEach((propertyName) => {
|
|
64
73
|
let columnName = propertyName;
|
|
65
|
-
const property =
|
|
74
|
+
const property = getEntityPropertyByCode(server, model, propertyName);
|
|
66
75
|
if (property) {
|
|
67
76
|
if (!isRelationProperty(property)) {
|
|
68
77
|
columnName = property.columnName || property.code;
|
|
69
|
-
|
|
78
|
+
if (property.isBaseProperty) {
|
|
79
|
+
baseRow[columnName] = entity[propertyName];
|
|
80
|
+
} else {
|
|
81
|
+
row[columnName] = entity[propertyName];
|
|
82
|
+
}
|
|
70
83
|
}
|
|
71
84
|
} else {
|
|
72
|
-
const oneRelationProperty = model
|
|
85
|
+
const oneRelationProperty = getEntityProperty(server, model, (item) => item.relation === "one" && item.targetIdColumnName === propertyName);
|
|
73
86
|
if (oneRelationProperty) {
|
|
74
|
-
|
|
87
|
+
if (oneRelationProperty.isBaseProperty) {
|
|
88
|
+
baseRow[columnName] = entity[propertyName];
|
|
89
|
+
} else {
|
|
90
|
+
row[columnName] = entity[propertyName];
|
|
91
|
+
}
|
|
75
92
|
}
|
|
76
93
|
}
|
|
77
|
-
})
|
|
94
|
+
});
|
|
78
95
|
|
|
79
96
|
return result;
|
|
80
|
-
}
|
|
97
|
+
}
|
|
@@ -34,9 +34,7 @@ export function removeFiltersWithNullValue(filters?: EntityFilterOptions[]) {
|
|
|
34
34
|
return result;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function transformFilterWithSubFilters(
|
|
38
|
-
filter: FindEntityExistenceFilterOptions | FindEntityLogicalFilterOptions,
|
|
39
|
-
): FindEntityExistenceFilterOptions | FindEntityLogicalFilterOptions | null {
|
|
37
|
+
function transformFilterWithSubFilters(filter: FindEntityExistenceFilterOptions | FindEntityLogicalFilterOptions): FindEntityExistenceFilterOptions | FindEntityLogicalFilterOptions | null {
|
|
40
38
|
const subFilters = removeFiltersWithNullValue(filter.filters);
|
|
41
39
|
if (!subFilters.length) {
|
|
42
40
|
return null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { IRpdServer } from "~/core/server";
|
|
2
|
+
import { RpdDataModel, RpdDataModelProperty } from "~/types";
|
|
3
|
+
|
|
4
|
+
export function getEntityProperties(server: IRpdServer, model: RpdDataModel) {
|
|
5
|
+
return model.properties;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getEntityPropertiesIncludingBase(server: IRpdServer, model: RpdDataModel) {
|
|
9
|
+
if (!model.base) {
|
|
10
|
+
return model.properties;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const baseModel = server.getModel({
|
|
14
|
+
singularCode: model.base,
|
|
15
|
+
});
|
|
16
|
+
baseModel.properties.forEach(prop => prop.isBaseProperty = true);
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
...baseModel.properties,
|
|
20
|
+
...model.properties,
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getEntityPropertyByCode(server: IRpdServer, model: RpdDataModel, propertyCode: string) {
|
|
25
|
+
return getEntityProperty(server, model, (e) => e.code === propertyCode);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getEntityProperty(server: IRpdServer, model: RpdDataModel, predicate: (item: RpdDataModelProperty) => boolean) {
|
|
29
|
+
let property = model.properties.find(predicate);
|
|
30
|
+
if (!property) {
|
|
31
|
+
const baseModelSingularCode = model.base;
|
|
32
|
+
if (baseModelSingularCode) {
|
|
33
|
+
const baseModel = server.getModel({
|
|
34
|
+
singularCode: baseModelSingularCode,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
property = baseModel.properties.find(predicate);
|
|
38
|
+
if (property) {
|
|
39
|
+
property.isBaseProperty = true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return property;
|
|
45
|
+
}
|
|
@@ -6,7 +6,7 @@ export function mapPropertyNameToColumnName(model: RpdDataModel, propertyName: s
|
|
|
6
6
|
return propertyName;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
const property = model.properties.find(item => item.code === propertyName);
|
|
9
|
+
const property = model.properties.find((item) => item.code === propertyName);
|
|
10
10
|
if (!property) {
|
|
11
11
|
return propertyName;
|
|
12
12
|
}
|
|
@@ -23,5 +23,5 @@ export function mapPropertyNamesToColumnNames(model: RpdDataModel, propertyNames
|
|
|
23
23
|
return [];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
return propertyNames.map(fieldName => mapPropertyNameToColumnName(model, fieldName));
|
|
27
|
-
}
|
|
26
|
+
return propertyNames.map((fieldName) => mapPropertyNameToColumnName(model, fieldName));
|
|
27
|
+
}
|
|
@@ -27,21 +27,6 @@ export function toIMF(date: Date): string {
|
|
|
27
27
|
const s = dtPad(date.getUTCSeconds().toString());
|
|
28
28
|
const y = date.getUTCFullYear();
|
|
29
29
|
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
30
|
-
const months = [
|
|
31
|
-
|
|
32
|
-
"Feb",
|
|
33
|
-
"Mar",
|
|
34
|
-
"Apr",
|
|
35
|
-
"May",
|
|
36
|
-
"Jun",
|
|
37
|
-
"Jul",
|
|
38
|
-
"Aug",
|
|
39
|
-
"Sep",
|
|
40
|
-
"Oct",
|
|
41
|
-
"Nov",
|
|
42
|
-
"Dec",
|
|
43
|
-
];
|
|
44
|
-
return `${days[date.getUTCDay()]}, ${d} ${
|
|
45
|
-
months[date.getUTCMonth()]
|
|
46
|
-
} ${y} ${h}:${min}:${s} GMT`;
|
|
30
|
+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
31
|
+
return `${days[date.getUTCDay()]}, ${d} ${months[date.getUTCMonth()]} ${y} ${h}:${min}:${s} GMT`;
|
|
47
32
|
}
|
|
@@ -100,11 +100,7 @@ const base64abc = [
|
|
|
100
100
|
* @param data
|
|
101
101
|
*/
|
|
102
102
|
export function encode(data: ArrayBuffer | string): string {
|
|
103
|
-
const uint8 = typeof data === "string"
|
|
104
|
-
? new TextEncoder().encode(data)
|
|
105
|
-
: data instanceof Uint8Array
|
|
106
|
-
? data
|
|
107
|
-
: new Uint8Array(data);
|
|
103
|
+
const uint8 = typeof data === "string" ? new TextEncoder().encode(data) : data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
108
104
|
let result = "",
|
|
109
105
|
i;
|
|
110
106
|
const l = uint8.length;
|
|
@@ -85,10 +85,7 @@ function toString(cookie: Cookie): string {
|
|
|
85
85
|
out.push("HttpOnly");
|
|
86
86
|
}
|
|
87
87
|
if (typeof cookie.maxAge === "number" && Number.isInteger(cookie.maxAge)) {
|
|
88
|
-
assert(
|
|
89
|
-
cookie.maxAge >= 0,
|
|
90
|
-
"Max-Age must be an integer superior or equal to 0",
|
|
91
|
-
);
|
|
88
|
+
assert(cookie.maxAge >= 0, "Max-Age must be an integer superior or equal to 0");
|
|
92
89
|
out.push(`Max-Age=${cookie.maxAge}`);
|
|
93
90
|
}
|
|
94
91
|
if (cookie.domain) {
|
|
@@ -104,9 +101,7 @@ function toString(cookie: Cookie): string {
|
|
|
104
101
|
}
|
|
105
102
|
if (cookie.expires) {
|
|
106
103
|
const { expires } = cookie;
|
|
107
|
-
const dateString = toIMF(
|
|
108
|
-
typeof expires === "number" ? new Date(expires) : expires,
|
|
109
|
-
);
|
|
104
|
+
const dateString = toIMF(typeof expires === "number" ? new Date(expires) : expires);
|
|
110
105
|
out.push(`Expires=${dateString}`);
|
|
111
106
|
}
|
|
112
107
|
if (cookie.unparsed) {
|
|
@@ -136,12 +131,8 @@ function validatePath(path: string | null) {
|
|
|
136
131
|
}
|
|
137
132
|
for (let i = 0; i < path.length; i++) {
|
|
138
133
|
const c = path.charAt(i);
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
) {
|
|
142
|
-
throw new Error(
|
|
143
|
-
path + ": Invalid cookie path char '" + c + "'",
|
|
144
|
-
);
|
|
134
|
+
if (c < String.fromCharCode(0x20) || c > String.fromCharCode(0x7e) || c == ";") {
|
|
135
|
+
throw new Error(path + ": Invalid cookie path char '" + c + "'");
|
|
145
136
|
}
|
|
146
137
|
}
|
|
147
138
|
}
|
|
@@ -155,20 +146,11 @@ function validateValue(name: string, value: string | null) {
|
|
|
155
146
|
if (value == null || name == null) return;
|
|
156
147
|
for (let i = 0; i < value.length; i++) {
|
|
157
148
|
const c = value.charAt(i);
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
c == String.fromCharCode(0x2c) || c == String.fromCharCode(0x3b) ||
|
|
161
|
-
c == String.fromCharCode(0x5c) || c == String.fromCharCode(0x7f)
|
|
162
|
-
) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
"RFC2616 cookie '" + name + "' cannot contain character '" + c + "'",
|
|
165
|
-
);
|
|
149
|
+
if (c < String.fromCharCode(0x21) || c == String.fromCharCode(0x22) || c == String.fromCharCode(0x2c) || c == String.fromCharCode(0x3b) || c == String.fromCharCode(0x5c) || c == String.fromCharCode(0x7f)) {
|
|
150
|
+
throw new Error("RFC2616 cookie '" + name + "' cannot contain character '" + c + "'");
|
|
166
151
|
}
|
|
167
152
|
if (c > String.fromCharCode(0x80)) {
|
|
168
|
-
throw new Error(
|
|
169
|
-
"RFC2616 cookie '" + name + "' can only have US-ASCII chars as value" +
|
|
170
|
-
c.charCodeAt(0).toString(16),
|
|
171
|
-
);
|
|
153
|
+
throw new Error("RFC2616 cookie '" + name + "' can only have US-ASCII chars as value" + c.charCodeAt(0).toString(16));
|
|
172
154
|
}
|
|
173
155
|
}
|
|
174
156
|
}
|
|
@@ -185,9 +167,7 @@ function validateDomain(domain: string) {
|
|
|
185
167
|
const char1 = domain.charAt(0);
|
|
186
168
|
const charN = domain.charAt(domain.length - 1);
|
|
187
169
|
if (char1 == "-" || charN == "." || charN == "-") {
|
|
188
|
-
throw new Error(
|
|
189
|
-
"Invalid first/last char in cookie domain: " + domain,
|
|
190
|
-
);
|
|
170
|
+
throw new Error("Invalid first/last char in cookie domain: " + domain);
|
|
191
171
|
}
|
|
192
172
|
}
|
|
193
173
|
|
|
@@ -275,11 +255,7 @@ export function setCookie(headers: Headers, cookie: Cookie) {
|
|
|
275
255
|
* @param name Name of cookie
|
|
276
256
|
* @param attributes Additional cookie attributes
|
|
277
257
|
*/
|
|
278
|
-
export function deleteCookie(
|
|
279
|
-
headers: Headers,
|
|
280
|
-
name: string,
|
|
281
|
-
attributes?: { path?: string; domain?: string },
|
|
282
|
-
) {
|
|
258
|
+
export function deleteCookie(headers: Headers, name: string, attributes?: { path?: string; domain?: string }) {
|
|
283
259
|
setCookie(headers, {
|
|
284
260
|
name: name,
|
|
285
261
|
value: "",
|
|
@@ -289,12 +265,10 @@ export function deleteCookie(
|
|
|
289
265
|
}
|
|
290
266
|
|
|
291
267
|
function parseSetCookie(value: string): Cookie | null {
|
|
292
|
-
const attrs = value
|
|
293
|
-
.split("
|
|
294
|
-
.
|
|
295
|
-
|
|
296
|
-
return [key, values.join("=")];
|
|
297
|
-
});
|
|
268
|
+
const attrs = value.split(";").map((attr) => {
|
|
269
|
+
const [key, ...values] = attr.trim().split("=");
|
|
270
|
+
return [key, values.join("=")];
|
|
271
|
+
});
|
|
298
272
|
const cookie: Cookie = {
|
|
299
273
|
name: attrs[0][0],
|
|
300
274
|
value: attrs[0][1],
|
|
@@ -308,9 +282,7 @@ function parseSetCookie(value: string): Cookie | null {
|
|
|
308
282
|
case "max-age":
|
|
309
283
|
cookie.maxAge = Number(value);
|
|
310
284
|
if (cookie.maxAge < 0) {
|
|
311
|
-
console.warn(
|
|
312
|
-
"Max-Age must be an integer superior or equal to 0. Cookie ignored.",
|
|
313
|
-
);
|
|
285
|
+
console.warn("Max-Age must be an integer superior or equal to 0. Cookie ignored.");
|
|
314
286
|
return null;
|
|
315
287
|
}
|
|
316
288
|
break;
|
|
@@ -339,29 +311,21 @@ function parseSetCookie(value: string): Cookie | null {
|
|
|
339
311
|
if (cookie.name.startsWith("__Secure-")) {
|
|
340
312
|
/** This requirement is mentioned in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie but not the RFC. */
|
|
341
313
|
if (!cookie.secure) {
|
|
342
|
-
console.warn(
|
|
343
|
-
"Cookies with names starting with `__Secure-` must be set with the secure flag. Cookie ignored.",
|
|
344
|
-
);
|
|
314
|
+
console.warn("Cookies with names starting with `__Secure-` must be set with the secure flag. Cookie ignored.");
|
|
345
315
|
return null;
|
|
346
316
|
}
|
|
347
317
|
}
|
|
348
318
|
if (cookie.name.startsWith("__Host-")) {
|
|
349
319
|
if (!cookie.secure) {
|
|
350
|
-
console.warn(
|
|
351
|
-
"Cookies with names starting with `__Host-` must be set with the secure flag. Cookie ignored.",
|
|
352
|
-
);
|
|
320
|
+
console.warn("Cookies with names starting with `__Host-` must be set with the secure flag. Cookie ignored.");
|
|
353
321
|
return null;
|
|
354
322
|
}
|
|
355
323
|
if (cookie.domain !== undefined) {
|
|
356
|
-
console.warn(
|
|
357
|
-
"Cookies with names starting with `__Host-` must not have a domain specified. Cookie ignored.",
|
|
358
|
-
);
|
|
324
|
+
console.warn("Cookies with names starting with `__Host-` must not have a domain specified. Cookie ignored.");
|
|
359
325
|
return null;
|
|
360
326
|
}
|
|
361
327
|
if (cookie.path !== "/") {
|
|
362
|
-
console.warn(
|
|
363
|
-
"Cookies with names starting with `__Host-` must have path be `/`. Cookie has been ignored.",
|
|
364
|
-
);
|
|
328
|
+
console.warn("Cookies with names starting with `__Host-` must have path be `/`. Cookie has been ignored.");
|
|
365
329
|
return null;
|
|
366
330
|
}
|
|
367
331
|
}
|
|
@@ -390,9 +354,12 @@ function parseSetCookie(value: string): Cookie | null {
|
|
|
390
354
|
export function getSetCookies(headers: Headers): Cookie[] {
|
|
391
355
|
// TODO(lino-levan): remove this ts-ignore when Typescript 5.2 lands in Deno
|
|
392
356
|
// @ts-ignore Typescript's TS Dom types will be out of date until 5.2
|
|
393
|
-
return
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
357
|
+
return (
|
|
358
|
+
(headers as any)
|
|
359
|
+
.getSetCookie()
|
|
360
|
+
/** Parse each `set-cookie` header separately */
|
|
361
|
+
.map(parseSetCookie)
|
|
362
|
+
/** Skip empty cookies */
|
|
363
|
+
.filter(Boolean) as Cookie[]
|
|
364
|
+
);
|
|
398
365
|
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export function getEntityPartChanges(
|
|
2
|
-
before: any,
|
|
3
|
-
after: any,
|
|
4
|
-
): Record<string, any> | null {
|
|
1
|
+
export function getEntityPartChanges(before: any, after: any): Record<string, any> | null {
|
|
5
2
|
if (!before) {
|
|
6
3
|
throw new Error("Argument 'before' can not be null.");
|
|
7
4
|
}
|
|
@@ -3,17 +3,9 @@ import { mergeInput } from "./inputHelper";
|
|
|
3
3
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
4
4
|
import EntityManager from "~/dataAccess/entityManager";
|
|
5
5
|
|
|
6
|
-
type EntityActionHandler = (
|
|
7
|
-
entityManager: EntityManager,
|
|
8
|
-
input: any,
|
|
9
|
-
) => Promise<any>;
|
|
6
|
+
type EntityActionHandler = (entityManager: EntityManager, input: any) => Promise<any>;
|
|
10
7
|
|
|
11
|
-
export default async function runCollectionEntityActionHandler(
|
|
12
|
-
ctx: ActionHandlerContext,
|
|
13
|
-
options: RunEntityActionHandlerOptions,
|
|
14
|
-
code: string,
|
|
15
|
-
handleEntityAction: EntityActionHandler,
|
|
16
|
-
) {
|
|
8
|
+
export default async function runCollectionEntityActionHandler(ctx: ActionHandlerContext, options: RunEntityActionHandlerOptions, code: string, handleEntityAction: EntityActionHandler) {
|
|
17
9
|
const { logger, server, input } = ctx;
|
|
18
10
|
|
|
19
11
|
const { defaultInput, fixedInput } = options;
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
* Auth manager plugin
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
RpdApplicationConfig,
|
|
7
|
-
} from "~/types";
|
|
5
|
+
import { RpdApplicationConfig } from "~/types";
|
|
8
6
|
import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "~/core/server";
|
|
9
7
|
|
|
10
8
|
import pluginActionHandlers from "./actionHandlers";
|
|
@@ -13,7 +11,6 @@ import pluginRoutes from "./routes";
|
|
|
13
11
|
import { RouteContext } from "~/core/routeContext";
|
|
14
12
|
import { verifyJwt } from "~/utilities/jwtUtility";
|
|
15
13
|
|
|
16
|
-
|
|
17
14
|
class AuthPlugin implements RapidPlugin {
|
|
18
15
|
get code(): string {
|
|
19
16
|
return "authManager";
|
|
@@ -59,7 +56,7 @@ class AuthPlugin implements RapidPlugin {
|
|
|
59
56
|
// Authorization header has no Bearer or no token
|
|
60
57
|
const authHeader = headers.get("Authorization")!;
|
|
61
58
|
if (!authHeader.startsWith("Bearer ") || authHeader.length <= 7) {
|
|
62
|
-
throw new Error(
|
|
59
|
+
throw new Error("AUTHORIZATION_HEADER_INVALID");
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
token = authHeader.slice(7);
|
|
@@ -4,11 +4,7 @@ import { RapidPlugin } from "~/core/server";
|
|
|
4
4
|
|
|
5
5
|
export const code = "changePassword";
|
|
6
6
|
|
|
7
|
-
export async function handler(
|
|
8
|
-
plugin: RapidPlugin,
|
|
9
|
-
ctx: ActionHandlerContext,
|
|
10
|
-
options: any,
|
|
11
|
-
) {
|
|
7
|
+
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
12
8
|
const { server, input, routerContext } = ctx;
|
|
13
9
|
const { response } = routerContext;
|
|
14
10
|
const { id, oldPassword, newPassword } = input;
|
|
@@ -18,9 +14,9 @@ export async function handler(
|
|
|
18
14
|
ctx.status = 401;
|
|
19
15
|
ctx.output = {
|
|
20
16
|
error: {
|
|
21
|
-
message: "You are not signed in."
|
|
22
|
-
}
|
|
23
|
-
}
|
|
17
|
+
message: "You are not signed in.",
|
|
18
|
+
},
|
|
19
|
+
};
|
|
24
20
|
return;
|
|
25
21
|
}
|
|
26
22
|
|
|
@@ -34,8 +30,8 @@ export async function handler(
|
|
|
34
30
|
operator: "eq",
|
|
35
31
|
field: "id",
|
|
36
32
|
value: userId,
|
|
37
|
-
}
|
|
38
|
-
]
|
|
33
|
+
},
|
|
34
|
+
],
|
|
39
35
|
});
|
|
40
36
|
|
|
41
37
|
if (!user) {
|
|
@@ -5,17 +5,13 @@ import { ActionHandlerContext } from "~/core/actionHandler";
|
|
|
5
5
|
import { RapidPlugin } from "~/core/server";
|
|
6
6
|
|
|
7
7
|
export interface UserAccessToken {
|
|
8
|
-
sub: "userAccessToken"
|
|
8
|
+
sub: "userAccessToken";
|
|
9
9
|
aud: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export const code = "createSession";
|
|
13
13
|
|
|
14
|
-
export async function handler(
|
|
15
|
-
plugin: RapidPlugin,
|
|
16
|
-
ctx: ActionHandlerContext,
|
|
17
|
-
options: any,
|
|
18
|
-
) {
|
|
14
|
+
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
19
15
|
const { server, input, routerContext } = ctx;
|
|
20
16
|
const { response } = routerContext;
|
|
21
17
|
const { account, password } = input;
|
|
@@ -30,8 +26,8 @@ export async function handler(
|
|
|
30
26
|
operator: "eq",
|
|
31
27
|
field: "login",
|
|
32
28
|
value: account,
|
|
33
|
-
}
|
|
34
|
-
]
|
|
29
|
+
},
|
|
30
|
+
],
|
|
35
31
|
});
|
|
36
32
|
|
|
37
33
|
if (!user) {
|
|
@@ -44,13 +40,16 @@ export async function handler(
|
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
const secretKey = Buffer.from(server.config.jwtKey, "base64");
|
|
47
|
-
const token = createJwt(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
const token = createJwt(
|
|
44
|
+
{
|
|
45
|
+
iss: "authManager",
|
|
46
|
+
sub: "userAccessToken",
|
|
47
|
+
aud: "" + user.id,
|
|
48
|
+
iat: Math.floor(Date.now() / 1000),
|
|
49
|
+
act: user.login,
|
|
50
|
+
} as UserAccessToken,
|
|
51
|
+
secretKey,
|
|
52
|
+
);
|
|
54
53
|
|
|
55
54
|
setCookie(response.headers, {
|
|
56
55
|
name: ctx.server.config.sessionCookieName,
|
|
@@ -4,11 +4,7 @@ import { setCookie } from "~/deno-std/http/cookie";
|
|
|
4
4
|
|
|
5
5
|
export const code = "deleteSession";
|
|
6
6
|
|
|
7
|
-
export async function handler(
|
|
8
|
-
plugin: RapidPlugin,
|
|
9
|
-
ctx: ActionHandlerContext,
|
|
10
|
-
options: any,
|
|
11
|
-
) {
|
|
7
|
+
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
12
8
|
const { server, input, routerContext } = ctx;
|
|
13
9
|
const { response } = routerContext;
|
|
14
10
|
|
|
@@ -3,11 +3,7 @@ import { RapidPlugin } from "~/core/server";
|
|
|
3
3
|
|
|
4
4
|
export const code = "getMyProfile";
|
|
5
5
|
|
|
6
|
-
export async function handler(
|
|
7
|
-
plugin: RapidPlugin,
|
|
8
|
-
ctx: ActionHandlerContext,
|
|
9
|
-
options: any,
|
|
10
|
-
) {
|
|
6
|
+
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
11
7
|
const { server, input, routerContext } = ctx;
|
|
12
8
|
|
|
13
9
|
const userId = routerContext.state.userId;
|
|
@@ -15,9 +11,9 @@ export async function handler(
|
|
|
15
11
|
ctx.status = 401;
|
|
16
12
|
ctx.output = {
|
|
17
13
|
error: {
|
|
18
|
-
message: "You are not signed in."
|
|
19
|
-
}
|
|
20
|
-
}
|
|
14
|
+
message: "You are not signed in.",
|
|
15
|
+
},
|
|
16
|
+
};
|
|
21
17
|
return;
|
|
22
18
|
}
|
|
23
19
|
|
|
@@ -28,7 +24,7 @@ export async function handler(
|
|
|
28
24
|
operator: "eq",
|
|
29
25
|
field: "id",
|
|
30
26
|
value: userId,
|
|
31
|
-
}
|
|
27
|
+
},
|
|
32
28
|
],
|
|
33
29
|
properties: ["id", "name", "login", "email", "department", "roles", "state", "createdAt"],
|
|
34
30
|
});
|
|
@@ -5,10 +5,4 @@ import * as deleteSession from "./deleteSession";
|
|
|
5
5
|
import * as getMyProfile from "./getMyProfile";
|
|
6
6
|
import * as resetPassword from "./resetPassword";
|
|
7
7
|
|
|
8
|
-
export default [
|
|
9
|
-
changePassword,
|
|
10
|
-
createSession,
|
|
11
|
-
deleteSession,
|
|
12
|
-
getMyProfile,
|
|
13
|
-
resetPassword,
|
|
14
|
-
] satisfies IPluginActionHandler[];
|
|
8
|
+
export default [changePassword, createSession, deleteSession, getMyProfile, resetPassword] satisfies IPluginActionHandler[];
|
|
@@ -4,11 +4,7 @@ import { RapidPlugin } from "~/core/server";
|
|
|
4
4
|
|
|
5
5
|
export const code = "resetPassword";
|
|
6
6
|
|
|
7
|
-
export async function handler(
|
|
8
|
-
plugin: RapidPlugin,
|
|
9
|
-
ctx: ActionHandlerContext,
|
|
10
|
-
options: any,
|
|
11
|
-
) {
|
|
7
|
+
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
12
8
|
const { server, input, routerContext } = ctx;
|
|
13
9
|
const { response } = routerContext;
|
|
14
10
|
const { userId, password } = input;
|
|
@@ -23,8 +19,8 @@ export async function handler(
|
|
|
23
19
|
operator: "eq",
|
|
24
20
|
field: "id",
|
|
25
21
|
value: userId,
|
|
26
|
-
}
|
|
27
|
-
]
|
|
22
|
+
},
|
|
23
|
+
],
|
|
28
24
|
});
|
|
29
25
|
|
|
30
26
|
if (!user) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RpdDataModel } from "~/types";
|
|
2
2
|
|
|
3
|
-
export default
|
|
3
|
+
export default {
|
|
4
4
|
maintainedBy: "authManager",
|
|
5
5
|
namespace: "auth",
|
|
6
6
|
name: "access_token",
|
|
@@ -53,4 +53,4 @@ export default {
|
|
|
53
53
|
required: true,
|
|
54
54
|
},
|
|
55
55
|
],
|
|
56
|
-
} as RpdDataModel;
|
|
56
|
+
} as RpdDataModel;
|
|
@@ -4,10 +4,4 @@ import resetPassword from "./resetPassword";
|
|
|
4
4
|
import signin from "./signin";
|
|
5
5
|
import signout from "./signout";
|
|
6
6
|
|
|
7
|
-
export default [
|
|
8
|
-
changePassword,
|
|
9
|
-
getMyProfile,
|
|
10
|
-
resetPassword,
|
|
11
|
-
signin,
|
|
12
|
-
signout,
|
|
13
|
-
]
|
|
7
|
+
export default [changePassword, getMyProfile, resetPassword, signin, signout];
|