@entity-access/server-pages 1.0.43 → 1.1.3

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.
Files changed (60) hide show
  1. package/dist/Page.d.ts +6 -13
  2. package/dist/Page.d.ts.map +1 -1
  3. package/dist/Page.js +10 -44
  4. package/dist/Page.js.map +1 -1
  5. package/dist/ServerPages.d.ts.map +1 -1
  6. package/dist/ServerPages.js +14 -2
  7. package/dist/ServerPages.js.map +1 -1
  8. package/dist/core/CacheProperty.d.ts +5 -0
  9. package/dist/core/CacheProperty.d.ts.map +1 -0
  10. package/dist/core/CacheProperty.js +19 -0
  11. package/dist/core/CacheProperty.js.map +1 -0
  12. package/dist/core/Executor.d.ts +5 -0
  13. package/dist/core/Executor.d.ts.map +1 -0
  14. package/dist/core/Executor.js +13 -0
  15. package/dist/core/Executor.js.map +1 -0
  16. package/dist/core/RouteTree.d.ts.map +1 -1
  17. package/dist/core/RouteTree.js +15 -6
  18. package/dist/core/RouteTree.js.map +1 -1
  19. package/dist/core/SessionUser.d.ts +7 -5
  20. package/dist/core/SessionUser.d.ts.map +1 -1
  21. package/dist/core/SessionUser.js +36 -0
  22. package/dist/core/SessionUser.js.map +1 -1
  23. package/dist/core/Wrapped.d.ts +14 -16
  24. package/dist/core/Wrapped.d.ts.map +1 -1
  25. package/dist/core/Wrapped.js +157 -234
  26. package/dist/core/Wrapped.js.map +1 -1
  27. package/dist/decorators/Prepare.d.ts +14 -0
  28. package/dist/decorators/Prepare.d.ts.map +1 -0
  29. package/dist/decorators/Prepare.js +111 -0
  30. package/dist/decorators/Prepare.js.map +1 -0
  31. package/dist/routes/api/entity/index.d.ts.map +1 -1
  32. package/dist/routes/api/entity/index.js +9 -3
  33. package/dist/routes/api/entity/index.js.map +1 -1
  34. package/dist/routes/api/entity/model/get.d.ts.map +1 -1
  35. package/dist/routes/api/entity/model/get.js.map +1 -1
  36. package/dist/routes/api/entity/query/get.d.ts.map +1 -1
  37. package/dist/routes/api/entity/query/get.js +9 -3
  38. package/dist/routes/api/entity/query/get.js.map +1 -1
  39. package/dist/services/CookieService.d.ts.map +1 -1
  40. package/dist/services/CookieService.js +8 -0
  41. package/dist/services/CookieService.js.map +1 -1
  42. package/dist/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +1 -1
  44. package/src/Page.tsx +11 -53
  45. package/src/ServerPages.ts +14 -2
  46. package/src/core/CacheProperty.ts +18 -0
  47. package/src/core/Executor.ts +16 -0
  48. package/src/core/RouteTree.ts +7 -2
  49. package/src/core/SessionUser.ts +21 -5
  50. package/src/core/Wrapped.ts +215 -269
  51. package/src/decorators/Prepare.ts +132 -0
  52. package/src/routes/api/entity/index.tsx +4 -1
  53. package/src/routes/api/entity/model/get.tsx +1 -1
  54. package/src/routes/api/entity/query/get.ts +4 -1
  55. package/src/services/CookieService.ts +9 -1
  56. package/dist/decorators/Authorize.d.ts +0 -2
  57. package/dist/decorators/Authorize.d.ts.map +0 -1
  58. package/dist/decorators/Authorize.js +0 -3
  59. package/dist/decorators/Authorize.js.map +0 -1
  60. package/src/decorators/Authorize.ts +0 -3
@@ -0,0 +1,132 @@
1
+ import busboy from "busboy";
2
+ import { Writable } from "node:stream";
3
+ import Page from "../Page.js";
4
+ import TempFolder from "../core/TempFolder.js";
5
+ import { LocalFile } from "../core/LocalFile.js";
6
+
7
+ export const prepareSymbol = Symbol("Parse");
8
+
9
+
10
+ export interface IFormData {
11
+ fields: { [key: string]: string};
12
+ files: LocalFile[];
13
+ }
14
+
15
+ const parseJsonBody = (page?): any => {
16
+
17
+ if (!page) {
18
+ return (target) => parseJsonBody(target);
19
+ }
20
+
21
+ if (!(page instanceof Page)) {
22
+ ((page as any)[prepareSymbol] ??= []).push(parseJsonBody);
23
+ return;
24
+ }
25
+
26
+ if (page.body) {
27
+ return;
28
+ }
29
+
30
+ return (async () => {
31
+
32
+ try {
33
+ let buffer = null as Buffer;
34
+ let encoding = page.request.headers["content-encoding"] ?? "utf-8";
35
+ const contentType = page.request.headers["content-type"];
36
+ if (!/\/json/i.test(contentType)) {
37
+ return {};
38
+ }
39
+ await new Promise<void>((resolve, reject) => {
40
+ page.request.pipe(new Writable({
41
+ write(chunk, enc, callback) {
42
+ encoding ||= enc;
43
+ let b = typeof chunk === "string"
44
+ ? Buffer.from(chunk)
45
+ : chunk as Buffer;
46
+ buffer = buffer
47
+ ? Buffer.concat([buffer, b])
48
+ : b;
49
+ callback();
50
+ },
51
+ final(callback) {
52
+ resolve();
53
+ callback();
54
+ },
55
+ }), { end: true });
56
+ });
57
+ const text = buffer.toString(encoding as any);
58
+ (page as any).body = (page.request as any).body = JSON.parse(text);
59
+ } catch (error) {
60
+ page.reportError(error);
61
+ (page as any).body = (page.request as any).body = {};
62
+ }
63
+ })();
64
+ };
65
+
66
+ const authorize = (page?): any => {
67
+ if (!page) {
68
+ return (target) => authorize(target);
69
+ }
70
+
71
+ if (!(page instanceof Page)) {
72
+ ((page as any)[prepareSymbol] ??= []).push(authorize);
73
+ return;
74
+ }
75
+
76
+ return page.sessionUser.authorize();
77
+ };
78
+
79
+ const parseForm = (page?): any => {
80
+ if (!page) {
81
+ return (target) => parseForm(target);
82
+ }
83
+
84
+ if (!(page instanceof Page)) {
85
+ ((page as any)[prepareSymbol] ??= []).push(parseForm);
86
+ return;
87
+ }
88
+
89
+ return (async () => {
90
+ const req = page.request;
91
+
92
+ let tempFolder: TempFolder;
93
+ const result: IFormData = {
94
+ fields: {},
95
+ files: []
96
+ };
97
+ try {
98
+ const bb = busboy({ headers: req.headers, defParamCharset: "utf8" });
99
+ const tasks = [];
100
+ await new Promise((resolve, reject) => {
101
+
102
+ bb.on("field", (name, value) => {
103
+ result.fields[name] = value;
104
+ });
105
+
106
+ bb.on("file", (name, file, info) => {
107
+ if (!tempFolder) {
108
+ tempFolder = new TempFolder();
109
+ req.disposables.push(tempFolder);
110
+ }
111
+ const tf = tempFolder.get(info.filename, info.mimeType);
112
+ tasks.push(tf.writeAll(file).then(() => {
113
+ result.files.push(tf);
114
+ }));
115
+ });
116
+ bb.on("error", reject);
117
+ bb.on("close", resolve);
118
+ req.pipe(bb);
119
+ });
120
+ await Promise.all(tasks);
121
+ } catch (error) {
122
+ page.reportError(error);
123
+ }
124
+ (page as any).form = (req as any).form = result;
125
+ })();
126
+ };
127
+
128
+ export const Prepare = {
129
+ parseJsonBody,
130
+ authorize,
131
+ parseForm
132
+ };
@@ -5,9 +5,12 @@ import SchemaRegistry from "@entity-access/entity-access/dist/decorators/SchemaR
5
5
  import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
6
6
  import Page, { IRouteCheck } from "../../../Page.js";
7
7
  import GraphService from "../../../services/GraphService.js";
8
+ import { Prepare } from "../../../decorators/Prepare.js";
8
9
 
9
10
  const added = Symbol("added");
10
11
 
12
+ @Prepare.authorize
13
+ @Prepare.parseJsonBody
11
14
  export default class extends Page {
12
15
 
13
16
  static canHandle(pageContext: IRouteCheck): boolean {
@@ -22,7 +25,7 @@ export default class extends Page {
22
25
  this.db.verifyFilters = true;
23
26
  this.db.raiseEvents = true;
24
27
 
25
- const body = await this.asyncJsonBody;
28
+ const body = this.body;
26
29
 
27
30
  if (/delete/i.test(this.method)) {
28
31
  return this.delete(body);
@@ -2,6 +2,7 @@ import Inject from "@entity-access/entity-access/dist/di/di.js";
2
2
  import EntityContext from "@entity-access/entity-access/dist/model/EntityContext.js";
3
3
  import Page from "../../../../Page.js";
4
4
  import ModelService from "../../../../services/ModelService.js";
5
+ import { Prepare } from "../../../../decorators/Prepare.js";
5
6
 
6
7
  export default class extends Page {
7
8
 
@@ -9,7 +10,6 @@ export default class extends Page {
9
10
  db: EntityContext;
10
11
 
11
12
  all() {
12
-
13
13
  return this.json(ModelService.getModel(this.db), 4);
14
14
  }
15
15
 
@@ -2,7 +2,10 @@ import Inject from "@entity-access/entity-access/dist/di/di.js";
2
2
  import EntityContext from "@entity-access/entity-access/dist/model/EntityContext.js";
3
3
  import Page from "../../../../Page.js";
4
4
  import EntityAccessServer from "../../../../services/EntityAccessServer.js";
5
+ import { Prepare } from "../../../../decorators/Prepare.js";
5
6
 
7
+ @Prepare.authorize
8
+ @Prepare.parseJsonBody
6
9
  export default class extends Page {
7
10
 
8
11
  @Inject
@@ -13,7 +16,7 @@ export default class extends Page {
13
16
  return this.json(await EntityAccessServer.query(this.db, {
14
17
  entity,
15
18
  ... this.query,
16
- ... await this.asyncJsonBody
19
+ ... this.body
17
20
  }));
18
21
  }
19
22
 
@@ -67,12 +67,20 @@ export default class CookieService {
67
67
 
68
68
  async createSessionUserFromCookie(cookie: string, ip: string) {
69
69
  const user = ServiceProvider.resolve(this, SessionUser);
70
+ const ua = user as any;
71
+ ua.isAuthorized = true;
72
+ ua.authorize = () => null;
73
+ ua.sessionID = null;
74
+ ua.userID = null;
75
+ ua.userName = null;
76
+ ua.roles = [];
77
+ ua.expiry = null;
70
78
  try {
71
79
  user.ipAddress = ip;
72
80
  if (cookie) {
73
81
  const userInfo = await this.getVerifiedUser(cookie);
74
82
  if (userInfo?.sessionID) {
75
- user.sessionID = userInfo.sessionID;
83
+ (user as any).sessionID = userInfo.sessionID;
76
84
  }
77
85
  if (userInfo?.userID) {
78
86
  user[tagForCache] = userInfo;
@@ -1,2 +0,0 @@
1
- export declare function Authorize(): void;
2
- //# sourceMappingURL=Authorize.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Authorize.d.ts","sourceRoot":"","sources":["../../src/decorators/Authorize.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,SAExB"}
@@ -1,3 +0,0 @@
1
- export function Authorize() {
2
- }
3
- //# sourceMappingURL=Authorize.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Authorize.js","sourceRoot":"","sources":["../../src/decorators/Authorize.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;AAEzB,CAAC"}
@@ -1,3 +0,0 @@
1
- export function Authorize() {
2
-
3
- }