Merge branch 'frontend' into gruppDM
This commit is contained in:
commit
7ed9398bcb
13 changed files with 149 additions and 38 deletions
|
@ -131,3 +131,11 @@ install-just:
|
|||
.PHONY: types
|
||||
types:
|
||||
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
|
||||
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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -58,6 +58,8 @@ interface API {
|
|||
getUserProjects(token: string): Promise<APIResponse<Project[]>>;
|
||||
/** Gets a project from id*/
|
||||
getProject(id: number): Promise<APIResponse<Project>>;
|
||||
/** Gets a project from id*/
|
||||
getAllUsers(token: string): Promise<APIResponse<string[]>>;
|
||||
}
|
||||
|
||||
// Export an instance of the API
|
||||
|
@ -94,7 +96,7 @@ export const api: API = {
|
|||
token: string,
|
||||
): Promise<APIResponse<User>> {
|
||||
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<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;
|
||||
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");
|
||||
|
|
|
@ -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 <li> element, which displays a modul with
|
||||
|
@ -20,7 +12,7 @@ interface UserProps {
|
|||
* 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 [username, setUsername] = useState("");
|
||||
|
||||
|
@ -46,12 +38,12 @@ export function UserListAdmin(props: UserProps): JSX.Element {
|
|||
{props.users.map((user) => (
|
||||
<li
|
||||
className="pt-5"
|
||||
key={user.userId}
|
||||
key={user}
|
||||
onClick={() => {
|
||||
handleClick(user.username);
|
||||
handleClick(user);
|
||||
}}
|
||||
>
|
||||
{user.username}
|
||||
{user}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
|
|
@ -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<string[]>([]);
|
||||
GetAllUsers({ setUsersProp: setUsers });
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -43,10 +43,6 @@ const router = createBrowserRouter([
|
|||
path: "/admin",
|
||||
element: <AdminMenuPage />,
|
||||
},
|
||||
{
|
||||
path: "/pm",
|
||||
element: <YourProjectsPage />,
|
||||
},
|
||||
{
|
||||
path: "/yourProjects",
|
||||
element: <YourProjectsPage />,
|
||||
|
|
30
testing.py
30
testing.py
|
@ -39,6 +39,35 @@ 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()
|
||||
|
|
Loading…
Reference in a new issue