diff --git a/backend/Makefile b/backend/Makefile index 65a2f3c..331f8d5 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -130,4 +130,12 @@ install-just: .PHONY: types types: - tygo generate \ No newline at end of file + tygo generate + +.PHONY: install-golds +install-golds: + go install go101.org/golds@latest + +.PHONY: golds +golds: + golds -port 6060 -nouses -plainsrc -wdpkgs-listing=promoted ./... 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/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(), } 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/frontend/src/API/API.ts b/frontend/src/API/API.ts index 3ebf343..e25f1d7 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -58,6 +58,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 @@ -94,7 +96,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", @@ -352,4 +354,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", + }); + } + }, }; 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; diff --git a/frontend/src/Components/LoginCheck.tsx b/frontend/src/Components/LoginCheck.tsx index ce7d52c..f44d7f3 100644 --- a/frontend/src/Components/LoginCheck.tsx +++ b/frontend/src/Components/LoginCheck.tsx @@ -32,16 +32,11 @@ function LoginCheck(props: { prevAuth = 1; return prevAuth; }); - } else if (token !== "" && props.username === "pm") { + } else if (token !== "") { props.setAuthority((prevAuth) => { prevAuth = 2; return prevAuth; }); - } else if (token !== "" && props.username === "user") { - props.setAuthority((prevAuth) => { - prevAuth = 3; - return prevAuth; - }); } } else { console.error("Token was undefined"); 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}
  • ))} 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(); diff --git a/frontend/src/Pages/App.tsx b/frontend/src/Pages/App.tsx index 69fd698..62e1b36 100644 --- a/frontend/src/Pages/App.tsx +++ b/frontend/src/Pages/App.tsx @@ -11,8 +11,6 @@ function App(): JSX.Element { if (authority === 1) { navigate("/admin"); } else if (authority === 2) { - navigate("/pm"); - } else if (authority === 3) { navigate("/yourProjects"); } }, [authority, navigate]); diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index ddf7119..25c7a35 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -43,10 +43,6 @@ const router = createBrowserRouter([ path: "/admin", element: , }, - { - path: "/pm", - element: , - }, { path: "/yourProjects", element: , 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()