Skip to content

Commit 0f1d30c

Browse files
authored
Merge pull request #147 from codelitdev/fix-signup
Fixed signing up from app; UI upliftment for billing and landing screen;
2 parents 5ff4165 + c55bcfc commit 0f1d30c

File tree

19 files changed

+553
-307
lines changed

19 files changed

+553
-307
lines changed
Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,7 @@
11
import test, { afterEach, describe, mock } from "node:test";
2-
import { createApikey } from "../../src/apikey/handlers";
3-
import assert from "node:assert";
4-
import queries from "../../src/apikey/queries";
52

63
describe("API key test suite", () => {
74
afterEach(() => {
85
mock.restoreAll();
96
});
10-
11-
test("Create API key throws an error if name is empty", async (t) => {
12-
const req = {
13-
body: {},
14-
};
15-
const res = {
16-
status: () => ({
17-
json: (data: any) => data,
18-
}),
19-
};
20-
const response = await createApikey(req, res, () => {});
21-
assert.strictEqual(response.error, "Name is required");
22-
});
23-
24-
test("Create API succeeds if name is provided.", async (t) => {
25-
const req = {
26-
body: {
27-
name: "Test API",
28-
},
29-
user: {
30-
id: "123",
31-
},
32-
};
33-
const res = {
34-
status: () => ({
35-
json: (data: any) => data,
36-
}),
37-
};
38-
mock.method(queries, "createApiKey").mock.mockImplementation(
39-
async () => ({ key: "123" }),
40-
);
41-
const response = await createApikey(req, res, () => {});
42-
assert.strictEqual(response.key, "123");
43-
});
447
});
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { Constants } from "@medialit/models";
2+
import test, { afterEach, describe, mock } from "node:test";
3+
import { uploadMedia } from "../../src/media/handlers";
4+
import assert from "node:assert";
5+
import { FILE_SIZE_EXCEEDED } from "../../src/config/strings";
6+
import mediaService from "../../src/media/service";
7+
8+
describe("Media handlers", () => {
9+
afterEach(() => {
10+
mock.restoreAll();
11+
});
12+
13+
test("should reject upload if file size exceeds limit for non-subscribed user", async () => {
14+
const req = {
15+
files: {
16+
file: {
17+
size: 100000000, // 100MB
18+
},
19+
},
20+
user: {
21+
id: "123",
22+
subscriptionStatus: Constants.SubscriptionStatus.NOT_SUBSCRIBED,
23+
},
24+
socket: {
25+
setTimeout: () => {},
26+
},
27+
};
28+
29+
const res = {
30+
status: (code: number) => ({
31+
json: (data: any) => ({ code, data }),
32+
}),
33+
};
34+
35+
const response = await uploadMedia(req, res, () => {});
36+
assert.strictEqual(response.code, 400);
37+
assert.ok(response.data.error.includes(FILE_SIZE_EXCEEDED));
38+
});
39+
40+
test("should reject upload if file size exceeds limit for subscribed user", async () => {
41+
const req = {
42+
files: {
43+
file: {
44+
size: 2147483648 + 1, // 2GB + 1 byte
45+
},
46+
},
47+
user: {
48+
id: "123",
49+
subscriptionStatus: Constants.SubscriptionStatus.SUBSCRIBED,
50+
},
51+
socket: {
52+
setTimeout: () => {},
53+
},
54+
};
55+
56+
const res = {
57+
status: (code: number) => ({
58+
json: (data: any) => ({ code, data }),
59+
}),
60+
};
61+
62+
const response = await uploadMedia(req, res, () => {});
63+
assert.strictEqual(response.code, 400);
64+
assert.ok(response.data.error.includes(FILE_SIZE_EXCEEDED));
65+
});
66+
67+
test("should allow larger file upload for subscribed user", async () => {
68+
const req = {
69+
files: {
70+
file: {
71+
size: 100000000, // 100MB - within subscribed limit
72+
},
73+
},
74+
user: {
75+
id: "123",
76+
subscriptionStatus: Constants.SubscriptionStatus.SUBSCRIBED,
77+
},
78+
socket: {
79+
setTimeout: () => {},
80+
},
81+
body: {},
82+
query: {},
83+
};
84+
85+
const res = {
86+
status: (code: number) => ({
87+
json: (data: any) => ({ code, data }),
88+
}),
89+
};
90+
91+
mock.method(mediaService, "upload").mock.mockImplementation(
92+
async () => "test-media-id",
93+
);
94+
95+
mock.method(mediaService, "getMediaDetails").mock.mockImplementation(
96+
async () => ({ id: "test-media-id" }),
97+
);
98+
99+
const response = await uploadMedia(req, res, () => {});
100+
assert.strictEqual(response.code, 200);
101+
});
102+
});

apps/api/src/apikey/queries.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,19 @@ export async function getApiKeyByUserId(
5252
return result;
5353
}
5454

55-
export async function deleteApiKey(
56-
userId: string,
57-
keyId: string,
58-
): Promise<void> {
59-
await ApikeyModel.deleteOne({
60-
key: keyId,
61-
userId,
62-
});
63-
}
55+
// export async function deleteApiKey(
56+
// userId: string,
57+
// keyId: string,
58+
// ): Promise<void> {
59+
// await ApikeyModel.deleteOne({
60+
// key: keyId,
61+
// userId,
62+
// });
63+
// }
6464

6565
export default {
6666
createApiKey,
6767
getApiKeyUsingKeyId,
6868
getApiKeyByUserId,
69-
deleteApiKey,
69+
// deleteApiKey,
7070
};

apps/api/src/config/constants.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ export const appName = process.env.APP_NAME || "MediaLit";
33
export const jwtSecret = process.env.JWT_SECRET || "r@nd0m1e";
44
export const jwtExpire = process.env.JWT_EXPIRES_IN || "1d";
55
export const tempFileDirForUploads = process.env.TEMP_FILE_DIR_FOR_UPLOADS;
6-
export const maxFileUploadSize = process.env.MAX_UPLOAD_SIZE || 2147483648;
6+
export const maxFileUploadSizeSubscribed = process.env
7+
.MAX_UPLOAD_SIZE_SUBSCRIBED
8+
? +process.env.MAX_UPLOAD_SIZE_SUBSCRIBED
9+
: 2147483648;
10+
export const maxFileUploadSizeNotSubscribed = process.env
11+
.MAX_UPLOAD_SIZE_NOT_SUBSCRIBED
12+
? +process.env.MAX_UPLOAD_SIZE_NOT_SUBSCRIBED
13+
: 52428800;
714
export const PRESIGNED_URL_VALIDITY_MINUTES = 5;
815
export const PRESIGNED_URL_LENGTH = 100;
916
export const MEDIA_ID_LENGTH = 40;

apps/api/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ app.set("trust proxy", process.env.ENABLE_TRUST_PROXY === "true");
2020

2121
app.use(express.json());
2222

23+
app.get("/health", (req, res) => {
24+
res.status(200).json({
25+
status: "ok",
26+
uptime: process.uptime(),
27+
});
28+
});
29+
2330
app.use("/settings/media", mediaSettingsRoutes(passport));
2431
app.use("/media/presigned", presignedUrlRoutes);
2532
app.use("/media", mediaRoutes);

apps/api/src/media/handlers.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import Joi from "joi";
2-
import { maxFileUploadSize } from "../config/constants";
2+
import {
3+
maxFileUploadSizeNotSubscribed,
4+
maxFileUploadSizeSubscribed,
5+
} from "../config/constants";
36
import {
47
FILE_IS_REQUIRED,
58
FILE_SIZE_EXCEEDED,
@@ -10,6 +13,7 @@ import logger from "../services/log";
1013
import { Request } from "express";
1114
import mediaService from "./service";
1215
import { getMediaCount as getCount, getTotalSpace } from "./queries";
16+
import { Constants } from "@medialit/models";
1317

1418
function validateUploadOptions(req: Request): Joi.ValidationResult {
1519
const uploadSchema = Joi.object({
@@ -21,6 +25,14 @@ function validateUploadOptions(req: Request): Joi.ValidationResult {
2125
return uploadSchema.validate({ caption, access, group });
2226
}
2327

28+
function getMaxFileUploadSize(req: any): number {
29+
const isSubscribed =
30+
req.user.subscriptionStatus === Constants.SubscriptionStatus.SUBSCRIBED;
31+
return isSubscribed
32+
? maxFileUploadSizeSubscribed
33+
: maxFileUploadSizeNotSubscribed;
34+
}
35+
2436
export async function uploadMedia(
2537
req: any,
2638
res: any,
@@ -32,8 +44,11 @@ export async function uploadMedia(
3244
return res.status(400).json({ error: FILE_IS_REQUIRED });
3345
}
3446

35-
if (req.files.file.size > maxFileUploadSize) {
36-
return res.status(400).json({ error: FILE_SIZE_EXCEEDED });
47+
const allowedFileSize = getMaxFileUploadSize(req);
48+
if (req.files.file.size > allowedFileSize) {
49+
return res.status(400).json({
50+
error: `${FILE_SIZE_EXCEEDED}. Allowed: ${allowedFileSize} bytes`,
51+
});
3752
}
3853

3954
const { error } = validateUploadOptions(req);

apps/api/src/services/s3.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,36 +37,43 @@ export interface PresignedURLParams {
3737
mimetype?: string;
3838
}
3939

40-
const s3Client = new S3Client({
41-
region: cloudRegion,
42-
endpoint: cloudEndpoint,
43-
credentials: {
44-
accessKeyId: cloudKey,
45-
secretAccessKey: cloudSecret,
46-
},
47-
});
40+
let s3Client: S3Client | null = null;
41+
42+
const getS3Client = () => {
43+
if (!s3Client) {
44+
s3Client = new S3Client({
45+
region: cloudRegion,
46+
endpoint: cloudEndpoint,
47+
credentials: {
48+
accessKeyId: cloudKey,
49+
secretAccessKey: cloudSecret,
50+
},
51+
});
52+
}
53+
return s3Client;
54+
};
4855

4956
export const putObject = async (params: UploadParams) => {
5057
const command = new PutObjectCommand(
5158
Object.assign({}, { Bucket: cloudBucket }, params),
5259
);
53-
const response = await s3Client.send(command);
60+
const response = await getS3Client().send(command);
5461
return response;
5562
};
5663

5764
export const deleteObject = async (params: DeleteParams) => {
5865
const command = new DeleteObjectCommand(
5966
Object.assign({}, { Bucket: cloudBucket }, params),
6067
);
61-
const response = await s3Client.send(command);
68+
const response = await getS3Client().send(command);
6269
return response;
6370
};
6471

6572
export const getObjectTagging = async (params: { Key: string }) => {
6673
const command = new GetObjectTaggingCommand(
6774
Object.assign({}, { Bucket: cloudBucket }, params),
6875
);
69-
const response = await s3Client.send(command);
76+
const response = await getS3Client().send(command);
7077
return response;
7178
};
7279

@@ -75,7 +82,7 @@ export const generateSignedUrl = async (key: string): Promise<string> => {
7582
Bucket: cloudBucket,
7683
Key: key,
7784
});
78-
const url = await getS3SignedUrl(s3Client, command);
85+
const url = await getS3SignedUrl(getS3Client(), command);
7986
return url;
8087
};
8188

File renamed without changes.

0 commit comments

Comments
 (0)