feat: add, delete student route met user logic + .js in files
This commit is contained in:
		
							parent
							
								
									e0a5596994
								
							
						
					
					
						commit
						ecad27ea4d
					
				
					 29 changed files with 301 additions and 159 deletions
				
			
		|  | @ -16,6 +16,7 @@ import loginRouter from './routes/login.js'; | ||||||
| const app: Express = express(); | const app: Express = express(); | ||||||
| const port: string | number = getNumericEnvVar(EnvVars.Port); | const port: string | number = getNumericEnvVar(EnvVars.Port); | ||||||
| 
 | 
 | ||||||
|  | app.use(express.json()); | ||||||
| 
 | 
 | ||||||
| // TODO Replace with Express routes
 | // TODO Replace with Express routes
 | ||||||
| app.get('/', (_, res: Response) => { | app.get('/', (_, res: Response) => { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { Request, Response } from 'express' | import { Request, Response } from 'express' | ||||||
| import { getAllAssignments, getAssignment } from '../services/assignments'; | import { getAllAssignments, getAssignment } from '../services/assignments.js'; | ||||||
| 
 | 
 | ||||||
| // typescript is annoy with with parameter forwarding from class.ts
 | // typescript is annoy with with parameter forwarding from class.ts
 | ||||||
| interface AssignmentParams { | interface AssignmentParams { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class'; | import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class.js'; | ||||||
| import { ClassDTO } from '../interfaces/classes'; |  | ||||||
| 
 | 
 | ||||||
| export async function getAllClassesHandler( | export async function getAllClassesHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { getAllGroups, getGroup } from '../services/groups'; | import { getAllGroups, getGroup } from '../services/groups.js'; | ||||||
| 
 | 
 | ||||||
| // typescript is annoywith with parameter forwarding from class.ts
 | // typescript is annoywith with parameter forwarding from class.ts
 | ||||||
| interface GroupParams { | interface GroupParams { | ||||||
|  |  | ||||||
|  | @ -1,53 +1,33 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; | import { | ||||||
| import { ClassDTO } from '../interfaces/classes'; |     getStudentClasses, | ||||||
| import { getAllAssignments } from '../services/assignments'; |     getStudentClassIds, | ||||||
|  |     StudentService | ||||||
|  | } from '../services/students.js'; | ||||||
|  | import { ClassDTO } from '../interfaces/classes.js'; | ||||||
|  | import { getAllAssignments } from '../services/assignments.js'; | ||||||
|  | import {createUserHandler, deleteUserHandler, getAllUsersHandler, getUserHandler} from "./users.js"; | ||||||
|  | import { Student } from "../entities/users/student.entity.js"; | ||||||
| 
 | 
 | ||||||
| // TODO: accept arguments (full, ...)
 | // TODO: accept arguments (full, ...)
 | ||||||
| // TODO: endpoints
 | // TODO: endpoints
 | ||||||
| export async function getAllStudentsHandler ( | export async function getAllStudentsHandler (req: Request, res: Response): Promise<void> { | ||||||
|     req: Request, |     await getAllUsersHandler<Student>(req, res, new StudentService()); | ||||||
|     res: Response, |  | ||||||
| ): Promise<void> { |  | ||||||
|     try { |  | ||||||
|         const students = await getAllStudents(); |  | ||||||
| 
 |  | ||||||
|         res.json({ |  | ||||||
|             students: students |  | ||||||
|         }); |  | ||||||
|     } catch (error) { |  | ||||||
|         console.error('Error fetching learning objects:', error); |  | ||||||
|         res.status(500).json({ error: 'Internal server error' }); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getStudentHandler( | export async function getStudentHandler(req: Request, res: Response): Promise<void> { | ||||||
|     req: Request, |     await getUserHandler<Student>(req, res, new StudentService()); | ||||||
|     res: Response, |  | ||||||
| ): Promise<void> { |  | ||||||
|     try { |  | ||||||
|         const username = req.params.id; |  | ||||||
|         const student = await getStudent(username); |  | ||||||
|      |  | ||||||
|         if (!student) { |  | ||||||
|             res.status(404).json({ error: "Student not found" }); |  | ||||||
|             return; |  | ||||||
|         } else { |  | ||||||
|             student.endpoints = { |  | ||||||
|                 classes: `/student/${req.params.id}/classes`, |  | ||||||
|                 questions: `/student/${req.params.id}/submissions`, |  | ||||||
|                 invitations: `/student/${req.params.id}/assignments`, |  | ||||||
|                 groups: `/student/${req.params.id}/groups`, |  | ||||||
|             } |  | ||||||
|             res.json(student); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     } catch (error) { | export async function createStudentHandler(req: Request, res: Response): Promise<void> { | ||||||
|         console.error('Error fetching learning objects:', error); |     await createUserHandler<Student>(req, res, new StudentService(), Student); | ||||||
|         res.status(500).json({ error: 'Internal server error' }); |  | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export async function deleteStudentHandler(req: Request, res: Response): Promise<void> { | ||||||
|  |     await deleteUserHandler<Student>(req, res, new StudentService()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| export async function getStudentClassesHandler ( | export async function getStudentClassesHandler ( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response, |     res: Response, | ||||||
|  | @ -75,6 +55,7 @@ export async function getStudentClassesHandler ( | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // TODO
 | ||||||
| // Might not be fully correct depending on if
 | // Might not be fully correct depending on if
 | ||||||
| // a class has an assignment, that all students
 | // a class has an assignment, that all students
 | ||||||
| // have this assignment.
 | // have this assignment.
 | ||||||
|  | @ -93,3 +74,5 @@ export async function getStudentAssignmentsHandler( | ||||||
|         assignments: assignments |         assignments: assignments | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
							
								
								
									
										106
									
								
								backend/src/controllers/users.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								backend/src/controllers/users.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | ||||||
|  | import { Request, Response } from 'express'; | ||||||
|  | import { UserService } from "../services/users.js"; | ||||||
|  | import {UserDTO} from "../interfaces/user.js"; | ||||||
|  | import {User} from "../entities/users/user.entity.js"; | ||||||
|  | 
 | ||||||
|  | export async function getAllUsersHandler<T extends User>( | ||||||
|  |     req: Request, | ||||||
|  |     res: Response, | ||||||
|  |     service: UserService<T> | ||||||
|  | ):  Promise<void> { | ||||||
|  |     try { | ||||||
|  |         const full = req.query.full === 'true'; | ||||||
|  | 
 | ||||||
|  |         let users: UserDTO[] | string[] = full | ||||||
|  |             ? await service.getAllUsers() | ||||||
|  |             : await service.getAllUserIds(); | ||||||
|  | 
 | ||||||
|  |         if (!users){ | ||||||
|  |             res.status(404).json({ error: `Users not found.` }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         res.status(201).json(users); | ||||||
|  | 
 | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error("❌ Error fetching users:", error); | ||||||
|  |         res.status(500).json({ error: "Internal server error" }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getUserHandler<T extends User>( | ||||||
|  |     req: Request, | ||||||
|  |     res: Response, | ||||||
|  |     service: UserService<T> | ||||||
|  | ):  Promise<void> { | ||||||
|  |     try { | ||||||
|  |         const username = req.params.username as string; | ||||||
|  | 
 | ||||||
|  |         if (!username) { | ||||||
|  |             res.status(400).json({ error: 'Missing required field: username' }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const user = await service.getUserByUsername(username); | ||||||
|  | 
 | ||||||
|  |         if (!user){ | ||||||
|  |             res.status(404).json({ error: `User with username '${username}' not found.` }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         res.status(201).json(user); | ||||||
|  | 
 | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error("❌ Error fetching users:", error); | ||||||
|  |         res.status(500).json({ error: "Internal server error" }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function createUserHandler<T extends User>( | ||||||
|  |     req: Request, | ||||||
|  |     res: Response, | ||||||
|  |     service: UserService<T>, | ||||||
|  |     UserClass: new () => T | ||||||
|  | ) { | ||||||
|  |     try { | ||||||
|  |         console.log("req", req) | ||||||
|  |         const userData = req.body as UserDTO; | ||||||
|  | 
 | ||||||
|  |         if (!userData.username || !userData.firstName || !userData.lastName) { | ||||||
|  |             res.status(400).json({ error: "Missing required fields: username, firstName, lastName" }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const newUser = await service.createUser(userData, UserClass); | ||||||
|  |         res.status(201).json(newUser); | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error("❌ Error creating user:", error); | ||||||
|  |         res.status(500).json({ error: "Internal server error" }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function deleteUserHandler<T extends User> ( | ||||||
|  |     req: Request, | ||||||
|  |     res: Response, | ||||||
|  |     service: UserService<T> | ||||||
|  | ) { | ||||||
|  |     try { | ||||||
|  |         const username = req.params.username; | ||||||
|  | 
 | ||||||
|  |         if (!username) { | ||||||
|  |             res.status(400).json({ error: "Missing required field: username" }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const deletedUser = await service.deleteUser(username); | ||||||
|  |         if (!deletedUser) { | ||||||
|  |             res.status(404).json({ error: `User with username '${username}' not found.` }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         res.status(200).json(deletedUser); | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error("❌ Error deleting user:", error); | ||||||
|  |         res.status(500).json({ error: "Internal server error" }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -59,7 +59,7 @@ function repositoryGetter<T extends AnyEntity, R extends EntityRepository<T>>( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Users */ | /* Users */ | ||||||
| export const getUserRepository = repositoryGetter<User, UserRepository>(User); | export const getUserRepository = repositoryGetter<User, UserRepository<User>>(User); | ||||||
| export const getStudentRepository = repositoryGetter< | export const getStudentRepository = repositoryGetter< | ||||||
|     Student, |     Student, | ||||||
|     StudentRepository |     StudentRepository | ||||||
|  |  | ||||||
|  | @ -1,11 +1,4 @@ | ||||||
| import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; |  | ||||||
| import { Student } from '../../entities/users/student.entity.js'; | import { Student } from '../../entities/users/student.entity.js'; | ||||||
|  | import {UserRepository} from "./user-repository.js"; | ||||||
| 
 | 
 | ||||||
| export class StudentRepository extends DwengoEntityRepository<Student> { | export class StudentRepository extends UserRepository<Student> {} | ||||||
|     public findByUsername(username: string): Promise<Student | null> { |  | ||||||
|         return this.findOne({ username: username }); |  | ||||||
|     } |  | ||||||
|     public deleteByUsername(username: string): Promise<void> { |  | ||||||
|         return this.deleteWhere({ username: username }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,11 +1,4 @@ | ||||||
| import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; |  | ||||||
| import { Teacher } from '../../entities/users/teacher.entity.js'; | import { Teacher } from '../../entities/users/teacher.entity.js'; | ||||||
|  | import {UserRepository} from "./user-repository.js"; | ||||||
| 
 | 
 | ||||||
| export class TeacherRepository extends DwengoEntityRepository<Teacher> { | export class TeacherRepository extends UserRepository<Teacher> {} | ||||||
|     public findByUsername(username: string): Promise<Teacher | null> { |  | ||||||
|         return this.findOne({ username: username }); |  | ||||||
|     } |  | ||||||
|     public deleteByUsername(username: string): Promise<void> { |  | ||||||
|         return this.deleteWhere({ username: username }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | ||||||
| import { User } from '../../entities/users/user.entity.js'; | import { User } from '../../entities/users/user.entity.js'; | ||||||
| 
 | 
 | ||||||
| export class UserRepository extends DwengoEntityRepository<User> { | export class UserRepository<T extends User> extends DwengoEntityRepository<T> { | ||||||
|     public findByUsername(username: string): Promise<User | null> { |     public findByUsername(username: string): Promise<T | null> { | ||||||
|         return this.findOne({ username: username }); |         return this.findOne({ username } as Partial<T>); | ||||||
|     } |     } | ||||||
|     public deleteByUsername(username: string): Promise<void> { |     public deleteByUsername(username: string): Promise<void> { | ||||||
|         return this.deleteWhere({ username: username }); |         return this.deleteWhere({ username } as Partial<T>); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,6 +13,15 @@ import { Attachment } from './attachment.entity.js'; | ||||||
| import { Teacher } from '../users/teacher.entity.js'; | import { Teacher } from '../users/teacher.entity.js'; | ||||||
| import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; | import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; | ||||||
| 
 | 
 | ||||||
|  | @Embeddable() | ||||||
|  | export class ReturnValue { | ||||||
|  |     @Property({ type: 'string' }) | ||||||
|  |     callbackUrl!: string; | ||||||
|  | 
 | ||||||
|  |     @Property({ type: 'json' }) | ||||||
|  |     callbackSchema!: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @Entity({ repository: () => LearningObjectRepository }) | @Entity({ repository: () => LearningObjectRepository }) | ||||||
| export class LearningObject { | export class LearningObject { | ||||||
|     @PrimaryKey({ type: 'string' }) |     @PrimaryKey({ type: 'string' }) | ||||||
|  | @ -88,15 +97,6 @@ export class EducationalGoal { | ||||||
|     id!: string; |     id!: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Embeddable() |  | ||||||
| export class ReturnValue { |  | ||||||
|     @Property({ type: 'string' }) |  | ||||||
|     callbackUrl!: string; |  | ||||||
| 
 |  | ||||||
|     @Property({ type: 'json' }) |  | ||||||
|     callbackSchema!: string; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export enum ContentType { | export enum ContentType { | ||||||
|     Markdown = 'text/markdown', |     Markdown = 'text/markdown', | ||||||
|     Image = 'image/image', |     Image = 'image/image', | ||||||
|  |  | ||||||
|  | @ -11,12 +11,4 @@ export class Student extends User { | ||||||
| 
 | 
 | ||||||
|     @ManyToMany(() => Group) |     @ManyToMany(() => Group) | ||||||
|     groups!: Collection<Group>; |     groups!: Collection<Group>; | ||||||
| 
 |  | ||||||
|     constructor( |  | ||||||
|         public username: string, |  | ||||||
|         public firstName: string, |  | ||||||
|         public lastName: string |  | ||||||
|     ) { |  | ||||||
|         super(); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| import { Assignment } from "../entities/assignments/assignment.entity"; | import { Assignment } from "../entities/assignments/assignment.entity.js"; | ||||||
| import { Class } from "../entities/classes/class.entity"; | import { GroupDTO, mapToGroupDTO } from "./groups.js"; | ||||||
| import { GroupDTO, mapToGroupDTO } from "./groups"; |  | ||||||
| 
 | 
 | ||||||
| export interface AssignmentDTO { | export interface AssignmentDTO { | ||||||
|     id: number, |     id: number, | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { Class } from "../entities/classes/class.entity"; | import { Class } from "../entities/classes/class.entity.js"; | ||||||
| 
 | 
 | ||||||
| export interface ClassDTO { | export interface ClassDTO { | ||||||
|     id: string; |     id: string; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import { Group } from "../entities/assignments/group.entity"; | import { Group } from "../entities/assignments/group.entity.js"; | ||||||
| import { AssignmentDTO, mapToAssignmentDTO } from "./assignments"; | import { AssignmentDTO, mapToAssignmentDTO } from "./assignments.js"; | ||||||
| import { mapToStudentDTO, StudentDTO } from "./students"; | import { mapToStudentDTO, StudentDTO } from "./students.js"; | ||||||
| 
 | 
 | ||||||
| export interface GroupDTO { | export interface GroupDTO { | ||||||
|     assignment: number | AssignmentDTO, |     assignment: number | AssignmentDTO, | ||||||
|  | @ -10,7 +10,7 @@ export interface GroupDTO { | ||||||
| 
 | 
 | ||||||
| export function mapToGroupDTO(group: Group): GroupDTO { | export function mapToGroupDTO(group: Group): GroupDTO { | ||||||
|     return { |     return { | ||||||
|         assignment: mapToAssignmentDTO(group.assignment, group.assignment.within), |         assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within),
 | ||||||
|         groupNumber: group.groupNumber, |         groupNumber: group.groupNumber, | ||||||
|         members: group.members.map(mapToStudentDTO), |         members: group.members.map(mapToStudentDTO), | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { Student } from "../entities/users/student.entity"; | import { Student } from "../entities/users/student.entity.js"; | ||||||
| 
 | 
 | ||||||
| export interface StudentDTO { | export interface StudentDTO { | ||||||
|     id: string; |     id: string; | ||||||
|  | @ -21,3 +21,12 @@ export function mapToStudentDTO(student: Student): StudentDTO { | ||||||
|         lastName: student.lastName, |         lastName: student.lastName, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export function mapToStudent(studentData: StudentDTO): Student { | ||||||
|  |     const student = new Student(); | ||||||
|  |     student.username = studentData.username; | ||||||
|  |     student.firstName = studentData.firstName; | ||||||
|  |     student.lastName = studentData.lastName; | ||||||
|  | 
 | ||||||
|  |     return student; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity"; | import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity.js"; | ||||||
| import { ClassDTO, mapToClassDTO } from "./classes"; | import { ClassDTO, mapToClassDTO } from "./classes.js"; | ||||||
| import { mapToTeacherDTO, TeacherDTO } from "./teacher"; | import { mapToTeacherDTO, TeacherDTO } from "./teacher.js"; | ||||||
| 
 | 
 | ||||||
| export interface TeacherInvitationDTO { | export interface TeacherInvitationDTO { | ||||||
|     sender: string | TeacherDTO, |     sender: string | TeacherDTO, | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { Teacher } from "../entities/users/teacher.entity"; | import { Teacher } from "../entities/users/teacher.entity.js"; | ||||||
| 
 | 
 | ||||||
| export interface TeacherDTO { | export interface TeacherDTO { | ||||||
|     id: string; |     id: string; | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								backend/src/interfaces/user.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								backend/src/interfaces/user.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | import { User } from "../entities/users/user.entity.js"; | ||||||
|  | 
 | ||||||
|  | export interface UserDTO { | ||||||
|  |     id?: string, | ||||||
|  |     username: string; | ||||||
|  |     firstName: string; | ||||||
|  |     lastName: string; | ||||||
|  |     endpoints?: { | ||||||
|  |         self: string; | ||||||
|  |         classes: string; | ||||||
|  |         questions: string; | ||||||
|  |         invitations: string; | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function mapToUserDTO(user: User): UserDTO { | ||||||
|  |     return { | ||||||
|  |         id: user.username, | ||||||
|  |         username: user.username, | ||||||
|  |         firstName: user.firstName, | ||||||
|  |         lastName: user.lastName, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function mapToUser<T extends User>(userData: UserDTO, userInstance: T): T { | ||||||
|  |     userInstance.username = userData.username; | ||||||
|  |     userInstance.firstName = userData.firstName; | ||||||
|  |     userInstance.lastName = userData.lastName; | ||||||
|  |     return userInstance; | ||||||
|  | } | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import express from 'express' | import express from 'express' | ||||||
| import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments'; | import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments.js'; | ||||||
| import groupRouter from './group.js'; | import groupRouter from './group.js'; | ||||||
| 
 | 
 | ||||||
| const router = express.Router({ mergeParams: true }); | const router = express.Router({ mergeParams: true }); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import express from 'express' | import express from 'express' | ||||||
| import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes'; | import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes.js'; | ||||||
| import assignmentRouter from './assignment.js'; | import assignmentRouter from './assignment.js'; | ||||||
| 
 | 
 | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import express from 'express' | import express from 'express' | ||||||
| import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups'; | import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups.js'; | ||||||
| const router = express.Router({ mergeParams: true }); | const router = express.Router({ mergeParams: true }); | ||||||
| 
 | 
 | ||||||
| // root endpoint used to search objects
 | // root endpoint used to search objects
 | ||||||
|  |  | ||||||
|  | @ -1,12 +1,24 @@ | ||||||
| import express from 'express' | import express from 'express' | ||||||
| import { getAllStudentsHandler, getStudentAssignmentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students'; | import { | ||||||
|  |     createStudentHandler, deleteStudentHandler, | ||||||
|  |     getAllStudentsHandler, | ||||||
|  |     getStudentAssignmentsHandler, | ||||||
|  |     getStudentClassesHandler, | ||||||
|  |     getStudentHandler | ||||||
|  | } from '../controllers/students.js'; | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| 
 | 
 | ||||||
| // root endpoint used to search objects
 | // root endpoint used to search objects
 | ||||||
| router.get('/', getAllStudentsHandler); | router.get('/', getAllStudentsHandler); | ||||||
| 
 | 
 | ||||||
|  | router.post('/', createStudentHandler); | ||||||
|  | 
 | ||||||
|  | router.delete('/:username', deleteStudentHandler); | ||||||
|  | 
 | ||||||
| // information about a student's profile
 | // information about a student's profile
 | ||||||
| router.get('/:id', getStudentHandler); | router.get('/:username', getStudentHandler); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| // the list of classes a student is in
 | // the list of classes a student is in
 | ||||||
| router.get('/:id/classes', getStudentClassesHandler); | router.get('/:id/classes', getStudentClassesHandler); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { getAssignmentRepository, getClassRepository } from "../data/repositories"; | import { getAssignmentRepository, getClassRepository } from "../data/repositories.js"; | ||||||
| import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments"; | import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments.js"; | ||||||
| 
 | 
 | ||||||
| export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> { | export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> { | ||||||
|     const classRepository = getClassRepository(); |     const classRepository = getClassRepository(); | ||||||
|  |  | ||||||
|  | @ -1,8 +1,7 @@ | ||||||
| import { getClassRepository, getTeacherInvitationRepository } from "../data/repositories"; | import { getClassRepository, getTeacherInvitationRepository } from "../data/repositories.js"; | ||||||
| import { Class } from "../entities/classes/class.entity"; | import { ClassDTO, mapToClassDTO } from "../interfaces/classes.js"; | ||||||
| import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; | import { mapToStudentDTO, StudentDTO } from "../interfaces/students.js"; | ||||||
| import { mapToStudentDTO, StudentDTO } from "../interfaces/students"; | import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from "../interfaces/teacher-invitation.js"; | ||||||
| import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from "../interfaces/teacher-invitation"; |  | ||||||
| 
 | 
 | ||||||
| export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[]> { | export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[]> { | ||||||
|     const classRepository = getClassRepository(); |     const classRepository = getClassRepository(); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { getAssignmentRepository, getClassRepository, getGroupRepository } from "../data/repositories"; | import { getAssignmentRepository, getClassRepository, getGroupRepository } from "../data/repositories.js"; | ||||||
| import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from "../interfaces/groups"; | import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from "../interfaces/groups.js"; | ||||||
| 
 | 
 | ||||||
| export async function getGroup( | export async function getGroup( | ||||||
|     classId: string, |     classId: string, | ||||||
|  |  | ||||||
|  | @ -1,26 +1,13 @@ | ||||||
| import { getClassRepository, getStudentRepository } from "../data/repositories"; | import { getClassRepository, getStudentRepository } from "../data/repositories.js"; | ||||||
| import { Class } from "../entities/classes/class.entity"; | import { Class } from "../entities/classes/class.entity.js"; | ||||||
| import { Student } from "../entities/users/student.entity"; | import { Student } from "../entities/users/student.entity.js"; | ||||||
| import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; | import { ClassDTO, mapToClassDTO } from "../interfaces/classes.js"; | ||||||
| import { StudentDTO, mapToStudentDTO } from "../interfaces/students"; | import {UserService} from "./users.js"; | ||||||
| 
 | 
 | ||||||
| 
 | export class StudentService extends UserService<Student> { | ||||||
| export async function getAllStudents(): Promise<StudentDTO[]> { |     constructor() { | ||||||
|     const studentRepository = getStudentRepository(); |         super(getStudentRepository()); | ||||||
|     const students = await studentRepository.find({}); |  | ||||||
| 
 |  | ||||||
|     return students.map(mapToStudentDTO); |  | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| export async function getStudent(username: string): Promise<StudentDTO | null> { |  | ||||||
|     const studentRepository = getStudentRepository(); |  | ||||||
|     const student = await studentRepository.findByUsername(username); |  | ||||||
| 
 |  | ||||||
|     if  (!student) {  |  | ||||||
|         return null;  |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return mapToStudentDTO(student); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function fetchStudentClasses(username: string): Promise<Class[]> { | async function fetchStudentClasses(username: string): Promise<Class[]> { | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								backend/src/services/users.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								backend/src/services/users.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | ||||||
|  | import { UserRepository } from "../data/users/user-repository.js"; | ||||||
|  | import { UserDTO, mapToUser, mapToUserDTO } from "../interfaces/user.js"; | ||||||
|  | import {User} from "../entities/users/user.entity.js"; | ||||||
|  | 
 | ||||||
|  | export class UserService<T extends User> { | ||||||
|  |     protected repository: UserRepository<T>; | ||||||
|  | 
 | ||||||
|  |     constructor(repository: UserRepository<T>) { | ||||||
|  |         this.repository = repository; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async getAllUsers(): Promise<UserDTO[]> { | ||||||
|  |         const users = await this.repository.findAll(); | ||||||
|  |         return users.map(mapToUserDTO); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async getAllUserIds(): Promise<string[]> { | ||||||
|  |         const users = await this.getAllUsers(); | ||||||
|  |         return users.map((user) => user.username); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async getUserByUsername(username: string): Promise<UserDTO | null> { | ||||||
|  |         const user = await this.repository.findByUsername(username) | ||||||
|  |         return user ? mapToUserDTO(user) : null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async createUser(userData: UserDTO, UserClass: new () => T): Promise<T> { | ||||||
|  |         const newUser = mapToUser(userData, new UserClass()); | ||||||
|  |         await this.repository.save(newUser); | ||||||
|  |         return newUser; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async deleteUser(username: string): Promise<UserDTO | null> { | ||||||
|  |         const user = await this.getUserByUsername(username); | ||||||
|  |         if (!user) return null; | ||||||
|  |         await this.repository.deleteByUsername(username) | ||||||
|  |         return mapToUserDTO(user); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| import fs from 'fs'; | import fs from 'fs'; | ||||||
| import path from 'path'; | import path from 'path'; | ||||||
| import yaml from 'js-yaml'; | import yaml from 'js-yaml'; | ||||||
| import {FALLBACK_LANG} from "../../config"; | import {FALLBACK_LANG} from "../config.js"; | ||||||
| 
 | 
 | ||||||
| export function loadTranslations<T>(language: string): T { | export function loadTranslations<T>(language: string): T { | ||||||
|     try { |     try { | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Gabriellvl
						Gabriellvl