@social-mail/social-mail-web-server 1.4.882 → 1.4.883

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 (43) hide show
  1. package/content/video/all.webm +0 -0
  2. package/dist/server/model/entities/WebSiteFolder.d.ts +2 -0
  3. package/dist/server/model/entities/WebSiteFolder.d.ts.map +1 -1
  4. package/dist/server/model/entities/WebSiteFolder.js +8 -0
  5. package/dist/server/model/entities/WebSiteFolder.js.map +1 -1
  6. package/dist/server/services/captcha/CaptchaService.d.ts +16 -0
  7. package/dist/server/services/captcha/CaptchaService.d.ts.map +1 -0
  8. package/dist/server/services/captcha/CaptchaService.js +107 -0
  9. package/dist/server/services/captcha/CaptchaService.js.map +1 -0
  10. package/dist/server/services/captcha/IVerification.d.ts +8 -0
  11. package/dist/server/services/captcha/IVerification.d.ts.map +1 -0
  12. package/dist/server/services/captcha/IVerification.js +2 -0
  13. package/dist/server/services/captcha/IVerification.js.map +1 -0
  14. package/dist/server/services/files/WebSiteService.d.ts +1 -0
  15. package/dist/server/services/files/WebSiteService.d.ts.map +1 -1
  16. package/dist/server/services/files/WebSiteService.js +58 -35
  17. package/dist/server/services/files/WebSiteService.js.map +1 -1
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/wwwroot/routes/api/site/contact/post.d.ts +13 -0
  20. package/dist/wwwroot/routes/api/site/contact/post.d.ts.map +1 -0
  21. package/dist/wwwroot/routes/api/site/contact/post.js +95 -0
  22. package/dist/wwwroot/routes/api/site/contact/post.js.map +1 -0
  23. package/dist/wwwroot/routes/api/users/captcha/index.d.ts +9 -0
  24. package/dist/wwwroot/routes/api/users/captcha/index.d.ts.map +1 -0
  25. package/dist/wwwroot/routes/api/users/captcha/index.js +37 -0
  26. package/dist/wwwroot/routes/api/users/captcha/index.js.map +1 -0
  27. package/dist/wwwroot/routes/api/users/captcha/post.d.ts +8 -0
  28. package/dist/wwwroot/routes/api/users/captcha/post.d.ts.map +1 -0
  29. package/dist/wwwroot/routes/api/users/captcha/post.js +23 -0
  30. package/dist/wwwroot/routes/api/users/captcha/post.js.map +1 -0
  31. package/dist/wwwroot/routes/api/users/captcha/put.d.ts +8 -0
  32. package/dist/wwwroot/routes/api/users/captcha/put.d.ts.map +1 -0
  33. package/dist/wwwroot/routes/api/users/captcha/put.js +40 -0
  34. package/dist/wwwroot/routes/api/users/captcha/put.js.map +1 -0
  35. package/package.json +1 -1
  36. package/src/server/model/entities/WebSiteFolder.ts +6 -0
  37. package/src/server/services/captcha/CaptchaService.ts +109 -0
  38. package/src/server/services/captcha/IVerification.ts +7 -0
  39. package/src/server/services/files/WebSiteService.ts +9 -0
  40. package/src/wwwroot/routes/api/site/contact/post.tsx +92 -0
  41. package/src/wwwroot/routes/api/users/captcha/index.tsx +32 -0
  42. package/src/wwwroot/routes/api/users/captcha/post.tsx +18 -0
  43. package/src/wwwroot/routes/api/users/captcha/put.tsx +32 -0
@@ -0,0 +1,13 @@
1
+ import Page from "@entity-access/server-pages/dist/Page.js";
2
+ import WebSiteService from "../../../../../server/services/files/WebSiteService.js";
3
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
4
+ import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
5
+ import EmailAddressService from "../../../../../server/services/EmailAddressService.js";
6
+ export default class extends Page {
7
+ websiteService: WebSiteService;
8
+ captchaService: CaptchaService;
9
+ db: SocialMailContext;
10
+ emailAddressService: EmailAddressService;
11
+ run(): Promise<import("@entity-access/server-pages/dist/Content.js").default>;
12
+ }
13
+ //# sourceMappingURL=post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/site/contact/post.tsx"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,cAAc,MAAM,wDAAwD,CAAC;AACpF,OAAO,cAAc,MAAM,0DAA0D,CAAC;AACtF,OAAO,iBAAiB,MAAM,kDAAkD,CAAC;AACjF,OAAO,mBAAmB,MAAM,uDAAuD,CAAC;AAIxF,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,cAAc,EAAE,cAAc,CAAC;IAG/B,cAAc,EAAE,cAAc,CAAC;IAG/B,EAAE,EAAE,iBAAiB,CAAC;IAGtB,mBAAmB,EAAE,mBAAmB,CAAC;IAEnC,GAAG;CAmEZ"}
@@ -0,0 +1,95 @@
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 Inject from "@entity-access/entity-access/dist/di/di.js";
11
+ import { Prepare } from "@entity-access/server-pages/dist/decorators/Prepare.js";
12
+ import Page from "@entity-access/server-pages/dist/Page.js";
13
+ import WebSiteService from "../../../../../server/services/files/WebSiteService.js";
14
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
15
+ import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
16
+ import EmailAddressService from "../../../../../server/services/EmailAddressService.js";
17
+ import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
18
+ let default_1 = class extends Page {
19
+ async run() {
20
+ const model = this.body;
21
+ await this.captchaService.verify(model.captcha);
22
+ const website = await this.websiteService.getWebSiteFolder(this.request.hostName?.toLocaleLowerCase());
23
+ const senderID = await this.emailAddressService.getId(website.fromEmail);
24
+ const to = await this.emailAddressService.getId(website.supportEmail);
25
+ const dateCreated = DateTime.now;
26
+ const dateUpdated = dateCreated;
27
+ const dateSent = dateCreated;
28
+ this.db.verifyFilters = false;
29
+ this.db.raiseEvents = true;
30
+ this.db.emails.add({
31
+ senderID,
32
+ recipients: [
33
+ this.db.emailRecipients.add({
34
+ emailAddressID: to
35
+ })
36
+ ],
37
+ dateCreated,
38
+ dateUpdated,
39
+ dateSent,
40
+ status: "scheduled",
41
+ subject: `Website Enquiry: ` + model.subject,
42
+ htmlBody: `<div>
43
+ You have received following enquiry on the website,
44
+ <table>
45
+ <tr>
46
+ <td>Name</td>
47
+ <td>${model.name}</td>
48
+ </tr>
49
+ <tr>
50
+ <td>Email</td>
51
+ <td>${model.email}</td>
52
+ </tr>
53
+ <tr>
54
+ <td>Phone</td>
55
+ <td>${model.phone}</td>
56
+ </tr>
57
+ <tr>
58
+ <td colspan="2">Notes</td>
59
+ </tr>
60
+ <tr>
61
+ <td colspan="2">
62
+ ${model.description}
63
+ </td>
64
+ </tr>
65
+ </table>
66
+ </div>`
67
+ });
68
+ await this.db.saveChanges();
69
+ await this.captchaService.delete(model.captcha);
70
+ return this.json({
71
+ sent: true
72
+ });
73
+ }
74
+ };
75
+ __decorate([
76
+ Inject,
77
+ __metadata("design:type", WebSiteService)
78
+ ], default_1.prototype, "websiteService", void 0);
79
+ __decorate([
80
+ Inject,
81
+ __metadata("design:type", CaptchaService)
82
+ ], default_1.prototype, "captchaService", void 0);
83
+ __decorate([
84
+ Inject,
85
+ __metadata("design:type", SocialMailContext)
86
+ ], default_1.prototype, "db", void 0);
87
+ __decorate([
88
+ Inject,
89
+ __metadata("design:type", EmailAddressService)
90
+ ], default_1.prototype, "emailAddressService", void 0);
91
+ default_1 = __decorate([
92
+ Prepare.parseJsonBody
93
+ ], default_1);
94
+ export default default_1;
95
+ //# sourceMappingURL=post.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/site/contact/post.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,wDAAwD,CAAC;AACjF,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,cAAc,MAAM,wDAAwD,CAAC;AACpF,OAAO,cAAc,MAAM,0DAA0D,CAAC;AACtF,OAAO,iBAAiB,MAAM,kDAAkD,CAAC;AACjF,OAAO,mBAAmB,MAAM,uDAAuD,CAAC;AACxF,OAAO,QAAQ,MAAM,qDAAqD,CAAC;AAG5D,gBAAA,KAAM,SAAQ,IAAI;IAc7B,KAAK,CAAC,GAAG;QAEL,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QAExB,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEhD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAEvG,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEzE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAEtE,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC;QACjC,MAAM,WAAW,GAAG,WAAW,CAAC;QAChC,MAAM,QAAQ,GAAG,WAAW,CAAC;QAE7B,IAAI,CAAC,EAAE,CAAC,aAAa,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,EAAE,CAAC,WAAW,GAAG,IAAI,CAAC;QAE3B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;YACf,QAAQ;YACR,UAAU,EAAE;gBACR,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC;oBACxB,cAAc,EAAE,EAAE;iBACrB,CAAC;aACL;YACD,WAAW;YACX,WAAW;YACX,QAAQ;YACR,MAAM,EAAE,WAAW;YACnB,OAAO,EAAE,mBAAmB,GAAG,KAAK,CAAC,OAAO;YAC5C,QAAQ,EAAE;;;;;8BAKQ,KAAK,CAAC,IAAI;;;;8BAIV,KAAK,CAAC,KAAK;;;;8BAIX,KAAK,CAAC,KAAK;;;;;;;8BAOX,KAAK,CAAC,WAAW;;;;mBAI5B;SACV,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;QAE5B,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEhD,OAAO,IAAI,CAAC,IAAI,CAAC;YACb,IAAI,EAAE,IAAI;SACb,CAAC,CAAC;IAEP,CAAC;CACJ,CAAA;AA9EG;IADC,MAAM;8BACS,cAAc;iDAAC;AAG/B;IADC,MAAM;8BACS,cAAc;iDAAC;AAG/B;IADC,MAAM;8BACH,iBAAiB;qCAAC;AAGtB;IADC,MAAM;8BACc,mBAAmB;sDAAC;AAZ9B;IADd,OAAO,CAAC,aAAa;aAkFrB"}
@@ -0,0 +1,9 @@
1
+ import Page from "@entity-access/server-pages/dist/Page.js";
2
+ import { TempFileResult } from "@entity-access/server-pages/dist/Content.js";
3
+ import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
4
+ export default class extends Page {
5
+ db: SocialMailContext;
6
+ private captchaService;
7
+ run(): Promise<TempFileResult>;
8
+ }
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/users/captcha/index.tsx"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAE7E,OAAO,iBAAiB,MAAM,kDAAkD,CAAC;AAGjF,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,EAAE,EAAE,iBAAiB,CAAC;IAGtB,OAAO,CAAC,cAAc,CAAiB;IAGjC,GAAG;CAcZ"}
@@ -0,0 +1,37 @@
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
+ /* eslint-disable no-console */
11
+ import Inject from "@entity-access/entity-access/dist/di/di.js";
12
+ import Page from "@entity-access/server-pages/dist/Page.js";
13
+ import { TempFileResult } from "@entity-access/server-pages/dist/Content.js";
14
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
15
+ import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
16
+ export default class default_1 extends Page {
17
+ async run() {
18
+ const [id, accessCode] = this.childPath;
19
+ const { code } = await this.db.verificationTokens.statements.select({}, {
20
+ verificationID: id,
21
+ accessCode
22
+ });
23
+ const file = await this.captchaService.getVideo(code);
24
+ return new TempFileResult(file, {
25
+ contentDisposition: "attachment"
26
+ });
27
+ }
28
+ }
29
+ __decorate([
30
+ Inject,
31
+ __metadata("design:type", SocialMailContext)
32
+ ], default_1.prototype, "db", void 0);
33
+ __decorate([
34
+ Inject,
35
+ __metadata("design:type", CaptchaService)
36
+ ], default_1.prototype, "captchaService", void 0);
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/users/captcha/index.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,+BAA+B;AAC/B,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAC7E,OAAO,cAAc,MAAM,0DAA0D,CAAC;AACtF,OAAO,iBAAiB,MAAM,kDAAkD,CAAC;AAGjF,MAAM,CAAC,OAAO,gBAAO,SAAQ,IAAI;IAS7B,KAAK,CAAC,GAAG;QAEL,MAAM,CAAE,EAAE,EAAE,UAAU,CAAE,GAAG,IAAI,CAAC,SAAkB,CAAC;QAEnD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE;YACpE,cAAc,EAAE,EAAE;YAClB,UAAU;SACb,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,IAAI,cAAc,CAAC,IAAI,EAAE;YAC5B,kBAAkB,EAAE,YAAY;SACnC,CAAC,CAAC;IACP,CAAC;CACJ;AApBG;IADC,MAAM;8BACH,iBAAiB;qCAAC;AAGd;IADP,MAAM;8BACiB,cAAc;iDAAC"}
@@ -0,0 +1,8 @@
1
+ import Page from "@entity-access/server-pages/dist/Page.js";
2
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
3
+ import { IVerification } from "../../../../../server/services/captcha/IVerification.js";
4
+ export default class extends Page<IVerification> {
5
+ captchaService: CaptchaService;
6
+ run(): Promise<import("@entity-access/server-pages/dist/Content.js").default>;
7
+ }
8
+ //# sourceMappingURL=post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/users/captcha/post.tsx"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAE5D,OAAO,cAAc,MAAM,0DAA0D,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,yDAAyD,CAAC;AAExF,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI,CAAC,aAAa,CAAC;IAG5C,cAAc,EAAE,cAAc,CAAC;IAEzB,GAAG;CAOZ"}
@@ -0,0 +1,23 @@
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 Page from "@entity-access/server-pages/dist/Page.js";
11
+ import Inject from "@entity-access/entity-access/dist/di/di.js";
12
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
13
+ export default class default_1 extends Page {
14
+ async run() {
15
+ this.captchaService.verify(this.body);
16
+ return this.json(this.body);
17
+ }
18
+ }
19
+ __decorate([
20
+ Inject,
21
+ __metadata("design:type", CaptchaService)
22
+ ], default_1.prototype, "captchaService", void 0);
23
+ //# sourceMappingURL=post.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/users/captcha/post.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,cAAc,MAAM,0DAA0D,CAAC;AAGtF,MAAM,CAAC,OAAO,gBAAO,SAAQ,IAAmB;IAK5C,KAAK,CAAC,GAAG;QAEL,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhC,CAAC;CAEJ;AATG;IADC,MAAM;8BACS,cAAc;iDAAC"}
@@ -0,0 +1,8 @@
1
+ import Page from "@entity-access/server-pages/dist/Page.js";
2
+ import Content from "@entity-access/server-pages/dist/Content.js";
3
+ export default class extends Page {
4
+ private captchaService;
5
+ private rateLimiterService;
6
+ run(): Promise<Content>;
7
+ }
8
+ //# sourceMappingURL=put.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/users/captcha/put.tsx"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,OAAO,MAAM,6CAA6C,CAAC;AAIlE,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,OAAO,CAAC,cAAc,CAAiB;IAGvC,OAAO,CAAC,kBAAkB,CAAqB;IAEzC,GAAG;CAiBZ"}
@@ -0,0 +1,40 @@
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 Inject from "@entity-access/entity-access/dist/di/di.js";
11
+ import Page from "@entity-access/server-pages/dist/Page.js";
12
+ import Content from "@entity-access/server-pages/dist/Content.js";
13
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
14
+ import RateLimiterService from "../../../../../server/services/rate-limiter/RateLimiterService.js";
15
+ export default class default_1 extends Page {
16
+ async run() {
17
+ const ip = this.request?.remoteIPAddress ?? "";
18
+ const rl = await this.rateLimiterService.acquire(ip, "captcha");
19
+ if (!rl) {
20
+ return Content.create({
21
+ body: "Rate Limited",
22
+ status: 429
23
+ });
24
+ }
25
+ const { id, accessCode } = await this.captchaService.generatePair(ip);
26
+ return this.json({
27
+ id,
28
+ accessCode
29
+ });
30
+ }
31
+ }
32
+ __decorate([
33
+ Inject,
34
+ __metadata("design:type", CaptchaService)
35
+ ], default_1.prototype, "captchaService", void 0);
36
+ __decorate([
37
+ Inject,
38
+ __metadata("design:type", RateLimiterService)
39
+ ], default_1.prototype, "rateLimiterService", void 0);
40
+ //# sourceMappingURL=put.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/users/captcha/put.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,OAAO,MAAM,6CAA6C,CAAC;AAClE,OAAO,cAAc,MAAM,0DAA0D,CAAC;AACtF,OAAO,kBAAkB,MAAM,mEAAmE,CAAC;AAEnG,MAAM,CAAC,OAAO,gBAAO,SAAQ,IAAI;IAQ7B,KAAK,CAAC,GAAG;QAEL,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe,IAAI,EAAE,CAAC;QAC/C,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAChE,IAAI,CAAC,EAAE,EAAE,CAAC;YACN,OAAO,OAAO,CAAC,MAAM,CAAC;gBAClB,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,GAAG;aACd,CAAC,CAAC;QACP,CAAC;QAED,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC,IAAI,CAAC;YACb,EAAE;YACF,UAAU;SACb,CAAC,CAAC;IACP,CAAC;CACJ;AAtBW;IADP,MAAM;8BACiB,cAAc;iDAAC;AAG/B;IADP,MAAM;8BACqB,kBAAkB;qDAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-web-server",
3
- "version": "1.4.882",
3
+ "version": "1.4.883",
4
4
  "description": "## Phase 1",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -49,6 +49,12 @@ export default class WebSiteFolder {
49
49
  @Column({ dataType:"BigInt", default: () => 0})
50
50
  public snapshotStorage: number;
51
51
 
52
+ @Column({ dataType:"Char", length: 200, nullable: true})
53
+ public supportEmail: string;
54
+
55
+ @Column({ dataType:"Char", length: 200, nullable: true})
56
+ public fromEmail: string;
57
+
52
58
  public folder: AppFile;
53
59
 
54
60
  currentVersion: AppFile;
@@ -0,0 +1,109 @@
1
+ import Inject, { RegisterScoped } from "@entity-access/entity-access/dist/di/di.js";
2
+ import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
3
+ import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
4
+ import ensureDir from "../../../common/FileApi.js";
5
+ import { spawnPromise } from "../../../common/spawnPromise.js";
6
+ import TempFileService from "../../storage/TempFileService.js";
7
+ import DiskCacheService from "../cache/DiskCacheService.js";
8
+ import EncryptionService from "../encryption/EncryptionService.js";
9
+ import { IVerification } from "./IVerification.js";
10
+ import SocialMailContext from "../../model/SocialMailContext.js";
11
+ import { randomUUID } from "crypto";
12
+
13
+ const captchaCache = "/cache/captcha";
14
+
15
+ ensureDir(captchaCache);
16
+
17
+ const zero = '0'.charCodeAt(0);
18
+
19
+ const filter = "[0]pad=width=750:height=200:x=0:y=0:color=white[v0];"
20
+ + "[0][1]hstack=inputs=2[i1];"
21
+ + "[i1]pad=width=750:height=200:x=0:y=0:color=white[v1];"
22
+ + "[0][1][2]hstack=inputs=3[i2];"
23
+ + "[i2]pad=width=750:height=200:x=0:y=0:color=white[v2];"
24
+ + "[0][1][2][3]hstack=inputs=4[i3];"
25
+ + "[i3]pad=width=750:height=200:x=0:y=0:color=white[v3];"
26
+ + "[0][1][2][3][4]hstack=inputs=5[i4];"
27
+ + "[i4]pad=width=750:height=200:x=0:y=0:color=white[v4];"
28
+ + "[v0][v1][v2][v3][v4]concat=n=5:v=1,format=yuv420p[v]";
29
+
30
+ @RegisterScoped
31
+ export default class CaptchaService {
32
+
33
+ @Inject
34
+ private diskCache: DiskCacheService;
35
+
36
+ @Inject
37
+ private encryption: EncryptionService;
38
+
39
+ @Inject
40
+ private db: SocialMailContext;
41
+
42
+ @Inject
43
+ private tfs: TempFileService;
44
+
45
+ async verify(v: IVerification) {
46
+ const { id, accessCode, code } = v;
47
+ const vt = await this.db.verificationTokens.statements.select({}, { verificationID: id as any, accessCode, code });
48
+ if (!vt) {
49
+ throw new EntityAccessError(`Invalid code`);
50
+ }
51
+ return true;
52
+ }
53
+
54
+ async delete(v: IVerification) {
55
+ const { id, accessCode, code } = v;
56
+ await this.db.verificationTokens.statements.delete({ verificationID: id as any, accessCode, code });
57
+ return true;
58
+ }
59
+
60
+ async generatePair(ip = "") {
61
+
62
+ const { db } = this;
63
+ let code = DateTime.now.msSinceEpoch.toString();
64
+ code = code.substring(code.length-5);
65
+
66
+ const accessCode = randomUUID();
67
+ const expiry = DateTime.now.addMinutes(15);
68
+
69
+ const v = await db.verificationTokens.statements.insert({
70
+ code,
71
+ accessCode,
72
+ expiry
73
+ });
74
+ return { id: v.verificationID, accessCode };
75
+ }
76
+
77
+ async getVideo(code: string) {
78
+ return this.diskCache.getOrCreate("captcha/" + code + ".gif", (filePath) => this.prepareVideo(code, filePath));
79
+ }
80
+
81
+ async prepareVideo(code: string, saveAs: string) {
82
+
83
+ const tf = await this.tfs.createTempFile(".webm", "code", "video/webm");
84
+
85
+ const input = "/app/content/video/all.webm";
86
+
87
+ await spawnPromise("/ffmpeg/ffmpeg", [
88
+ "-ss", ((code.charCodeAt(0) - zero) * 3.5).toString(), "-t", "3.5", "-i", input,
89
+ "-ss", ((code.charCodeAt(1) - zero) * 3.5).toString(), "-t", "3.5", "-i", input,
90
+ "-ss", ((code.charCodeAt(2) - zero) * 3.5).toString(), "-t", "3.5", "-i", input,
91
+ "-ss", ((code.charCodeAt(3) - zero) * 3.5).toString(), "-t", "3.5", "-i", input,
92
+ "-ss", ((code.charCodeAt(4) - zero) * 3.5).toString(), "-t", "3.5", "-i", input,
93
+ "-filter_complex", filter,
94
+ "-map", "[v]",
95
+ "-y", tf.path
96
+ ], {
97
+ logData: false
98
+ });
99
+
100
+ await spawnPromise("/ffmpeg/ffmpeg", [
101
+ "-i", tf.path,
102
+ "-filter:v", "scale=300:-1",
103
+ "-y", saveAs
104
+ ],{
105
+ logData: false
106
+ });
107
+ }
108
+
109
+ }
@@ -0,0 +1,7 @@
1
+ export interface IVerification {
2
+ smsConfig: any;
3
+ id: string;
4
+ accessCode: string;
5
+ code: string;
6
+ verified?: string;
7
+ }
@@ -28,6 +28,15 @@ export default class WebSiteService {
28
28
  return folder;
29
29
  }
30
30
 
31
+ @cacheFor()
32
+ async getWebSiteFolder(host: string) {
33
+ using scope = globalServices.createScope();
34
+ const db = scope.resolve(SocialMailContext);
35
+ const folder = await db.websiteFolders.where({ host }, (p) => (x) => x.hosts.some((s) => s.host === p.host))
36
+ .first();
37
+ return folder;
38
+ }
39
+
31
40
  async getCurrentSnapshotFolder(host: string) {
32
41
  using scope = globalServices.createScope();
33
42
  const db = scope.resolve(SocialMailContext);
@@ -0,0 +1,92 @@
1
+ import Inject from "@entity-access/entity-access/dist/di/di.js";
2
+ import { Prepare } from "@entity-access/server-pages/dist/decorators/Prepare.js";
3
+ import Page from "@entity-access/server-pages/dist/Page.js";
4
+ import WebSiteService from "../../../../../server/services/files/WebSiteService.js";
5
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
6
+ import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
7
+ import EmailAddressService from "../../../../../server/services/EmailAddressService.js";
8
+ import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
9
+
10
+ @Prepare.parseJsonBody
11
+ export default class extends Page {
12
+
13
+ @Inject
14
+ websiteService: WebSiteService;
15
+
16
+ @Inject
17
+ captchaService: CaptchaService;
18
+
19
+ @Inject
20
+ db: SocialMailContext;
21
+
22
+ @Inject
23
+ emailAddressService: EmailAddressService;
24
+
25
+ async run() {
26
+
27
+ const model = this.body;
28
+
29
+ await this.captchaService.verify(model.captcha);
30
+
31
+ const website = await this.websiteService.getWebSiteFolder(this.request.hostName?.toLocaleLowerCase());
32
+
33
+ const senderID = await this.emailAddressService.getId(website.fromEmail);
34
+
35
+ const to = await this.emailAddressService.getId(website.supportEmail);
36
+
37
+ const dateCreated = DateTime.now;
38
+ const dateUpdated = dateCreated;
39
+ const dateSent = dateCreated;
40
+
41
+ this.db.verifyFilters = false;
42
+ this.db.raiseEvents = true;
43
+
44
+ this.db.emails.add({
45
+ senderID,
46
+ recipients: [
47
+ this.db.emailRecipients.add({
48
+ emailAddressID: to
49
+ })
50
+ ],
51
+ dateCreated,
52
+ dateUpdated,
53
+ dateSent,
54
+ status: "scheduled",
55
+ subject: `Website Enquiry: ` + model.subject,
56
+ htmlBody: `<div>
57
+ You have received following enquiry on the website,
58
+ <table>
59
+ <tr>
60
+ <td>Name</td>
61
+ <td>${model.name}</td>
62
+ </tr>
63
+ <tr>
64
+ <td>Email</td>
65
+ <td>${model.email}</td>
66
+ </tr>
67
+ <tr>
68
+ <td>Phone</td>
69
+ <td>${model.phone}</td>
70
+ </tr>
71
+ <tr>
72
+ <td colspan="2">Notes</td>
73
+ </tr>
74
+ <tr>
75
+ <td colspan="2">
76
+ ${model.description}
77
+ </td>
78
+ </tr>
79
+ </table>
80
+ </div>`
81
+ });
82
+
83
+ await this.db.saveChanges();
84
+
85
+ await this.captchaService.delete(model.captcha);
86
+
87
+ return this.json({
88
+ sent: true
89
+ });
90
+
91
+ }
92
+ }
@@ -0,0 +1,32 @@
1
+ /* eslint-disable no-console */
2
+ import Inject from "@entity-access/entity-access/dist/di/di.js";
3
+ import Page from "@entity-access/server-pages/dist/Page.js";
4
+ import { TempFileResult } from "@entity-access/server-pages/dist/Content.js";
5
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
6
+ import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
7
+
8
+
9
+ export default class extends Page {
10
+
11
+ @Inject
12
+ db: SocialMailContext;
13
+
14
+ @Inject
15
+ private captchaService: CaptchaService;
16
+
17
+
18
+ async run() {
19
+
20
+ const [ id, accessCode ] = this.childPath as any[];
21
+
22
+ const { code } = await this.db.verificationTokens.statements.select({}, {
23
+ verificationID: id,
24
+ accessCode
25
+ });
26
+
27
+ const file = await this.captchaService.getVideo(code);
28
+ return new TempFileResult(file, {
29
+ contentDisposition: "attachment"
30
+ });
31
+ }
32
+ }
@@ -0,0 +1,18 @@
1
+ import Page from "@entity-access/server-pages/dist/Page.js";
2
+ import Inject from "@entity-access/entity-access/dist/di/di.js";
3
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
4
+ import { IVerification } from "../../../../../server/services/captcha/IVerification.js";
5
+
6
+ export default class extends Page<IVerification> {
7
+
8
+ @Inject
9
+ captchaService: CaptchaService;
10
+
11
+ async run() {
12
+
13
+ this.captchaService.verify(this.body);
14
+ return this.json(this.body);
15
+
16
+ }
17
+
18
+ }
@@ -0,0 +1,32 @@
1
+ import Inject from "@entity-access/entity-access/dist/di/di.js";
2
+ import Page from "@entity-access/server-pages/dist/Page.js";
3
+ import Content from "@entity-access/server-pages/dist/Content.js";
4
+ import CaptchaService from "../../../../../server/services/captcha/CaptchaService.js";
5
+ import RateLimiterService from "../../../../../server/services/rate-limiter/RateLimiterService.js";
6
+
7
+ export default class extends Page {
8
+
9
+ @Inject
10
+ private captchaService: CaptchaService;
11
+
12
+ @Inject
13
+ private rateLimiterService: RateLimiterService;
14
+
15
+ async run() {
16
+
17
+ const ip = this.request?.remoteIPAddress ?? "";
18
+ const rl = await this.rateLimiterService.acquire(ip, "captcha");
19
+ if (!rl) {
20
+ return Content.create({
21
+ body: "Rate Limited",
22
+ status: 429
23
+ });
24
+ }
25
+
26
+ const { id, accessCode } = await this.captchaService.generatePair(ip);
27
+ return this.json({
28
+ id,
29
+ accessCode
30
+ });
31
+ }
32
+ }