feat: add, delete student route met user logic + .js in files

This commit is contained in:
Gabriellvl 2025-03-09 20:18:11 +01:00
parent e0a5596994
commit ecad27ea4d
29 changed files with 301 additions and 159 deletions

View file

@ -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) => {

View file

@ -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 {
@ -41,4 +41,4 @@ export async function getAssignmentHandler(
} }
res.json(assignment); res.json(assignment);
} }

View file

@ -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,
@ -61,10 +60,10 @@ export async function getTeacherInvitationsHandler(
): Promise<void> { ): Promise<void> {
const classId = req.params.id; const classId = req.params.id;
const full = req.query.full === "true"; // TODO: not implemented yet const full = req.query.full === "true"; // TODO: not implemented yet
const invitations = await getClassTeacherInvitations(classId, full); const invitations = await getClassTeacherInvitations(classId, full);
res.json({ res.json({
invitations: invitations, invitations: invitations,
}); });
} }

View file

@ -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 {
@ -52,4 +52,4 @@ export async function getAllGroupsHandler(
res.json({ res.json({
groups: groups, groups: groups,
}); });
} }

View file

@ -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) {
console.error('Error fetching learning objects:', error);
res.status(500).json({ error: 'Internal server error' });
}
} }
export async function createStudentHandler(req: Request, res: Response): Promise<void> {
await createUserHandler<Student>(req, res, new StudentService(), Student);
}
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.
@ -92,4 +73,6 @@ export async function getStudentAssignmentsHandler(
res.json({ res.json({
assignments: assignments assignments: assignments
}); });
} }

View 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" });
}
}

View file

@ -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

View file

@ -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 });
}
}

View file

@ -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 });
}
}

View file

@ -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>);
} }
} }

View file

@ -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',

View file

@ -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();
}
} }

View file

@ -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,
@ -34,4 +33,4 @@ export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO {
language: assignment.learningPathLanguage, language: assignment.learningPathLanguage,
// groups: assignment.groups.map(mapToGroupDTO), // groups: assignment.groups.map(mapToGroupDTO),
}; };
} }

View file

@ -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;

View file

@ -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),
} }
@ -22,4 +22,4 @@ export function mapToGroupDTOId(group: Group): GroupDTO {
groupNumber: group.groupNumber, groupNumber: group.groupNumber,
members: group.members.map(member => member.username), members: group.members.map(member => member.username),
} }
} }

View file

@ -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;
@ -20,4 +20,13 @@ export function mapToStudentDTO(student: Student): StudentDTO {
firstName: student.firstName, firstName: student.firstName,
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;
}

View file

@ -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,
@ -22,4 +22,4 @@ export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): Tea
receiver: invitation.receiver.username, receiver: invitation.receiver.username,
class: invitation.class.classId, class: invitation.class.classId,
}; };
} }

View file

@ -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;
@ -20,4 +20,4 @@ export function mapToTeacherDTO(teacher: Teacher): TeacherDTO {
firstName: teacher.firstName, firstName: teacher.firstName,
lastName: teacher.lastName, lastName: teacher.lastName,
}; };
} }

View 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;
}

View file

@ -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 });
@ -28,4 +28,4 @@ router.get('/:id/questions', (req, res) => {
router.use('/:assignmentid/groups', groupRouter); router.use('/:assignmentid/groups', groupRouter);
export default router export default router

View file

@ -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();
@ -16,4 +16,4 @@ router.get('/:id/students', getClassStudentsHandler);
router.use('/:classid/assignments', assignmentRouter); router.use('/:classid/assignments', assignmentRouter);
export default router export default router

View file

@ -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
@ -15,4 +15,4 @@ router.get('/:id/question', (req, res) => {
}); });
}) })
export default router export default router

View file

@ -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);
@ -18,10 +30,10 @@ router.get('/:id/submissions', (req, res) => {
}); });
}) })
// the list of assignments a student has // the list of assignments a student has
router.get('/:id/assignments', getStudentAssignmentsHandler); router.get('/:id/assignments', getStudentAssignmentsHandler);
// the list of groups a student is in // the list of groups a student is in
router.get('/:id/groups', (req, res) => { router.get('/:id/groups', (req, res) => {
res.json({ res.json({
@ -36,4 +48,4 @@ router.get('/:id/questions', (req, res) => {
}); });
}) })
export default router export default router

View file

@ -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();
@ -8,7 +8,7 @@ export async function getAllAssignments(classid: string, full: boolean): Promise
if (!cls) { if (!cls) {
return []; return [];
} }
const assignmentRepository = getAssignmentRepository(); const assignmentRepository = getAssignmentRepository();
const assignments = await assignmentRepository.findAllAssignmentsInClass(cls); const assignments = await assignmentRepository.findAllAssignmentsInClass(cls);
@ -26,7 +26,7 @@ export async function getAssignment(classid: string, id: number): Promise<Assign
if (!cls) { if (!cls) {
return null; return null;
} }
const assignmentRepository = getAssignmentRepository(); const assignmentRepository = getAssignmentRepository();
const assignment = await assignmentRepository.findByClassAndId(cls, id); const assignment = await assignmentRepository.findByClassAndId(cls, id);
@ -35,4 +35,4 @@ export async function getAssignment(classid: string, id: number): Promise<Assign
} }
return mapToAssignmentDTO(assignment); return mapToAssignmentDTO(assignment);
} }

View file

@ -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();
@ -11,7 +10,7 @@ export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[
if (!classes) { if (!classes) {
return []; return [];
} }
if (full) { if (full) {
return classes.map(mapToClassDTO); return classes.map(mapToClassDTO);
} else { } else {
@ -66,4 +65,4 @@ export async function getClassTeacherInvitations(classId: string, full: boolean)
} }
return invitations.map(mapToTeacherInvitationDTOIds); return invitations.map(mapToTeacherInvitationDTOIds);
} }

View file

@ -1,9 +1,9 @@
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,
assignmentNumber: number, assignmentNumber: number,
groupNumber: number, groupNumber: number,
full: boolean, full: boolean,
): Promise<GroupDTO | null> { ): Promise<GroupDTO | null> {
@ -64,4 +64,4 @@ export async function getAllGroups(
} }
return groups.map(mapToGroupDTOId); return groups.map(mapToGroupDTOId);
} }

View file

@ -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[]> {

View 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);
}
}

View file

@ -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 {