Merge remote-tracking branch 'origin/AlexTester' into BumBranch
This commit is contained in:
commit
5d714bbacf
8 changed files with 219 additions and 68 deletions
|
@ -42,6 +42,7 @@ type Database interface {
|
||||||
IsProjectManager(username string, projectname string) (bool, error)
|
IsProjectManager(username string, projectname string) (bool, error)
|
||||||
GetProjectTimes(projectName string) (map[string]int, error)
|
GetProjectTimes(projectName string) (map[string]int, error)
|
||||||
UpdateWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error
|
UpdateWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error
|
||||||
|
RemoveProject(projectname string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// This struct is a wrapper type that holds the database connection
|
// This struct is a wrapper type that holds the database connection
|
||||||
|
@ -595,3 +596,8 @@ func (d *Db) GetProjectTimes(projectName string) (map[string]int, error) {
|
||||||
|
|
||||||
return totalTime, nil
|
return totalTime, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Db) RemoveProject(projectname string) error {
|
||||||
|
_, err := d.Exec("DELETE FROM projects WHERE name = ?", projectname)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -935,3 +935,33 @@ func TestUpdateWeeklyReport(t *testing.T) {
|
||||||
t.Error("UpdateWeeklyReport failed: report not updated correctly")
|
t.Error("UpdateWeeklyReport failed: report not updated correctly")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveProject(t *testing.T) {
|
||||||
|
db, err := setupAdvancedState()
|
||||||
|
if err != nil {
|
||||||
|
t.Error("setupState failed:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Promote user to Admin
|
||||||
|
err = db.PromoteToAdmin("demouser")
|
||||||
|
if err != nil {
|
||||||
|
t.Error("PromoteToAdmin failed:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove project
|
||||||
|
err = db.RemoveProject("projecttest")
|
||||||
|
if err != nil {
|
||||||
|
t.Error("RemoveProject failed:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the project was removed
|
||||||
|
projects, err := db.GetAllProjects()
|
||||||
|
if err != nil {
|
||||||
|
t.Error("GetAllProjects failed:", err)
|
||||||
|
}
|
||||||
|
if len(projects) != 0 {
|
||||||
|
t.Error("RemoveProject failed: expected 0, got", len(projects))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ type GlobalState interface {
|
||||||
GetAllUsersProject(c *fiber.Ctx) error // WIP
|
GetAllUsersProject(c *fiber.Ctx) error // WIP
|
||||||
GetUnsignedReports(c *fiber.Ctx) error //
|
GetUnsignedReports(c *fiber.Ctx) error //
|
||||||
UpdateWeeklyReport(c *fiber.Ctx) error
|
UpdateWeeklyReport(c *fiber.Ctx) error
|
||||||
|
RemoveProject(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Constructor"
|
// "Constructor"
|
||||||
|
|
|
@ -219,7 +219,7 @@ func (gs *GState) IsProjectManagerHandler(c *fiber.Ctx) error {
|
||||||
username := claims["name"].(string)
|
username := claims["name"].(string)
|
||||||
|
|
||||||
// Extract necessary parameters from the request query string
|
// Extract necessary parameters from the request query string
|
||||||
projectName := c.Params("projectName")
|
projectName := c.Query("projectName")
|
||||||
|
|
||||||
log.Info("Checking if user ", username, " is a project manager for project ", projectName)
|
log.Info("Checking if user ", username, " is a project manager for project ", projectName)
|
||||||
|
|
||||||
|
@ -231,59 +231,85 @@ func (gs *GState) IsProjectManagerHandler(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the result as JSON
|
// Return the result as JSON
|
||||||
return c.JSON(fiber.Map{"isProjectManager": isManager})
|
return c.JSON(map[string]bool{"isProjectManager": isManager})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *GState) GetProjectTimesHandler(c *fiber.Ctx) error {
|
func (gs *GState) GetProjectTimesHandler(c *fiber.Ctx) error {
|
||||||
// Get the username from the token
|
// Get the username from the token
|
||||||
user := c.Locals("user").(*jwt.Token)
|
user := c.Locals("user").(*jwt.Token)
|
||||||
claims := user.Claims.(jwt.MapClaims)
|
claims := user.Claims.(jwt.MapClaims)
|
||||||
username := claims["name"].(string)
|
username := claims["name"].(string)
|
||||||
|
|
||||||
// Get project
|
// Get project
|
||||||
projectName := c.Params("projectName")
|
projectName := c.Params("projectName")
|
||||||
if projectName == "" {
|
if projectName == "" {
|
||||||
log.Info("No project name provided")
|
log.Info("No project name provided")
|
||||||
return c.Status(400).SendString("No project name provided")
|
return c.Status(400).SendString("No project name provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all users in the project and roles
|
// Get all users in the project and roles
|
||||||
userProjects, err := gs.Db.GetAllUsersProject(projectName)
|
userProjects, err := gs.Db.GetAllUsersProject(projectName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Error getting users in project:", err)
|
log.Info("Error getting users in project:", err)
|
||||||
return c.Status(500).SendString(err.Error())
|
return c.Status(500).SendString(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is member
|
// If the user is member
|
||||||
isMember := false
|
isMember := false
|
||||||
for _, userProject := range userProjects {
|
for _, userProject := range userProjects {
|
||||||
if userProject.Username == username {
|
if userProject.Username == username {
|
||||||
isMember = true
|
isMember = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is admin
|
// If the user is admin
|
||||||
if !isMember {
|
if !isMember {
|
||||||
isAdmin, err := gs.Db.IsSiteAdmin(username)
|
isAdmin, err := gs.Db.IsSiteAdmin(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Error checking admin status:", err)
|
log.Info("Error checking admin status:", err)
|
||||||
return c.Status(500).SendString(err.Error())
|
return c.Status(500).SendString(err.Error())
|
||||||
}
|
}
|
||||||
if !isAdmin {
|
if !isAdmin {
|
||||||
log.Info("User is neither a project member nor a site admin:", username)
|
log.Info("User is neither a project member nor a site admin:", username)
|
||||||
return c.Status(403).SendString("User is neither a project member nor a site admin")
|
return c.Status(403).SendString("User is neither a project member nor a site admin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get project times
|
// Get project times
|
||||||
projectTimes, err := gs.Db.GetProjectTimes(projectName)
|
projectTimes, err := gs.Db.GetProjectTimes(projectName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Error getting project times:", err)
|
log.Info("Error getting project times:", err)
|
||||||
return c.Status(500).SendString(err.Error())
|
return c.Status(500).SendString(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return project times as JSON
|
// Return project times as JSON
|
||||||
log.Info("Returning project times for project:", projectName)
|
log.Info("Returning project times for project:", projectName)
|
||||||
return c.JSON(projectTimes)
|
return c.JSON(projectTimes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gs *GState) RemoveProject(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("user").(*jwt.Token)
|
||||||
|
claims := user.Claims.(jwt.MapClaims)
|
||||||
|
username := claims["name"].(string)
|
||||||
|
|
||||||
|
// Check if the user is a site admin
|
||||||
|
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 not a site admin:", username)
|
||||||
|
return c.Status(403).SendString("User is not a site admin")
|
||||||
|
}
|
||||||
|
|
||||||
|
projectName := c.Params("projectName")
|
||||||
|
|
||||||
|
if err := gs.Db.RemoveProject(projectName); err != nil {
|
||||||
|
return c.Status(500).SendString((err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(200).SendString("Project deleted")
|
||||||
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ func main() {
|
||||||
server.Post("/api/ProjectRoleChange", gs.ProjectRoleChange)
|
server.Post("/api/ProjectRoleChange", gs.ProjectRoleChange)
|
||||||
server.Get("/api/getUsersProject/:projectName", gs.ListAllUsersProject)
|
server.Get("/api/getUsersProject/:projectName", gs.ListAllUsersProject)
|
||||||
server.Put("/api/updateWeeklyReport", gs.UpdateWeeklyReport)
|
server.Put("/api/updateWeeklyReport", gs.UpdateWeeklyReport)
|
||||||
|
server.Delete("/api/removeProject/:projectName", gs.RemoveProject)
|
||||||
|
|
||||||
// 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))
|
||||||
|
|
|
@ -47,7 +47,6 @@ interface API {
|
||||||
* @returns {Promise<APIResponse<boolean>>} A promise containing the API response indicating if the user is a project manager.
|
* @returns {Promise<APIResponse<boolean>>} A promise containing the API response indicating if the user is a project manager.
|
||||||
*/
|
*/
|
||||||
checkIfProjectManager(
|
checkIfProjectManager(
|
||||||
username: string,
|
|
||||||
projectName: string,
|
projectName: string,
|
||||||
token: string,
|
token: string,
|
||||||
): Promise<APIResponse<boolean>>;
|
): Promise<APIResponse<boolean>>;
|
||||||
|
@ -133,6 +132,11 @@ interface API {
|
||||||
projectName: string,
|
projectName: string,
|
||||||
token: string,
|
token: string,
|
||||||
): Promise<APIResponse<UserProjectMember[]>>;
|
): Promise<APIResponse<UserProjectMember[]>>;
|
||||||
|
|
||||||
|
removeProject(
|
||||||
|
projectName: string,
|
||||||
|
token: string,
|
||||||
|
): Promise<APIResponse<string>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An instance of the API */
|
/** An instance of the API */
|
||||||
|
@ -190,19 +194,20 @@ export const api: API = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async checkIfProjectManager(
|
async checkIfProjectManager(
|
||||||
username: string,
|
|
||||||
projectName: string,
|
projectName: string,
|
||||||
token: string,
|
token: string,
|
||||||
): Promise<APIResponse<boolean>> {
|
): Promise<APIResponse<boolean>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/checkIfProjectManager", {
|
const response = await fetch(
|
||||||
method: "GET",
|
`/api/checkIfProjectManager?projectName=${projectName}`,
|
||||||
headers: {
|
{
|
||||||
"Content-Type": "application/json",
|
method: "GET",
|
||||||
Authorization: "Bearer " + token,
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: "Bearer " + token,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ username, projectName }),
|
);
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return {
|
return {
|
||||||
|
@ -214,7 +219,7 @@ export const api: API = {
|
||||||
return { success: true, data };
|
return { success: true, data };
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { success: false, message: "fuck" };
|
return { success: false, message: "Failed to check if project manager" };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -484,4 +489,34 @@ export const api: API = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async removeProject(
|
||||||
|
projectName: string,
|
||||||
|
token: string,
|
||||||
|
): Promise<APIResponse<string>> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/projectdelete/${projectName}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: "Bearer " + token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return Promise.resolve({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to remove project",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const data = await response.text();
|
||||||
|
return Promise.resolve({ success: true, message: data });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return Promise.resolve({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to remove project",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,26 @@
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { api } from "../../API/API";
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import Button from "../../Components/Button";
|
import Button from "../../Components/Button";
|
||||||
|
|
||||||
|
async function handleDeleteProject(
|
||||||
|
projectName: string,
|
||||||
|
token: string,
|
||||||
|
): Promise<void> {
|
||||||
|
await api.removeProject(projectName, token);
|
||||||
|
}
|
||||||
|
|
||||||
function AdminProjectPage(): JSX.Element {
|
function AdminProjectPage(): JSX.Element {
|
||||||
const content = <></>;
|
const content = <></>;
|
||||||
|
const { projectName } = useParams();
|
||||||
|
const token = localStorage.getItem("accessToken");
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
text="Delete"
|
text="Delete"
|
||||||
onClick={(): void => {
|
onClick={() => handleDeleteProject(projectName, token)}
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
/>
|
/>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
|
@ -20,4 +29,5 @@ function AdminProjectPage(): JSX.Element {
|
||||||
|
|
||||||
return <BasicWindow content={content} buttons={buttons} />;
|
return <BasicWindow content={content} buttons={buttons} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AdminProjectPage;
|
export default AdminProjectPage;
|
||||||
|
|
44
testing.py
44
testing.py
|
@ -44,6 +44,7 @@ getUsersProjectPath = base_url + "/api/getUsersProject"
|
||||||
getUnsignedReportsPath = base_url + "/api/getUnsignedReports"
|
getUnsignedReportsPath = base_url + "/api/getUnsignedReports"
|
||||||
getChangeUserNamePath = base_url + "/api/changeUserName"
|
getChangeUserNamePath = base_url + "/api/changeUserName"
|
||||||
getUpdateWeeklyReportPath = base_url + "/api/updateWeeklyReport"
|
getUpdateWeeklyReportPath = base_url + "/api/updateWeeklyReport"
|
||||||
|
removeProjectPath = base_url + "/api/removeProject"
|
||||||
|
|
||||||
#ta bort auth i handlern för att få testet att gå igenom
|
#ta bort auth i handlern för att få testet att gå igenom
|
||||||
def test_ProjectRoleChange():
|
def test_ProjectRoleChange():
|
||||||
|
@ -465,7 +466,47 @@ def test_update_weekly_report():
|
||||||
assert response.status_code == 200, "Update weekly report failed"
|
assert response.status_code == 200, "Update weekly report failed"
|
||||||
gprint("test_update_weekly_report successful")
|
gprint("test_update_weekly_report successful")
|
||||||
|
|
||||||
|
|
||||||
|
def test_remove_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},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a new project
|
||||||
|
new_project = randomString()
|
||||||
|
response = requests.post(
|
||||||
|
addProjectPath,
|
||||||
|
json={"name": new_project, "description": "This is a project"},
|
||||||
|
headers={"Authorization": "Bearer " + admin_token},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200, "Add project failed"
|
||||||
|
|
||||||
|
# Remove the project
|
||||||
|
response = requests.delete(
|
||||||
|
removeProjectPath + "/" + new_project,
|
||||||
|
headers={"Authorization": "Bearer " + admin_token},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200, "Remove project failed"
|
||||||
|
gprint("test_remove_project successful")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
test_remove_project()
|
||||||
test_get_user_projects()
|
test_get_user_projects()
|
||||||
test_create_user()
|
test_create_user()
|
||||||
test_login()
|
test_login()
|
||||||
|
@ -482,4 +523,5 @@ if __name__ == "__main__":
|
||||||
test_get_unsigned_reports()
|
test_get_unsigned_reports()
|
||||||
test_list_all_users_project()
|
test_list_all_users_project()
|
||||||
test_change_user_name()
|
test_change_user_name()
|
||||||
test_update_weekly_report()
|
test_update_weekly_report()
|
||||||
|
|
Loading…
Reference in a new issue