Skip to content

Commit

Permalink
Add controlllers test files
Browse files Browse the repository at this point in the history
  • Loading branch information
n1klaus committed May 22, 2023
1 parent 486b93c commit eec5743
Show file tree
Hide file tree
Showing 22 changed files with 1,144 additions and 94 deletions.
1 change: 1 addition & 0 deletions backend/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
*.config.js
*.config.ts
node_modules/
dist/
4 changes: 2 additions & 2 deletions backend/babel.config.cjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module.exports = {
presets: [
[
'@babel/preset-typescript',
"@babel/preset-typescript",
{
targets: {
node: 'current',
node: "current",
},
},
],
Expand Down
7 changes: 5 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@
"@types/fluent-ffmpeg": "^2.1.21",
"@types/jsonwebtoken": "^9.0.1",
"@types/mime-types": "^2.1.1",
"@types/mocha": "^10.0.1",
"@types/multer": "^1.4.7",
"@types/node": "^18.11.18",
"@types/qs": "^6.9.7",
"@types/sinon": "^10.0.15",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.1",
"@typescript-eslint/parser": "^5.59.1",
Expand All @@ -55,14 +57,14 @@
"nodemon": "^2.0.22",
"prettier": "^2.8.8",
"semistandard": "^16.0.1",
"sinon": "^15.0.3",
"sinon": "^15.1.0",
"ts-node-dev": "^2.0.0",
"typescript": "^4.9.5"
},
"dependencies": {
"@types/morgan": "^1.9.4",
"@aws-sdk/client-s3": "^3.327.0",
"@aws-sdk/lib-storage": "^3.312.0",
"@types/morgan": "^1.9.4",
"aws-sdk": "^2.1359.0",
"axios": "^1.2.2",
"bcryptjs": "^2.4.3",
Expand All @@ -79,6 +81,7 @@
"mime-type": "^4.0.0",
"mongoose": "^7.0.3",
"multer": "^1.4.5-lts.1",
"node-mocks-http": "^1.12.2",
"qs": "^6.11.0",
"redis": "^4.6.5",
"uuid": "^9.0.0",
Expand Down
21 changes: 10 additions & 11 deletions backend/src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function exclude<User, Key extends keyof User>(
return modifiedUser;
}

const DEFAULT_AVATAR = process.env.DEFAULT_AVATAR as unknown as string;
const DEFAULT_AVATAR = process.env.DEFAULT_AVATAR as string;

class AuthController {
static async registerHandler(
Expand Down Expand Up @@ -162,11 +162,10 @@ class AuthController {
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(req.body.password, salt);
user.password = hash;
user.save();
await user.save();

const TOKEN_EXPIRES_IN = process.env
.TOKEN_EXPIRES_IN as unknown as number;
const TOKEN_SECRET = process.env.JWT_SECRET as unknown as string;
const TOKEN_EXPIRES_IN = Number(process.env.TOKEN_EXPIRES_IN);
const TOKEN_SECRET = process.env.JWT_SECRET as string;
const token = jwt.sign({ sub: user.id }, TOKEN_SECRET, {
expiresIn: `${TOKEN_EXPIRES_IN}m`,
});
Expand All @@ -185,8 +184,7 @@ class AuthController {
}

static async googleOauthHandler(req: Request, res: Response) {
const FRONTEND_ENDPOINT = process.env
.FRONTEND_ENDPOINT as unknown as string;
const FRONTEND_ENDPOINT = process.env.FRONTEND_ENDPOINT as string;

try {
const code = req.query.code as string;
Expand All @@ -203,7 +201,9 @@ class AuthController {

const {
// eslint-disable-next-line @typescript-eslint/naming-convention
verified_email, email, picture,
verified_email,
email,
picture,
} = await getGoogleUser({
id_token,
access_token,
Expand Down Expand Up @@ -249,9 +249,8 @@ class AuthController {
await user.save();
}

const TOKEN_EXPIRES_IN = process.env
.TOKEN_EXPIRES_IN as unknown as number;
const TOKEN_SECRET = process.env.JWT_SECRET as unknown as string;
const TOKEN_EXPIRES_IN = Number(process.env.TOKEN_EXPIRES_IN);
const TOKEN_SECRET = process.env.JWT_SECRET as string;
const token = jwt.sign({ sub: user.id }, TOKEN_SECRET, {
expiresIn: `${TOKEN_EXPIRES_IN}m`,
});
Expand Down
3 changes: 1 addition & 2 deletions backend/src/controllers/channel.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import Video from '../models/video.model';
import { ChannelModel as Channel } from '../models/channel.model';
import createError from '../error';

// const DEFAULT_AVATAR = process.env.DEFAULT_AVATAR as unknown as string;
const DEFAULT_THUMBNAIL = process.env.DEFAULT_THUMBNAIL as unknown as string;
const DEFAULT_THUMBNAIL = process.env.DEFAULT_THUMBNAIL as string;

class ChannelController {
static async createChannel(req: Request, resp: Response, next: NextFunction) {
Expand Down
2 changes: 1 addition & 1 deletion backend/src/controllers/comment.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class CommentController {
const video = await Video.findById(req.params.id);
if (userId === comment?.userId || userId === video?.userId) {
await Comment.findByIdAndDelete(req.params.id);
return resp.status(204).json('The comment has been deleted.');
return resp.status(204).send('The comment has been deleted.');
}
return next(createError(403, 'You can only delete your comment!'));
} catch (err) {
Expand Down
9 changes: 5 additions & 4 deletions backend/src/controllers/download.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ const s3: S3 = new S3(s3Config);

class DownloadController {
static async downloadVideo(req: Request, resp: Response, next: NextFunction) {
const video = await Video.findById(req.params.id);
if (!video) {
return next(createError(404, 'Video not found!'));
}
try {
const video = await Video.findById(req.params.id);
if (!video) {
return next(createError(404, 'Video not found!'));
}

// Get Video Metadata from AWS S3 Bucket
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Expand Down
18 changes: 10 additions & 8 deletions backend/src/controllers/stream.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable no-bitwise */
/* eslint-disable consistent-return */
import os from 'os';
import { NextFunction, Request, Response } from 'express';
import { S3, GetObjectCommand } from '@aws-sdk/client-s3';
import ffmpeg from 'fluent-ffmpeg';
Expand All @@ -11,14 +12,14 @@ import createError from '../error';

config();

const s3: S3 = new S3(s3Config);
// Set the path to the ffmpeg binary
// Set the path to the ffmpeg binary based on the operating system
const ffmpegPath = os.platform() === 'win32'
? 'C:\\ProgramData\\chocolatey\\bin\\ffmpeg.exe'
: '/usr/bin/ffmpeg';

// linux
// ffmpeg.setFfmpegPath('/usr/bin/ffmpeg');
ffmpeg.setFfmpegPath(ffmpegPath);

// Windows
ffmpeg.setFfmpegPath('C:\\ProgramData\\chocolatey\\bin\\ffmpeg.exe');
const s3: S3 = new S3(s3Config);

class StreamingController {
static async getStream(req: Request, resp: Response, next: NextFunction) {
Expand All @@ -39,7 +40,8 @@ class StreamingController {
resp.set('Content-Type', 'video/mp4');
resp.set('Transfer-Encoding', 'chunked');

let totalTime: number;
let totalTime = 0; // Initialize totalTime

// Stream the video
ffmpeg(stream)
// set the size
Expand Down Expand Up @@ -74,7 +76,7 @@ class StreamingController {

// AND HERE IS THE CALCULATION
const percent = (time / totalTime) * 100;
console.log(`Processing: ${percent >= 0 ? (0 | percent) : 0}% done`);
console.log(`Processing: ${percent >= 0 ? 0 | percent : 0}% done`);
})
.pipe(resp, { end: true });
} catch (e) {
Expand Down
100 changes: 53 additions & 47 deletions backend/src/controllers/upload.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,68 @@ const s3: S3 = new S3(s3Config);
const storage = multer.memoryStorage();
const upload = multer({ storage }).single('video');

const DEFAULT_THUMBNAIL = process.env.DEFAULT_THUMBNAIL as string;

class UploadController {
static async uploadVideo(req: Request, resp: Response, next: NextFunction) {
const userId = String(resp.locals.user._id);
const user = await User.findById(userId);
if (!user) {
return next(createError(401, 'User not found!'));
}
const channel = await Channel.findById(req.params.id);
if (!channel) {
return next(createError(401, 'Channel not found!'));
}
try {
const userId = String(resp.locals.user._id);
const user = await User.findById(userId);
if (!user) {
return next(createError(401, 'User not found!'));
}
const channel = await Channel.findById(req.params.id);
if (!channel) {
return next(createError(401, 'Channel not found!'));
}

// Create a unique ID for the video
const videoUUID = randomUUID();

// Call multer middleware to get the video file
upload(req, resp, async (err: any) => {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
console.error(err);
return next(createError(400, 'Error uploading video file!'));
}
if (err) {
// An unknown error occurred when uploading.
console.error(err);
return next(createError(500, 'Failed to upload video file!'));
}
await new Promise<any>((resolve, reject) => {
upload(req, resp, async (err: any) => {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
console.error(err);
reject(createError(400, 'Error uploading video file!'));
}
if (err) {
// An unknown error occurred when uploading.
console.error(err);
reject(createError(500, 'Failed to upload video file!'));
}

// Create a temporary path to store the video
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: `${videoUUID}.mp4`,
Body: req?.file?.buffer,
};
// Upload the video to AWS S3 Bucket
const data = await new Upload({
client: s3,
params,
}).done();
// Save the video metadata to MongoDB
const video = new Video({
userId,
channelId: channel._id,
imgUrl: req.body.imgUrl || process.env.DEFAULT_THUMBNAIL,
title: req.body.title,
filename: `${videoUUID}.mp4`,
description: req.body.description || videoUUID,
videoUrl: (data as any)?.Location,
...req.body,
});
// Create a temporary path to store the video
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: `${videoUUID}.mp4`,
Body: req?.file?.buffer,
};
// Upload the video to AWS S3 Bucket
const data = await new Upload({
client: s3,
params,
}).done();
// Save the video metadata to MongoDB
const video = new Video({
userId,
channelId: channel._id,
imgUrl: req.body.imgUrl || DEFAULT_THUMBNAIL,
title: req.body.title,
filename: `${videoUUID}.mp4`,
description: req.body.description || videoUUID,
videoUrl: (data as any)?.Location,
...req.body,
});

await video.save();
channel.videos.push(video._id.toString());
await channel.save();

await video.save();
channel.videos.push(video._id.toString());
await channel.save();
// Send the response to the client
return resp.status(200).json(video);
// Send the response to the client
return resolve(resp.status(200).json(video));
});
});
} catch (e) {
console.error(e);
Expand Down
2 changes: 1 addition & 1 deletion backend/src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UserController {
return res.status(200).json({
status: 'success',
data: {
user: exclude(user, ['subcriptions', 'history']),
user: exclude(user, ['subscriptions', 'history']),
},
});
} catch (err: any) {
Expand Down
6 changes: 2 additions & 4 deletions backend/src/controllers/video.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class VideoController {
}
const video = await Video.findById(req.params.id);
if (!video) {
console.error('Video was not found!!!');
return next(createError(404, 'Video not found'));
}
const updatedVideo = await Video.findByIdAndUpdate(
Expand All @@ -20,7 +19,7 @@ class VideoController {
},
{ new: true },
);
if (!updatedVideo?.isModified) {
if (!updatedVideo || !updatedVideo?.isModified) {
return next(createError(404, 'Video not found'));
}
return resp.status(200).json(updatedVideo);
Expand All @@ -33,7 +32,6 @@ class VideoController {
}
const video = await Video.findById(req.params.id);
if (!video) {
console.error('Video was not found!!!');
return next(createError(404, 'Video not found'));
}
const updatedVideo = await Video.findByIdAndUpdate(
Expand All @@ -43,7 +41,7 @@ class VideoController {
},
{ new: true },
);
if (!updatedVideo?.isModified) {
if (!updatedVideo || !updatedVideo?.isModified) {
return next(createError(404, 'Video not found'));
}
return resp.status(200).json(updatedVideo);
Expand Down
6 changes: 1 addition & 5 deletions backend/src/middleware/requireLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { NextFunction, Request, Response } from 'express';

// Read from the local response object to get the stored user json data
// for endpoints that require a logged in user
const requireLogin = (
req: Request,
resp: Response,
next: NextFunction,
) => {
const requireLogin = (req: Request, resp: Response, next: NextFunction) => {
try {
const { user } = resp.locals;
if (!user) {
Expand Down
8 changes: 1 addition & 7 deletions backend/src/middleware/validate.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { NextFunction, Request, Response } from 'express';
import { AnyZodObject, ZodError } from 'zod';

const validate = (
schema: AnyZodObject,
) => (
req: Request,
res: Response,
next: NextFunction,
) => {
const validate = (schema: AnyZodObject) => (req: Request, res: Response, next: NextFunction) => {
try {
schema.parse({
params: req.params,
Expand Down
Loading

0 comments on commit eec5743

Please sign in to comment.