Merge branch 'frontend' into gruppDM
This commit is contained in:
commit
7ed9398bcb
13 changed files with 149 additions and 38 deletions
|
@ -130,4 +130,12 @@ install-just:
|
||||||
|
|
||||||
.PHONY: types
|
.PHONY: types
|
||||||
types:
|
types:
|
||||||
tygo generate
|
tygo generate
|
||||||
|
|
||||||
|
.PHONY: install-golds
|
||||||
|
install-golds:
|
||||||
|
go install go101.org/golds@latest
|
||||||
|
|
||||||
|
.PHONY: golds
|
||||||
|
golds:
|
||||||
|
golds -port 6060 -nouses -plainsrc -wdpkgs-listing=promoted ./...
|
||||||
|
|
|
@ -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
|
// ProjectRoleChange is a handler that changes a user's role within a project
|
||||||
func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error {
|
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
|
// Extract the necessary parameters from the request
|
||||||
username := c.Params("username")
|
data := new(types.RoleChange)
|
||||||
projectName := c.Params("projectName")
|
if err := c.BodyParser(data); err != nil {
|
||||||
role := c.Params("role")
|
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
|
// 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())
|
return c.Status(500).SendString(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,10 +101,15 @@ func (gs *GState) Login(c *fiber.Ctx) error {
|
||||||
return c.SendStatus(fiber.StatusUnauthorized)
|
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
|
// Create the Claims
|
||||||
claims := jwt.MapClaims{
|
claims := jwt.MapClaims{
|
||||||
"name": u.Username,
|
"name": u.Username,
|
||||||
"admin": false,
|
"admin": isAdmin,
|
||||||
"exp": time.Now().Add(time.Hour * 72).Unix(),
|
"exp": time.Now().Add(time.Hour * 72).Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,3 +13,9 @@ type NewProject struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RoleChange struct {
|
||||||
|
Role string `json:"role" tstype:"'project_manager' | 'user'"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Projectname string `json:"projectname"`
|
||||||
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ func main() {
|
||||||
server.Get("/api/users/all", gs.ListAllUsers)
|
server.Get("/api/users/all", gs.ListAllUsers)
|
||||||
server.Get("/api/getWeeklyReportsUser", gs.GetWeeklyReportsUserHandler)
|
server.Get("/api/getWeeklyReportsUser", gs.GetWeeklyReportsUserHandler)
|
||||||
server.Get("api/checkIfProjectManager", gs.IsProjectManagerHandler)
|
server.Get("api/checkIfProjectManager", gs.IsProjectManagerHandler)
|
||||||
|
server.Post("/api/ProjectRoleChange", gs.ProjectRoleChange)
|
||||||
// Announce the port we are listening on and start the server
|
// Announce the port we are listening on and start the server
|
||||||
err = server.Listen(fmt.Sprintf(":%d", conf.Port))
|
err = server.Listen(fmt.Sprintf(":%d", conf.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -58,6 +58,8 @@ interface API {
|
||||||
getUserProjects(token: string): Promise<APIResponse<Project[]>>;
|
getUserProjects(token: string): Promise<APIResponse<Project[]>>;
|
||||||
/** Gets a project from id*/
|
/** Gets a project from id*/
|
||||||
getProject(id: number): Promise<APIResponse<Project>>;
|
getProject(id: number): Promise<APIResponse<Project>>;
|
||||||
|
/** Gets a project from id*/
|
||||||
|
getAllUsers(token: string): Promise<APIResponse<string[]>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export an instance of the API
|
// Export an instance of the API
|
||||||
|
@ -94,7 +96,7 @@ export const api: API = {
|
||||||
token: string,
|
token: string,
|
||||||
): Promise<APIResponse<User>> {
|
): Promise<APIResponse<User>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/userdelete", {
|
const response = await fetch(`/api/userdelete/${username}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -352,4 +354,32 @@ export const api: API = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Gets all users
|
||||||
|
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",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
35
frontend/src/Components/GetAllUsers.tsx
Normal file
35
frontend/src/Components/GetAllUsers.tsx
Normal file
|
@ -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<string[]>([]);
|
||||||
|
* GetAllUsers({ setUsersProp: setUsers });
|
||||||
|
*/
|
||||||
|
function GetAllUsers(props: {
|
||||||
|
setUsersProp: Dispatch<React.SetStateAction<string[]>>;
|
||||||
|
}): void {
|
||||||
|
const setUsers: Dispatch<React.SetStateAction<string[]>> = props.setUsersProp;
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUsers = async (): Promise<void> => {
|
||||||
|
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;
|
|
@ -32,16 +32,11 @@ function LoginCheck(props: {
|
||||||
prevAuth = 1;
|
prevAuth = 1;
|
||||||
return prevAuth;
|
return prevAuth;
|
||||||
});
|
});
|
||||||
} else if (token !== "" && props.username === "pm") {
|
} else if (token !== "") {
|
||||||
props.setAuthority((prevAuth) => {
|
props.setAuthority((prevAuth) => {
|
||||||
prevAuth = 2;
|
prevAuth = 2;
|
||||||
return prevAuth;
|
return prevAuth;
|
||||||
});
|
});
|
||||||
} else if (token !== "" && props.username === "user") {
|
|
||||||
props.setAuthority((prevAuth) => {
|
|
||||||
prevAuth = 3;
|
|
||||||
return prevAuth;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error("Token was undefined");
|
console.error("Token was undefined");
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { PublicUser } from "../Types/goTypes";
|
|
||||||
import UserInfoModal from "./UserInfoModal";
|
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
|
* A list of users for admin manage users page, that sets an onClick
|
||||||
* function for eact user <li> element, which displays a modul with
|
* function for eact user <li> element, which displays a modul with
|
||||||
|
@ -20,7 +12,7 @@ interface UserProps {
|
||||||
* return <UserList users={users} />;
|
* return <UserList users={users} />;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function UserListAdmin(props: UserProps): JSX.Element {
|
export function UserListAdmin(props: { users: string[] }): JSX.Element {
|
||||||
const [modalVisible, setModalVisible] = useState(false);
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
|
|
||||||
|
@ -46,12 +38,12 @@ export function UserListAdmin(props: UserProps): JSX.Element {
|
||||||
{props.users.map((user) => (
|
{props.users.map((user) => (
|
||||||
<li
|
<li
|
||||||
className="pt-5"
|
className="pt-5"
|
||||||
key={user.userId}
|
key={user}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleClick(user.username);
|
handleClick(user);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{user.username}
|
{user}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -2,15 +2,13 @@ import BasicWindow from "../../Components/BasicWindow";
|
||||||
import Button from "../../Components/Button";
|
import Button from "../../Components/Button";
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
import { UserListAdmin } from "../../Components/UserListAdmin";
|
import { UserListAdmin } from "../../Components/UserListAdmin";
|
||||||
import { PublicUser } from "../../Types/goTypes";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import GetAllUsers from "../../Components/GetAllUsers";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
function AdminManageUsers(): JSX.Element {
|
function AdminManageUsers(): JSX.Element {
|
||||||
//TODO: Change so that it reads users from database
|
const [users, setUsers] = useState<string[]>([]);
|
||||||
const users: PublicUser[] = [];
|
GetAllUsers({ setUsersProp: setUsers });
|
||||||
for (let i = 1; i <= 20; i++) {
|
|
||||||
users.push({ userId: "id" + i, username: "Example User " + i });
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ function App(): JSX.Element {
|
||||||
if (authority === 1) {
|
if (authority === 1) {
|
||||||
navigate("/admin");
|
navigate("/admin");
|
||||||
} else if (authority === 2) {
|
} else if (authority === 2) {
|
||||||
navigate("/pm");
|
|
||||||
} else if (authority === 3) {
|
|
||||||
navigate("/yourProjects");
|
navigate("/yourProjects");
|
||||||
}
|
}
|
||||||
}, [authority, navigate]);
|
}, [authority, navigate]);
|
||||||
|
|
|
@ -43,10 +43,6 @@ const router = createBrowserRouter([
|
||||||
path: "/admin",
|
path: "/admin",
|
||||||
element: <AdminMenuPage />,
|
element: <AdminMenuPage />,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/pm",
|
|
||||||
element: <YourProjectsPage />,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/yourProjects",
|
path: "/yourProjects",
|
||||||
element: <YourProjectsPage />,
|
element: <YourProjectsPage />,
|
||||||
|
|
30
testing.py
30
testing.py
|
@ -39,7 +39,36 @@ promoteToAdminPath = base_url + "/api/promoteToAdmin"
|
||||||
getUserProjectsPath = base_url + "/api/getUserProjects"
|
getUserProjectsPath = base_url + "/api/getUserProjects"
|
||||||
getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser"
|
getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser"
|
||||||
checkIfProjectManagerPath = base_url + "/api/checkIfProjectManager"
|
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():
|
def test_get_user_projects():
|
||||||
|
|
||||||
|
@ -324,3 +353,4 @@ if __name__ == "__main__":
|
||||||
test_add_user_to_project()
|
test_add_user_to_project()
|
||||||
test_get_weekly_reports_user()
|
test_get_weekly_reports_user()
|
||||||
test_check_if_project_manager()
|
test_check_if_project_manager()
|
||||||
|
test_ProjectRoleChange()
|
||||||
|
|
Loading…
Reference in a new issue