Skip to content

Commit

Permalink
Task 10 - backend (#8)
Browse files Browse the repository at this point in the history
* changes

* createRequest function

tried to make createRequest function

* post route

* deletechapter function

* just some slight comments!

* changed chapter model and implemented createchapter and deletechapter

deletechapter doesn't work in postman but createchapter does

* routes

---------

Co-authored-by: michaelfenggg <[email protected]>
Co-authored-by: kygchng <[email protected]>
  • Loading branch information
3 people authored Nov 10, 2024
1 parent 932b115 commit c0e8276
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 15 deletions.
133 changes: 127 additions & 6 deletions server/src/controllers/chapter.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getAllChaptersFromDB,
getChapterById,
deleteChapterByID,
createChapterByID,
} from '../services/chapter.service.ts';
import { IChapter } from '../models/chapter.model.ts';

Expand Down Expand Up @@ -59,19 +60,139 @@ const deleteChapter = async (
next(ApiError.missingFields(['id']));
return;
}
// get chapter email by chapter ID
// get chapter by chapter ID
const chapter: IChapter | null = await getChapterById(id);
if (!chapter) {
next(ApiError.notFound(`Chapter does not exist`));
return;
}
deleteChapterByID(id);

deleteChapterByID(id)
.then(() => res.sendStatus(StatusCode.OK))
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch((e) => {
next(ApiError.internal('Failed to delete chapter.'));
});
};

const createChapter = async (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
const {
city,
state,
isAcceptingRequests,
email,
password,
verified,
verificationToken,
resetPasswordToken,
resetPasswordTokenExpiryDate,
isAdmin,
} = req.body;
if (!city || !(typeof city === 'string')) {
next(ApiError.notFound(`city does not exist or is invalid`));
return;
}
if (!state || !(typeof state === 'string')) {
next(ApiError.notFound(`state does not exist or is invalid`));
return;
}
if (isAcceptingRequests !== true && isAcceptingRequests !== false) {
next(ApiError.notFound(`isAcceptingRequests does not exist or is invalid`));
return;
}
if (!email || !(typeof email === 'string')) {
next(ApiError.notFound(`email does not exist or is invalid`));
return;
}
if (!password || !(typeof password === 'string')) {
next(ApiError.notFound(`password does not exist or is invalid`));
return;
}
if (verified !== true && verified !== false) {
next(ApiError.notFound(`verified does not exist or is invalid`));
return;
}
// not sure if this is right, it was chat gpt'ed lol
if (
verificationToken !== undefined &&
verificationToken !== null &&
typeof verificationToken !== 'string'
) {
next(
ApiError.notFound(
`verificationToken must be a string, null, or undefined`,
),
);
return;
}

if (
resetPasswordToken !== undefined &&
resetPasswordToken !== null &&
typeof resetPasswordToken !== 'string'
) {
next(
ApiError.notFound(
`resetPasswordToken must be a string, null, or undefined`,
),
);
return;
}

if (
resetPasswordTokenExpiryDate !== undefined &&
resetPasswordTokenExpiryDate !== null
) {
try {
// Convert the string to a Date object
req.body.resetPasswordTokenExpiryDate = new Date(
resetPasswordTokenExpiryDate,
);
} catch (e) {
next(
ApiError.notFound(
`resetPasswordTokenExpiryDate must be a valid date string, null, or undefined`,
),
);
return;
}
}
if (isAdmin !== true && isAdmin !== false) {
next(ApiError.notFound(`isAdmin does not exist or is invalid`));
return;
}
try {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const user = await createChapterByID(
city,
state,
isAcceptingRequests,
email,
password,
verified,
verificationToken,
resetPasswordToken,
resetPasswordTokenExpiryDate,
isAdmin,
);
res.sendStatus(StatusCode.CREATED);
}
catch (err) {
next(ApiError.internal('Unable to register user.'));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
// Add better error handling
// console.error('Chapter creation error:', err);
if (err.code === 11000) {
// MongoDB duplicate key error
next(
ApiError.badRequest('A chapter with this city or email already exists'),
);
} else {
next(ApiError.internal(`Unable to register chapter: ${err.message}`));
}
}
};

export { toggleRequest, getAllChapters, deleteChapter };
export { toggleRequest, getAllChapters, deleteChapter, createChapter };
8 changes: 4 additions & 4 deletions server/src/models/chapter.model.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import mongoose from 'mongoose';

const ChapterSchema = new mongoose.Schema({
username: {
city: {
type: String,
required: true,
unique: true,
},
location: {
state: {
type: String,
required: true,
},
Expand Down Expand Up @@ -56,8 +56,8 @@ const ChapterSchema = new mongoose.Schema({

interface IChapter extends mongoose.Document {
_id: string;
username: string;
location: string;
city: string;
state: string;
isAcceptingRequests: boolean;
email: string;
password: string;
Expand Down
4 changes: 2 additions & 2 deletions server/src/routes/birthdayRequest.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ router.put('/updatestatus/:id', isAuthenticated, isAdmin, updateRequestStatus);

router.delete('/deleterequest/:id', isAuthenticated, isAdmin, deleteRequest);

router.post('/createrequest', createRequest);
// isAuthenticated, isAdmin,
router.post('/createrequest', isAuthenticated, isAdmin, createRequest);

export default router;
6 changes: 6 additions & 0 deletions server/src/routes/chapter.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { isAdmin } from '../controllers/admin.middleware.ts';
import {
toggleRequest,
getAllChapters,
createChapter,
deleteChapter,
} from '../controllers/chapter.controller.ts';
import { isAuthenticated } from '../controllers/auth.middleware.ts';
import 'dotenv/config';
Expand All @@ -14,4 +16,8 @@ router.put('/toggleRequests/:id', isAuthenticated, isAdmin, toggleRequest);

router.get('/all', isAuthenticated, isAdmin, getAllChapters);

router.post('/create/', isAuthenticated, isAdmin, createChapter);

router.delete('/delete/:id', isAuthenticated, isAdmin, deleteChapter);

export default router;
1 change: 0 additions & 1 deletion server/src/routes/routers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const prefixToRouterMap: { prefix: string; router: Router }[] = [
prefix: '/api/birthdayrequest',
router: birthdayRequestRouter,
},

];

export default prefixToRouterMap;
52 changes: 50 additions & 2 deletions server/src/services/chapter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,54 @@ const getChapterById = async (id: string) => {
const deleteChapterByID = async (id: string) => {
const chapter = await Chapter.findByIdAndDelete(id).exec();
return chapter;
}
};

/**
* Creates a new chapter in the database.
* @param city - The city the chapter is located in
* @param state - The state the chapter is located in
* @param isAcceptingRequests - Whether the chapter is accepting requests
* @param email - The email of the chapter
* @param password - The password of the chapter
* @param verified - Whether the chapter is verified
* @param verificationToken - The verification token of the chapter
* @param resetPasswordToken - The reset password token of the chapter
* @param resetPasswordTokenExpiryDate - The expiry date of the reset password token
* @param isAdmin - Whether the chapter is an admin
* @returns The created {@link Chapter}
*/
const createChapterByID = async (
city: string,
state: string,
isAcceptingRequests: boolean,
email: string,
password: string,
verified: boolean,
verificationToken: string,
resetPasswordToken: string,
resetPasswordTokenExpiryDate: Date,
isAdmin: boolean,
) => {
const newChapter = new Chapter({
city,
state,
isAcceptingRequests,
email,
password,
verified,
verificationToken,
resetPasswordToken,
resetPasswordTokenExpiryDate,
isAdmin,
});
const returnedChapter = await newChapter.save();
return returnedChapter;
};

export { toggleRequestByID, getAllChaptersFromDB, getChapterById, deleteChapterByID };
export {
toggleRequestByID,
getAllChaptersFromDB,
getChapterById,
deleteChapterByID,
createChapterByID,
};

0 comments on commit c0e8276

Please sign in to comment.