Skip to content

Commit

Permalink
refactor: CRUD is now in user service only
Browse files Browse the repository at this point in the history
- Many issues this is related to:
- #13
- #32 , partially, still testing.
- #29 & #17
  • Loading branch information
G0maa committed Jan 25, 2023
1 parent 674a31c commit 576c72f
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 98 deletions.
18 changes: 12 additions & 6 deletions src/controllers/student.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-misused-promises */
import express, { Request, Response } from 'express';
import { getStudent, getStudents } from '../services/student.service';
import { createUser, deleteUser, updateUser } from '../services/user.service';
import {
createUser,
deleteUser,
getUser,
getUsers,
updateUser,
} from '../services/user.service';
import {
setAuthorizedRoles,
isAuthenticated,
Expand All @@ -19,17 +24,18 @@ import { ZUserDetailsQuery } from '../validator/userDetails.validator';

const studentRouter = express.Router();

// GET, GET:id, POST, DELETE, PUT
studentRouter.get(
'/',
setAuthorizedRoles([ZRole.enum.Admin]),
isAuthenticated,
async (req, res) => {
// Can this look better? To-Do
const searchQueryUser = ZUserQuery.parse(req.query);
const searchQueryUserDetails = ZUserDetailsQuery.parse(req.body);
const searchQueryUserDetails = ZUserDetailsQuery.parse(req.query);
const searchQueryStudent = ZStudentQuery.parse(req.query);

const allStudents = await getStudents(
const allStudents = await getUsers(
'Student',
searchQueryUser,
searchQueryUserDetails,
searchQueryStudent
Expand All @@ -40,7 +46,7 @@ studentRouter.get(

studentRouter.get('/:id', isAuthenticated, async (req, res) => {
const zUuid = ZUuid.parse(req.params.id);
const student = await getStudent(zUuid);
const student = await getUser(zUuid, 'Student');
return res.status(200).json(student).end();
});

Expand Down
22 changes: 18 additions & 4 deletions src/controllers/teacher.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-misused-promises */
import express, { Request, Response } from 'express';
import { getTeacher, getTeachers } from '../services/teacher.service';
import { createUser, deleteUser, updateUser } from '../services/user.service';
import {
createUser,
deleteUser,
getUser,
getUsers,
updateUser,
} from '../services/user.service';
import {
setAuthorizedRoles,
isAuthenticated,
Expand All @@ -15,6 +20,7 @@ import {
ZTeacherQuery,
} from '../validator/teacher.validator';
import { ZUserQuery } from '../validator/user.validator';
import { ZUserDetailsQuery } from '../validator/userDetails.validator';

const teacherRouter = express.Router();

Expand All @@ -24,17 +30,25 @@ teacherRouter.get(
setAuthorizedRoles([ZRole.enum.Admin]),
isAuthenticated,
async (req, res) => {
// Route validation for this will be redundant,
// as client can't send objects in a req.query nor should it.
const searchQueryUser = ZUserQuery.parse(req.query);
const searchQueryUserDetails = ZUserDetailsQuery.parse(req.query);
const searchQueryTeacher = ZTeacherQuery.parse(req.query);

const query = await getTeachers(searchQueryUser, searchQueryTeacher);
const query = await getUsers(
'Teacher',
searchQueryUser,
searchQueryUserDetails,
searchQueryTeacher
);
return res.status(200).json(query).end();
}
);

teacherRouter.get('/:id', isAuthenticated, async (req, res) => {
const zUuid = ZUuid.parse(req.params.id);
const query = await getTeacher(zUuid);
const query = await getUser(zUuid, 'Teacher');
return res.status(200).json(query).end();
});

Expand Down
34 changes: 0 additions & 34 deletions src/services/student.service.ts

This file was deleted.

28 changes: 0 additions & 28 deletions src/services/teacher.service.ts

This file was deleted.

45 changes: 40 additions & 5 deletions src/services/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
import { Student, Teacher, User, Admin } from '../models';
import UserDetails from '../models/userDetails';
import { Role, ZUuid } from '../validator/general.validator';
import { ZStudentPost, ZStudentPut } from '../validator/student.validator';
import { ZTeacherPost, ZTeacherPut } from '../validator/teacher.validator';
import { ZUserPost, ZUserPut } from '../validator/user.validator';
import {
ZStudentPost,
ZStudentPut,
ZStudentQuery,
} from '../validator/student.validator';
import {
ZTeacherPost,
ZTeacherPut,
ZTeacherQuery,
} from '../validator/teacher.validator';
import { ZUserPost, ZUserPut, ZUserQuery } from '../validator/user.validator';
import {
ZUserDetailsPost,
ZUserDetailsPut,
ZUserDetailsQuery,
} from '../validator/userDetails.validator';

const roleModels = { Student, Teacher, Admin };

const getUsers = async (
role: Role,
userQuery: ZUserQuery,
userDetailsQuery: ZUserDetailsQuery,
roleQuery: ZStudentQuery | ZTeacherQuery
) => {
const query = await User.findAll({
include: [
{ model: UserDetails, where: { ...userDetailsQuery } },
{ model: roleModels[role], where: roleQuery },
],
where: { role, ...userQuery },
});
return query;
};

const getUser = async (userId: ZUuid, role: Role) => {
const query = await User.findOne({
include: [{ model: UserDetails }, { model: roleModels[role] }],
where: { id: userId },
});
return query;
};

// Testing this out
// Validators DOES NOT set role attribute by themselves.
const createUser = async (
zUser: ZUserPost['body']['user'],
zUserDetails: ZUserDetailsPost['body']['userDetails'],
Expand Down Expand Up @@ -62,12 +96,13 @@ const updateUser = async (
await userDetails.save();
await roleObject.save();

return { user, userDetails, [roleName]: roleObject };
// ...user, trying to make the response body somewhat consistent.
return { ...user, userDetails, [roleName]: roleObject };
};

// Validation???
const deleteUser = async (id: ZUuid, role: Role) => {
await User.destroy({ where: { id, role } });
};

export { createUser, updateUser, deleteUser };
export { getUsers, getUser, createUser, updateUser, deleteUser };
15 changes: 9 additions & 6 deletions src/tests/student.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ describe('CRUD of Student', () => {
.set('Cookie', [sessionId])
.expect(200);

expect(get.body.user.role).toMatch('Student');
expect(get.body.user.username).toMatch('S');
expect(get.body.role).toMatch('Student');
expect(get.body.username).toMatch('S');
});

test('POST & GET full student', async () => {
Expand All @@ -81,9 +81,11 @@ describe('CRUD of Student', () => {
.set('Cookie', [sessionId])
.expect(200);

expect(newStudent.body.parentName).toEqual(fullStudent.student.parentName);
expect(newStudent.body.user.email).toEqual(fullStudent.user.email);
expect(newStudent.body.user.userDetails.bloodGroup).toEqual(
expect(newStudent.body.student.parentName).toEqual(
fullStudent.student.parentName
);
expect(newStudent.body.email).toEqual(fullStudent.user.email);
expect(newStudent.body.userDetails.bloodGroup).toEqual(
fullStudent.userDetails.bloodGroup
);
});
Expand All @@ -102,7 +104,8 @@ describe('CRUD of Student', () => {
.set('Cookie', [sessionId])
.expect(200);

expect(res2.body.classId).toEqual(classId);
console.log('res2', res2.body);
expect(res2.body.student.classId).toEqual(classId);
});

test('Fails when adding a Student with a non-existent Class', async () => {
Expand Down
12 changes: 7 additions & 5 deletions src/tests/teacher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ describe('CRUD of Teacher', () => {
.set('Cookie', [sessionId])
.expect(200);

expect(get.body.user.role).toEqual('Teacher');
expect(get.body.user.username).toMatch('T');
expect(get.body.role).toEqual('Teacher');
expect(get.body.username).toMatch('T');
});

test('POST & GET full teacher', async () => {
Expand All @@ -76,9 +76,11 @@ describe('CRUD of Teacher', () => {
.set('Cookie', [sessionId])
.expect(200);

expect(newTeacher.body.department).toEqual(fullTeacher.teacher.department);
expect(newTeacher.body.user.email).toEqual(fullTeacher.user.email);
expect(newTeacher.body.user.userDetails.bloodGroup).toEqual(
expect(newTeacher.body.teacher.department).toEqual(
fullTeacher.teacher.department
);
expect(newTeacher.body.email).toEqual(fullTeacher.user.email);
expect(newTeacher.body.userDetails.bloodGroup).toEqual(
fullTeacher.userDetails.bloodGroup
);
});
Expand Down
12 changes: 8 additions & 4 deletions src/utils/init.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs';
import { Admin, Student, Teacher, User } from '../models';
import UserDetails from '../models/userDetails';
import { ZRole } from '../validator/general.validator';
import { hashPassword } from './helpers';

Expand All @@ -14,18 +15,19 @@ const init = async () => {
const hashedPassword = await hashPassword(password);

// this is solely for the purpose of testing if the user has a hashed password.
// also #bug, isReset logic is illogical, if true => user can & should reset,
// also To-Do, isReset logic is illogical, if true => user can & should reset,
await Admin.create(
{
user: {
username: 'A0001',
password: hashedPassword,
role: ZRole.Enum.Admin,
isReset: true,
userDetails: {},
},
},
{
include: User,
include: [{ model: User, include: [{ model: UserDetails }] }],
}
);

Expand All @@ -37,10 +39,11 @@ const init = async () => {
password,
role: ZRole.enum.Student,
studyYear: '1',
userDetails: {},
},
},
{
include: User,
include: [{ model: User, include: [{ model: UserDetails }] }],
}
);

Expand All @@ -50,10 +53,11 @@ const init = async () => {
username: 'T0001',
password,
role: ZRole.enum.Teacher,
userDetails: {},
},
},
{
include: User,
include: [{ model: User, include: [{ model: UserDetails }] }],
}
);

Expand Down
5 changes: 2 additions & 3 deletions src/validator/teacher.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ export const ZTeacher = z
education: z.string().max(64),
})
.partial();
export type ZTeacher = z.infer<typeof ZTeacher>;

export const ZTeacherQuery = ZTeacher.extend({
department: ZTeacher.shape.department.transform((attribute) =>
ToLikeQuery(attribute)
),
}).partial();
export type ZTeacherQuery = z.infer<typeof ZTeacherQuery>;

export const ZTeacherPost = z.object({
body: ZUserPost.shape.body
Expand All @@ -34,7 +36,4 @@ export const ZTeacherPut = z.object({
teacher: ZTeacher.omit({ userId: true }).required(),
}),
});

export type ZTeacherPut = z.infer<typeof ZTeacherPut>;
export type ZTeacherQuery = z.infer<typeof ZTeacherQuery>;
export type ZTeacher = z.infer<typeof ZTeacher>;
5 changes: 2 additions & 3 deletions src/validator/userDetails.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const ZUserDetails = z
address: z.string().max(64),
})
.partial();
export type ZUserDetails = z.infer<typeof ZUserDetails>;

export const ZUserDetailsQuery = ZUserDetails.extend({
firstName: ZUserDetails.shape.firstName.transform((attribute) =>
Expand All @@ -24,6 +25,7 @@ export const ZUserDetailsQuery = ZUserDetails.extend({
ToLikeQuery(attribute)
),
}).partial();
export type ZUserDetailsQuery = z.infer<typeof ZUserDetailsQuery>;

export const ZUserDetailsPost = z.object({
body: z.object({
Expand All @@ -40,7 +42,4 @@ export const ZUserDetailsPut = z.object({
userDetails: ZUserDetails.required().omit({ serial: true }),
}),
});

export type ZUserDetailsPut = z.infer<typeof ZUserDetailsPut>;
export type ZUserDetailsQuery = z.infer<typeof ZUserDetailsQuery>;
export type ZUserDetails = z.infer<typeof ZUserDetails>;

0 comments on commit 576c72f

Please sign in to comment.