@social-mail/social-mail-web-server 1.4.910 → 1.4.911
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/server/model/entities/AppFile.d.ts +1 -0
- package/dist/server/model/entities/AppFile.d.ts.map +1 -1
- package/dist/server/model/entities/AppFile.js +6 -0
- package/dist/server/model/entities/AppFile.js.map +1 -1
- package/dist/server/model/events/AppFileEvents.d.ts.map +1 -1
- package/dist/server/model/events/AppFileEvents.js +16 -9
- package/dist/server/model/events/AppFileEvents.js.map +1 -1
- package/dist/server/seed/ui/seed-ui.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/wwwroot/routes/api/emails/files/get.d.ts +9 -0
- package/dist/wwwroot/routes/api/emails/files/get.d.ts.map +1 -0
- package/dist/wwwroot/routes/api/emails/files/get.js +76 -0
- package/dist/wwwroot/routes/api/emails/files/get.js.map +1 -0
- package/package.json +1 -1
- package/src/server/model/entities/AppFile.ts +12 -0
- package/src/server/model/events/AppFileEvents.ts +13 -8
- package/src/server/seed/ui/seed-ui.ts +1 -1
- package/src/wwwroot/routes/api/emails/files/get.ts +72 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TempFileResult } from "@entity-access/server-pages/dist/Content.js";
|
|
2
|
+
import Page from "@entity-access/server-pages/dist/Page.js";
|
|
3
|
+
export default class extends Page {
|
|
4
|
+
private tfs;
|
|
5
|
+
private cacheService;
|
|
6
|
+
private db;
|
|
7
|
+
run(): Promise<import("@entity-access/server-pages/dist/Content.js").default | TempFileResult>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=get.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/emails/files/get.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAC7E,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAU5D,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,OAAO,CAAC,GAAG,CAAkB;IAG7B,OAAO,CAAC,YAAY,CAAe;IAGnC,OAAO,CAAC,EAAE,CAAoB;IAExB,GAAG;CAgDZ"}
|
|
@@ -0,0 +1,76 @@
|
|
|
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, { ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
11
|
+
import { TempFileResult } from "@entity-access/server-pages/dist/Content.js";
|
|
12
|
+
import Page from "@entity-access/server-pages/dist/Page.js";
|
|
13
|
+
import { Prepare } from "@entity-access/server-pages/dist/decorators/Prepare.js";
|
|
14
|
+
import TimeSpan from "@entity-access/entity-access/dist/types/TimeSpan.js";
|
|
15
|
+
import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
|
|
16
|
+
import CacheService from "../../../../../server/services/cache/CacheService.js";
|
|
17
|
+
import FileConversionService from "../../../../../server/services/convert/FileConversionService.js";
|
|
18
|
+
import ImageConverterService from "../../../../../server/services/image-converter/ImageConverterService.js";
|
|
19
|
+
import TempFileService from "../../../../../server/storage/TempFileService.js";
|
|
20
|
+
let default_1 = class extends Page {
|
|
21
|
+
async run() {
|
|
22
|
+
const type = this.childPath[0];
|
|
23
|
+
// we will not convert as BigInt might have loss of data
|
|
24
|
+
const emailID = this.childPath[1];
|
|
25
|
+
const fileContentID = this.childPath[2];
|
|
26
|
+
if (!await this.db.emails.filtered("read").where({ emailID }, (p) => (x) => x.emailID === p.emailID)
|
|
27
|
+
.some()) {
|
|
28
|
+
return this.notFound(true);
|
|
29
|
+
}
|
|
30
|
+
const af = await this.db.appFiles.where({ emailID, fileContentID }, (p) => (x) => x.emailID === p.emailID
|
|
31
|
+
&& x.fileContentID === p.fileContentID)
|
|
32
|
+
.first();
|
|
33
|
+
this.cacheControl = "public, max-age=2592000, immutable";
|
|
34
|
+
let file = await this.tfs.downloadAppFile(af);
|
|
35
|
+
const key = this.request.path;
|
|
36
|
+
const ttl = TimeSpan.fromDays(30);
|
|
37
|
+
// transform here...
|
|
38
|
+
if (/^(size|jpg|png|webp|gif|face\-circle)\(/i.test(type)) {
|
|
39
|
+
file = await this.cacheService.get({ key, ttl, factory: async () => {
|
|
40
|
+
// resize...
|
|
41
|
+
const ics = ServiceProvider.resolve(this, ImageConverterService);
|
|
42
|
+
return await ics.transform(type, file, this.childPath[this.childPath.length - 1]);
|
|
43
|
+
} });
|
|
44
|
+
}
|
|
45
|
+
else if (/^(pdf|html|webm)$/i.test(type)) {
|
|
46
|
+
file = await this.cacheService.get({ key, ttl, factory: async () => {
|
|
47
|
+
const ics = ServiceProvider.resolve(this, FileConversionService);
|
|
48
|
+
return await ics[type.toLowerCase()](file, this.childPath[this.childPath.length - 1]);
|
|
49
|
+
} });
|
|
50
|
+
}
|
|
51
|
+
return new TempFileResult(file, {
|
|
52
|
+
contentDisposition: type === "download"
|
|
53
|
+
? "attachment"
|
|
54
|
+
: "inline",
|
|
55
|
+
immutable: true,
|
|
56
|
+
etag: false
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
__decorate([
|
|
61
|
+
Inject,
|
|
62
|
+
__metadata("design:type", TempFileService)
|
|
63
|
+
], default_1.prototype, "tfs", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
Inject,
|
|
66
|
+
__metadata("design:type", CacheService)
|
|
67
|
+
], default_1.prototype, "cacheService", void 0);
|
|
68
|
+
__decorate([
|
|
69
|
+
Inject,
|
|
70
|
+
__metadata("design:type", SocialMailContext)
|
|
71
|
+
], default_1.prototype, "db", void 0);
|
|
72
|
+
default_1 = __decorate([
|
|
73
|
+
Prepare.authorize
|
|
74
|
+
], default_1);
|
|
75
|
+
export default default_1;
|
|
76
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/api/emails/files/get.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -23,6 +23,8 @@ import { apiPath } from "../../../common/globalEnv.js";
|
|
|
23
23
|
import type Store from "./Store.js";
|
|
24
24
|
import type { StoreItem, StoreJournal, StoreMediaFile } from "./Store.js";
|
|
25
25
|
import CheckConstraint from "@entity-access/entity-access/dist/decorators/CheckConstraint.js";
|
|
26
|
+
import { ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
27
|
+
import SignerService from "../../services/SignerService.js";
|
|
26
28
|
|
|
27
29
|
const accessTypesEnum = ["create", "read", "write", "delegate"] as const;
|
|
28
30
|
export type fileAccessTypes = typeof accessTypesEnum[number];
|
|
@@ -201,6 +203,9 @@ export default class AppFile {
|
|
|
201
203
|
|
|
202
204
|
public websiteVersions: WebSiteFolderVersion[];
|
|
203
205
|
stores: Store[];
|
|
206
|
+
|
|
207
|
+
signed: string;
|
|
208
|
+
|
|
204
209
|
storeJournals: StoreJournal[];
|
|
205
210
|
storeItems: StoreItem[];
|
|
206
211
|
currentVersionWebSites: WebSiteFolder[];
|
|
@@ -208,6 +213,9 @@ export default class AppFile {
|
|
|
208
213
|
|
|
209
214
|
@ReadOnlyJsonProperty
|
|
210
215
|
public get url() {
|
|
216
|
+
if (this.emailID) {
|
|
217
|
+
return apiPath(`/api/emails/files/view/${this.emailID}/${this.fileContentID}/${this.name}`);
|
|
218
|
+
}
|
|
211
219
|
return apiPath(`/api/files/view/${this.appFileID}/${this.fileContentID}/${this.name}`);
|
|
212
220
|
}
|
|
213
221
|
|
|
@@ -217,6 +225,9 @@ export default class AppFile {
|
|
|
217
225
|
|
|
218
226
|
@ReadOnlyJsonProperty
|
|
219
227
|
public get downloadUrl() {
|
|
228
|
+
if (this.emailID) {
|
|
229
|
+
return apiPath(`/api/emails/files/download/${this.emailID}/${this.fileContentID}/${this.name}`);
|
|
230
|
+
}
|
|
220
231
|
return apiPath(`/api/files/download/${this.appFileID}/${this.fileContentID}/${this.name}`);
|
|
221
232
|
}
|
|
222
233
|
|
|
@@ -225,6 +236,7 @@ export default class AppFile {
|
|
|
225
236
|
}
|
|
226
237
|
|
|
227
238
|
[GraphService.appendToGraph]() {
|
|
239
|
+
|
|
228
240
|
return {
|
|
229
241
|
url: this.url,
|
|
230
242
|
downloadUrl: this.downloadUrl
|
|
@@ -137,15 +137,17 @@ export default class AppFileEvents extends AuthenticatedEvents<AppFile> {
|
|
|
137
137
|
const tmpFolder= `/tmp-${userID}`;
|
|
138
138
|
return query.where({ userID, tmpFolder, readFileAccess }, (p) => (x) => x.creatorID === p.userID
|
|
139
139
|
|| Sql.text.likeAny(x.path, p.readFileAccess)
|
|
140
|
+
|
|
140
141
|
/** Template creator must assign read/write permission separately */
|
|
141
142
|
// || x.templates.some((t) =>
|
|
142
143
|
// t.domain.domainUsers.some((d) => d.userID === p.userID)
|
|
143
144
|
// || t.mailbox.userMailboxes.some((u) => u.userID === p.userID)
|
|
144
145
|
// || t.mailbox.domain.domainUsers.some((u) => u.userID === p.userID))
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
146
|
+
|
|
147
|
+
/** Email Attachment will be downloaded directly */
|
|
148
|
+
// || x.email.mailboxes.some((mb) =>
|
|
149
|
+
// mb.mailbox.userMailboxes.some((um) => um.userID === p.userID)
|
|
150
|
+
// || mb.mailbox.domain.hostedDomain.domainUsers.some((du) => du.userID === p.userID )
|
|
149
151
|
);
|
|
150
152
|
}
|
|
151
153
|
|
|
@@ -162,10 +164,13 @@ export default class AppFileEvents extends AuthenticatedEvents<AppFile> {
|
|
|
162
164
|
const tmpFolder= `/tmp-${userID}`;
|
|
163
165
|
return query.where({ userID, tmpFolder, writeFileAccess }, (p) => (x) => x.creatorID === p.userID
|
|
164
166
|
|| Sql.text.likeAny(x.path, p.writeFileAccess)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
)
|
|
167
|
+
|
|
168
|
+
/** Email Attachments cannot be manipulated anyway */
|
|
169
|
+
|
|
170
|
+
// || x.email.mailboxes.some((mb) =>
|
|
171
|
+
// mb.mailbox.userMailboxes.some((um) => um.userID === p.userID)
|
|
172
|
+
// || mb.mailbox.domain.hostedDomain.domainUsers.some((du) => du.userID === p.userID )
|
|
173
|
+
// )
|
|
169
174
|
);
|
|
170
175
|
}
|
|
171
176
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import Inject, { ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import { TempFileResult } from "@entity-access/server-pages/dist/Content.js";
|
|
3
|
+
import Page from "@entity-access/server-pages/dist/Page.js";
|
|
4
|
+
import { Prepare } from "@entity-access/server-pages/dist/decorators/Prepare.js";
|
|
5
|
+
import TimeSpan from "@entity-access/entity-access/dist/types/TimeSpan.js";
|
|
6
|
+
import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
|
|
7
|
+
import CacheService from "../../../../../server/services/cache/CacheService.js";
|
|
8
|
+
import FileConversionService from "../../../../../server/services/convert/FileConversionService.js";
|
|
9
|
+
import ImageConverterService from "../../../../../server/services/image-converter/ImageConverterService.js";
|
|
10
|
+
import TempFileService from "../../../../../server/storage/TempFileService.js";
|
|
11
|
+
|
|
12
|
+
@Prepare.authorize
|
|
13
|
+
export default class extends Page {
|
|
14
|
+
|
|
15
|
+
@Inject
|
|
16
|
+
private tfs: TempFileService;
|
|
17
|
+
|
|
18
|
+
@Inject
|
|
19
|
+
private cacheService: CacheService;
|
|
20
|
+
|
|
21
|
+
@Inject
|
|
22
|
+
private db: SocialMailContext;
|
|
23
|
+
|
|
24
|
+
async run() {
|
|
25
|
+
|
|
26
|
+
const type = this.childPath[0];
|
|
27
|
+
// we will not convert as BigInt might have loss of data
|
|
28
|
+
const emailID = this.childPath[1] as unknown as number;
|
|
29
|
+
const fileContentID = this.childPath[2] as unknown as number;
|
|
30
|
+
|
|
31
|
+
if(!await this.db.emails.filtered("read").where({ emailID }, (p) => (x) => x.emailID === p.emailID)
|
|
32
|
+
.some()) {
|
|
33
|
+
return this.notFound(true);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const af = await this.db.appFiles.where({ emailID, fileContentID}, (p) => (x) => x.emailID === p.emailID
|
|
37
|
+
&& x.fileContentID === p.fileContentID)
|
|
38
|
+
.first();
|
|
39
|
+
|
|
40
|
+
this.cacheControl = "public, max-age=2592000, immutable";
|
|
41
|
+
let file = await this.tfs.downloadAppFile(af);
|
|
42
|
+
|
|
43
|
+
const key = this.request.path;
|
|
44
|
+
|
|
45
|
+
const ttl = TimeSpan.fromDays(30);
|
|
46
|
+
|
|
47
|
+
// transform here...
|
|
48
|
+
if (/^(size|jpg|png|webp|gif|face\-circle)\(/i.test(type)) {
|
|
49
|
+
file = await this.cacheService.get({ key, ttl, factory: async () => {
|
|
50
|
+
// resize...
|
|
51
|
+
const ics = ServiceProvider.resolve(this, ImageConverterService);
|
|
52
|
+
return await ics.transform(type, file, this.childPath[this.childPath.length-1] );
|
|
53
|
+
} });
|
|
54
|
+
} else if (/^(pdf|html|webm)$/i.test(type)) {
|
|
55
|
+
file = await this.cacheService.get({ key, ttl, factory: async () => {
|
|
56
|
+
const ics = ServiceProvider.resolve(this, FileConversionService);
|
|
57
|
+
return await ics[type.toLowerCase()](file, this.childPath[this.childPath.length-1] );
|
|
58
|
+
} });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return new TempFileResult(
|
|
62
|
+
file,
|
|
63
|
+
{
|
|
64
|
+
contentDisposition: type === "download"
|
|
65
|
+
? "attachment"
|
|
66
|
+
: "inline",
|
|
67
|
+
immutable: true,
|
|
68
|
+
etag: false
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|