From 52aecd14d42330802056d699f92ba6558d255568 Mon Sep 17 00:00:00 2001 From: pavel Hamawand Date: Tue, 19 Mar 2024 03:14:14 +0100 Subject: [PATCH 001/154] minor fix --- frontend/src/Pages/YourProjectsPage.tsx | 26 +++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 973baa3..5de772f 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -1,6 +1,5 @@ -import { useState, createContext, useEffect } from "react"; +import { useState, createContext } from "react"; import { Project } from "../Types/goTypes"; -import { api } from "../API/API"; import { Link } from "react-router-dom"; import BasicWindow from "../Components/BasicWindow"; @@ -28,10 +27,25 @@ function UserProjectPage(): JSX.Element { // Mock data const projects: Project[] = [ - { id: "1", name: "Project Test App" }, - { id: "2", name: "Project 2" }, - { id: "3", name: "Project 3" }, - // Add more mock projects as needed + { + id: 1, + name: "Project Test App", + description: "Description 1", + owner: "Owner 1", + }, + { + id: 2, + name: "Project 2", + description: "Description 2", + owner: "Owner 2", + }, + { + id: 3, + name: "Project 3", + description: "Description 3", + owner: "Owner 3", + }, + // Add more mock projects as neededects as needed ]; const handleProjectClick = (projectName: string): void => { From 4df8d3f8581c2eed3cda217b1c43f707f3962a95 Mon Sep 17 00:00:00 2001 From: pavel Hamawand Date: Tue, 19 Mar 2024 03:22:54 +0100 Subject: [PATCH 002/154] new component --- frontend/src/Components/ChangeUsername.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 frontend/src/Components/ChangeUsername.tsx diff --git a/frontend/src/Components/ChangeUsername.tsx b/frontend/src/Components/ChangeUsername.tsx new file mode 100644 index 0000000..e69de29 From 8b7ad8911b07956cf4a5ce659026ac283b4acb39 Mon Sep 17 00:00:00 2001 From: pavel Hamawand Date: Tue, 19 Mar 2024 03:39:05 +0100 Subject: [PATCH 003/154] implementing ChangeUser --- frontend/src/Components/ChangeUsername.tsx | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/frontend/src/Components/ChangeUsername.tsx b/frontend/src/Components/ChangeUsername.tsx index e69de29..71d5e57 100644 --- a/frontend/src/Components/ChangeUsername.tsx +++ b/frontend/src/Components/ChangeUsername.tsx @@ -0,0 +1,38 @@ +import React, { useState } from "react"; +import { api } from "../API/API"; +import InputField from "./InputField"; +import BackButton from "./BackButton"; +import Button from "./Button"; + + +function ChangeUsername(): JSX.Element { + const [newUsername, setNewUsername] = useState(""); + + const handleChange = (e: React.ChangeEvent): void => { + setNewUsername(e.target.value); + }; + + const handleSubmit = async (): Promise => { + try { + // Call the API function to update the username + await api.updateUsername(newUsername); + // Optionally, add a success message or redirect the user + } catch (error) { + console.error("Error updating username:", error); + // Optionally, handle the error + } + }; + + return ( +
+ +
+ ); +} + +export default ChangeUsername; From cbb62438c8790fb7fa478804b99112adb9113100 Mon Sep 17 00:00:00 2001 From: pavel Hamawand Date: Tue, 19 Mar 2024 03:40:17 +0100 Subject: [PATCH 004/154] implementing AdminChangeUsername --- frontend/src/Pages/AdminPages/AdminChangeUsername.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx b/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx index 7eb2e2e..b130fae 100644 --- a/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx +++ b/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx @@ -1,9 +1,14 @@ import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; +import ChangeUsername from "../../Components/ChangeUsername"; function AdminChangeUsername(): JSX.Element { - const content = <>; + const content = ( + <> + + + ); const buttons = ( <> From 5f6977354f143e519abfbe9f88dc6bc3535fa268 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Tue, 19 Mar 2024 04:02:04 +0100 Subject: [PATCH 005/154] Justfile save-release target now saves image with name containing commit hash and date --- Justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 432fbd1..cb905e4 100644 --- a/Justfile +++ b/Justfile @@ -15,7 +15,7 @@ remove-podman-containers: # Saves the release container to a tarball, pigz is just gzip but multithreaded save-release: build-container-release - podman save --format=oci-archive ttime-server | pigz -9 > ttime-server.tar.gz + podman save --format=oci-archive ttime-server | pigz -9 > ttime-server_`date -I`_`git rev-parse --short HEAD`.tar.gz # Loads the release container from a tarball load-release file: From 08532444f089c17f077d4513a2dfd8d04195a5fc Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 09:14:30 +0100 Subject: [PATCH 006/154] Cleanup YourProjectsPage --- frontend/src/Pages/YourProjectsPage.tsx | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 0f2428e..b5644c3 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -1,13 +1,11 @@ -import { useState, createContext } from "react"; +import { useState, useEffect } from "react"; import { Project } from "../Types/goTypes"; import { Link } from "react-router-dom"; import BasicWindow from "../Components/BasicWindow"; - -export const ProjectNameContext = createContext(""); +import { api } from "../API/API"; function UserProjectPage(): JSX.Element { const [projects, setProjects] = useState([]); - const [selectedProject, setSelectedProject] = useState(""); const getProjects = async (): Promise => { const token = localStorage.getItem("accessToken") ?? ""; @@ -24,29 +22,19 @@ function UserProjectPage(): JSX.Element { void getProjects(); }, []); - const handleProjectClick = (projectName: string): void => { - setSelectedProject(projectName); - }; - const content = ( - + <>

Your Projects

{projects.map((project, index) => ( - { - handleProjectClick(project.name); - }} - key={index} - > +

{project.name}

))}
-
+ ); const buttons = <>; From d775a6e381f7d2ccac0c1b035ae1b540d7238ee3 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 09:21:33 +0100 Subject: [PATCH 007/154] Update navigation in NewWeeklyReport component --- frontend/src/Components/NewWeeklyReport.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Components/NewWeeklyReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx index ab9084d..b8a6f7e 100644 --- a/frontend/src/Components/NewWeeklyReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -45,7 +45,7 @@ export default function NewWeeklyReport(): JSX.Element { } e.preventDefault(); void handleNewWeeklyReport(); - navigate("/project"); + navigate(-1); }} >
From 53f468d7c89b791428da33aff193d707ca4823a3 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 09:23:09 +0100 Subject: [PATCH 008/154] Update navigation in EditWeeklyReport component --- frontend/src/Components/EditWeeklyReport.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx index b0e8771..3da3b86 100644 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ b/frontend/src/Components/EditWeeklyReport.tsx @@ -82,7 +82,7 @@ export default function GetWeeklyReport(): JSX.Element { } e.preventDefault(); void handleNewWeeklyReport(); - navigate("/project"); + navigate(-1); }} >
From 4f53f9de94e5b83361c3b0cc8dd6778f0fc08eb0 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 09:33:20 +0100 Subject: [PATCH 009/154] Fix initial value of week state in NewWeeklyReport component for error message --- frontend/src/Components/NewWeeklyReport.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Components/NewWeeklyReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx index b8a6f7e..e53823d 100644 --- a/frontend/src/Components/NewWeeklyReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -5,7 +5,7 @@ import { useNavigate, useParams } from "react-router-dom"; import Button from "./Button"; export default function NewWeeklyReport(): JSX.Element { - const [week, setWeek] = useState(); + const [week, setWeek] = useState(0); const [developmentTime, setDevelopmentTime] = useState(); const [meetingTime, setMeetingTime] = useState(); const [adminTime, setAdminTime] = useState(); @@ -19,7 +19,7 @@ export default function NewWeeklyReport(): JSX.Element { const handleNewWeeklyReport = async (): Promise => { const newWeeklyReport: NewWeeklyReport = { projectName: projectName ?? "", - week: week ?? 0, + week: week, developmentTime: developmentTime ?? 0, meetingTime: meetingTime ?? 0, adminTime: adminTime ?? 0, From cda2b72d08031330b3d7f5676815df381f627a35 Mon Sep 17 00:00:00 2001 From: Mattias Date: Tue, 19 Mar 2024 09:34:37 +0100 Subject: [PATCH 010/154] projectName is now fetched from params --- frontend/src/Components/EditWeeklyReport.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx index 3da3b86..0bfc608 100644 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ b/frontend/src/Components/EditWeeklyReport.tsx @@ -1,11 +1,10 @@ import { useState, useEffect } from "react"; import { NewWeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import Button from "./Button"; export default function GetWeeklyReport(): JSX.Element { - const [projectName, setProjectName] = useState(""); const [week, setWeek] = useState(0); const [developmentTime, setDevelopmentTime] = useState(0); const [meetingTime, setMeetingTime] = useState(0); @@ -16,12 +15,13 @@ export default function GetWeeklyReport(): JSX.Element { const token = localStorage.getItem("accessToken") ?? ""; const username = localStorage.getItem("username") ?? ""; + const { projectName } = useParams(); useEffect(() => { const fetchWeeklyReport = async (): Promise => { const response = await api.getWeeklyReport( username, - projectName, + projectName ?? "", week.toString(), token, ); @@ -37,7 +37,7 @@ export default function GetWeeklyReport(): JSX.Element { studyTime: 0, testingTime: 0, }; - setProjectName(report.projectName); + setWeek(report.week); setDevelopmentTime(report.developmentTime); setMeetingTime(report.meetingTime); @@ -55,7 +55,7 @@ export default function GetWeeklyReport(): JSX.Element { const handleNewWeeklyReport = async (): Promise => { const newWeeklyReport: NewWeeklyReport = { - projectName, + projectName: projectName ?? "", week, developmentTime, meetingTime, From a30a6a498899f04ddceacd9b635211ef0062603c Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 09:37:13 +0100 Subject: [PATCH 011/154] Fix button UserNewTimeReportPage --- .../src/Pages/UserPages/UserNewTimeReportPage.tsx | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx index 2cdeb15..cd69b3b 100644 --- a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx @@ -1,7 +1,6 @@ +import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; -import Button from "../../Components/Button"; import NewWeeklyReport from "../../Components/NewWeeklyReport"; -import { Link } from "react-router-dom"; function UserNewTimeReportPage(): JSX.Element { const content = ( @@ -13,15 +12,7 @@ function UserNewTimeReportPage(): JSX.Element { const buttons = ( <> - -
+ ); +} \ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 20ecbcd..29a67d1 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -30,6 +30,7 @@ import AdminProjectStatistics from "./Pages/AdminPages/AdminProjectStatistics.ts import AdminProjectViewMemberInfo from "./Pages/AdminPages/AdminProjectViewMemberInfo.tsx"; import AdminProjectPage from "./Pages/AdminPages/AdminProjectPage.tsx"; import NotFoundPage from "./Pages/NotFoundPage.tsx"; +import UnauthorizedPage from "./Pages/UnauthorizedPage.tsx"; // This is where the routes are mounted const router = createBrowserRouter([ @@ -146,6 +147,10 @@ const router = createBrowserRouter([ path: "/adminManageUser", element: , }, + { + path: "unauthorized", + element: , + }, ]); // Semi-hacky way to get the root element From 900c1614e9dc6c9621ab826f647249b55a61d23c Mon Sep 17 00:00:00 2001 From: Mattias Date: Tue, 19 Mar 2024 22:50:57 +0100 Subject: [PATCH 039/154] minor fix --- frontend/src/Pages/UnauthorizedPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Pages/UnauthorizedPage.tsx b/frontend/src/Pages/UnauthorizedPage.tsx index ed21b25..37e3d2c 100644 --- a/frontend/src/Pages/UnauthorizedPage.tsx +++ b/frontend/src/Pages/UnauthorizedPage.tsx @@ -15,4 +15,4 @@ export default function UnauthorizedPage(): JSX.Element {
); -} \ No newline at end of file +} From ffaa6616281dcd4165e575bd9d660b27e4908d8b Mon Sep 17 00:00:00 2001 From: Mattias Date: Tue, 19 Mar 2024 22:51:54 +0100 Subject: [PATCH 040/154] Minor fix --- frontend/src/main.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 29a67d1..ddf7119 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -148,7 +148,7 @@ const router = createBrowserRouter([ element: , }, { - path: "unauthorized", + path: "/unauthorized", element: , }, ]); From cb44954477c975d77e5f05588e13f4253acaa47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20H=C3=B6gbom=20Aronson?= Date: Tue, 19 Mar 2024 23:08:14 +0100 Subject: [PATCH 041/154] -added auth for rolechange, endpoint and test --- .../handlers/handlers_project_related.go | 26 +++++++++++++--- backend/internal/types/project.go | 6 ++++ backend/main.go | 2 +- testing.py | 30 +++++++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index df9f3e0..2ab5869 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -49,13 +49,31 @@ func (gs *GState) GetUserProjects(c *fiber.Ctx) error { // ProjectRoleChange is a handler that changes a user's role within a project func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error { + + //check token and get username of current user + user := c.Locals("user").(*jwt.Token) + claims := user.Claims.(jwt.MapClaims) + projectManagerUsername := claims["name"].(string) + log.Info(projectManagerUsername) // Extract the necessary parameters from the request - username := c.Params("username") - projectName := c.Params("projectName") - role := c.Params("role") + data := new(types.RoleChange) + if err := c.BodyParser(data); err != nil { + log.Info("error parsing username, project or role") + return c.Status(400).SendString(err.Error()) + } + + // dubble diping and checcking if current user is + + if ismanager, err := gs.Db.IsProjectManager(projectManagerUsername, data.Projectname); err != nil { + log.Warn("Error checking if projectmanager:", err) + return c.Status(500).SendString(err.Error()) + } else if !ismanager { + log.Warn("tried chaning role when not projectmanager:", err) + return c.Status(401).SendString("you can not change role when not projectManager") + } // Change the user's role within the project in the database - if err := gs.Db.ChangeUserRole(username, projectName, role); err != nil { + if err := gs.Db.ChangeUserRole(data.Username, data.Projectname, data.Role); err != nil { return c.Status(500).SendString(err.Error()) } diff --git a/backend/internal/types/project.go b/backend/internal/types/project.go index 7e1747f..c336bcb 100644 --- a/backend/internal/types/project.go +++ b/backend/internal/types/project.go @@ -13,3 +13,9 @@ type NewProject struct { Name string `json:"name"` Description string `json:"description"` } + +type RoleChange struct { + Role string `json:"role" tstype:"'project_manager' | 'user'"` + Username string `json:"username"` + Projectname string `json:"projectname"` +} diff --git a/backend/main.go b/backend/main.go index abdf0db..60027fd 100644 --- a/backend/main.go +++ b/backend/main.go @@ -96,7 +96,7 @@ func main() { server.Get("/api/users/all", gs.ListAllUsers) server.Get("/api/getWeeklyReportsUser", gs.GetWeeklyReportsUserHandler) server.Get("api/checkIfProjectManager", gs.IsProjectManagerHandler) - + server.Post("/api/ProjectRoleChange", gs.ProjectRoleChange) // Announce the port we are listening on and start the server err = server.Listen(fmt.Sprintf(":%d", conf.Port)) if err != nil { diff --git a/testing.py b/testing.py index 670abcd..0b803f5 100644 --- a/testing.py +++ b/testing.py @@ -39,7 +39,36 @@ promoteToAdminPath = base_url + "/api/promoteToAdmin" getUserProjectsPath = base_url + "/api/getUserProjects" getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser" checkIfProjectManagerPath = base_url + "/api/checkIfProjectManager" +ProjectRoleChangePath = base_url + "/api/ProjectRoleChange" +#ta bort auth i handlern för att få testet att gå igenom +def test_ProjectRoleChange(): + dprint("Testing ProjectRoleChange") + project_manager = randomString() + register(project_manager, "project_manager_password") + + token = login(project_manager, "project_manager_password").json()[ + "token" + ] + response = requests.post( + addProjectPath, + json={"name": projectName, "description": "This is a project"}, + headers={"Authorization": "Bearer " + token}, + ) + response = requests.post( + ProjectRoleChangePath, + headers={"Authorization": "Bearer " + token}, + json={ + "username": username, + "projectName": projectName, + "week": 1 + }, + ) + if response.status_code != 200: + print("auth not working, för att man inte kan få tag på pm token atm, för att få igenom det så ta bort auth i handler") + + assert response.status_code == 200, "change role successfully" + def test_get_user_projects(): @@ -324,3 +353,4 @@ if __name__ == "__main__": test_add_user_to_project() test_get_weekly_reports_user() test_check_if_project_manager() + test_ProjectRoleChange() From 863a14c316eafb0d1d0dbc1d5392e771bc95c659 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 23:44:00 +0100 Subject: [PATCH 042/154] Add WeeklyReport type and update getWeeklyReportsForProject method --- frontend/src/API/API.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index fc2367b..3ebf343 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -4,6 +4,7 @@ import { User, Project, NewProject, + WeeklyReport, } from "../Types/goTypes"; // This type of pattern should be hard to misuse @@ -49,9 +50,10 @@ interface API { token: string, ): Promise>; getWeeklyReportsForProject( + username: string, projectName: string, token: string, - ): Promise>; + ): Promise>; /** Gets all the projects of a user*/ getUserProjects(token: string): Promise>; /** Gets a project from id*/ @@ -272,15 +274,19 @@ export const api: API = { } }, - async getWeeklyReportsForProject(projectName: string, token: string) { + async getWeeklyReportsForProject( + username: string, + projectName: string, + token: string, + ) { try { - const response = await fetch("/api/getWeeklyReportsForProject", { + const response = await fetch("/api/getWeeklyReportsUser", { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, - body: JSON.stringify({ projectName }), + body: JSON.stringify({ username, projectName }), }); if (!response.ok) { @@ -289,13 +295,13 @@ export const api: API = { message: "Failed to get weekly reports for project", }; } else { - const data = (await response.json()) as NewWeeklyReport[]; + const data = (await response.json()) as WeeklyReport[]; return { success: true, data }; } } catch (e) { return { success: false, - message: "Failed to get weekly reports for project", + message: "fuck", }; } }, From b5d3ab7cb73e2a75473770b6166ce94d152bb776 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Tue, 19 Mar 2024 23:44:25 +0100 Subject: [PATCH 043/154] Refactor AllTimeReportsInProject component to use API for fetching weekly reports --- .../Components/AllTimeReportsInProject.tsx | 75 ++++--------------- 1 file changed, 16 insertions(+), 59 deletions(-) diff --git a/frontend/src/Components/AllTimeReportsInProject.tsx b/frontend/src/Components/AllTimeReportsInProject.tsx index 067712e..cc2bac4 100644 --- a/frontend/src/Components/AllTimeReportsInProject.tsx +++ b/frontend/src/Components/AllTimeReportsInProject.tsx @@ -1,68 +1,25 @@ import React, { useEffect, useState } from "react"; -import { NewWeeklyReport } from "../Types/goTypes"; +import { WeeklyReport } from "../Types/goTypes"; import { Link, useParams } from "react-router-dom"; +import { api } from "../API/API"; function AllTimeReportsInProject(): JSX.Element { const { projectName } = useParams(); - const [weeklyReports, setWeeklyReports] = useState([]); - - /* const getWeeklyReports = async (): Promise => { - const token = localStorage.getItem("accessToken") ?? ""; - const response = await api.getWeeklyReports(token); - console.log(response); - if (response.success) { - setWeeklyReports(response.data ?? []); - } else { - console.error(response.message); - } -}; */ + const [weeklyReports, setWeeklyReports] = useState([]); const getWeeklyReports = async (): Promise => { - const report: NewWeeklyReport[] = [ - { - projectName: projectName ?? "", - week: 10, - developmentTime: 1, - meetingTime: 1, - adminTime: 1, - ownWorkTime: 1, - studyTime: 1, - testingTime: 1, - }, - { - projectName: projectName ?? "", - week: 11, - developmentTime: 1, - meetingTime: 1, - adminTime: 1, - ownWorkTime: 100, - studyTime: 1, - testingTime: 1, - }, - { - projectName: projectName ?? "", - week: 12, - developmentTime: 1, - meetingTime: 1, - adminTime: 1, - ownWorkTime: 1, - studyTime: 1, - testingTime: 1000, - }, - { - projectName: projectName ?? "", - week: 20, - developmentTime: 1, - meetingTime: 1, - adminTime: 1, - ownWorkTime: 1, - studyTime: 1, - testingTime: 10000, - }, - // Add more reports as needed - ]; - setWeeklyReports(report); - await Promise.resolve(); + const token = localStorage.getItem("accessToken") ?? ""; + const response = await api.getWeeklyReportsForProject( + localStorage.getItem("username") ?? "", + projectName ?? "", + token, + ); + console.log(response); + if (response.success) { + setWeeklyReports(response.data ?? []); + } else { + console.error(response.message); + } }; // Call getProjects when the component mounts @@ -96,7 +53,7 @@ function AllTimeReportsInProject(): JSX.Element {

{"Signed: "} - YES + {newWeeklyReport.signedBy ? "YES" : "NO"}

From b7b831d869b2dc0f0f314339853209821f139b85 Mon Sep 17 00:00:00 2001 From: Melker Date: Tue, 19 Mar 2024 23:54:54 +0100 Subject: [PATCH 044/154] Lagt till om Admin=True/false --- backend/internal/handlers/handlers_user_related.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/internal/handlers/handlers_user_related.go b/backend/internal/handlers/handlers_user_related.go index 96fddb7..75b8953 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -101,10 +101,15 @@ func (gs *GState) Login(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusUnauthorized) } + isAdmin, err := gs.Db.IsSiteAdmin(u.Username) + if err != nil { + log.Info("Error checking admin status:", err) + return c.Status(500).SendString(err.Error()) +} // Create the Claims claims := jwt.MapClaims{ "name": u.Username, - "admin": false, + "admin": isAdmin, "exp": time.Now().Add(time.Hour * 72).Unix(), } From 8300fb3a6fe0ec4abe47a8e5bde02928b21b845d Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 00:10:24 +0100 Subject: [PATCH 045/154] Added getAllUsers to API --- frontend/src/API/API.ts | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 8fd66d3..7f5c420 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -45,6 +45,8 @@ interface API { getUserProjects(token: string): Promise>; /** Gets a project from id*/ getProject(id: number): Promise>; + /** Gets a project from id*/ + getAllUsers(token: string): Promise>; } // Export an instance of the API @@ -81,7 +83,7 @@ export const api: API = { token: string, ): Promise> { try { - const response = await fetch("/api/userdelete", { + const response = await fetch(`/api/userdelete/${username}`, { method: "POST", headers: { "Content-Type": "application/json", @@ -278,4 +280,32 @@ export const api: API = { }; } }, + + // Gets all users + async getAllUsers(token: string): Promise> { + 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", + }); + } + }, }; From cc231dbfaad1f5adbff021cd6270ad7db2f38ba3 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 00:14:23 +0100 Subject: [PATCH 046/154] Component for getting all users --- frontend/src/Components/GetAllUsers.tsx | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 frontend/src/Components/GetAllUsers.tsx diff --git a/frontend/src/Components/GetAllUsers.tsx b/frontend/src/Components/GetAllUsers.tsx new file mode 100644 index 0000000..73ad244 --- /dev/null +++ b/frontend/src/Components/GetAllUsers.tsx @@ -0,0 +1,35 @@ +import { Dispatch, useEffect } from "react"; +import { api } from "../API/API"; + +/** + * Gets all usernames in the system and puts them in an array + * @param props - A setStateAction for the array you want to put users in + * @returns {void} Nothing + * @example + * const [users, setUsers] = useState([]); + * GetAllUsers({ setUsersProp: setUsers }); + */ +function GetAllUsers(props: { + setUsersProp: Dispatch>; +}): void { + const setUsers: Dispatch> = props.setUsersProp; + useEffect(() => { + const fetchUsers = async (): Promise => { + try { + const token = localStorage.getItem("accessToken") ?? ""; + const response = await api.getAllUsers(token); + if (response.success) { + setUsers(response.data ?? []); + } else { + console.error("Failed to fetch users:", response.message); + } + } catch (error) { + console.error("Error fetching users:", error); + } + }; + + void fetchUsers(); + }, [setUsers]); +} + +export default GetAllUsers; From b20817ec8aafd833b4e37e989db5cf45b830a7a9 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 00:16:30 +0100 Subject: [PATCH 047/154] Small fix to props and imports --- frontend/src/Components/UserListAdmin.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/frontend/src/Components/UserListAdmin.tsx b/frontend/src/Components/UserListAdmin.tsx index 3d2bcae..76cae9f 100644 --- a/frontend/src/Components/UserListAdmin.tsx +++ b/frontend/src/Components/UserListAdmin.tsx @@ -1,14 +1,6 @@ import { useState } from "react"; -import { PublicUser } from "../Types/goTypes"; import UserInfoModal from "./UserInfoModal"; -/** - * The props for the UserProps component - */ -interface UserProps { - users: PublicUser[]; -} - /** * A list of users for admin manage users page, that sets an onClick * function for eact user
  • element, which displays a modul with @@ -20,7 +12,7 @@ interface UserProps { * return ; */ -export function UserListAdmin(props: UserProps): JSX.Element { +export function UserListAdmin(props: { users: string[] }): JSX.Element { const [modalVisible, setModalVisible] = useState(false); const [username, setUsername] = useState(""); @@ -46,12 +38,12 @@ export function UserListAdmin(props: UserProps): JSX.Element { {props.users.map((user) => (
  • { - handleClick(user.username); + handleClick(user); }} > - {user.username} + {user}
  • ))} From 4e100229f5c3c84d65865547de4c8e1cd03fc2d1 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 00:16:56 +0100 Subject: [PATCH 048/154] Now uses GetAllUsers --- frontend/src/Pages/AdminPages/AdminManageUsers.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx index 0939d77..353fddc 100644 --- a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx @@ -2,15 +2,13 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import BackButton from "../../Components/BackButton"; import { UserListAdmin } from "../../Components/UserListAdmin"; -import { PublicUser } from "../../Types/goTypes"; import { useNavigate } from "react-router-dom"; +import GetAllUsers from "../../Components/GetAllUsers"; +import { useState } from "react"; function AdminManageUsers(): JSX.Element { - //TODO: Change so that it reads users from database - const users: PublicUser[] = []; - for (let i = 1; i <= 20; i++) { - users.push({ userId: "id" + i, username: "Example User " + i }); - } + const [users, setUsers] = useState([]); + GetAllUsers({ setUsersProp: setUsers }); const navigate = useNavigate(); From b13a8b54323db49cb72f7f248f4b867b7d993264 Mon Sep 17 00:00:00 2001 From: dDogge Date: Wed, 20 Mar 2024 00:35:37 +0100 Subject: [PATCH 049/154] Merge --- .../handlers/handlers_project_related.go | 25 +++++++++++++++++ backend/main.go | 2 ++ testing.py | 28 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 2ab5869..a92616d 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -118,6 +118,31 @@ func (gs *GState) ListAllUsersProject(c *fiber.Ctx) error { return c.Status(400).SendString("No project name provided") } + // Get the user token + userToken := c.Locals("user").(*jwt.Token) + claims := userToken.Claims.(jwt.MapClaims) + username := claims["name"].(string) + + // Check if the user is a project manager for the specified project + isManager, err := gs.Db.IsProjectManager(username, projectName) + if err != nil { + log.Info("Error checking project manager status:", err) + return c.Status(500).SendString(err.Error()) + } + + // If the user is not a project manager, check if the user is a site admin + if !isManager { + isAdmin, err := gs.Db.IsSiteAdmin(username) + if err != nil { + log.Info("Error checking admin status:", err) + return c.Status(500).SendString(err.Error()) + } + if !isAdmin { + log.Info("User is neither a project manager nor a site admin:", username) + return c.Status(403).SendString("User is neither a project manager nor a site admin") + } + } + // Get all users associated with the project from the database users, err := gs.Db.GetAllUsersProject(projectName) if err != nil { diff --git a/backend/main.go b/backend/main.go index 60027fd..b907177 100644 --- a/backend/main.go +++ b/backend/main.go @@ -97,6 +97,8 @@ func main() { server.Get("/api/getWeeklyReportsUser", gs.GetWeeklyReportsUserHandler) server.Get("api/checkIfProjectManager", gs.IsProjectManagerHandler) server.Post("/api/ProjectRoleChange", gs.ProjectRoleChange) + server.Get("/api/getUsersProject/:projectName", gs.ListAllUsersProject) + // Announce the port we are listening on and start the server err = server.Listen(fmt.Sprintf(":%d", conf.Port)) if err != nil { diff --git a/testing.py b/testing.py index 0b803f5..491419f 100644 --- a/testing.py +++ b/testing.py @@ -40,6 +40,7 @@ getUserProjectsPath = base_url + "/api/getUserProjects" getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser" checkIfProjectManagerPath = base_url + "/api/checkIfProjectManager" ProjectRoleChangePath = base_url + "/api/ProjectRoleChange" +getUsersProjectPath = base_url + "/api/getUsersProject" #ta bort auth i handlern för att få testet att gå igenom def test_ProjectRoleChange(): @@ -338,7 +339,33 @@ def test_check_if_project_manager(): assert response.status_code == 200, "Check if project manager failed" gprint("test_check_if_project_manager successful") +def test_list_all_users_project(): + # Log in as a user who is a member of the project + admin_username = randomString() + admin_password = "admin_password2" + dprint( + "Registering with username: ", admin_username, " and password: ", admin_password + ) + response = requests.post( + registerPath, json={"username": admin_username, "password": admin_password} + ) + dprint(response.text) + # Log in as the admin + admin_token = login(admin_username, admin_password).json()["token"] + response = requests.post( + promoteToAdminPath, + json={"username": admin_username}, + headers={"Authorization": "Bearer " + admin_token}, + ) + + # Make a request to list all users associated with the project + response = requests.get( + getUsersProjectPath + "/" + projectName, + headers={"Authorization": "Bearer " + admin_token}, + ) + assert response.status_code == 200, "List all users project failed" + gprint("test_list_all_users_project sucessful") if __name__ == "__main__": @@ -354,3 +381,4 @@ if __name__ == "__main__": test_get_weekly_reports_user() test_check_if_project_manager() test_ProjectRoleChange() + test_list_all_users_project() From 7b78767f5016251fe1d47feecc4c56385526fec5 Mon Sep 17 00:00:00 2001 From: al8763be Date: Wed, 20 Mar 2024 01:14:30 +0100 Subject: [PATCH 050/154] restore --- frontend/src/API/API.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index fc2367b..6a52fb8 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -4,6 +4,7 @@ import { User, Project, NewProject, + WeeklyReport, } from "../Types/goTypes"; // This type of pattern should be hard to misuse @@ -49,9 +50,10 @@ interface API { token: string, ): Promise>; getWeeklyReportsForProject( + username: string, projectName: string, token: string, - ): Promise>; + ): Promise>; /** Gets all the projects of a user*/ getUserProjects(token: string): Promise>; /** Gets a project from id*/ @@ -272,15 +274,19 @@ export const api: API = { } }, - async getWeeklyReportsForProject(projectName: string, token: string) { + async getWeeklyReportsForProject( + username: string, + projectName: string, + token: string, + ) { try { - const response = await fetch("/api/getWeeklyReportsForProject", { + const response = await fetch("/api/getWeeklyReportsUser", { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, - body: JSON.stringify({ projectName }), + body: JSON.stringify({ username, projectName }), }); if (!response.ok) { @@ -289,7 +295,7 @@ export const api: API = { message: "Failed to get weekly reports for project", }; } else { - const data = (await response.json()) as NewWeeklyReport[]; + const data = (await response.json()) as WeeklyReport[]; return { success: true, data }; } } catch (e) { From 033268f4eff1908317f86e93f7c73664860ebe9d Mon Sep 17 00:00:00 2001 From: Davenludd Date: Wed, 20 Mar 2024 08:47:11 +0100 Subject: [PATCH 051/154] Added info to component --- frontend/src/Components/AllTimeReportsInProject.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/Components/AllTimeReportsInProject.tsx b/frontend/src/Components/AllTimeReportsInProject.tsx index cc2bac4..809e6ed 100644 --- a/frontend/src/Components/AllTimeReportsInProject.tsx +++ b/frontend/src/Components/AllTimeReportsInProject.tsx @@ -1,3 +1,6 @@ +//Info: This component is used to display all the time reports for a project. It will display the week number, +//total time spent, and if the report has been signed or not. The user can click on a report to edit it. + import React, { useEffect, useState } from "react"; import { WeeklyReport } from "../Types/goTypes"; import { Link, useParams } from "react-router-dom"; From a468b896db0018d70e6b350b76a4f0cdcd1f9143 Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 10:41:16 +0100 Subject: [PATCH 052/154] WIP for funcs that need to be implemented --- backend/internal/handlers/global_state.go | 27 +++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 5d01368..1492a09 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -22,20 +22,19 @@ type GlobalState interface { PromoteToAdmin(c *fiber.Ctx) error GetWeeklyReportsUserHandler(c *fiber.Ctx) error IsProjectManagerHandler(c *fiber.Ctx) error - // GetProject(c *fiber.Ctx) error // To get a specific project - // UpdateProject(c *fiber.Ctx) error // To update a project - // DeleteProject(c *fiber.Ctx) error // To delete a project - // CreateTask(c *fiber.Ctx) error // To create a new task - // GetTasks(c *fiber.Ctx) error // To get all tasks - // GetTask(c *fiber.Ctx) error // To get a specific task - // UpdateTask(c *fiber.Ctx) error // To update a task - // DeleteTask(c *fiber.Ctx) error // To delete a task - // CreateCollection(c *fiber.Ctx) error // To create a new collection - // GetCollections(c *fiber.Ctx) error // To get all collections - // GetCollection(c *fiber.Ctx) error // To get a specific collection - // UpdateCollection(c *fiber.Ctx) error // To update a collection - // DeleteCollection(c *fiber.Ctx) error // To delete a collection - // SignCollection(c *fiber.Ctx) error // To sign a collection + // UpdateProject(c *fiber.Ctx) error // To update a project // WIP + // DeleteProject(c *fiber.Ctx) error // To delete a project // WIP + // CreateTask(c *fiber.Ctx) error // To create a new task // WIP + // GetTasks(c *fiber.Ctx) error // To get all tasks // WIP + // GetTask(c *fiber.Ctx) error // To get a specific task // WIP + // UpdateTask(c *fiber.Ctx) error // To update a task // WIP + // DeleteTask(c *fiber.Ctx) error // To delete a task // WIP + // CreateCollection(c *fiber.Ctx) error // To create a new collection // WIP + // GetCollections(c *fiber.Ctx) error // To get all collections // WIP + // GetCollection(c *fiber.Ctx) error // To get a specific collection // WIP + // UpdateCollection(c *fiber.Ctx) error // To update a collection // WIP + // DeleteCollection(c *fiber.Ctx) error // To delete a collection // WIP + // SignCollection(c *fiber.Ctx) error // To sign a collection // WIP ListAllUsers(c *fiber.Ctx) error // To get a list of all users in the application database ListAllUsersProject(c *fiber.Ctx) error // To get a list of all users for a specific project ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project From cd74758b2f647c291e86b96be1f8c6c3e345c0c1 Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 11:09:48 +0100 Subject: [PATCH 053/154] DeleteProject added in db.go, untested --- backend/internal/database/db.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 842ffbd..92cbc71 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -3,6 +3,7 @@ package database import ( "embed" "errors" + "fmt" "path/filepath" "ttime/internal/types" @@ -19,6 +20,7 @@ type Database interface { PromoteToAdmin(username string) error GetUserId(username string) (int, error) AddProject(name string, description string, username string) error + // DeleteProject(name string, username string) error Migrate() error MigrateSampleData() error GetProjectId(projectname string) (int, error) @@ -70,6 +72,8 @@ const getProjectsForUser = `SELECT p.id, p.name, p.description FROM projects p JOIN user_roles ur ON p.id = ur.project_id JOIN users u ON ur.user_id = u.id WHERE u.username = ?` +const deleteProject = `DELETE FROM projects + WHERE id = ? AND owner_username = ?` // DbConnect connects to the database func DbConnect(dbpath string) Database { @@ -225,6 +229,21 @@ func (d *Db) AddProject(name string, description string, username string) error return err } +func (d *Db) DeleteProject(projectID string, username string) error { + tx := d.MustBegin() + + _, err := tx.Exec(deleteProject, projectID, username) + + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + return fmt.Errorf("error rolling back transaction: %v, delete error: %v", rollbackErr, err) + } + panic(err) + } + + return err +} + func (d *Db) GetAllUsersProject(projectname string) ([]UserProjectMember, error) { // Define the SQL query to fetch users and their roles for a given project query := ` From dce91943b329eb3a308d7bcbd72625959f59269a Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 11:22:33 +0100 Subject: [PATCH 054/154] Added DeleteProject handler, untested --- backend/internal/database/db.go | 2 +- .../internal/handlers/handlers_project_related.go | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 92cbc71..680d7e2 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -20,7 +20,7 @@ type Database interface { PromoteToAdmin(username string) error GetUserId(username string) (int, error) AddProject(name string, description string, username string) error - // DeleteProject(name string, username string) error + DeleteProject(name string, username string) error Migrate() error MigrateSampleData() error GetProjectId(projectname string) (int, error) diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index a92616d..be4ffef 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -30,6 +30,18 @@ func (gs *GState) CreateProject(c *fiber.Ctx) error { return c.Status(200).SendString("Project added") } +func (gs *GState) DeleteProject(c *fiber.Ctx) error { + + projectID := c.Params("projectID") + username := c.Params("username") + + if err := gs.Db.DeleteProject(projectID, username); err != nil { + return c.Status(500).SendString((err.Error())) + } + + return c.Status(200).SendString("Project deleted") +} + // GetUserProjects returns all projects that the user is a member of func (gs *GState) GetUserProjects(c *fiber.Ctx) error { // First we get the username from the token From c01dd21b0a202220fb9cb8a6ef12d9e619fed2f9 Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 11:23:24 +0100 Subject: [PATCH 055/154] uncommented --- backend/internal/handlers/global_state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 1492a09..7a4213b 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -23,7 +23,7 @@ type GlobalState interface { GetWeeklyReportsUserHandler(c *fiber.Ctx) error IsProjectManagerHandler(c *fiber.Ctx) error // UpdateProject(c *fiber.Ctx) error // To update a project // WIP - // DeleteProject(c *fiber.Ctx) error // To delete a project // WIP + DeleteProject(c *fiber.Ctx) error // To delete a project // WIP // CreateTask(c *fiber.Ctx) error // To create a new task // WIP // GetTasks(c *fiber.Ctx) error // To get all tasks // WIP // GetTask(c *fiber.Ctx) error // To get a specific task // WIP From bb93cef1d3fbda86d34fb3053b4dd8ceeb4d305c Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 11:43:47 +0100 Subject: [PATCH 056/154] New deleteproject handler, WIP --- backend/internal/handlers/handlers_project_related.go | 5 +++++ backend/main.go | 1 + 2 files changed, 6 insertions(+) diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index be4ffef..7b95c26 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -226,3 +226,8 @@ func (gs *GState) IsProjectManagerHandler(c *fiber.Ctx) error { // Return the result as JSON return c.JSON(map[string]bool{"isProjectManager": isManager}) } + +func (gs *GState) CreateTask(c *fiber.Ctx) error { + + return nil +} diff --git a/backend/main.go b/backend/main.go index b907177..d0ccdb1 100644 --- a/backend/main.go +++ b/backend/main.go @@ -87,6 +87,7 @@ func main() { server.Get("/api/getUserProjects", gs.GetUserProjects) server.Post("/api/loginrenew", gs.LoginRenew) server.Delete("/api/userdelete/:username", gs.UserDelete) // Perhaps just use POST to avoid headaches + server.Delete("api/project", gs.DeleteProject) // WIP server.Post("/api/project", gs.CreateProject) server.Get("/api/project/:projectId", gs.GetProject) server.Get("/api/getWeeklyReport", gs.GetWeeklyReport) From a5adec82e24b959af3d9c0982e66f94987fe4d20 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 11:51:04 +0100 Subject: [PATCH 057/154] Modul for showing projectinfo *not finished* --- frontend/src/Components/ProjectInfoModal.tsx | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 frontend/src/Components/ProjectInfoModal.tsx diff --git a/frontend/src/Components/ProjectInfoModal.tsx b/frontend/src/Components/ProjectInfoModal.tsx new file mode 100644 index 0000000..11d29c1 --- /dev/null +++ b/frontend/src/Components/ProjectInfoModal.tsx @@ -0,0 +1,44 @@ +import Button from "./Button"; + +function UserInfoModal(props: { + isVisible: boolean; + projectname: string; + onClose: () => void; +}): JSX.Element { + if (!props.isVisible) return <>; + + return ( +
    +
    +

    {props.projectname}

    +
    +

    + Members of this project: +

    +
    {/*Show all members in project*/}
    +
    +
    +
    +
    +
    + ); +} + +export default UserInfoModal; From e271794b57faf12b1635ddc6fde73adcb5784196 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 11:51:50 +0100 Subject: [PATCH 058/154] List for showing all projects as admin --- frontend/src/Components/ProjectListAdmin.tsx | 56 ++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 frontend/src/Components/ProjectListAdmin.tsx diff --git a/frontend/src/Components/ProjectListAdmin.tsx b/frontend/src/Components/ProjectListAdmin.tsx new file mode 100644 index 0000000..dbc7403 --- /dev/null +++ b/frontend/src/Components/ProjectListAdmin.tsx @@ -0,0 +1,56 @@ +import { useState } from "react"; +import { NewProject } from "../Types/goTypes"; +import ProjectInfoModal from "./ProjectInfoModal"; + +/** + * A list of projects for admin manage projects page, that sets an onClick + * function for eact project
  • element, which displays a modul with + * user info. + * @param props - An array of projects to display + * @returns {JSX.Element} The project list + * @example + * const projects: NewProject[] = [{ name: "Project", description: "New" }]; + * return + */ + +export function ProjectListAdmin(props: { + projects: NewProject[]; +}): JSX.Element { + const [modalVisible, setModalVisible] = useState(false); + const [projectname, setProjectname] = useState(""); + + const handleClick = (username: string): void => { + setProjectname(username); + setModalVisible(true); + }; + + const handleClose = (): void => { + setProjectname(""); + setModalVisible(false); + }; + + return ( + <> + +
    +
      + {props.projects.map((project) => ( +
    • { + handleClick(project.name); + }} + > + {project.name} +
    • + ))} +
    +
    + + ); +} From 6317c7674c0957a9b3eed01d7ade1143a57b38c7 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 11:53:27 +0100 Subject: [PATCH 059/154] Now uses projectListAdmin to show projects --- .../src/Pages/AdminPages/AdminManageProjects.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx index 177f55b..14e44be 100644 --- a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx @@ -2,9 +2,20 @@ import { Link } from "react-router-dom"; import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; +import { ProjectListAdmin } from "../../Components/ProjectListAdmin"; +import { NewProject } from "../../Types/goTypes"; function AdminManageProjects(): JSX.Element { - const content = <>; + //TODO: Use fetch to get all projects + const projects: NewProject[] = [{ name: "Project", description: "New" }]; + const content = ( + <> +

    Manage Projects

    +
    + +
    + + ); const buttons = ( <> From 1919b7cb990d11f4769e713bcb5189b13f5fb0c7 Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 12:11:05 +0100 Subject: [PATCH 060/154] Added ChangeUserName in db --- backend/internal/database/db.go | 16 +++++++++ backend/internal/handlers/global_state.go | 1 + .../handlers/handlers_project_related.go | 34 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 680d7e2..8b0c8c4 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -27,6 +27,7 @@ type Database interface { AddWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error AddUserToProject(username string, projectname string, role string) error ChangeUserRole(username string, projectname string, role string) error + ChangeUserName(username string, newname string) error GetAllUsersProject(projectname string) ([]UserProjectMember, error) GetAllUsersApplication() ([]string, error) GetProjectsForUser(username string) ([]types.Project, error) @@ -67,6 +68,7 @@ const addWeeklyReport = `WITH UserLookup AS (SELECT id FROM users WHERE username VALUES ((SELECT id FROM ProjectLookup), (SELECT id FROM UserLookup),?, ?, ?, ?, ?, ?, ?);` const addUserToProject = "INSERT INTO user_roles (user_id, project_id, p_role) VALUES (?, ?, ?)" // WIP const changeUserRole = "UPDATE user_roles SET p_role = ? WHERE user_id = ? AND project_id = ?" +const changeUserName = "UPDATE user SET username = ? WHERE user_id = ?" // WIP const getProjectsForUser = `SELECT p.id, p.name, p.description FROM projects p JOIN user_roles ur ON p.id = ur.project_id @@ -169,6 +171,20 @@ func (d *Db) ChangeUserRole(username string, projectname string, role string) er return err3 } +// ChangeUserRole changes the role of a user within a project. +func (d *Db) ChangeUserName(username string, newname string) error { + // Get the user ID + var userid int + userid, err := d.GetUserId(username) + if err != nil { + panic(err) + } + + // Execute the SQL query to change the user's role + _, err2 := d.Exec(changeUserName, username, userid) + return err2 +} + // GetUserRole retrieves the role of a user within a project. func (d *Db) GetUserRole(username string, projectname string) (string, error) { var role string diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 7a4213b..1934b21 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -38,6 +38,7 @@ type GlobalState interface { ListAllUsers(c *fiber.Ctx) error // To get a list of all users in the application database ListAllUsersProject(c *fiber.Ctx) error // To get a list of all users for a specific project ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project + // ProjectNameChange(c * fiber.Ctx) error // WIP } // "Constructor" diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 7b95c26..055328b 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -93,6 +93,40 @@ func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } +// ProjectRoleChange is a handler that changes a user's role within a project +func (gs *GState) ProjectNameChange(c *fiber.Ctx) error { + + //check token and get username of current user + user := c.Locals("user").(*jwt.Token) + claims := user.Claims.(jwt.MapClaims) + projectManagerUsername := claims["name"].(string) + log.Info(projectManagerUsername) + // Extract the necessary parameters from the request + data := new(types.RoleChange) + if err := c.BodyParser(data); err != nil { + log.Info("error parsing username, project or role") + return c.Status(400).SendString(err.Error()) + } + + // dubble diping and checcking if current user is + + if ismanager, err := gs.Db.IsProjectManager(projectManagerUsername, data.Projectname); err != nil { + log.Warn("Error checking if projectmanager:", err) + return c.Status(500).SendString(err.Error()) + } else if !ismanager { + log.Warn("tried chaning name when not projectmanager:", err) + return c.Status(401).SendString("you can not change name when not projectManager") + } + + // Change the user's role within the project in the database + if err := gs.Db.ChangeUserRole(data.Username, data.Projectname, data.Role); err != nil { + return c.Status(500).SendString(err.Error()) + } + + // Return a success message + return c.SendStatus(fiber.StatusOK) +} + // GetProject retrieves a specific project by its ID func (gs *GState) GetProject(c *fiber.Ctx) error { // Extract the project ID from the request parameters or body From cea2b6c03cba35a49a421a93420009fb59ebc9cf Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 12:25:07 +0100 Subject: [PATCH 061/154] GetProjects compo --- frontend/src/Components/GetProjects.tsx | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 frontend/src/Components/GetProjects.tsx diff --git a/frontend/src/Components/GetProjects.tsx b/frontend/src/Components/GetProjects.tsx new file mode 100644 index 0000000..d6ab1f7 --- /dev/null +++ b/frontend/src/Components/GetProjects.tsx @@ -0,0 +1,37 @@ +import { Dispatch, useEffect } from "react"; +import { Project } from "../Types/goTypes"; +import { api } from "../API/API"; + +/** + * Gets all projects that user is a member of + * @param props - A setStateAction for the array you want to put projects in + * @returns {void} Nothing + * @example + * const [projects, setProjects] = useState([]); + * GetAllUsers({ setProjectsProp: setProjects }); + */ +function GetProjects(props: { + setProjectsProp: Dispatch>; +}): void { + const setProjects: Dispatch> = + props.setProjectsProp; + useEffect(() => { + const fetchUsers = async (): Promise => { + try { + const token = localStorage.getItem("accessToken") ?? ""; + const response = await api.getUserProjects(token); + if (response.success) { + setProjects(response.data ?? []); + } else { + console.error("Failed to fetch projects:", response.message); + } + } catch (error) { + console.error("Error fetching projects:", error); + } + }; + + void fetchUsers(); + }, [setProjects]); +} + +export default GetProjects; From 33b269e0c987faacfe8e487c516ae772cb880736 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Wed, 20 Mar 2024 12:25:59 +0100 Subject: [PATCH 062/154] Now uses GetProjects --- frontend/src/Pages/AdminPages/AdminManageProjects.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx index 14e44be..7ea45df 100644 --- a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx @@ -3,11 +3,13 @@ import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import { ProjectListAdmin } from "../../Components/ProjectListAdmin"; -import { NewProject } from "../../Types/goTypes"; +import { Project } from "../../Types/goTypes"; +import GetProjects from "../../Components/GetProjects"; +import { useState } from "react"; function AdminManageProjects(): JSX.Element { - //TODO: Use fetch to get all projects - const projects: NewProject[] = [{ name: "Project", description: "New" }]; + const [projects, setProjects] = useState([]); + GetProjects({ setProjectsProp: setProjects }); const content = ( <>

    Manage Projects

    From 1b21b2574aa51dc16443792fe084a6dae55fd572 Mon Sep 17 00:00:00 2001 From: Mattias Date: Wed, 20 Mar 2024 12:36:30 +0100 Subject: [PATCH 063/154] Comp for displaying projectmembers and changed path in main --- frontend/src/Components/ProjectMembers.tsx | 99 +++++++++++++++++++ .../ProjectManagerPages/PMProjectMembers.tsx | 13 ++- frontend/src/main.tsx | 8 +- 3 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 frontend/src/Components/ProjectMembers.tsx diff --git a/frontend/src/Components/ProjectMembers.tsx b/frontend/src/Components/ProjectMembers.tsx new file mode 100644 index 0000000..e1f261e --- /dev/null +++ b/frontend/src/Components/ProjectMembers.tsx @@ -0,0 +1,99 @@ +import { useEffect, useState } from "react"; +import { Link, useParams } from "react-router-dom"; + +function ProjectMembers(): JSX.Element { + const { projectName } = useParams(); + const [projectMembers, setProjectMembers] = useState([]); + + // const getProjectMembers = async (): Promise => { + // const token = localStorage.getItem("accessToken") ?? ""; + // const response = await api.getProjectMembers(projectName ?? "", token); + // console.log(response); + // if (response.success) { + // setProjectMembers(response.data ?? []); + // } else { + // console.error(response.message); + // } + // }; + + interface ProjectMember { + username: string; + role: string; + } + + const mockProjectMembers = [ + { + username: "username1", + role: "Project Manager", + }, + { + username: "username2", + role: "System Manager", + }, + { + username: "username3", + role: "Developer", + }, + { + username: "username4", + role: "Tester", + }, + { + username: "username5", + role: "Tester", + }, + { + username: "username6", + role: "Tester", + }, + ]; + + const getProjectMembers = async (): Promise => { + // Use the mock data + setProjectMembers(mockProjectMembers); + + await Promise.resolve(); + }; + + useEffect(() => { + void getProjectMembers(); + }, []); + + return ( + <> +
    + {projectMembers.map((projectMember, index) => ( +

    +
    +
    +

    {projectMember.username}

    + Role: +

    {projectMember.role}

    +
    +
    +
    + +

    + View Reports +

    + + +

    + Change Role +

    + +
    +
    +
    +

    + ))} +
    + + ); +} + +export default ProjectMembers; diff --git a/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx b/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx index 9fe96cf..11b8636 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx @@ -1,10 +1,19 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import BackButton from "../../Components/BackButton"; -import { Link } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; +import ProjectMembers from "../../Components/ProjectMembers"; function PMProjectMembers(): JSX.Element { - const content = <>; + const { projectName } = useParams(); + const content = ( + <> +

    + All Members In: {projectName}{" "} +

    + + + ); const buttons = ( <> diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 25c7a35..bac2292 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -64,7 +64,7 @@ const router = createBrowserRouter([ element: , }, { - path: "/changeRole", + path: "/changeRole/:projectName/:username", element: , }, { @@ -72,11 +72,11 @@ const router = createBrowserRouter([ element: , }, { - path: "/projectMembers", + path: "/projectMembers/:projectName", element: , }, { - path: "/PMProjectPage", + path: "/PMProjectPage/:projectName", element: , }, { @@ -88,7 +88,7 @@ const router = createBrowserRouter([ element: , }, { - path: "/unsignedReports", + path: "/unsignedReports/:projectName", element: , }, { From 3515a86bbb7dd6062efc9e94dae3c6252a99270b Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 12:50:04 +0100 Subject: [PATCH 064/154] Added ChangeUserName handler, untested and WIP, --- backend/internal/handlers/global_state.go | 2 +- .../handlers/handlers_project_related.go | 34 ----------- .../handlers/handlers_user_related.go | 58 +++++++++++++++---- backend/internal/types/project.go | 5 ++ backend/main.go | 1 + 5 files changed, 53 insertions(+), 47 deletions(-) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 1934b21..4a4b73f 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -38,7 +38,7 @@ type GlobalState interface { ListAllUsers(c *fiber.Ctx) error // To get a list of all users in the application database ListAllUsersProject(c *fiber.Ctx) error // To get a list of all users for a specific project ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project - // ProjectNameChange(c * fiber.Ctx) error // WIP + ChangeUserName(c *fiber.Ctx) error // WIP } // "Constructor" diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 055328b..7b95c26 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -93,40 +93,6 @@ func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } -// ProjectRoleChange is a handler that changes a user's role within a project -func (gs *GState) ProjectNameChange(c *fiber.Ctx) error { - - //check token and get username of current user - user := c.Locals("user").(*jwt.Token) - claims := user.Claims.(jwt.MapClaims) - projectManagerUsername := claims["name"].(string) - log.Info(projectManagerUsername) - // Extract the necessary parameters from the request - data := new(types.RoleChange) - if err := c.BodyParser(data); err != nil { - log.Info("error parsing username, project or role") - return c.Status(400).SendString(err.Error()) - } - - // dubble diping and checcking if current user is - - if ismanager, err := gs.Db.IsProjectManager(projectManagerUsername, data.Projectname); err != nil { - log.Warn("Error checking if projectmanager:", err) - return c.Status(500).SendString(err.Error()) - } else if !ismanager { - log.Warn("tried chaning name when not projectmanager:", err) - return c.Status(401).SendString("you can not change name when not projectManager") - } - - // Change the user's role within the project in the database - if err := gs.Db.ChangeUserRole(data.Username, data.Projectname, data.Role); err != nil { - return c.Status(500).SendString(err.Error()) - } - - // Return a success message - return c.SendStatus(fiber.StatusOK) -} - // GetProject retrieves a specific project by its ID func (gs *GState) GetProject(c *fiber.Ctx) error { // Extract the project ID from the request parameters or body diff --git a/backend/internal/handlers/handlers_user_related.go b/backend/internal/handlers/handlers_user_related.go index 75b8953..862416c 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -105,7 +105,7 @@ func (gs *GState) Login(c *fiber.Ctx) error { if err != nil { log.Info("Error checking admin status:", err) return c.Status(500).SendString(err.Error()) -} + } // Create the Claims claims := jwt.MapClaims{ "name": u.Username, @@ -187,17 +187,17 @@ func (gs *GState) ListAllUsers(c *fiber.Ctx) error { return c.JSON(users) } -// @Summary PromoteToAdmin -// @Description promote chosen user to admin -// @Tags User -// @Accept json -// @Produce plain -// @Param NewUser body types.NewUser true "user info" -// @Success 200 {json} json "Successfully prometed user" -// @Failure 400 {string} string "bad request" -// @Failure 401 {string} string "Unauthorized" -// @Failure 500 {string} string "Internal server error" -// @Router /promoteToAdmin [post] +// @Summary PromoteToAdmin +// @Description promote chosen user to admin +// @Tags User +// @Accept json +// @Produce plain +// @Param NewUser body types.NewUser true "user info" +// @Success 200 {json} json "Successfully prometed user" +// @Failure 400 {string} string "bad request" +// @Failure 401 {string} string "Unauthorized" +// @Failure 500 {string} string "Internal server error" +// @Router /promoteToAdmin [post] func (gs *GState) PromoteToAdmin(c *fiber.Ctx) error { // Extract the username from the request body var newUser types.NewUser @@ -219,3 +219,37 @@ func (gs *GState) PromoteToAdmin(c *fiber.Ctx) error { // Return a success message return c.SendStatus(fiber.StatusOK) } + +// Changes a users name in the database +func (gs *GState) ChangeUserName(c *fiber.Ctx) error { + + //check token and get username of current user + user := c.Locals("user").(*jwt.Token) + claims := user.Claims.(jwt.MapClaims) + projectManagerUsername := claims["name"].(string) + log.Info(projectManagerUsername) + // Extract the necessary parameters from the request + data := new(types.NameChange) + if err := c.BodyParser(data); err != nil { + log.Info("error parsing username, project or role") + return c.Status(400).SendString(err.Error()) + } + + // dubble diping and checcking if current user is + + if ismanager, err := gs.Db.IsProjectManager(projectManagerUsername, c.Params(data.Name)); err != nil { + log.Warn("Error checking if projectmanager:", err) + return c.Status(500).SendString(err.Error()) + } else if !ismanager { + log.Warn("tried changing name when not projectmanager:", err) + return c.Status(401).SendString("you can not change name when not projectManager") + } + + // Change the user's name within the project in the database + if err := gs.Db.ChangeUserName(projectManagerUsername, data.Name); err != nil { + return c.Status(500).SendString(err.Error()) + } + + // Return a success message + return c.SendStatus(fiber.StatusOK) +} diff --git a/backend/internal/types/project.go b/backend/internal/types/project.go index c336bcb..6a7c91a 100644 --- a/backend/internal/types/project.go +++ b/backend/internal/types/project.go @@ -19,3 +19,8 @@ type RoleChange struct { Username string `json:"username"` Projectname string `json:"projectname"` } + +type NameChange struct { + ID int `json:"id" db:"id"` + Name string `json:"name" db:"name"` +} diff --git a/backend/main.go b/backend/main.go index d0ccdb1..8a70186 100644 --- a/backend/main.go +++ b/backend/main.go @@ -93,6 +93,7 @@ func main() { server.Get("/api/getWeeklyReport", gs.GetWeeklyReport) server.Post("/api/signReport", gs.SignReport) server.Put("/api/addUserToProject", gs.AddUserToProjectHandler) + server.Put("/api/changeUserName", gs.ChangeUserName) server.Post("/api/promoteToAdmin", gs.PromoteToAdmin) server.Get("/api/users/all", gs.ListAllUsers) server.Get("/api/getWeeklyReportsUser", gs.GetWeeklyReportsUserHandler) From a18ce465de6639b994b22d55d0c28ed5d44da252 Mon Sep 17 00:00:00 2001 From: borean Date: Wed, 20 Mar 2024 13:03:43 +0100 Subject: [PATCH 065/154] Added a handler for getting all users for a specific project, WIP and untested --- backend/internal/handlers/global_state.go | 1 + backend/internal/handlers/handlers_user_related.go | 14 ++++++++++++++ backend/main.go | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 4a4b73f..a3e43ce 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -39,6 +39,7 @@ type GlobalState interface { ListAllUsersProject(c *fiber.Ctx) error // To get a list of all users for a specific project ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project ChangeUserName(c *fiber.Ctx) error // WIP + GetAllUsersProject(c *fiber.Ctx) error // WIP } // "Constructor" diff --git a/backend/internal/handlers/handlers_user_related.go b/backend/internal/handlers/handlers_user_related.go index 862416c..ea511ac 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -187,6 +187,20 @@ func (gs *GState) ListAllUsers(c *fiber.Ctx) error { return c.JSON(users) } +func (gs *GState) GetAllUsersProject(c *fiber.Ctx) error { + // Get all users from a project + projectName := c.Params("projectName") + users, err := gs.Db.GetAllUsersProject(projectName) + if err != nil { + log.Info("Error getting users from project:", err) // Debug print + return c.Status(500).SendString(err.Error()) + } + + log.Info("Returning all users") + // Return the list of users as JSON + return c.JSON(users) +} + // @Summary PromoteToAdmin // @Description promote chosen user to admin // @Tags User diff --git a/backend/main.go b/backend/main.go index 8a70186..888cb51 100644 --- a/backend/main.go +++ b/backend/main.go @@ -88,8 +88,9 @@ func main() { server.Post("/api/loginrenew", gs.LoginRenew) server.Delete("/api/userdelete/:username", gs.UserDelete) // Perhaps just use POST to avoid headaches server.Delete("api/project", gs.DeleteProject) // WIP - server.Post("/api/project", gs.CreateProject) + server.Post("/api/project", gs.CreateProject) // WIP server.Get("/api/project/:projectId", gs.GetProject) + server.Get("/api/project/getAllUsers", gs.GetAllUsersProject) server.Get("/api/getWeeklyReport", gs.GetWeeklyReport) server.Post("/api/signReport", gs.SignReport) server.Put("/api/addUserToProject", gs.AddUserToProjectHandler) From d3bb6f49e5d597b7c73816de2cbffd54dd766978 Mon Sep 17 00:00:00 2001 From: Mattias Date: Wed, 20 Mar 2024 13:51:49 +0100 Subject: [PATCH 066/154] New comp changeRoles --- frontend/src/Components/ChangeRoles.tsx | 83 +++++++++++++++++++ .../ProjectManagerPages/PMChangeRole.tsx | 15 ++-- 2 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 frontend/src/Components/ChangeRoles.tsx diff --git a/frontend/src/Components/ChangeRoles.tsx b/frontend/src/Components/ChangeRoles.tsx new file mode 100644 index 0000000..e11d623 --- /dev/null +++ b/frontend/src/Components/ChangeRoles.tsx @@ -0,0 +1,83 @@ +import { useState } from "react"; +import { useParams } from "react-router-dom"; +import Button from "./Button"; + +export default function ChangeRoles(): JSX.Element { + const [selectedRole, setSelectedRole] = useState(""); + const { username } = useParams(); + + const handleRoleChange = ( + event: React.ChangeEvent, + ): void => { + setSelectedRole(event.target.value); + }; + + // const handleSubmit = async (event: React.FormEvent) => { + // event.preventDefault(); + + // const response = await api.changeRole(username, selectedRole, token); + // if (response.success) { + // console.log("Role changed successfully"); + // } else { + // console.error("Failed to change role:", response.message); + // } + // }; + + return ( + <> +

    + Change roll for: {username} +

    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    ; -} From aa5c4017bb3087d475e4fd85a1f94c7a9d5463c6 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Wed, 20 Mar 2024 13:54:13 +0100 Subject: [PATCH 073/154] Docs/Comments to DisplayUserProjects component --- frontend/src/Components/DisplayUserProjects.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/Components/DisplayUserProjects.tsx b/frontend/src/Components/DisplayUserProjects.tsx index 266f1ce..f4fd782 100644 --- a/frontend/src/Components/DisplayUserProjects.tsx +++ b/frontend/src/Components/DisplayUserProjects.tsx @@ -3,6 +3,10 @@ import { Project } from "../Types/goTypes"; import { Link } from "react-router-dom"; import { api } from "../API/API"; +/** + * Renders a component that displays the projects a user is a part of and links to the projects start-page. + * @returns The JSX element representing the component. + */ function DisplayUserProject(): JSX.Element { const [projects, setProjects] = useState([]); @@ -16,6 +20,7 @@ function DisplayUserProject(): JSX.Element { console.error(response.message); } }; + // Call getProjects when the component mounts useEffect(() => { void getProjects(); From dbeeb609b322d0572abff578e00ac7c0ad44d020 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Wed, 20 Mar 2024 13:54:32 +0100 Subject: [PATCH 074/154] Docs/Comments to GetWeeklyReport component --- frontend/src/Components/EditWeeklyReport.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx index 3017204..e824b19 100644 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ b/frontend/src/Components/EditWeeklyReport.tsx @@ -4,6 +4,10 @@ import { api } from "../API/API"; import { useNavigate, useParams } from "react-router-dom"; import Button from "./Button"; +/** + * Renders the component for editing a weekly report. + * @returns JSX.Element + */ export default function GetWeeklyReport(): JSX.Element { const [week, setWeek] = useState(0); const [developmentTime, setDevelopmentTime] = useState(0); From cf6c8cd34c779b86ffa07a96427aa66a1be7d1a8 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Wed, 20 Mar 2024 13:54:59 +0100 Subject: [PATCH 075/154] Docs/Comments to Footer component --- frontend/src/Components/Footer.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontend/src/Components/Footer.tsx b/frontend/src/Components/Footer.tsx index a3b7469..192926f 100644 --- a/frontend/src/Components/Footer.tsx +++ b/frontend/src/Components/Footer.tsx @@ -1,5 +1,13 @@ +//info: Footer component to display the footer of a page where the buttons are placed import React from "react"; +/** + * Footer component. + * + * @param {Object} props - The component props. + * @param {React.ReactNode} props.children - The children elements to render inside the footer (buttons). + * @returns {JSX.Element} The rendered footer component. + */ function Footer({ children }: { children: React.ReactNode }): JSX.Element { return (