@entity-access/server-pages 1.0.42 → 1.1.2
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/Page.d.ts +6 -13
- package/dist/Page.d.ts.map +1 -1
- package/dist/Page.js +10 -41
- package/dist/Page.js.map +1 -1
- package/dist/ServerPages.d.ts.map +1 -1
- package/dist/ServerPages.js +14 -2
- package/dist/ServerPages.js.map +1 -1
- package/dist/core/CacheProperty.d.ts +5 -0
- package/dist/core/CacheProperty.d.ts.map +1 -0
- package/dist/core/CacheProperty.js +19 -0
- package/dist/core/CacheProperty.js.map +1 -0
- package/dist/core/Executor.d.ts +5 -0
- package/dist/core/Executor.d.ts.map +1 -0
- package/dist/core/Executor.js +13 -0
- package/dist/core/Executor.js.map +1 -0
- package/dist/core/RouteTree.d.ts.map +1 -1
- package/dist/core/RouteTree.js +15 -6
- package/dist/core/RouteTree.js.map +1 -1
- package/dist/core/SessionUser.d.ts +7 -5
- package/dist/core/SessionUser.d.ts.map +1 -1
- package/dist/core/SessionUser.js +36 -0
- package/dist/core/SessionUser.js.map +1 -1
- package/dist/core/Wrapped.d.ts +13 -16
- package/dist/core/Wrapped.d.ts.map +1 -1
- package/dist/core/Wrapped.js +151 -235
- package/dist/core/Wrapped.js.map +1 -1
- package/dist/decorators/Prepare.d.ts +14 -0
- package/dist/decorators/Prepare.d.ts.map +1 -0
- package/dist/decorators/Prepare.js +111 -0
- package/dist/decorators/Prepare.js.map +1 -0
- package/dist/routes/api/entity/index.d.ts.map +1 -1
- package/dist/routes/api/entity/index.js +9 -3
- package/dist/routes/api/entity/index.js.map +1 -1
- package/dist/routes/api/entity/model/get.d.ts.map +1 -1
- package/dist/routes/api/entity/model/get.js.map +1 -1
- package/dist/routes/api/entity/query/get.d.ts.map +1 -1
- package/dist/routes/api/entity/query/get.js +9 -3
- package/dist/routes/api/entity/query/get.js.map +1 -1
- package/dist/services/CookieService.d.ts.map +1 -1
- package/dist/services/CookieService.js +10 -2
- package/dist/services/CookieService.js.map +1 -1
- package/dist/socket/SocketService.d.ts.map +1 -1
- package/dist/socket/SocketService.js +1 -3
- package/dist/socket/SocketService.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Page.tsx +11 -51
- package/src/ServerPages.ts +14 -2
- package/src/core/CacheProperty.ts +18 -0
- package/src/core/Executor.ts +16 -0
- package/src/core/RouteTree.ts +7 -3
- package/src/core/SessionUser.ts +21 -5
- package/src/core/Wrapped.ts +206 -270
- package/src/decorators/Prepare.ts +132 -0
- package/src/index.d.ts +10 -10
- package/src/routes/api/entity/index.tsx +4 -1
- package/src/routes/api/entity/model/get.tsx +1 -1
- package/src/routes/api/entity/query/get.ts +4 -1
- package/src/services/CookieService.ts +10 -2
- package/src/socket/SocketService.ts +1 -2
- package/dist/decorators/Authorize.d.ts +0 -2
- package/dist/decorators/Authorize.d.ts.map +0 -1
- package/dist/decorators/Authorize.js +0 -3
- package/dist/decorators/Authorize.js.map +0 -1
- package/src/decorators/Authorize.ts +0 -3
package/src/Page.tsx
CHANGED
|
@@ -45,20 +45,20 @@ export default class Page {
|
|
|
45
45
|
|
|
46
46
|
response: WrappedResponse;
|
|
47
47
|
|
|
48
|
-
get query() {
|
|
48
|
+
get query(): any {
|
|
49
49
|
return this.request?.query;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
get
|
|
53
|
-
return this.request?.
|
|
52
|
+
get body(): any {
|
|
53
|
+
return this.request?.body;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
get
|
|
57
|
-
return this.request?.
|
|
56
|
+
get form() {
|
|
57
|
+
return this.request?.form;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
get
|
|
61
|
-
return this.request?.
|
|
60
|
+
get sessionUser() {
|
|
61
|
+
return this.request?.sessionUser;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
get url() {
|
|
@@ -75,13 +75,6 @@ export default class Page {
|
|
|
75
75
|
|
|
76
76
|
childPath: string[];
|
|
77
77
|
|
|
78
|
-
/**
|
|
79
|
-
* List of all paths that were tried before executing this page.
|
|
80
|
-
*/
|
|
81
|
-
notFoundPath: string[];
|
|
82
|
-
|
|
83
|
-
sessionUser: SessionUser;
|
|
84
|
-
|
|
85
78
|
filePath: string;
|
|
86
79
|
|
|
87
80
|
cacheControl: string;
|
|
@@ -94,47 +87,14 @@ export default class Page {
|
|
|
94
87
|
this.cacheControl = "no-cache, no-store, max-age=0";
|
|
95
88
|
}
|
|
96
89
|
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
reportError(error) {
|
|
91
|
+
console.error(error);
|
|
99
92
|
}
|
|
100
93
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return this.formDataPromise ??= (async () => {
|
|
104
|
-
let tempFolder: TempFolder;
|
|
105
|
-
const result: IFormData = {
|
|
106
|
-
fields: {},
|
|
107
|
-
files: []
|
|
108
|
-
};
|
|
109
|
-
const req = this.request;
|
|
110
|
-
const bb = busboy({ headers: req.headers , defParamCharset: "utf8" });
|
|
111
|
-
const tasks = [];
|
|
112
|
-
await new Promise((resolve, reject) => {
|
|
113
|
-
|
|
114
|
-
bb.on("field", (name, value) => {
|
|
115
|
-
result.fields[name] = value;
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
bb.on("file", (name, file, info) => {
|
|
119
|
-
if(!tempFolder) {
|
|
120
|
-
tempFolder = new TempFolder();
|
|
121
|
-
this.disposables.push(tempFolder);
|
|
122
|
-
}
|
|
123
|
-
const tf = tempFolder.get(info.filename, info.mimeType);
|
|
124
|
-
tasks.push(tf.writeAll(file).then(() => {
|
|
125
|
-
result.files.push(tf);
|
|
126
|
-
}));
|
|
127
|
-
});
|
|
128
|
-
bb.on("error", reject);
|
|
129
|
-
bb.on("close", resolve);
|
|
130
|
-
req.pipe(bb);
|
|
131
|
-
});
|
|
132
|
-
await Promise.all(tasks);
|
|
133
|
-
return result;
|
|
134
|
-
})();
|
|
94
|
+
run(): IPageResult | Promise<IPageResult> {
|
|
95
|
+
return this.notFound();
|
|
135
96
|
}
|
|
136
97
|
|
|
137
|
-
|
|
138
98
|
protected content(body: string, status = 200, contentType = "text/html") {
|
|
139
99
|
return Content.create({ body, status, contentType });
|
|
140
100
|
}
|
package/src/ServerPages.ts
CHANGED
|
@@ -13,6 +13,10 @@ import { Wrapped } from "./core/Wrapped.js";
|
|
|
13
13
|
import { SecureContext } from "node:tls";
|
|
14
14
|
import AcmeCertificateService, { IAcmeOptions } from "./ssl/AcmeCertificateService.js";
|
|
15
15
|
import ChallengeServer from "./ssl/ChallengeServer.js";
|
|
16
|
+
import SessionUser from "./core/SessionUser.js";
|
|
17
|
+
import CookieService from "./services/CookieService.js";
|
|
18
|
+
import TokenService from "./services/TokenService.js";
|
|
19
|
+
import Executor from "./core/Executor.js";
|
|
16
20
|
|
|
17
21
|
RegisterSingleton
|
|
18
22
|
export default class ServerPages {
|
|
@@ -145,7 +149,15 @@ export default class ServerPages {
|
|
|
145
149
|
|
|
146
150
|
using scope = ServiceProvider.createScope(this);
|
|
147
151
|
let sent = false;
|
|
148
|
-
const
|
|
152
|
+
const user = scope.resolve(SessionUser);
|
|
153
|
+
user.resp = resp;
|
|
154
|
+
user.authorize = async () => {
|
|
155
|
+
const cookieService = scope.resolve(CookieService);
|
|
156
|
+
const tokenService = scope.resolve(TokenService);
|
|
157
|
+
await cookieService.createSessionUserFromCookie(tokenService.authCookieName, req.remoteIPAddress);
|
|
158
|
+
(user as any).isAuthorized = true;
|
|
159
|
+
};
|
|
160
|
+
const acceptJson = req.accepts("json");
|
|
149
161
|
|
|
150
162
|
|
|
151
163
|
try {
|
|
@@ -165,7 +177,7 @@ export default class ServerPages {
|
|
|
165
177
|
page.childPath = childPath;
|
|
166
178
|
page.request = req;
|
|
167
179
|
page.response = resp;
|
|
168
|
-
const content = await
|
|
180
|
+
const content = await Executor.run(page);
|
|
169
181
|
resp.setHeader("cache-control", page.cacheControl);
|
|
170
182
|
resp.removeHeader("etag");
|
|
171
183
|
sent = true;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const CacheProperty = {
|
|
2
|
+
value: (target: any, name: string, value: any) => {
|
|
3
|
+
Object.defineProperty(target, name, {
|
|
4
|
+
value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true
|
|
7
|
+
});
|
|
8
|
+
return value;
|
|
9
|
+
},
|
|
10
|
+
get: (target: any, name: string, get: Function) => {
|
|
11
|
+
Object.defineProperty(target, name, {
|
|
12
|
+
get: get as any,
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true
|
|
15
|
+
});
|
|
16
|
+
return get.call(target);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Page from "../Page.js";
|
|
2
|
+
import { prepareSymbol } from "../decorators/Prepare.js";
|
|
3
|
+
|
|
4
|
+
export default class Executor {
|
|
5
|
+
|
|
6
|
+
public static async run(c: Page) {
|
|
7
|
+
let ps = c.constructor[prepareSymbol];
|
|
8
|
+
if (ps) {
|
|
9
|
+
for (const iterator of ps) {
|
|
10
|
+
await iterator();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return c.run();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
package/src/core/RouteTree.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { readdirSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
import Page from "../Page.js";
|
|
4
|
-
import SessionUser from "./SessionUser.js";
|
|
5
4
|
import { IRouteCheck, isPage } from "../Page.js";
|
|
6
5
|
import { pathToFileURL } from "url";
|
|
7
6
|
import Content, { IPageResult } from "../Content.js";
|
|
7
|
+
import { prepareSymbol } from "../decorators/Prepare.js";
|
|
8
8
|
|
|
9
9
|
export interface IRouteHandler {
|
|
10
10
|
get?: Promise<typeof Page>;
|
|
@@ -113,12 +113,16 @@ export default class RouteTree {
|
|
|
113
113
|
if (pageClass[isPage]) {
|
|
114
114
|
return pageClass as typeof Page;
|
|
115
115
|
}
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
const c = class extends Page {
|
|
117
|
+
|
|
118
|
+
[prepareSymbol] = pageClass[prepareSymbol];
|
|
119
|
+
|
|
120
|
+
async run() {
|
|
118
121
|
const r = await pageClass.call(this);
|
|
119
122
|
return Content.create(r);
|
|
120
123
|
}
|
|
121
124
|
}
|
|
125
|
+
return c;
|
|
122
126
|
})();
|
|
123
127
|
|
|
124
128
|
(this.handler ??= {})[name] = promise;
|
package/src/core/SessionUser.ts
CHANGED
|
@@ -14,27 +14,37 @@ export default class SessionUser {
|
|
|
14
14
|
/**
|
|
15
15
|
* SessionID saved in database for current session.
|
|
16
16
|
*/
|
|
17
|
-
sessionID: number
|
|
17
|
+
get sessionID(): number | null {
|
|
18
|
+
throw new Error("Please call Authorize first");
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* UserID
|
|
21
23
|
*/
|
|
22
|
-
userID
|
|
24
|
+
get userID(): number | null {
|
|
25
|
+
throw new Error("Please call Authorize first");
|
|
26
|
+
}
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
29
|
* Logged in user name
|
|
26
30
|
*/
|
|
27
|
-
userName
|
|
31
|
+
get userName(): string {
|
|
32
|
+
throw new Error("Please call Authorize first");
|
|
33
|
+
}
|
|
28
34
|
|
|
29
35
|
/**
|
|
30
36
|
* Application Roles, user is associated with.
|
|
31
37
|
*/
|
|
32
|
-
roles
|
|
38
|
+
get roles(): string[] {
|
|
39
|
+
throw new Error("Please call Authorize first");
|
|
40
|
+
}
|
|
33
41
|
|
|
34
42
|
/**
|
|
35
43
|
* Expiry date, after which this session is invalid
|
|
36
44
|
*/
|
|
37
|
-
expiry
|
|
45
|
+
get expiry(): Date {
|
|
46
|
+
throw new Error("Please call Authorize first");
|
|
47
|
+
}
|
|
38
48
|
|
|
39
49
|
/**
|
|
40
50
|
* If set to true, session is no longer valid.
|
|
@@ -49,9 +59,15 @@ export default class SessionUser {
|
|
|
49
59
|
|
|
50
60
|
public resp: WrappedResponse;
|
|
51
61
|
|
|
62
|
+
private isAuthorized = false;
|
|
63
|
+
|
|
52
64
|
@Inject
|
|
53
65
|
protected tokenService: TokenService;
|
|
54
66
|
|
|
67
|
+
public async authorize() {
|
|
68
|
+
this.isAuthorized = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
isInRole(role: roles) {
|
|
56
72
|
return this.roles?.includes(role) ?? false;
|
|
57
73
|
}
|