584 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			584 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {
 | |
|   NewWeeklyReport,
 | |
|   NewUser,
 | |
|   User,
 | |
|   Project,
 | |
|   NewProject,
 | |
|   UserProjectMember,
 | |
|   WeeklyReport,
 | |
|   StrNameChange,
 | |
|   NewProjMember,
 | |
| } from "../Types/goTypes";
 | |
| 
 | |
| /**
 | |
|  * Response object returned by API methods.
 | |
|  */
 | |
| export interface APIResponse<T> {
 | |
|   /** Indicates whether the API call was successful */
 | |
|   success: boolean;
 | |
|   /** Optional message providing additional information or error description */
 | |
|   message?: string;
 | |
|   /** Optional data returned by the API method */
 | |
|   data?: T;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Interface defining methods that an instance of the API must implement.
 | |
|  */
 | |
| interface API {
 | |
|   /**
 | |
|    * Register a new user
 | |
|    * @param {NewUser} user The user object to be registered
 | |
|    * @returns {Promise<APIResponse<User>>} A promise containing the API response with the user data.
 | |
|    */
 | |
|   registerUser(user: NewUser): Promise<APIResponse<User>>;
 | |
| 
 | |
|   /**
 | |
|    * Removes a user.
 | |
|    * @param {string} username The username of the user to be removed.
 | |
|    * @param {string} token The authentication token.
 | |
|    * @returns {Promise<APIResponse<User>>} A promise containing the API response with the removed user data.
 | |
|    */
 | |
|   removeUser(username: string, token: string): Promise<APIResponse<User>>;
 | |
| 
 | |
|   /**
 | |
|    * Check if user is project manager.
 | |
|    * @param {string} username The username of the user.
 | |
|    * @param {string} projectName The name of the project.
 | |
|    * @param {string} token The authentication token.
 | |
|    * @returns {Promise<APIResponse<boolean>>} A promise containing the API response indicating if the user is a project manager.
 | |
|    */
 | |
|   checkIfProjectManager(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<boolean>>;
 | |
| 
 | |
|   /** Logs in a user with the provided credentials.
 | |
|    * @param {NewUser} NewUser The user object containing username and password.
 | |
|    * @returns {Promise<APIResponse<string>>} A promise resolving to an API response with a token.
 | |
|    */
 | |
|   login(NewUser: NewUser): Promise<APIResponse<string>>;
 | |
| 
 | |
|   /**
 | |
|    *  Renew the token
 | |
|    * @param {string} token The current authentication token.
 | |
|    * @returns {Promise<APIResponse<string>>} A promise resolving to an API response with a renewed token.
 | |
|    */
 | |
|   renewToken(token: string): Promise<APIResponse<string>>;
 | |
| 
 | |
|   /** Promote user to admin */
 | |
| 
 | |
|   /** Creates a new project.
 | |
|    * @param {NewProject} project The project object containing name and description.
 | |
|    * @param {string} token The authentication token.
 | |
|    * @returns {Promise<APIResponse<Project>>} A promise resolving to an API response with the created project.
 | |
|    */
 | |
|   createProject(
 | |
|     project: NewProject,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<Project>>;
 | |
| 
 | |
|   /** Submits a weekly report
 | |
|    * @param {NewWeeklyReport} weeklyReport The weekly report object.
 | |
|    * @param {string} token The authentication token.
 | |
|    * @returns {Promise<APIResponse<NewWeeklyReport>>} A promise resolving to an API response with the submitted report.
 | |
|    */
 | |
|   submitWeeklyReport(
 | |
|     weeklyReport: NewWeeklyReport,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<string>>;
 | |
| 
 | |
|   /** Gets a weekly report for a specific user, project and week
 | |
|    * @param {string} projectName The name of the project.
 | |
|    * @param {string} week The week number.
 | |
|    * @param {string} token The authentication token.
 | |
|    * @returns {Promise<APIResponse<WeeklyReport>>} A promise resolving to an API response with the retrieved report.
 | |
|    */
 | |
|   getWeeklyReport(
 | |
|     projectName: string,
 | |
|     week: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<WeeklyReport>>;
 | |
| 
 | |
|   /**
 | |
|    * Returns all the weekly reports for a user in a particular project
 | |
|    * The username is derived from the token
 | |
|    * @param {string} projectName The name of the project
 | |
|    * @param {string} token The token of the user
 | |
|    * @returns {APIResponse<WeeklyReport[]>} A list of weekly reports
 | |
|    */
 | |
|   getWeeklyReportsForUser(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<WeeklyReport[]>>;
 | |
| 
 | |
|   /** Gets all the projects of a user
 | |
|    * @param {string} token - The authentication token.
 | |
|    * @returns {Promise<APIResponse<Project[]>>} A promise containing the API response with the user's projects.
 | |
|    */
 | |
|   getUserProjects(token: string): Promise<APIResponse<Project[]>>;
 | |
| 
 | |
|   /** Gets a project by its id.
 | |
|    * @param {number} id The id of the project to retrieve.
 | |
|    * @returns {Promise<APIResponse<Project>>} A promise resolving to an API response containing the project data.
 | |
|    */
 | |
|   getProject(id: number): Promise<APIResponse<Project>>;
 | |
| 
 | |
|   /** Gets a list of all users.
 | |
|    * @param {string} token The authentication token of the requesting user.
 | |
|    * @returns {Promise<APIResponse<string[]>>} A promise resolving to an API response containing the list of users.
 | |
|    */
 | |
|   getAllUsers(token: string): Promise<APIResponse<string[]>>;
 | |
|   /** Gets all users in a project from name*/
 | |
|   getAllUsersProject(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<UserProjectMember[]>>;
 | |
|   /**
 | |
|    * Changes the username of a user in the database.
 | |
|    * @param {StrNameChange} data The object containing the previous and new username.
 | |
|    * @param {string} token The authentication token.
 | |
|    * @returns {Promise<APIResponse<void>>} A promise resolving to an API response.
 | |
|    */
 | |
|   changeUserName(
 | |
|     data: StrNameChange,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<void>>;
 | |
|   addUserToProject(
 | |
|     user: NewProjMember,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<NewProjMember>>;
 | |
| 
 | |
|   removeProject(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<string>>;
 | |
| }
 | |
| 
 | |
| /** An instance of the API */
 | |
| export const api: API = {
 | |
|   async registerUser(user: NewUser): Promise<APIResponse<User>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/register", {
 | |
|         method: "POST",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|         },
 | |
|         body: JSON.stringify(user),
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return {
 | |
|           success: false,
 | |
|           message: "Failed to register user: " + response.status,
 | |
|         };
 | |
|       } else {
 | |
|         // const data = (await response.json()) as User; // The API does not currently return the user
 | |
|         return { success: true };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return {
 | |
|         success: false,
 | |
|         message: "Unknown error while registering user",
 | |
|       };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async removeUser(
 | |
|     username: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<User>> {
 | |
|     try {
 | |
|       const response = await fetch(`/api/userdelete/${username}`, {
 | |
|         method: "DELETE",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|         body: JSON.stringify(username),
 | |
|       });
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Could not remove user" };
 | |
|       } else {
 | |
|         return { success: true };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to remove user" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async checkIfProjectManager(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<boolean>> {
 | |
|     try {
 | |
|       const response = await fetch(
 | |
|         `/api/checkIfProjectManager/${projectName}`,
 | |
|         {
 | |
|           method: "GET",
 | |
|           headers: {
 | |
|             "Content-Type": "application/json",
 | |
|             Authorization: "Bearer " + token,
 | |
|           },
 | |
|         },
 | |
|       );
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return {
 | |
|           success: false,
 | |
|           message: "Failed to check if project manager",
 | |
|         };
 | |
|       } else {
 | |
|         const data = (await response.json()) as boolean;
 | |
|         return { success: true, data };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to check if project manager" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async createProject(
 | |
|     project: NewProject,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<Project>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/project", {
 | |
|         method: "POST",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|         body: JSON.stringify(project),
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Failed to create project" };
 | |
|       } else {
 | |
|         const data = (await response.json()) as Project;
 | |
|         return { success: true, data };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to create project" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async addUserToProject(
 | |
|     user: NewProjMember,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<NewProjMember>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/addUserToProject", {
 | |
|         method: "PUT",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|         body: JSON.stringify(user),
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Failed to add member" };
 | |
|       } else {
 | |
|         return { success: true, message: "Added member" };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to add member" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async renewToken(token: string): Promise<APIResponse<string>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/loginrenew", {
 | |
|         method: "POST",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Failed to renew token" };
 | |
|       } else {
 | |
|         const data = (await response.json()) as string;
 | |
|         return { success: true, data };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to renew token" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async getUserProjects(token: string): Promise<APIResponse<Project[]>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/getUserProjects", {
 | |
|         method: "GET",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return Promise.resolve({
 | |
|           success: false,
 | |
|           message: "Failed to get user projects",
 | |
|         });
 | |
|       } else {
 | |
|         const data = (await response.json()) as Project[];
 | |
|         return Promise.resolve({ success: true, data });
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return Promise.resolve({
 | |
|         success: false,
 | |
|         message: "API fucked",
 | |
|       });
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async submitWeeklyReport(
 | |
|     weeklyReport: NewWeeklyReport,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<string>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/submitWeeklyReport", {
 | |
|         method: "POST",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|         body: JSON.stringify(weeklyReport),
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return {
 | |
|           success: false,
 | |
|           message: "Failed to submit weekly report",
 | |
|         };
 | |
|       }
 | |
| 
 | |
|       const data = await response.text();
 | |
|       return { success: true, message: data };
 | |
|     } catch (e) {
 | |
|       return {
 | |
|         success: false,
 | |
|         message: "Failed to submit weekly report",
 | |
|       };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async getWeeklyReport(
 | |
|     projectName: string,
 | |
|     week: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<WeeklyReport>> {
 | |
|     try {
 | |
|       const response = await fetch(
 | |
|         `/api/getWeeklyReport?projectName=${projectName}&week=${week}`,
 | |
|         {
 | |
|           method: "GET",
 | |
|           headers: {
 | |
|             "Content-Type": "application/json",
 | |
|             Authorization: "Bearer " + token,
 | |
|           },
 | |
|         },
 | |
|       );
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Failed to get weekly report" };
 | |
|       } else {
 | |
|         const data = (await response.json()) as WeeklyReport;
 | |
|         return { success: true, data };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to get weekly report" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async getWeeklyReportsForUser(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<WeeklyReport[]>> {
 | |
|     try {
 | |
|       const response = await fetch(`/api/getWeeklyReportsUser/${projectName}`, {
 | |
|         method: "GET",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return {
 | |
|           success: false,
 | |
|           message:
 | |
|             "Failed to get weekly reports for project: Response code " +
 | |
|             response.status,
 | |
|         };
 | |
|       } else {
 | |
|         const data = (await response.json()) as WeeklyReport[];
 | |
|         return { success: true, data };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return {
 | |
|         success: false,
 | |
|         message: "Failed to get weekly reports for project, unknown error",
 | |
|       };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async login(NewUser: NewUser): Promise<APIResponse<string>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/login", {
 | |
|         method: "POST",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|         },
 | |
|         body: JSON.stringify(NewUser),
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Failed to login" };
 | |
|       } else {
 | |
|         const data = (await response.json()) as { token: string }; // Update the type of 'data'
 | |
|         return { success: true, data: data.token };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return Promise.resolve({ success: false, message: "Failed to login" });
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async getProject(id: number): Promise<APIResponse<Project>> {
 | |
|     try {
 | |
|       const response = await fetch(`/api/project/${id}`, {
 | |
|         method: "GET",
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return {
 | |
|           success: false,
 | |
|           message: "Failed to get project: Response code " + response.status,
 | |
|         };
 | |
|       } else {
 | |
|         const data = (await response.json()) as Project;
 | |
|         return { success: true, data };
 | |
|       }
 | |
|       // The code below is garbage but satisfies the linter
 | |
|       // This needs fixing, do not copy this pattern
 | |
|     } catch (e: unknown) {
 | |
|       return {
 | |
|         success: false,
 | |
|         message: "Failed to get project: " + (e as Error).toString(),
 | |
|       };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async getAllUsers(token: string): Promise<APIResponse<string[]>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/users/all", {
 | |
|         method: "GET",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return Promise.resolve({
 | |
|           success: false,
 | |
|           message: "Failed to get users",
 | |
|         });
 | |
|       } else {
 | |
|         const data = (await response.json()) as string[];
 | |
|         return Promise.resolve({ success: true, data });
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return Promise.resolve({
 | |
|         success: false,
 | |
|         message: "API is not ok",
 | |
|       });
 | |
|     }
 | |
|   },
 | |
|   //Gets all users in a project
 | |
|   async getAllUsersProject(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<UserProjectMember[]>> {
 | |
|     try {
 | |
|       const response = await fetch(`/api/getUsersProject/${projectName}`, {
 | |
|         method: "GET",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return Promise.resolve({
 | |
|           success: false,
 | |
|           message: "Failed to get users",
 | |
|         });
 | |
|       } else {
 | |
|         const data = (await response.json()) as UserProjectMember[];
 | |
|         return Promise.resolve({ success: true, data });
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return Promise.resolve({
 | |
|         success: false,
 | |
|         message: "API is not ok",
 | |
|       });
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async changeUserName(
 | |
|     data: StrNameChange,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<void>> {
 | |
|     try {
 | |
|       const response = await fetch("/api/changeUserName", {
 | |
|         method: "PUT",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|         body: JSON.stringify(data),
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return { success: false, message: "Failed to change username" };
 | |
|       } else {
 | |
|         return { success: true };
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return { success: false, message: "Failed to change username" };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   async removeProject(
 | |
|     projectName: string,
 | |
|     token: string,
 | |
|   ): Promise<APIResponse<string>> {
 | |
|     try {
 | |
|       const response = await fetch(`/api/projectdelete/${projectName}`, {
 | |
|         method: "DELETE",
 | |
|         headers: {
 | |
|           "Content-Type": "application/json",
 | |
|           Authorization: "Bearer " + token,
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       if (!response.ok) {
 | |
|         return Promise.resolve({
 | |
|           success: false,
 | |
|           message: "Failed to remove project",
 | |
|         });
 | |
|       } else {
 | |
|         const data = await response.text();
 | |
|         return Promise.resolve({ success: true, message: data });
 | |
|       }
 | |
|     } catch (e) {
 | |
|       return Promise.resolve({
 | |
|         success: false,
 | |
|         message: "Failed to remove project",
 | |
|       });
 | |
|     }
 | |
|   },
 | |
| };
 | 
