Skip to content

Commit cea970d

Browse files
vince-hzhyrious
andauthored
feat(v2): add temp-photo/upload/{start,finish} endpoints (#728) (#729)
Co-authored-by: hyrious <hyrious@outlook.com>
1 parent 4776c28 commit cea970d

File tree

12 files changed

+246
-0
lines changed

12 files changed

+246
-0
lines changed

config/defaults.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ cloud_storage:
4949
- gif
5050
- mp3
5151
- mp4
52+
temp_photo:
53+
# max single file size: 5M
54+
single_file_size: 5242880
55+
# max files per day per user: 60
56+
total_files: 60
57+
prefix_path: cloud-storage/temp-photo
58+
allow_suffix:
59+
- png
60+
- jpg
61+
- jpeg
5262

5363
user:
5464
avatar:

config/test.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ cloud_storage:
4444
- gif
4545
- mp3
4646
- mp4
47+
temp_photo:
48+
single_file_size: 5242880
49+
total_files: 60
50+
prefix_path: cloud-storage/temp-photo
51+
allow_suffix:
52+
- png
53+
- jpg
54+
- jpeg
4755

4856
user:
4957
avatar:

src/constants/Config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ export const CloudStorage = {
142142
totalSize: config.cloud_storage.total_size,
143143
prefixPath: config.cloud_storage.prefix_path,
144144
allowFileSuffix: config.cloud_storage.allow_file_suffix,
145+
tempPhoto: {
146+
singleFileSize: config.cloud_storage.temp_photo.single_file_size,
147+
totalFiles: config.cloud_storage.temp_photo.total_files,
148+
prefixPath: config.cloud_storage.temp_photo.prefix_path,
149+
allowSuffix: config.cloud_storage.temp_photo.allow_suffix,
150+
},
145151
};
146152

147153
export const StorageService = {

src/plugins/Ajv.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ const avatarSuffix: FormatDefinition<string> = {
4141
},
4242
};
4343

44+
const tempPhotoSuffix: FormatDefinition<string> = {
45+
validate: fileName => {
46+
const suffix = path.extname(fileName).slice(1).toLowerCase();
47+
48+
return CloudStorage.tempPhoto.allowSuffix.includes(suffix);
49+
},
50+
};
51+
4452
const oauthLogoSuffix: FormatDefinition<string> = {
4553
validate: fileName => {
4654
const suffix = path.extname(fileName).slice(1).toLowerCase();
@@ -98,6 +106,7 @@ export const ajvSelfPlugin = (ajv: Ajv): void => {
98106
ajv.addFormat("uuid-v4", uuidV4);
99107
ajv.addFormat("file-suffix", fileSuffix);
100108
ajv.addFormat("avatar-suffix", avatarSuffix);
109+
ajv.addFormat("temp-photo-suffix", tempPhotoSuffix);
101110
ajv.addFormat("oauth-logo-suffix", oauthLogoSuffix);
102111
ajv.addFormat("url", url);
103112
ajv.addFormat("https", https);

src/utils/ParseConfig.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ type Config = {
6666
total_size: number;
6767
prefix_path: string;
6868
allow_file_suffix: string[];
69+
temp_photo: {
70+
single_file_size: number;
71+
total_files: number;
72+
prefix_path: string;
73+
allow_suffix: string[];
74+
};
6975
};
7076
user: {
7177
avatar: {

src/utils/Redis.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export const RedisKey = {
99
agoraRTMUserToken: (userUUID: string): string => `agora:rtm:userUUID:${userUUID}`,
1010
cloudStorageFileInfo: (userUUID: string, fileUUID: string): string =>
1111
`cloudStorage:${userUUID}:${fileUUID}`,
12+
cloudStorageTempPhotoInfo: (userUUID: string, fileUUID: string): string =>
13+
`cloudStorage:tempPhoto:${userUUID}:${fileUUID}`,
1214
userAvatarFileInfo: (userUUID: string, fileUUID: string): string =>
1315
`user:avatar:${userUUID}:${fileUUID}`,
1416
roomInviteCode: (inviteCode: string): string => `room:invite:${inviteCode}`,

src/v2/controllers/routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { developerOAuthRouters } from "./developer/routes";
44
import { applicationRouters } from "./application/routes";
55
import { roomRouters } from "./room/routes";
66
import { oauthRouters } from "./auth2/routes";
7+
import { tempPhotoRouters } from "./temp-photo/routes";
78

89
export const v2Routes = [
910
userRouters,
@@ -12,4 +13,5 @@ export const v2Routes = [
1213
applicationRouters,
1314
roomRouters,
1415
oauthRouters,
16+
tempPhotoRouters,
1517
];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Server } from "../../../utils/registryRoutersV2";
2+
import { tempPhotoUploadStart, tempPhotoUploadStartSchema } from "./upload/start";
3+
import { tempPhotoUploadFinish, tempPhotoUploadFinishSchema } from "./upload/finish";
4+
5+
export const tempPhotoRouters = (server: Server): void => {
6+
server.post("temp-photo/upload/start", tempPhotoUploadStart, {
7+
schema: tempPhotoUploadStartSchema,
8+
});
9+
10+
server.post("temp-photo/upload/finish", tempPhotoUploadFinish, {
11+
schema: tempPhotoUploadFinishSchema,
12+
});
13+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Type } from "@sinclair/typebox";
2+
import { FastifyRequestTypebox, Response } from "../../../../types/Server";
3+
import { successJSON } from "../../internal/utils/response-json";
4+
import { CloudStorageUploadService } from "../../../services/cloud-storage/upload";
5+
6+
export const tempPhotoUploadFinishSchema = {
7+
body: Type.Object(
8+
{
9+
fileUUID: Type.String({
10+
format: "uuid-v4",
11+
}),
12+
},
13+
{
14+
additionalProperties: false,
15+
},
16+
),
17+
};
18+
19+
export const tempPhotoUploadFinish = async (
20+
req: FastifyRequestTypebox<typeof tempPhotoUploadFinishSchema>,
21+
): Promise<Response> => {
22+
const cloudStorageUploadSVC = new CloudStorageUploadService(
23+
req.ids,
24+
req.DBTransaction,
25+
req.userUUID,
26+
);
27+
28+
await cloudStorageUploadSVC.tempPhotoFinish({
29+
fileUUID: req.body.fileUUID,
30+
});
31+
32+
return successJSON({});
33+
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Static, Type } from "@sinclair/typebox";
2+
import { CloudStorage } from "../../../../constants/Config";
3+
import { FastifyRequestTypebox, Response } from "../../../../types/Server";
4+
import { successJSON } from "../../internal/utils/response-json";
5+
import { CloudStorageUploadService } from "../../../services/cloud-storage/upload";
6+
import { uploadStartReturnSchema } from "../../../services/cloud-storage/upload.schema";
7+
import { useOnceService } from "../../../service-locator";
8+
9+
export const tempPhotoUploadStartSchema = {
10+
body: Type.Object(
11+
{
12+
fileName: Type.String({
13+
minLength: 3,
14+
maxLength: 128,
15+
format: "temp-photo-suffix",
16+
}),
17+
fileSize: Type.Integer({
18+
maximum: CloudStorage.tempPhoto.singleFileSize,
19+
minimum: 1,
20+
}),
21+
},
22+
{
23+
additionalProperties: false,
24+
},
25+
),
26+
};
27+
28+
export const tempPhotoUploadStart = async (
29+
req: FastifyRequestTypebox<typeof tempPhotoUploadStartSchema>,
30+
): Promise<Response<Static<typeof uploadStartReturnSchema>>> => {
31+
const complianceText = useOnceService("complianceText", req.ids);
32+
await complianceText.assertTextNormal(req.body.fileName);
33+
34+
const cloudStorageUploadSVC = new CloudStorageUploadService(
35+
req.ids,
36+
req.DBTransaction,
37+
req.userUUID,
38+
);
39+
40+
const result = await cloudStorageUploadSVC.tempPhotoStart({
41+
fileName: req.body.fileName,
42+
fileSize: req.body.fileSize,
43+
});
44+
45+
return successJSON(result);
46+
};

0 commit comments

Comments
 (0)