From 76fefd2b2482a4aee882dff68e7a73fb26aa9980 Mon Sep 17 00:00:00 2001 From: dDogge Date: Mon, 18 Mar 2024 13:32:55 +0100 Subject: [PATCH 01/40] Added function to check if someone is admin --- backend/internal/database/db.go | 21 ++++++++++++++ backend/internal/database/db_test.go | 43 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 5cbb13f..82a3551 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -32,6 +32,7 @@ type Database interface { GetUserRole(username string, projectname string) (string, error) GetWeeklyReport(username string, projectName string, week int) (types.WeeklyReport, error) SignWeeklyReport(reportId int, projectManagerId int) error + IsSiteAdmin(username string) (bool, error) } // This struct is a wrapper type that holds the database connection @@ -313,6 +314,26 @@ func (d *Db) SignWeeklyReport(reportId int, projectManagerId int) error { return err } +// IsSiteAdmin checks if a given username is a site admin +func (d *Db) IsSiteAdmin(username string) (bool, error) { + // Define the SQL query to check if the user is a site admin + query := ` + SELECT COUNT(*) FROM site_admin + JOIN users ON site_admin.admin_id = users.id + WHERE users.username = ? + ` + + // Execute the query + var count int + err := d.Get(&count, query, username) + if err != nil { + return false, err + } + + // If count is greater than 0, the user is a site admin + return count > 0, nil +} + // Reads a directory of migration files and applies them to the database. // This will eventually be used on an embedded directory func (d *Db) Migrate() error { diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 09de45b..2378b3d 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -536,3 +536,46 @@ func TestSignWeeklyReportByAnotherProjectManager(t *testing.T) { t.Error("Expected SignWeeklyReport to fail with a project manager who is not in the project, but it didn't") } } + +func TestIsSiteAdmin(t *testing.T) { + db, err := setupState() + if err != nil { + t.Error("setupState failed:", err) + } + + // Add a site admin + err = db.AddUser("admin", "password") + if err != nil { + t.Error("AddUser failed:", err) + } + + // Promote the user to site admin + err = db.PromoteToAdmin("admin") + if err != nil { + t.Error("PromoteToAdmin failed:", err) + } + + // Check if the user is a site admin + isAdmin, err := db.IsSiteAdmin("admin") + if err != nil { + t.Error("IsSiteAdmin failed:", err) + } + if !isAdmin { + t.Error("IsSiteAdmin failed: expected true, got false") + } + + // Add a regular user + err = db.AddUser("regularuser", "password") + if err != nil { + t.Error("AddUser failed:", err) + } + + // Check if the regular user is not a site admin + isRegularUserAdmin, err := db.IsSiteAdmin("regularuser") + if err != nil { + t.Error("IsSiteAdmin failed:", err) + } + if isRegularUserAdmin { + t.Error("IsSiteAdmin failed: expected false, got true") + } +} From 49793787792171b72450b0825deac96b40b10a32 Mon Sep 17 00:00:00 2001 From: dDogge Date: Mon, 18 Mar 2024 14:47:15 +0100 Subject: [PATCH 02/40] Handler for AddUserToProject and promoteToAdmin, successfully tested --- backend/internal/handlers/global_state.go | 2 + .../handlers/handlers_project_related.go | 42 +++++++++++++++++++ .../handlers/handlers_user_related.go | 23 ++++++++++ backend/main.go | 3 ++ 4 files changed, 70 insertions(+) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index c8beb1c..ef7e48d 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -17,6 +17,8 @@ type GlobalState interface { SubmitWeeklyReport(c *fiber.Ctx) error GetWeeklyReport(c *fiber.Ctx) error SignReport(c *fiber.Ctx) error + AddUserToProjectHandler(c *fiber.Ctx) error + PromoteToAdmin(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 diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 6a430e9..74f57f7 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -96,3 +96,45 @@ func (gs *GState) ListAllUsersProject(c *fiber.Ctx) error { // Return the list of users as JSON return c.JSON(users) } + +// AddUserToProjectHandler is a handler that adds a user to a project with a specified role +func (gs *GState) AddUserToProjectHandler(c *fiber.Ctx) error { + // Extract necessary parameters from the request + var requestData struct { + Username string `json:"username"` + ProjectName string `json:"projectName"` + Role string `json:"role"` + } + if err := c.BodyParser(&requestData); err != nil { + println("Error parsing request body:", err) + return c.Status(400).SendString("Bad request") + } + + // Check if the user adding another user to the project is a site admin + user := c.Locals("user").(*jwt.Token) + claims := user.Claims.(jwt.MapClaims) + adminUsername := claims["name"].(string) + println("Admin username from claims:", adminUsername) + + isAdmin, err := gs.Db.IsSiteAdmin(adminUsername) + if err != nil { + println("Error checking admin status:", err) + return c.Status(500).SendString(err.Error()) + } + + if !isAdmin { + println("User is not a site admin:", adminUsername) + return c.Status(403).SendString("User is not a site admin") + } + + // Add the user to the project with the specified role + err = gs.Db.AddUserToProject(requestData.Username, requestData.ProjectName, requestData.Role) + if err != nil { + println("Error adding user to project:", err) + return c.Status(500).SendString(err.Error()) + } + + // Return success message + println("User added to project successfully:", requestData.Username) + return c.SendStatus(fiber.StatusOK) +} diff --git a/backend/internal/handlers/handlers_user_related.go b/backend/internal/handlers/handlers_user_related.go index 0619ea5..0f7c047 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -1,6 +1,7 @@ package handlers import ( + "fmt" "time" "ttime/internal/types" @@ -122,3 +123,25 @@ func (gs *GState) ListAllUsers(c *fiber.Ctx) error { // Return the list of users as JSON return c.JSON(users) } + +func (gs *GState) PromoteToAdmin(c *fiber.Ctx) error { + // Extract the username from the request body + var newUser types.NewUser + if err := c.BodyParser(&newUser); err != nil { + return c.Status(400).SendString("Bad request") + } + username := newUser.Username + + println("Promoting user to admin:", username) // Debug print + + // Promote the user to a site admin in the database + if err := gs.Db.PromoteToAdmin(username); err != nil { + fmt.Println("Error promoting user to admin:", err) // Debug print + return c.Status(500).SendString(err.Error()) + } + + println("User promoted to admin successfully:", username) // Debug print + + // Return a success message + return c.SendStatus(fiber.StatusOK) +} diff --git a/backend/main.go b/backend/main.go index bc33942..7cf6c9f 100644 --- a/backend/main.go +++ b/backend/main.go @@ -79,6 +79,9 @@ func main() { server.Delete("/api/userdelete/:username", gs.UserDelete) // Perhaps just use POST to avoid headaches server.Post("/api/project", gs.CreateProject) server.Get("/api/getWeeklyReport", gs.GetWeeklyReport) + server.Post("/api/signReport", gs.SignReport) + server.Put("/api/addUserToProject", gs.AddUserToProjectHandler) + server.Post("/api/promoteToAdmin", gs.PromoteToAdmin) // Announce the port we are listening on and start the server err = server.Listen(fmt.Sprintf(":%d", conf.Port)) From 3a3690e3da72fcc2e173520006defdd6f9054b04 Mon Sep 17 00:00:00 2001 From: borean Date: Mon, 18 Mar 2024 15:12:11 +0100 Subject: [PATCH 03/40] ignore go.work.sum --- .gitignore | 1 + go.work.sum | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index bdbfff8..313b735 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ dist/ .vscode/ .idea/ .DS_Store +.go.work.sum # Ignore configuration files .env diff --git a/go.work.sum b/go.work.sum index a58340b..087c85b 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,15 +1,28 @@ -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From 9ad89d60636ac6091d71b0bf307982becc9b89fe Mon Sep 17 00:00:00 2001 From: dDogge Date: Mon, 18 Mar 2024 16:01:00 +0100 Subject: [PATCH 04/40] Handler for SignReport added and corresponding test in testing.pu added --- .../handlers/handlers_report_related.go | 32 +++-- testing.py | 124 +++++++++++++++++- 2 files changed, 141 insertions(+), 15 deletions(-) diff --git a/backend/internal/handlers/handlers_report_related.go b/backend/internal/handlers/handlers_report_related.go index 509bd67..291d068 100644 --- a/backend/internal/handlers/handlers_report_related.go +++ b/backend/internal/handlers/handlers_report_related.go @@ -64,30 +64,42 @@ func (gs *GState) GetWeeklyReport(c *fiber.Ctx) error { return c.JSON(report) } +type ReportId struct { + ReportId int +} + func (gs *GState) SignReport(c *fiber.Ctx) error { + println("Signing report...") // Extract the necessary parameters from the token user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) - managerUsername := claims["name"].(string) + projectManagerUsername := claims["name"].(string) - // Extract the report ID and project manager ID from request parameters - reportID, err := strconv.Atoi(c.Params("reportId")) - if err != nil { - return c.Status(400).SendString("Invalid report ID") + // Extract report ID from the request query parameters + // reportID := c.Query("reportId") + rid := new(ReportId) + if err := c.BodyParser(rid); err != nil { + return err } + println("Signing report for: ", rid.ReportId) + // reportIDInt, err := strconv.Atoi(rid.ReportId) + // println("Signing report for: ", rid.ReportId) + // if err != nil { + // return c.Status(400).SendString("Invalid report ID") + // } - // Call the database function to get the project manager ID - managerID, err := gs.Db.GetUserId(managerUsername) + // Get the project manager's ID + projectManagerID, err := gs.Db.GetUserId(projectManagerUsername) if err != nil { return c.Status(500).SendString("Failed to get project manager ID") } + println("blabla", projectManagerID) // Call the database function to sign the weekly report - err = gs.Db.SignWeeklyReport(reportID, managerID) + err = gs.Db.SignWeeklyReport(rid.ReportId, projectManagerID) if err != nil { - return c.Status(500).SendString("Failed to sign the weekly report: " + err.Error()) + return c.Status(500).SendString(err.Error()) } - // Return success response return c.Status(200).SendString("Weekly report signed successfully") } diff --git a/testing.py b/testing.py index 38d09cc..164c64e 100644 --- a/testing.py +++ b/testing.py @@ -22,6 +22,9 @@ loginPath = base_url + "/api/login" addProjectPath = base_url + "/api/project" submitReportPath = base_url + "/api/submitReport" getWeeklyReportPath = base_url + "/api/getWeeklyReport" +signReportPath = base_url + "/api/signReport" +addUserToProjectPath = base_url + "/api/addUserToProject" +promoteToAdminPath = base_url + "/api/promoteToAdmin" # Posts the username and password to the register endpoint @@ -43,20 +46,20 @@ def login(username: string, password: string): print(response.text) return response - +# Test function to login def test_login(): response = login(username, "always_same") assert response.status_code == 200, "Login failed" print("Login successful") return response.json()["token"] - +# Test function to create a new user def test_create_user(): response = register(username, "always_same") assert response.status_code == 200, "Registration failed" print("Registration successful") - +# Test function to add a project def test_add_project(): loginResponse = login(username, "always_same") token = loginResponse.json()["token"] @@ -69,7 +72,7 @@ def test_add_project(): assert response.status_code == 200, "Add project failed" print("Add project successful") - +# Test function to submit a report def test_submit_report(): token = login(username, "always_same").json()["token"] response = requests.post( @@ -90,6 +93,7 @@ def test_submit_report(): assert response.status_code == 200, "Submit report failed" print("Submit report successful") +# Test function to get a weekly report def test_get_weekly_report(): token = login(username, "always_same").json()["token"] response = requests.get( @@ -99,9 +103,119 @@ def test_get_weekly_report(): ) print(response.text) +# Test function to add a user to a project +def test_add_user_to_project(): + # Log in as a site admin + admin_username = randomString() + admin_password = "admin_password" + print("Registering with username: ", admin_username, " and password: ", admin_password) + response = requests.post( + registerPath, json={"username": admin_username, "password": admin_password} + ) + print(response.text) + + admin_token = login(admin_username, admin_password).json()["token"] + response = requests.post(promoteToAdminPath, json={"username": admin_username}, headers={"Authorization": "Bearer " + admin_token}) + print(response.text) + assert response.status_code == 200, "Promote to site admin failed" + print("Admin promoted to site admin successfully") + + # Create a new user to add to the project + new_user = randomString() + register(new_user, "new_user_password") + + # Add the new user to the project as a member + response = requests.put( + addUserToProjectPath, + json={"projectName": projectName, "username": new_user, "role": "member"}, + headers={"Authorization": "Bearer " + admin_token}, + ) + + print(response.text) + assert response.status_code == 200, "Add user to project failed" + print("Add user to project successful") + +# Test function to sign a report +def test_sign_report(): + # Create a project manager user + project_manager = randomString() + register(project_manager, "project_manager_password") + + # Register an admin + admin_username = randomString() + admin_password = "admin_password2" + print("Registering with username: ", admin_username, " and password: ", admin_password) + response = requests.post( + registerPath, json={"username": admin_username, "password": admin_password} + ) + print(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}) + + response = requests.put( + addUserToProjectPath, + json={"projectName": projectName, "username": project_manager, "role": "project_manager"}, + headers={"Authorization": "Bearer " + admin_token}, + ) + assert response.status_code == 200, "Add project manager to project failed" + print("Project manager added to project successfully") + + # Log in as the project manager + project_manager_token = login(project_manager, "project_manager_password").json()["token"] + + # Submit a report for the project + token = login(username, "always_same").json()["token"] + response = requests.post( + submitReportPath, + json={ + "projectName": projectName, + "week": 1, + "developmentTime": 10, + "meetingTime": 5, + "adminTime": 5, + "ownWorkTime": 10, + "studyTime": 10, + "testingTime": 10, + }, + headers={"Authorization": "Bearer " + token}, + ) + assert response.status_code == 200, "Submit report failed" + print("Submit report successful") + + # Retrieve the report ID + response = requests.get( + getWeeklyReportPath, + headers={"Authorization": "Bearer " + token}, + params={"username": username, "projectName": projectName , "week": 1} + ) + print(response.text) + report_id = response.json()["reportId"] + + # Sign the report as the project manager + response = requests.post( + signReportPath, + json={"reportId": report_id}, + headers={"Authorization": "Bearer " + project_manager_token}, + ) + assert response.status_code == 200, "Sign report failed" + print("Sign report successful") + + # Retrieve the report ID again for confirmation + response = requests.get( + getWeeklyReportPath, + headers={"Authorization": "Bearer " + token}, + params={"username": username, "projectName": projectName , "week": 1} + ) + print(response.text) + + if __name__ == "__main__": test_create_user() test_login() test_add_project() test_submit_report() - test_get_weekly_report() \ No newline at end of file + test_get_weekly_report() + test_sign_report() + test_add_user_to_project() \ No newline at end of file From 0c2617d0cb9dd03a73005bb6347d16ac7fd3ddc1 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 16:42:35 +0100 Subject: [PATCH 05/40] Full fix for getProject route, testing, integration testing and frontend-API code --- backend/internal/database/db.go | 5 +++- backend/internal/database/db_test.go | 30 +++++++++++++++++++ backend/internal/handlers/global_state.go | 1 + .../handlers/handlers_project_related.go | 5 ++++ backend/main.go | 1 + frontend/src/API/API.ts | 27 +++++++++++++++++ testing.py | 15 +++++++++- 7 files changed, 82 insertions(+), 2 deletions(-) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 5cbb13f..a5360e6 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -106,7 +106,10 @@ func (d *Db) GetAllProjects() ([]types.Project, error) { // GetProject retrieves a specific project by its ID. func (d *Db) GetProject(projectId int) (types.Project, error) { var project types.Project - err := d.Select(&project, "SELECT * FROM projects WHERE id = ?") + err := d.Get(&project, "SELECT * FROM projects WHERE id = ?", projectId) + if err != nil { + println("Error getting project: ", err) + } return project, err } diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 09de45b..a7f3878 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -536,3 +536,33 @@ func TestSignWeeklyReportByAnotherProjectManager(t *testing.T) { t.Error("Expected SignWeeklyReport to fail with a project manager who is not in the project, but it didn't") } } + +func TestGetProject(t *testing.T) { + db, err := setupState() + if err != nil { + t.Error("setupState failed:", err) + } + + // Add a user + err = db.AddUser("testuser", "password") + if err != nil { + t.Error("AddUser failed:", err) + } + + // Add a project + err = db.AddProject("testproject", "description", "testuser") + if err != nil { + t.Error("AddProject failed:", err) + } + + // Retrieve the added project + project, err := db.GetProject(1) + if err != nil { + t.Error("GetProject failed:", err) + } + + // Check if the retrieved project matches the expected values + if project.Name != "testproject" { + t.Errorf("Expected Name to be testproject, got %s", project.Name) + } +} diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index c8beb1c..92bc19d 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -17,6 +17,7 @@ type GlobalState interface { SubmitWeeklyReport(c *fiber.Ctx) error GetWeeklyReport(c *fiber.Ctx) error SignReport(c *fiber.Ctx) error + GetProject(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 diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 6a430e9..d779663 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -66,6 +66,10 @@ func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error { func (gs *GState) GetProject(c *fiber.Ctx) error { // Extract the project ID from the request parameters or body projectID := c.Params("projectID") + if projectID == "" { + return c.Status(400).SendString("No project ID provided") + } + println("Getting project with ID: ", projectID) // Parse the project ID into an integer projectIDInt, err := strconv.Atoi(projectID) @@ -80,6 +84,7 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { } // Return the project as JSON + println("Returning project: ", project.Name) return c.JSON(project) } diff --git a/backend/main.go b/backend/main.go index bc33942..920696b 100644 --- a/backend/main.go +++ b/backend/main.go @@ -78,6 +78,7 @@ func main() { server.Post("/api/loginrenew", gs.LoginRenew) server.Delete("/api/userdelete/:username", gs.UserDelete) // Perhaps just use POST to avoid headaches server.Post("/api/project", gs.CreateProject) + server.Get("/api/project/:projectId", gs.GetProject) server.Get("/api/getWeeklyReport", gs.GetWeeklyReport) // Announce the port we are listening on and start the server diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index ac0f531..e8566b6 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -46,6 +46,7 @@ interface API { username: string, token: string, ): Promise>; + getProject(id: number): Promise>; } // Export an instance of the API @@ -253,4 +254,30 @@ export const api: API = { return Promise.resolve({ success: false, message: "Failed to login" }); } }, + + // Gets a projet by id, currently untested since we have no javascript-based tests + async getProject(id: number): Promise> { + try { + const response = await fetch(`/api/project/${id}`, { + method: "GET", + }); + + if (!response.ok) { + return { + success: false, + message: "Failed to get project: Response code " + response.status, + }; + } else { + const data = (await response.json()) as Project; + return { success: true, data }; + } + // The code below is garbage but satisfies the linter + // This needs fixing, do not copy this pattern + } catch (e: unknown) { + return { + success: false, + message: "Failed to get project: " + (e as Error).toString(), + }; + } + }, }; diff --git a/testing.py b/testing.py index 38d09cc..fd4ec74 100644 --- a/testing.py +++ b/testing.py @@ -22,6 +22,7 @@ loginPath = base_url + "/api/login" addProjectPath = base_url + "/api/project" submitReportPath = base_url + "/api/submitReport" getWeeklyReportPath = base_url + "/api/getWeeklyReport" +getProjectPath = base_url + "/api/project" # Posts the username and password to the register endpoint @@ -98,10 +99,22 @@ def test_get_weekly_report(): params={"username": username, "projectName": projectName , "week": 1} ) print(response.text) + assert response.status_code == 200, "Get weekly report failed" + +# Tests getting a project by id +def test_get_project(): + token = login(username, "always_same").json()["token"] + response = requests.get( + getProjectPath + "/1", # Assumes that the project with id 1 exists + headers={"Authorization": "Bearer " + token}, + ) + print(response.text) + assert response.status_code == 200, "Get project failed" if __name__ == "__main__": test_create_user() test_login() test_add_project() test_submit_report() - test_get_weekly_report() \ No newline at end of file + test_get_weekly_report() + test_get_project() \ No newline at end of file From 531e9a0535b873188219bff887824e8f08b2d2b1 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 17:38:45 +0100 Subject: [PATCH 06/40] Fix links in UserProjectPage component --- frontend/src/Pages/UserPages/UserProjectPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserProjectPage.tsx b/frontend/src/Pages/UserPages/UserProjectPage.tsx index 4760217..eab866b 100644 --- a/frontend/src/Pages/UserPages/UserProjectPage.tsx +++ b/frontend/src/Pages/UserPages/UserProjectPage.tsx @@ -7,12 +7,12 @@ function UserProjectPage(): JSX.Element { <>

{useLocation().state}

- +

Your Time Reports

- +

New Time Report

From 4392b6839742a891355709cce6e52c3206e42a80 Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 17:40:53 +0100 Subject: [PATCH 07/40] Removed duplicate getUserProjects --- frontend/src/API/API.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index b512e1d..b3cb776 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -29,11 +29,6 @@ interface API { project: NewProject, token: string, ): Promise>; - /** Gets all the projects of a user*/ - getUserProjects( - username: string, - token: string, - ): Promise>; /** Submit a weekly report */ submitWeeklyReport( project: NewWeeklyReport, From a2ad2913e4a65e45cd91f69a155898d4127ec7d4 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 19:34:15 +0100 Subject: [PATCH 08/40] Add NotFoundPage component --- frontend/src/Pages/NotFoundPage.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 frontend/src/Pages/NotFoundPage.tsx diff --git a/frontend/src/Pages/NotFoundPage.tsx b/frontend/src/Pages/NotFoundPage.tsx new file mode 100644 index 0000000..cae9861 --- /dev/null +++ b/frontend/src/Pages/NotFoundPage.tsx @@ -0,0 +1,18 @@ +import Button from "../Components/Button"; + +export default function NotFoundPage(): JSX.Element { + return ( + + ); +} From 3e9dc87100eed22a6ba1382727cc8041d7c3d6d5 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 19:36:28 +0100 Subject: [PATCH 09/40] Add NotFoundPage to handle 404 errors --- frontend/src/main.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 193b692..a1e466e 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -29,12 +29,14 @@ import AdminProjectManageMembers from "./Pages/AdminPages/AdminProjectManageMemb import AdminProjectStatistics from "./Pages/AdminPages/AdminProjectStatistics.tsx"; import AdminProjectViewMemberInfo from "./Pages/AdminPages/AdminProjectViewMemberInfo.tsx"; import AdminProjectPage from "./Pages/AdminPages/AdminProjectPage.tsx"; +import NotFoundPage from "./Pages/NotFoundPage.tsx"; // This is where the routes are mounted const router = createBrowserRouter([ { path: "/", element: , + errorElement: , }, { path: "/admin", From d64ec708a160ad4fd48293dbe22b9212b48761e7 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 19:37:37 +0100 Subject: [PATCH 10/40] Minor fixes --- frontend/src/Pages/YourProjectsPage.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index aabc606..e45d237 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -7,10 +7,10 @@ import BasicWindow from "../Components/BasicWindow"; export const ProjectNameContext = createContext(""); function UserProjectPage(): JSX.Element { - const [projects, setProjects] = useState([]); - const [selectedProject, setSelectedProject] = useState(""); + /* const [projects, setProjects] = useState([]); + */ const [selectedProject, setSelectedProject] = useState(""); - const getProjects = async (): Promise => { + /* const getProjects = async (): Promise => { const username = localStorage.getItem("username") ?? ""; // replace with actual username const token = localStorage.getItem("accessToken") ?? ""; // replace with actual token const response = await api.getUserProjects(username, token); @@ -24,7 +24,15 @@ function UserProjectPage(): JSX.Element { // Call getProjects when the component mounts useEffect(() => { getProjects(); - }, []); + }, []); */ + + // Mock data + const projects: Project[] = [ + { id: "1", name: "Project 1" }, + { id: "2", name: "Project 2" }, + { id: "3", name: "Project 3" }, + // Add more mock projects as needed + ]; const handleProjectClick = (projectName: string): void => { setSelectedProject(projectName); From 4683dd459ac565cfacab98a835a8d17bd27fe84e Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 20:56:00 +0100 Subject: [PATCH 11/40] Remove code related to demo button in backend --- backend/internal/handlers/global_state.go | 22 +++++----------------- backend/main.go | 6 +----- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 566d549..932451d 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -34,29 +34,17 @@ type GlobalState interface { // 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 - GetButtonCount(c *fiber.Ctx) error // For demonstration purposes - IncrementButtonCount(c *fiber.Ctx) error // For demonstration purposes - 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 + 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 } // "Constructor" func NewGlobalState(db database.Database) GlobalState { - return &GState{Db: db, ButtonCount: 0} + return &GState{Db: db} } // The global state, which implements all the handlers type GState struct { - Db database.Database - ButtonCount int -} - -func (gs *GState) GetButtonCount(c *fiber.Ctx) error { - return c.Status(200).JSON(fiber.Map{"pressCount": gs.ButtonCount}) -} - -func (gs *GState) IncrementButtonCount(c *fiber.Ctx) error { - gs.ButtonCount++ - return c.Status(200).JSON(fiber.Map{"pressCount": gs.ButtonCount}) + Db database.Database } diff --git a/backend/main.go b/backend/main.go index 3e2fb75..da89043 100644 --- a/backend/main.go +++ b/backend/main.go @@ -61,11 +61,6 @@ func main() { // Register our unprotected routes server.Post("/api/register", gs.Register) - - // Register handlers for example button count - server.Get("/api/button", gs.GetButtonCount) - server.Post("/api/button", gs.IncrementButtonCount) - server.Post("/api/login", gs.Login) // Every route from here on will require a valid JWT @@ -73,6 +68,7 @@ func main() { SigningKey: jwtware.SigningKey{Key: []byte("secret")}, })) + // Protected routes (require a valid JWT bearer token authentication header) server.Post("/api/submitReport", gs.SubmitWeeklyReport) server.Get("/api/getUserProjects", gs.GetUserProjects) server.Post("/api/loginrenew", gs.LoginRenew) From 8eb23bf7f9ae41f616ab37bf489e180bd11d3022 Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 21:08:33 +0100 Subject: [PATCH 12/40] lint bro happ + test for getUserProject --- frontend/src/API/API.ts | 6 +++++- frontend/src/Components/EditWeeklyReport.tsx | 4 ++-- frontend/src/Components/NewWeeklyReport.tsx | 2 +- .../src/Components/UserProjectListAdmin.tsx | 2 +- frontend/src/Pages/YourProjectsPage.tsx | 4 ++-- testing.py | 17 +++++++++++------ 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index b3cb776..6078513 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -150,7 +150,10 @@ export const api: API = { } }, - async getUserProjects(token: string): Promise> { + async getUserProjects( + username: string, + token: string, + ): Promise> { try { const response = await fetch("/api/getUserProjects", { method: "GET", @@ -158,6 +161,7 @@ export const api: API = { "Content-Type": "application/json", Authorization: "Bearer " + token, }, + body: JSON.stringify({ username }), }); if (!response.ok) { diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx index 9321d73..b0e8771 100644 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ b/frontend/src/Components/EditWeeklyReport.tsx @@ -50,8 +50,8 @@ export default function GetWeeklyReport(): JSX.Element { } }; - fetchWeeklyReport(); - }, []); + void fetchWeeklyReport(); + }, [projectName, token, username, week]); const handleNewWeeklyReport = async (): Promise => { const newWeeklyReport: NewWeeklyReport = { diff --git a/frontend/src/Components/NewWeeklyReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx index 4f919aa..0a84b48 100644 --- a/frontend/src/Components/NewWeeklyReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -1,5 +1,5 @@ import { useState, useContext } from "react"; -import { NewWeeklyReport } from "../Types/goTypes"; +import type { NewWeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; import { useNavigate } from "react-router-dom"; import Button from "./Button"; diff --git a/frontend/src/Components/UserProjectListAdmin.tsx b/frontend/src/Components/UserProjectListAdmin.tsx index 423e793..69258a1 100644 --- a/frontend/src/Components/UserProjectListAdmin.tsx +++ b/frontend/src/Components/UserProjectListAdmin.tsx @@ -9,7 +9,7 @@ const UserProjectListAdmin: React.FC = () => { const fetchProjects = async (): Promise => { try { const token = localStorage.getItem("accessToken") ?? ""; - const username = getUsernameFromContext(); // Assuming you have a function to get the username from your context + const username = "NoUser"; // getUsernameFromContext(); // Assuming you have a function to get the username from your context const response = await api.getUserProjects(username, token); if (response.success) { diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index aabc606..4c6e77f 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -1,4 +1,4 @@ -import React, { useState, createContext, useEffect } from "react"; +import { useState, createContext, useEffect } from "react"; import { Project } from "../Types/goTypes"; import { api } from "../API/API"; import { Link } from "react-router-dom"; @@ -23,7 +23,7 @@ function UserProjectPage(): JSX.Element { }; // Call getProjects when the component mounts useEffect(() => { - getProjects(); + void getProjects(); }, []); const handleProjectClick = (projectName: string): void => { diff --git a/testing.py b/testing.py index e342598..6381afc 100644 --- a/testing.py +++ b/testing.py @@ -22,13 +22,11 @@ loginPath = base_url + "/api/login" addProjectPath = base_url + "/api/project" submitReportPath = base_url + "/api/submitReport" getWeeklyReportPath = base_url + "/api/getWeeklyReport" -<<<<<<< HEAD getProjectPath = base_url + "/api/project" -======= signReportPath = base_url + "/api/signReport" addUserToProjectPath = base_url + "/api/addUserToProject" promoteToAdminPath = base_url + "/api/promoteToAdmin" ->>>>>>> 9ad89d60636ac6091d71b0bf307982becc9b89fe +getUserProjectsPath = base_url + "/api/getUserProjects" # Posts the username and password to the register endpoint @@ -150,6 +148,16 @@ def test_add_user_to_project(): assert response.status_code == 200, "Add user to project failed" print("Add user to project successful") + # Check if the user is added to the project + response = requests.get( + getUserProjectsPath, + json={"username": new_user}, + headers={"Authorization": "Bearer " + admin_token}, + ) + print(response.text) + assert response.status_code == 200, "Get user projects failed" + print("got user projects successfully") + # Test function to sign a report def test_sign_report(): # Create a project manager user @@ -232,9 +240,6 @@ if __name__ == "__main__": test_add_project() test_submit_report() test_get_weekly_report() -<<<<<<< HEAD test_get_project() -======= test_sign_report() test_add_user_to_project() ->>>>>>> 9ad89d60636ac6091d71b0bf307982becc9b89fe From e0de61dd94c97600b551ddf10d0061a4362f03f9 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 21:24:26 +0100 Subject: [PATCH 13/40] Type fixes in frontend, Register & YourProjectsPage --- frontend/src/Components/Register.tsx | 4 ++-- frontend/src/Pages/YourProjectsPage.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index facca39..7b003cb 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -48,7 +48,7 @@ export default function Register(): JSX.Element { { setUsername(e.target.value); }} @@ -56,7 +56,7 @@ export default function Register(): JSX.Element { { setPassword(e.target.value); }} diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 4c6e77f..32ba0ed 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -53,7 +53,7 @@ function UserProjectPage(): JSX.Element { const buttons = <>; - return ; + return ; } export default UserProjectPage; From 25713443e21eed8830c2b33f54470534727659f6 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:33:20 +0100 Subject: [PATCH 14/40] Remove username prop from BasicWindow component --- frontend/src/Components/BasicWindow.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/src/Components/BasicWindow.tsx b/frontend/src/Components/BasicWindow.tsx index 1835d6a..d5fd3b6 100644 --- a/frontend/src/Components/BasicWindow.tsx +++ b/frontend/src/Components/BasicWindow.tsx @@ -2,17 +2,15 @@ import Header from "./Header"; import Footer from "./Footer"; function BasicWindow({ - username, content, buttons, }: { - username: string; content: React.ReactNode; buttons: React.ReactNode; }): JSX.Element { return (
-
+
{content}
{buttons}
From b9d7e57f2cfb6c09ce9b60fafdce93f2ca7c253e Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:37:31 +0100 Subject: [PATCH 15/40] Update background image in Header component --- frontend/src/Components/Header.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/Components/Header.tsx b/frontend/src/Components/Header.tsx index 819c5de..5cdb421 100644 --- a/frontend/src/Components/Header.tsx +++ b/frontend/src/Components/Header.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; import { Link } from "react-router-dom"; +import backgroundImage from "../assets/1.jpg"; function Header(): JSX.Element { const [isOpen, setIsOpen] = useState(false); @@ -11,7 +12,7 @@ function Header(): JSX.Element { return (
Date: Mon, 18 Mar 2024 21:37:52 +0100 Subject: [PATCH 16/40] Update user navigation route --- frontend/src/Pages/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Pages/App.tsx b/frontend/src/Pages/App.tsx index 4263815..69fd698 100644 --- a/frontend/src/Pages/App.tsx +++ b/frontend/src/Pages/App.tsx @@ -13,7 +13,7 @@ function App(): JSX.Element { } else if (authority === 2) { navigate("/pm"); } else if (authority === 3) { - navigate("/user"); + navigate("/yourProjects"); } }, [authority, navigate]); From 93addc98704f7feac829a97285709b808032c141 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:40:07 +0100 Subject: [PATCH 17/40] Fixes in NewWeeklyReport component --- frontend/src/Components/NewWeeklyReport.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/frontend/src/Components/NewWeeklyReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx index 4f919aa..86322e7 100644 --- a/frontend/src/Components/NewWeeklyReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -1,9 +1,8 @@ -import { useState, useContext } from "react"; +import { useState } 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"; -import { ProjectNameContext } from "../Pages/YourProjectsPage"; export default function NewWeeklyReport(): JSX.Element { const [week, setWeek] = useState(0); @@ -14,12 +13,12 @@ export default function NewWeeklyReport(): JSX.Element { const [studyTime, setStudyTime] = useState(0); const [testingTime, setTestingTime] = useState(0); - const projectName = useContext(ProjectNameContext); + const { projectName } = useParams(); const token = localStorage.getItem("accessToken") ?? ""; const handleNewWeeklyReport = async (): Promise => { const newWeeklyReport: NewWeeklyReport = { - projectName, + projectName: projectName ?? "", week, developmentTime, meetingTime, @@ -46,7 +45,7 @@ export default function NewWeeklyReport(): JSX.Element { } e.preventDefault(); void handleNewWeeklyReport(); - navigate("/project"); + navigate(-1); }} >
From 31c5a78dae812238a65ff71b448d1102296903f1 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:52:34 +0100 Subject: [PATCH 18/40] Refactor routing paths in main.tsx --- frontend/src/main.tsx | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index a1e466e..1c39ae9 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -46,30 +46,26 @@ const router = createBrowserRouter([ path: "/pm", element: , }, - { - path: "/user", - element: , - }, { path: "/yourProjects", element: , }, { - path: "/editTimeReport", - element: , - }, - { - path: "/newTimeReport", - element: , - }, - { - path: "/project", + path: "/project/:projectName", element: , }, { - path: "/projectPage", + path: "/newTimeReport/:projectName", + element: , + }, + { + path: "/projectPage/:projectName", element: , }, + { + path: "/editTimeReport", + element: , + }, { path: "/changeRole", element: , From f16dc1722cb073659e984464dd7faf2c0a2c1056 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:53:16 +0100 Subject: [PATCH 19/40] Update project name in YourProjectsPage.tsx URL --- frontend/src/Pages/YourProjectsPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index e45d237..9e33696 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -28,7 +28,7 @@ function UserProjectPage(): JSX.Element { // Mock data const projects: Project[] = [ - { id: "1", name: "Project 1" }, + { id: "1", name: "Project Test App" }, { id: "2", name: "Project 2" }, { id: "3", name: "Project 3" }, // Add more mock projects as needed @@ -44,7 +44,7 @@ function UserProjectPage(): JSX.Element {
{projects.map((project, index) => ( { handleProjectClick(project.name); }} From 6982d2101666aaacee94485436fb5c6b247ca82c Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:55:15 +0100 Subject: [PATCH 20/40] Add project name to URL in UserProjectPage --- frontend/src/Pages/UserPages/UserProjectPage.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserProjectPage.tsx b/frontend/src/Pages/UserPages/UserProjectPage.tsx index eab866b..51effff 100644 --- a/frontend/src/Pages/UserPages/UserProjectPage.tsx +++ b/frontend/src/Pages/UserPages/UserProjectPage.tsx @@ -1,18 +1,20 @@ -import { Link, useLocation } from "react-router-dom"; +import { Link, useLocation, useParams } from "react-router-dom"; import BasicWindow from "../../Components/BasicWindow"; import BackButton from "../../Components/BackButton"; function UserProjectPage(): JSX.Element { + const { projectName } = useParams(); + const content = ( <>

{useLocation().state}

- +

Your Time Reports

- +

New Time Report

From 59add3b6b3912094862c0db49ca03f03acf6ee0c Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:55:47 +0100 Subject: [PATCH 21/40] Remove username prop from BasicWindow component --- frontend/src/Pages/UserPages/UserProjectPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Pages/UserPages/UserProjectPage.tsx b/frontend/src/Pages/UserPages/UserProjectPage.tsx index 51effff..80a0035 100644 --- a/frontend/src/Pages/UserPages/UserProjectPage.tsx +++ b/frontend/src/Pages/UserPages/UserProjectPage.tsx @@ -29,6 +29,6 @@ function UserProjectPage(): JSX.Element { ); - return ; + return ; } export default UserProjectPage; From 5a4049eaf3f77356816d2b026443dfe2816c6a8f Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 21:56:37 +0100 Subject: [PATCH 22/40] Remove username prop from BasicWindow component --- frontend/src/Pages/YourProjectsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 9e33696..d64df81 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -61,7 +61,7 @@ function UserProjectPage(): JSX.Element { const buttons = <>; - return ; + return ; } export default UserProjectPage; From 55fd42090d640e9c8aebde10eea3f474a3cda600 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 22:00:58 +0100 Subject: [PATCH 23/40] Remove username prop from BasicWindow component on all pages --- frontend/src/Pages/AdminPages/AdminAddProject.tsx | 2 +- frontend/src/Pages/AdminPages/AdminAddUser.tsx | 2 +- frontend/src/Pages/AdminPages/AdminChangeUsername.tsx | 2 +- frontend/src/Pages/AdminPages/AdminManageProjects.tsx | 2 +- frontend/src/Pages/AdminPages/AdminManageUsers.tsx | 2 +- frontend/src/Pages/AdminPages/AdminMenuPage.tsx | 2 +- frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx | 2 +- frontend/src/Pages/AdminPages/AdminProjectChangeUserRole.tsx | 2 +- frontend/src/Pages/AdminPages/AdminProjectManageMembers.tsx | 2 +- frontend/src/Pages/AdminPages/AdminProjectPage.tsx | 2 +- frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx | 2 +- frontend/src/Pages/AdminPages/AdminProjectViewMemberInfo.tsx | 2 +- frontend/src/Pages/AdminPages/AdminViewUserInfo.tsx | 2 +- frontend/src/Pages/ProjectManagerPages/PMChangeRole.tsx | 2 +- frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx | 2 +- frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx | 2 +- frontend/src/Pages/ProjectManagerPages/PMProjectPage.tsx | 2 +- .../src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx | 4 ++-- frontend/src/Pages/ProjectManagerPages/PMTotalTimeRole.tsx | 2 +- frontend/src/Pages/ProjectManagerPages/PMUnsignedReports.tsx | 2 +- .../src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx | 3 ++- frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx | 2 +- frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx | 2 +- frontend/src/Pages/UserPages/UserViewTimeReportsPage.tsx | 2 +- 24 files changed, 26 insertions(+), 25 deletions(-) diff --git a/frontend/src/Pages/AdminPages/AdminAddProject.tsx b/frontend/src/Pages/AdminPages/AdminAddProject.tsx index 6df8851..aedbd3f 100644 --- a/frontend/src/Pages/AdminPages/AdminAddProject.tsx +++ b/frontend/src/Pages/AdminPages/AdminAddProject.tsx @@ -11,6 +11,6 @@ function AdminAddProject(): JSX.Element { ); - return ; + return ; } export default AdminAddProject; diff --git a/frontend/src/Pages/AdminPages/AdminAddUser.tsx b/frontend/src/Pages/AdminPages/AdminAddUser.tsx index c0f9492..38f00d5 100644 --- a/frontend/src/Pages/AdminPages/AdminAddUser.tsx +++ b/frontend/src/Pages/AdminPages/AdminAddUser.tsx @@ -21,6 +21,6 @@ function AdminAddUser(): JSX.Element { ); - return ; + return ; } export default AdminAddUser; diff --git a/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx b/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx index 2e03a8c..1756433 100644 --- a/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx +++ b/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx @@ -23,6 +23,6 @@ function AdminChangeUsername(): JSX.Element { ); - return ; + return ; } export default AdminChangeUsername; diff --git a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx index c5cba2e..177f55b 100644 --- a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx @@ -21,6 +21,6 @@ function AdminManageProjects(): JSX.Element { ); - return ; + return ; } export default AdminManageProjects; diff --git a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx index e62a54c..0939d77 100644 --- a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx @@ -36,6 +36,6 @@ function AdminManageUsers(): JSX.Element { ); - return ; + return ; } export default AdminManageUsers; diff --git a/frontend/src/Pages/AdminPages/AdminMenuPage.tsx b/frontend/src/Pages/AdminPages/AdminMenuPage.tsx index a8da80e..ed2118d 100644 --- a/frontend/src/Pages/AdminPages/AdminMenuPage.tsx +++ b/frontend/src/Pages/AdminPages/AdminMenuPage.tsx @@ -22,6 +22,6 @@ function AdminMenuPage(): JSX.Element { const buttons = <>; - return ; + return ; } export default AdminMenuPage; diff --git a/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx b/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx index 63fdb4b..96167cb 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx @@ -23,6 +23,6 @@ function AdminProjectAddMember(): JSX.Element { ); - return ; + return ; } export default AdminProjectAddMember; diff --git a/frontend/src/Pages/AdminPages/AdminProjectChangeUserRole.tsx b/frontend/src/Pages/AdminPages/AdminProjectChangeUserRole.tsx index dd80fa9..dd355e8 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectChangeUserRole.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectChangeUserRole.tsx @@ -23,6 +23,6 @@ function AdminProjectChangeUserRole(): JSX.Element { ); - return ; + return ; } export default AdminProjectChangeUserRole; diff --git a/frontend/src/Pages/AdminPages/AdminProjectManageMembers.tsx b/frontend/src/Pages/AdminPages/AdminProjectManageMembers.tsx index 717e8c5..c89e4c4 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectManageMembers.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectManageMembers.tsx @@ -23,6 +23,6 @@ function AdminProjectManageMembers(): JSX.Element { ); - return ; + return ; } export default AdminProjectManageMembers; diff --git a/frontend/src/Pages/AdminPages/AdminProjectPage.tsx b/frontend/src/Pages/AdminPages/AdminProjectPage.tsx index 0b15aeb..a1266ad 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectPage.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectPage.tsx @@ -23,6 +23,6 @@ function AdminProjectPage(): JSX.Element { ); - return ; + return ; } export default AdminProjectPage; diff --git a/frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx b/frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx index a5d9f95..dbf3428 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx @@ -16,6 +16,6 @@ function AdminProjectStatistics(): JSX.Element { ); - return ; + return ; } export default AdminProjectStatistics; diff --git a/frontend/src/Pages/AdminPages/AdminProjectViewMemberInfo.tsx b/frontend/src/Pages/AdminPages/AdminProjectViewMemberInfo.tsx index e15ef35..1c9f28c 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectViewMemberInfo.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectViewMemberInfo.tsx @@ -23,6 +23,6 @@ function AdminProjectViewMemberInfo(): JSX.Element { ); - return ; + return ; } export default AdminProjectViewMemberInfo; diff --git a/frontend/src/Pages/AdminPages/AdminViewUserInfo.tsx b/frontend/src/Pages/AdminPages/AdminViewUserInfo.tsx index 44cd2fa..8b7cd8a 100644 --- a/frontend/src/Pages/AdminPages/AdminViewUserInfo.tsx +++ b/frontend/src/Pages/AdminPages/AdminViewUserInfo.tsx @@ -26,6 +26,6 @@ function AdminViewUserInfo(): JSX.Element { ); - return ; + return ; } export default AdminViewUserInfo; diff --git a/frontend/src/Pages/ProjectManagerPages/PMChangeRole.tsx b/frontend/src/Pages/ProjectManagerPages/PMChangeRole.tsx index 606e474..9f233a1 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMChangeRole.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMChangeRole.tsx @@ -18,6 +18,6 @@ function ChangeRole(): JSX.Element { ); - return ; + return ; } export default ChangeRole; diff --git a/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx b/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx index 19ebbd9..c76947b 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx @@ -10,6 +10,6 @@ function PMOtherUsersTR(): JSX.Element { ); - return ; + return ; } export default PMOtherUsersTR; diff --git a/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx b/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx index bbafd6a..9fe96cf 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx @@ -30,6 +30,6 @@ function PMProjectMembers(): JSX.Element { ); - return ; + return ; } export default PMProjectMembers; diff --git a/frontend/src/Pages/ProjectManagerPages/PMProjectPage.tsx b/frontend/src/Pages/ProjectManagerPages/PMProjectPage.tsx index 8e724f3..bd4e6ef 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMProjectPage.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMProjectPage.tsx @@ -31,6 +31,6 @@ function PMProjectPage(): JSX.Element { ); - return ; + return ; } export default PMProjectPage; diff --git a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx index 35ed6ac..44d2cda 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx @@ -1,6 +1,6 @@ import BasicWindow from "../../Components/BasicWindow"; -import Button from "../../Components/Button"; import TimeReport from "../../Components/NewWeeklyReport"; +import BackButton from "../../Components/BackButton"; function PMTotalTimeActivity(): JSX.Element { const content = ( @@ -18,6 +18,6 @@ function PMTotalTimeActivity(): JSX.Element { ); - return ; + return ; } export default PMTotalTimeActivity; diff --git a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeRole.tsx b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeRole.tsx index 05d902f..c0161f8 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeRole.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeRole.tsx @@ -10,6 +10,6 @@ function PMTotalTimeRole(): JSX.Element { ); - return ; + return ; } export default PMTotalTimeRole; diff --git a/frontend/src/Pages/ProjectManagerPages/PMUnsignedReports.tsx b/frontend/src/Pages/ProjectManagerPages/PMUnsignedReports.tsx index fae3842..713efec 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMUnsignedReports.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMUnsignedReports.tsx @@ -10,6 +10,6 @@ function PMUnsignedReports(): JSX.Element { ); - return ; + return ; } export default PMUnsignedReports; diff --git a/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx b/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx index 9ca963c..6e28071 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx @@ -1,6 +1,7 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import TimeReport from "../../Components/NewWeeklyReport"; +import BackButton from "../../Components/BackButton"; function PMViewUnsignedReport(): JSX.Element { const content = ( @@ -32,6 +33,6 @@ function PMViewUnsignedReport(): JSX.Element { ); - return ; + return ; } export default PMViewUnsignedReport; diff --git a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx index e1b1d66..317cec8 100644 --- a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx @@ -16,6 +16,6 @@ function UserEditTimeReportPage(): JSX.Element { ); - return ; + return ; } export default UserEditTimeReportPage; diff --git a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx index e54b207..2cdeb15 100644 --- a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx @@ -25,6 +25,6 @@ function UserNewTimeReportPage(): JSX.Element { ); - return ; + return ; } export default UserNewTimeReportPage; diff --git a/frontend/src/Pages/UserPages/UserViewTimeReportsPage.tsx b/frontend/src/Pages/UserPages/UserViewTimeReportsPage.tsx index 1d2c3f4..ca326a0 100644 --- a/frontend/src/Pages/UserPages/UserViewTimeReportsPage.tsx +++ b/frontend/src/Pages/UserPages/UserViewTimeReportsPage.tsx @@ -15,6 +15,6 @@ function UserViewTimeReportsPage(): JSX.Element { ); - return ; + return ; } export default UserViewTimeReportsPage; From c31f145c358bdaabf70122b7c70bbcd3703ccc6e Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 22:07:02 +0100 Subject: [PATCH 24/40] Database sample data, make target and go code --- backend/Makefile | 9 ++++ backend/internal/database/db.go | 43 +++++++++++++++++++ .../database/sample_data/0010_sample_data.sql | 7 +++ backend/main.go | 5 +++ 4 files changed, 64 insertions(+) create mode 100644 backend/internal/database/sample_data/0010_sample_data.sql diff --git a/backend/Makefile b/backend/Makefile index da0e254..65a2f3c 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -10,6 +10,7 @@ DB_FILE = db.sqlite3 # Directory containing migration SQL scripts MIGRATIONS_DIR = internal/database/migrations +SAMPLE_DATA_DIR = internal/database/sample_data # Build target build: @@ -54,6 +55,14 @@ migrate: sqlite3 $(DB_FILE) < $$file; \ done +sampledata: + @echo "If this ever fails, run make clean and try again" + @echo "Migrating database $(DB_FILE) using SQL scripts in $(SAMPLE_DATA_DIR)" + @for file in $(wildcard $(SAMPLE_DATA_DIR)/*.sql); do \ + echo "Applying migration: $$file"; \ + sqlite3 $(DB_FILE) < $$file; \ + done + # Target added primarily for CI/CD to ensure that the database is created before running tests db.sqlite3: make migrate diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index e2aa366..95cf8ed 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -20,6 +20,7 @@ type Database interface { GetUserId(username string) (int, error) AddProject(name string, description string, username string) error Migrate() error + MigrateSampleData() error GetProjectId(projectname string) (int, error) 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 @@ -49,6 +50,9 @@ type UserProjectMember struct { //go:embed migrations var scripts embed.FS +//go:embed sample_data +var sampleData embed.FS + // TODO: Possibly break these out into separate files bundled with the embed package? const userInsert = "INSERT INTO users (username, password) VALUES (?, ?)" const projectInsert = "INSERT INTO projects (name, description, owner_user_id) SELECT ?, ?, id FROM users WHERE username = ?" @@ -378,3 +382,42 @@ func (d *Db) Migrate() error { return nil } + +// MigrateSampleData applies sample data to the database. +func (d *Db) MigrateSampleData() error { + // Insert sample data + files, err := sampleData.ReadDir("sample_data") + if err != nil { + return err + } + + if len(files) == 0 { + println("No sample data files found") + } + tr := d.MustBegin() + + // Iterate over each SQL file and execute it + for _, file := range files { + if file.IsDir() || filepath.Ext(file.Name()) != ".sql" { + continue + } + + // This is perhaps not the most elegant way to do this + sqlBytes, err := sampleData.ReadFile("sample_data/" + file.Name()) + if err != nil { + return err + } + + sqlQuery := string(sqlBytes) + _, err = tr.Exec(sqlQuery) + if err != nil { + return err + } + } + + if tr.Commit() != nil { + return err + } + + return nil +} diff --git a/backend/internal/database/sample_data/0010_sample_data.sql b/backend/internal/database/sample_data/0010_sample_data.sql new file mode 100644 index 0000000..f3d9412 --- /dev/null +++ b/backend/internal/database/sample_data/0010_sample_data.sql @@ -0,0 +1,7 @@ +INSERT OR IGNORE INTO users (username, password) VALUES + ('admin', 'password'), + ('user', 'password'); + +INSERT OR IGNORE INTO projects (name, description, owner_user_id) VALUES + ('Project 1', 'Description 1', 1), + ('Project 2', 'Description 2', 2); \ No newline at end of file diff --git a/backend/main.go b/backend/main.go index da89043..24c3702 100644 --- a/backend/main.go +++ b/backend/main.go @@ -48,11 +48,16 @@ func main() { fmt.Println("Error migrating database: ", err) } + if err = db.MigrateSampleData(); err != nil { + fmt.Println("Error migrating sample data: ", err) + } + // Get our global state gs := handlers.NewGlobalState(db) // Create the server server := fiber.New() + // Mounts the swagger documentation, this is available at /swagger/index.html server.Get("/swagger/*", swagger.HandlerDefault) // Mount our static files (Beware of the security implications of this!) From f5a914330f278a5d4ab7e3ece6bb99fb26e63a7d Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 22:10:19 +0100 Subject: [PATCH 25/40] Removed userId identifier from user table, introducing numerous errors --- backend/internal/database/migrations/0010_users.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/internal/database/migrations/0010_users.sql b/backend/internal/database/migrations/0010_users.sql index d2e2dd1..a3ee5b1 100644 --- a/backend/internal/database/migrations/0010_users.sql +++ b/backend/internal/database/migrations/0010_users.sql @@ -4,7 +4,6 @@ -- password is the hashed password CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, - userId TEXT DEFAULT (HEX(RANDOMBLOB(4))) NOT NULL UNIQUE, username VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL ); From 472940cedc91f42054dd7bd43965740a7a603d91 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 22:20:25 +0100 Subject: [PATCH 26/40] Remove index from userId --- backend/internal/database/migrations/0010_users.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/internal/database/migrations/0010_users.sql b/backend/internal/database/migrations/0010_users.sql index a3ee5b1..e7c770b 100644 --- a/backend/internal/database/migrations/0010_users.sql +++ b/backend/internal/database/migrations/0010_users.sql @@ -9,5 +9,4 @@ CREATE TABLE IF NOT EXISTS users ( ); -- Users are commonly searched by username and userId -CREATE INDEX IF NOT EXISTS users_username_index ON users (username); -CREATE INDEX IF NOT EXISTS users_userId_index ON users (userId); \ No newline at end of file +CREATE INDEX IF NOT EXISTS users_username_index ON users (username); \ No newline at end of file From 7ae6cce6b42027aa4ef6345e818dc874c3839111 Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 22:39:02 +0100 Subject: [PATCH 27/40] Sample data --- .../database/migrations/0010_users.sql | 2 +- .../database/sample_data/0010_sample_data.sql | 53 ++++++++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/backend/internal/database/migrations/0010_users.sql b/backend/internal/database/migrations/0010_users.sql index a3ee5b1..93c4df8 100644 --- a/backend/internal/database/migrations/0010_users.sql +++ b/backend/internal/database/migrations/0010_users.sql @@ -10,4 +10,4 @@ CREATE TABLE IF NOT EXISTS users ( -- Users are commonly searched by username and userId CREATE INDEX IF NOT EXISTS users_username_index ON users (username); -CREATE INDEX IF NOT EXISTS users_userId_index ON users (userId); \ No newline at end of file +CREATE INDEX IF NOT EXISTS users_userId_index ON users (Id); \ No newline at end of file diff --git a/backend/internal/database/sample_data/0010_sample_data.sql b/backend/internal/database/sample_data/0010_sample_data.sql index f3d9412..d3012c6 100644 --- a/backend/internal/database/sample_data/0010_sample_data.sql +++ b/backend/internal/database/sample_data/0010_sample_data.sql @@ -1,7 +1,48 @@ -INSERT OR IGNORE INTO users (username, password) VALUES - ('admin', 'password'), - ('user', 'password'); +INSERT OR IGNORE INTO users(username, password) +VALUES ("admin", "123"); -INSERT OR IGNORE INTO projects (name, description, owner_user_id) VALUES - ('Project 1', 'Description 1', 1), - ('Project 2', 'Description 2', 2); \ No newline at end of file +INSERT OR IGNORE INTO users(username, password) +VALUES ("user", "123"); + +INSERT OR IGNORE INTO users(username, password) +VALUES ("user2", "123"); + +INSERT OR IGNORE INTO projects(name,description,owner_user_id) +VALUES ("projecttest","test project", 1) + +INSERT OR IGNORE INTO projects(name,description,owner_user_id) +VALUES ("projecttest2","test project2", 1) + +INSERT OR IGNORE INTO projects(name,description,owner_user_id) +VALUES ("projecttest3","test project3", 1) + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (1,1,"project_manager"); + +INSERT INTO user_roles(user_id,project_id,p_role) +VALUES (2,1,"member"); + +INSERT INTO user_roles(user_id,project_id,p_role) +VALUES (3,1,"member"); + +INSERT INTO user_roles(user_id,project_id,p_role) +VALUES (3,2,"member"); + +INSERT INTO user_roles(user_id,project_id,p_role) +VALUES (3,3,"member"); + +INSERT INTO user_roles(user_id,project_id,p_role) +VALUES (2,1,"project_manager"); + + +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 = 'admin'; + +SELECT id FROM users WHERE username = "admin" + +SELECT id FROM users WHERE username = "user" + +SELECT id FROM users WHERE username = "user2" From a5399c9335219b0301837722c98c945231409d2a Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 22:39:43 +0100 Subject: [PATCH 28/40] Samle data without query --- backend/internal/database/sample_data/0010_sample_data.sql | 6 ------ 1 file changed, 6 deletions(-) diff --git a/backend/internal/database/sample_data/0010_sample_data.sql b/backend/internal/database/sample_data/0010_sample_data.sql index d3012c6..0af0d66 100644 --- a/backend/internal/database/sample_data/0010_sample_data.sql +++ b/backend/internal/database/sample_data/0010_sample_data.sql @@ -35,12 +35,6 @@ INSERT INTO user_roles(user_id,project_id,p_role) VALUES (2,1,"project_manager"); -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 = 'admin'; - SELECT id FROM users WHERE username = "admin" SELECT id FROM users WHERE username = "user" From 95b09a8ce776b00f42f66188a5eccd0d673a66ac Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 22:46:53 +0100 Subject: [PATCH 29/40] Fixed getProjectForUsers --- backend/internal/database/db.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 95cf8ed..25dd04b 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -64,9 +64,10 @@ const addWeeklyReport = `WITH UserLookup AS (SELECT id FROM users WHERE username 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 getProjectsForUser = `SELECT projects.id, projects.name, projects.description, projects.owner_user_id - FROM projects JOIN user_roles ON projects.id = user_roles.project_id - JOIN users ON user_roles.user_id = users.id WHERE users.username = ?;` +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 = ?` // DbConnect connects to the database func DbConnect(dbpath string) Database { From 8df3311f5a41003264fdbf35f647be069b1e02b1 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 22:59:16 +0100 Subject: [PATCH 30/40] Remove duplicate code in UserProjectPage --- frontend/src/Pages/YourProjectsPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index adf4482..973baa3 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -62,7 +62,6 @@ function UserProjectPage(): JSX.Element { const buttons = <>; return ; - return ; } export default UserProjectPage; From cc09eb0ead42a79912c32e052823a5295231b643 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 23:01:30 +0100 Subject: [PATCH 31/40] Remove duplicate import statements --- frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx | 1 - frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx index 5e0b6c7..676ea28 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx @@ -1,7 +1,6 @@ import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import TimeReport from "../../Components/NewWeeklyReport"; -import BackButton from "../../Components/BackButton"; function PMTotalTimeActivity(): JSX.Element { const content = ( diff --git a/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx b/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx index 6276d16..aea25fb 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx @@ -2,7 +2,6 @@ import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import TimeReport from "../../Components/NewWeeklyReport"; -import BackButton from "../../Components/BackButton"; function PMViewUnsignedReport(): JSX.Element { const content = ( From 7932350980a99f2faf85bd4c40b42bea03febabc Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 23:04:08 +0100 Subject: [PATCH 32/40] Exit with non-zero if migration fails --- backend/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/main.go b/backend/main.go index 24c3702..16a033c 100644 --- a/backend/main.go +++ b/backend/main.go @@ -46,10 +46,12 @@ func main() { // Migrate the database if err = db.Migrate(); err != nil { fmt.Println("Error migrating database: ", err) + os.Exit(1) } if err = db.MigrateSampleData(); err != nil { fmt.Println("Error migrating sample data: ", err) + os.Exit(1) } // Get our global state From 2cff1d55f9829393765180d4035308b5b1ccd46d Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 23:08:38 +0100 Subject: [PATCH 33/40] Fixed migration data --- .../database/sample_data/0010_sample_data.sql | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/backend/internal/database/sample_data/0010_sample_data.sql b/backend/internal/database/sample_data/0010_sample_data.sql index 0af0d66..4dac91b 100644 --- a/backend/internal/database/sample_data/0010_sample_data.sql +++ b/backend/internal/database/sample_data/0010_sample_data.sql @@ -8,35 +8,28 @@ INSERT OR IGNORE INTO users(username, password) VALUES ("user2", "123"); INSERT OR IGNORE INTO projects(name,description,owner_user_id) -VALUES ("projecttest","test project", 1) +VALUES ("projecttest","test project", 1); INSERT OR IGNORE INTO projects(name,description,owner_user_id) -VALUES ("projecttest2","test project2", 1) +VALUES ("projecttest2","test project2", 1); INSERT OR IGNORE INTO projects(name,description,owner_user_id) -VALUES ("projecttest3","test project3", 1) +VALUES ("projecttest3","test project3", 1); INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) VALUES (1,1,"project_manager"); -INSERT INTO user_roles(user_id,project_id,p_role) +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) VALUES (2,1,"member"); -INSERT INTO user_roles(user_id,project_id,p_role) +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) VALUES (3,1,"member"); -INSERT INTO user_roles(user_id,project_id,p_role) +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) VALUES (3,2,"member"); -INSERT INTO user_roles(user_id,project_id,p_role) +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) VALUES (3,3,"member"); -INSERT INTO user_roles(user_id,project_id,p_role) +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) VALUES (2,1,"project_manager"); - - -SELECT id FROM users WHERE username = "admin" - -SELECT id FROM users WHERE username = "user" - -SELECT id FROM users WHERE username = "user2" From 9056aafd2eb470841eb2f97b7806c6a1e21a5148 Mon Sep 17 00:00:00 2001 From: al8763be Date: Mon, 18 Mar 2024 23:34:03 +0100 Subject: [PATCH 34/40] Test for getUserProjectsAdded --- testing.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/testing.py b/testing.py index 6381afc..c094dca 100644 --- a/testing.py +++ b/testing.py @@ -28,6 +28,21 @@ addUserToProjectPath = base_url + "/api/addUserToProject" promoteToAdminPath = base_url + "/api/promoteToAdmin" getUserProjectsPath = base_url + "/api/getUserProjects" +def test_get_user_projects(): + + print("Testing get user projects") + loginResponse = login("user2", "123") + # Check if the user is added to the project + response = requests.get( + getUserProjectsPath, + json={"username": "user2"}, + headers={"Authorization": "Bearer " + loginResponse.json()["token"]}, + ) + print(response.text) + print(response.json()) + assert response.status_code == 200, "Get user projects failed" + print("got user projects successfully") + # Posts the username and password to the register endpoint def register(username: string, password: string): @@ -146,17 +161,7 @@ def test_add_user_to_project(): print(response.text) assert response.status_code == 200, "Add user to project failed" - print("Add user to project successful") - - # Check if the user is added to the project - response = requests.get( - getUserProjectsPath, - json={"username": new_user}, - headers={"Authorization": "Bearer " + admin_token}, - ) - print(response.text) - assert response.status_code == 200, "Get user projects failed" - print("got user projects successfully") + print("Add user to project successful") # Test function to sign a report def test_sign_report(): @@ -235,6 +240,7 @@ def test_sign_report(): if __name__ == "__main__": + test_get_user_projects() test_create_user() test_login() test_add_project() From 0fa7558d646992bdb2f379a958cfb2b498049d87 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 23:38:50 +0100 Subject: [PATCH 35/40] Proper logging, all endpoint debug printing replaced with suitable log level --- .../handlers/handlers_project_related.go | 17 +++++------ .../handlers/handlers_report_related.go | 15 +++++----- .../handlers/handlers_user_related.go | 28 ++++++++++--------- backend/main.go | 3 ++ 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 3732249..96f6840 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -5,6 +5,7 @@ import ( "ttime/internal/types" "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/log" "github.com/golang-jwt/jwt/v5" ) @@ -69,7 +70,7 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { if projectID == "" { return c.Status(400).SendString("No project ID provided") } - println("Getting project with ID: ", projectID) + log.Info("Getting project with ID: ", projectID) // Parse the project ID into an integer projectIDInt, err := strconv.Atoi(projectID) @@ -84,7 +85,7 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { } // Return the project as JSON - println("Returning project: ", project.Name) + log.Info("Returning project: ", project.Name) return c.JSON(project) } @@ -111,7 +112,7 @@ func (gs *GState) AddUserToProjectHandler(c *fiber.Ctx) error { Role string `json:"role"` } if err := c.BodyParser(&requestData); err != nil { - println("Error parsing request body:", err) + log.Info("Error parsing request body:", err) return c.Status(400).SendString("Bad request") } @@ -119,27 +120,27 @@ func (gs *GState) AddUserToProjectHandler(c *fiber.Ctx) error { user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) adminUsername := claims["name"].(string) - println("Admin username from claims:", adminUsername) + log.Info("Admin username from claims:", adminUsername) isAdmin, err := gs.Db.IsSiteAdmin(adminUsername) if err != nil { - println("Error checking admin status:", err) + log.Info("Error checking admin status:", err) return c.Status(500).SendString(err.Error()) } if !isAdmin { - println("User is not a site admin:", adminUsername) + log.Info("User is not a site admin:", adminUsername) return c.Status(403).SendString("User is not a site admin") } // Add the user to the project with the specified role err = gs.Db.AddUserToProject(requestData.Username, requestData.ProjectName, requestData.Role) if err != nil { - println("Error adding user to project:", err) + log.Info("Error adding user to project:", err) return c.Status(500).SendString(err.Error()) } // Return success message - println("User added to project successfully:", requestData.Username) + log.Info("User added to project successfully:", requestData.Username) return c.SendStatus(fiber.StatusOK) } diff --git a/backend/internal/handlers/handlers_report_related.go b/backend/internal/handlers/handlers_report_related.go index 291d068..9219bd9 100644 --- a/backend/internal/handlers/handlers_report_related.go +++ b/backend/internal/handlers/handlers_report_related.go @@ -5,6 +5,7 @@ import ( "ttime/internal/types" "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/log" "github.com/golang-jwt/jwt/v5" ) @@ -37,16 +38,16 @@ func (gs *GState) SubmitWeeklyReport(c *fiber.Ctx) error { // Handler for retrieving weekly report func (gs *GState) GetWeeklyReport(c *fiber.Ctx) error { // Extract the necessary parameters from the request - println("GetWeeklyReport") + log.Info("GetWeeklyReport") user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) username := claims["name"].(string) // Extract project name and week from query parameters projectName := c.Query("projectName") - println(projectName) + log.Info(projectName) week := c.Query("week") - println(week) + log.Info(week) // Convert week to integer weekInt, err := strconv.Atoi(week) @@ -69,7 +70,7 @@ type ReportId struct { } func (gs *GState) SignReport(c *fiber.Ctx) error { - println("Signing report...") + log.Info("Signing report...") // Extract the necessary parameters from the token user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) @@ -81,9 +82,9 @@ func (gs *GState) SignReport(c *fiber.Ctx) error { if err := c.BodyParser(rid); err != nil { return err } - println("Signing report for: ", rid.ReportId) + log.Info("Signing report for: ", rid.ReportId) // reportIDInt, err := strconv.Atoi(rid.ReportId) - // println("Signing report for: ", rid.ReportId) + // log.Info("Signing report for: ", rid.ReportId) // if err != nil { // return c.Status(400).SendString("Invalid report ID") // } @@ -93,7 +94,7 @@ func (gs *GState) SignReport(c *fiber.Ctx) error { if err != nil { return c.Status(500).SendString("Failed to get project manager ID") } - println("blabla", projectManagerID) + log.Info("blabla", projectManagerID) // Call the database function to sign the weekly report err = gs.Db.SignWeeklyReport(rid.ReportId, projectManagerID) diff --git a/backend/internal/handlers/handlers_user_related.go b/backend/internal/handlers/handlers_user_related.go index 0f7c047..24175ee 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -1,10 +1,11 @@ package handlers import ( - "fmt" "time" "ttime/internal/types" + "github.com/gofiber/fiber/v2/log" + "github.com/gofiber/fiber/v2" "github.com/golang-jwt/jwt/v5" ) @@ -23,16 +24,17 @@ import ( func (gs *GState) Register(c *fiber.Ctx) error { u := new(types.NewUser) if err := c.BodyParser(u); err != nil { - println("Error parsing body") + log.Warn("Error parsing body") return c.Status(400).SendString(err.Error()) } - println("Adding user:", u.Username) + log.Info("Adding user:", u.Username) + log.Info("Adding user:", u.Username) if err := gs.Db.AddUser(u.Username, u.Password); err != nil { return c.Status(500).SendString(err.Error()) } - println("User added:", u.Username) + log.Info("User added:", u.Username) return c.Status(200).SendString("User added") } @@ -61,13 +63,13 @@ func (gs *GState) Login(c *fiber.Ctx) error { // The body type is identical to a NewUser u := new(types.NewUser) if err := c.BodyParser(u); err != nil { - println("Error parsing body") + log.Warn("Error parsing body") return c.Status(400).SendString(err.Error()) } - println("Username:", u.Username) + log.Info("Username:", u.Username) if !gs.Db.CheckUser(u.Username, u.Password) { - println("User not found") + log.Info("User not found") return c.SendStatus(fiber.StatusUnauthorized) } @@ -80,16 +82,16 @@ func (gs *GState) Login(c *fiber.Ctx) error { // Create token token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - println("Token created for user:", u.Username) + log.Info("Token created for user:", u.Username) // Generate encoded token and send it as response. t, err := token.SignedString([]byte("secret")) if err != nil { - println("Error signing token") + log.Warn("Error signing token") return c.SendStatus(fiber.StatusInternalServerError) } - println("Successfully signed token for user:", u.Username) + log.Info("Successfully signed token for user:", u.Username) return c.JSON(fiber.Map{"token": t}) } @@ -132,15 +134,15 @@ func (gs *GState) PromoteToAdmin(c *fiber.Ctx) error { } username := newUser.Username - println("Promoting user to admin:", username) // Debug print + log.Info("Promoting user to admin:", username) // Debug print // Promote the user to a site admin in the database if err := gs.Db.PromoteToAdmin(username); err != nil { - fmt.Println("Error promoting user to admin:", err) // Debug print + log.Info("Error promoting user to admin:", err) // Debug print return c.Status(500).SendString(err.Error()) } - println("User promoted to admin successfully:", username) // Debug print + log.Info("User promoted to admin successfully:", username) // Debug print // Return a success message return c.SendStatus(fiber.StatusOK) diff --git a/backend/main.go b/backend/main.go index da89043..5517dbe 100644 --- a/backend/main.go +++ b/backend/main.go @@ -10,6 +10,7 @@ import ( "github.com/BurntSushi/toml" "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/swagger" jwtware "github.com/gofiber/contrib/jwt" @@ -53,6 +54,8 @@ func main() { // Create the server server := fiber.New() + server.Use(logger.New()) + server.Get("/swagger/*", swagger.HandlerDefault) // Mount our static files (Beware of the security implications of this!) From 4c297ab2efc799a56f26b81ea7cc191751666038 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 18 Mar 2024 23:39:02 +0100 Subject: [PATCH 36/40] Old unresolved merge conflict fixed --- testing.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/testing.py b/testing.py index e342598..7a8a52b 100644 --- a/testing.py +++ b/testing.py @@ -22,13 +22,10 @@ loginPath = base_url + "/api/login" addProjectPath = base_url + "/api/project" submitReportPath = base_url + "/api/submitReport" getWeeklyReportPath = base_url + "/api/getWeeklyReport" -<<<<<<< HEAD getProjectPath = base_url + "/api/project" -======= signReportPath = base_url + "/api/signReport" addUserToProjectPath = base_url + "/api/addUserToProject" promoteToAdminPath = base_url + "/api/promoteToAdmin" ->>>>>>> 9ad89d60636ac6091d71b0bf307982becc9b89fe # Posts the username and password to the register endpoint @@ -232,9 +229,6 @@ if __name__ == "__main__": test_add_project() test_submit_report() test_get_weekly_report() -<<<<<<< HEAD test_get_project() -======= test_sign_report() test_add_user_to_project() ->>>>>>> 9ad89d60636ac6091d71b0bf307982becc9b89fe From fe08d01e15ed9e293e8c02449d947bc6f002697b Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Tue, 19 Mar 2024 00:00:18 +0100 Subject: [PATCH 37/40] Insanely verbose logging --- .../handlers/handlers_project_related.go | 10 +++++++ .../handlers/handlers_report_related.go | 30 ++++++++++++------- .../handlers/handlers_user_related.go | 16 ++++++++-- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go index 96f6840..f3a7ea0 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -68,6 +68,7 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { // Extract the project ID from the request parameters or body projectID := c.Params("projectID") if projectID == "" { + log.Info("No project ID provided") return c.Status(400).SendString("No project ID provided") } log.Info("Getting project with ID: ", projectID) @@ -75,12 +76,14 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { // Parse the project ID into an integer projectIDInt, err := strconv.Atoi(projectID) if err != nil { + log.Info("Invalid project ID") return c.Status(400).SendString("Invalid project ID") } // Get the project from the database by its ID project, err := gs.Db.GetProject(projectIDInt) if err != nil { + log.Info("Error getting project:", err) return c.Status(500).SendString(err.Error()) } @@ -92,13 +95,20 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { func (gs *GState) ListAllUsersProject(c *fiber.Ctx) error { // Extract the project name from the request parameters or body projectName := c.Params("projectName") + if projectName == "" { + log.Info("No project name provided") + return c.Status(400).SendString("No project name provided") + } // Get all users associated with the project from the database users, err := gs.Db.GetAllUsersProject(projectName) if err != nil { + log.Info("Error getting users for project:", err) return c.Status(500).SendString(err.Error()) } + log.Info("Returning users for project: ", projectName) + // Return the list of users as JSON return c.JSON(users) } diff --git a/backend/internal/handlers/handlers_report_related.go b/backend/internal/handlers/handlers_report_related.go index 9219bd9..85eb6e2 100644 --- a/backend/internal/handlers/handlers_report_related.go +++ b/backend/internal/handlers/handlers_report_related.go @@ -17,50 +17,62 @@ func (gs *GState) SubmitWeeklyReport(c *fiber.Ctx) error { report := new(types.NewWeeklyReport) if err := c.BodyParser(report); err != nil { + log.Info("Error parsing weekly report") return c.Status(400).SendString(err.Error()) } // Make sure all the fields of the report are valid if report.Week < 1 || report.Week > 52 { + log.Info("Invalid week number") return c.Status(400).SendString("Invalid week number") } if report.DevelopmentTime < 0 || report.MeetingTime < 0 || report.AdminTime < 0 || report.OwnWorkTime < 0 || report.StudyTime < 0 || report.TestingTime < 0 { + log.Info("Invalid time report") return c.Status(400).SendString("Invalid time report") } if err := gs.Db.AddWeeklyReport(report.ProjectName, username, report.Week, report.DevelopmentTime, report.MeetingTime, report.AdminTime, report.OwnWorkTime, report.StudyTime, report.TestingTime); err != nil { + log.Info("Error adding weekly report") return c.Status(500).SendString(err.Error()) } + log.Info("Weekly report added") return c.Status(200).SendString("Time report added") } // Handler for retrieving weekly report func (gs *GState) GetWeeklyReport(c *fiber.Ctx) error { // Extract the necessary parameters from the request - log.Info("GetWeeklyReport") user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) username := claims["name"].(string) + log.Info("Getting weekly report for: ", username) + // Extract project name and week from query parameters projectName := c.Query("projectName") - log.Info(projectName) week := c.Query("week") - log.Info(week) + + if projectName == "" || week == "" { + log.Info("Missing project name or week number") + return c.Status(400).SendString("Missing project name or week number") + } // Convert week to integer weekInt, err := strconv.Atoi(week) if err != nil { + log.Info("Invalid week number") return c.Status(400).SendString("Invalid week number") } // Call the database function to get the weekly report report, err := gs.Db.GetWeeklyReport(username, projectName, weekInt) if err != nil { + log.Info("Error getting weekly report from db:", err) return c.Status(500).SendString(err.Error()) } + log.Info("Returning weekly report") // Return the retrieved weekly report return c.JSON(report) } @@ -70,12 +82,13 @@ type ReportId struct { } func (gs *GState) SignReport(c *fiber.Ctx) error { - log.Info("Signing report...") // Extract the necessary parameters from the token user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) projectManagerUsername := claims["name"].(string) + log.Info("Signing report for: ", projectManagerUsername) + // Extract report ID from the request query parameters // reportID := c.Query("reportId") rid := new(ReportId) @@ -83,22 +96,19 @@ func (gs *GState) SignReport(c *fiber.Ctx) error { return err } log.Info("Signing report for: ", rid.ReportId) - // reportIDInt, err := strconv.Atoi(rid.ReportId) - // log.Info("Signing report for: ", rid.ReportId) - // if err != nil { - // return c.Status(400).SendString("Invalid report ID") - // } // Get the project manager's ID projectManagerID, err := gs.Db.GetUserId(projectManagerUsername) if err != nil { + log.Info("Failed to get project manager ID") return c.Status(500).SendString("Failed to get project manager ID") } - log.Info("blabla", projectManagerID) + log.Info("Project manager ID: ", projectManagerID) // Call the database function to sign the weekly report err = gs.Db.SignWeeklyReport(rid.ReportId, projectManagerID) if err != nil { + log.Info("Error signing weekly report:", err) 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 24175ee..8f4108c 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -28,9 +28,9 @@ func (gs *GState) Register(c *fiber.Ctx) error { return c.Status(400).SendString(err.Error()) } - log.Info("Adding user:", u.Username) log.Info("Adding user:", u.Username) if err := gs.Db.AddUser(u.Username, u.Password); err != nil { + log.Warn("Error adding user:", err) return c.Status(500).SendString(err.Error()) } @@ -48,13 +48,16 @@ func (gs *GState) UserDelete(c *fiber.Ctx) error { auth_username := c.Locals("user").(*jwt.Token).Claims.(jwt.MapClaims)["name"].(string) if username != auth_username { + log.Info("User tried to delete another user") return c.Status(403).SendString("You can only delete yourself") } if err := gs.Db.RemoveUser(username); err != nil { + log.Warn("Error deleting user:", err) return c.Status(500).SendString(err.Error()) } + log.Info("User deleted:", username) return c.Status(200).SendString("User deleted") } @@ -67,7 +70,7 @@ func (gs *GState) Login(c *fiber.Ctx) error { return c.Status(400).SendString(err.Error()) } - log.Info("Username:", u.Username) + log.Info("Username logging in:", u.Username) if !gs.Db.CheckUser(u.Username, u.Password) { log.Info("User not found") return c.SendStatus(fiber.StatusUnauthorized) @@ -97,8 +100,10 @@ func (gs *GState) Login(c *fiber.Ctx) error { // LoginRenew is a simple handler that renews the token func (gs *GState) LoginRenew(c *fiber.Ctx) error { - // For testing: curl localhost:3000/restricted -H "Authorization: Bearer " user := c.Locals("user").(*jwt.Token) + + log.Info("Renewing token for user:", user.Claims.(jwt.MapClaims)["name"]) + claims := user.Claims.(jwt.MapClaims) claims["exp"] = time.Now().Add(time.Hour * 72).Unix() renewed := jwt.MapClaims{ @@ -109,8 +114,11 @@ func (gs *GState) LoginRenew(c *fiber.Ctx) error { token := jwt.NewWithClaims(jwt.SigningMethodHS256, renewed) t, err := token.SignedString([]byte("secret")) if err != nil { + log.Warn("Error signing token") return c.SendStatus(fiber.StatusInternalServerError) } + + log.Info("Successfully renewed token for user:", user.Claims.(jwt.MapClaims)["name"]) return c.JSON(fiber.Map{"token": t}) } @@ -119,9 +127,11 @@ func (gs *GState) ListAllUsers(c *fiber.Ctx) error { // Get all users from the database users, err := gs.Db.GetAllUsersApplication() if err != nil { + log.Info("Error getting users from db:", 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) } From 83f8097c2b8e7fcd07f10c2be5b813b02fc40d69 Mon Sep 17 00:00:00 2001 From: al8763be Date: Tue, 19 Mar 2024 00:20:08 +0100 Subject: [PATCH 38/40] API getUserProjects Fucked --- frontend/src/API/API.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 6078513..a06f804 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -176,7 +176,7 @@ export const api: API = { } catch (e) { return Promise.resolve({ success: false, - message: "Failed to get user projects", + message: "API fucked", }); } }, From 59c4dab2e26ccb942ab38d7621d27d69654f2754 Mon Sep 17 00:00:00 2001 From: al8763be Date: Tue, 19 Mar 2024 00:26:17 +0100 Subject: [PATCH 39/40] quick fix for getUserProjects API --- frontend/src/API/API.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index a06f804..cab3b6b 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -150,10 +150,7 @@ export const api: API = { } }, - async getUserProjects( - username: string, - token: string, - ): Promise> { + async getUserProjects(token: string): Promise> { try { const response = await fetch("/api/getUserProjects", { method: "GET", @@ -161,7 +158,6 @@ export const api: API = { "Content-Type": "application/json", Authorization: "Bearer " + token, }, - body: JSON.stringify({ username }), }); if (!response.ok) { From d7e14f18860c41e5a0416e1584bba63d9daace14 Mon Sep 17 00:00:00 2001 From: al8763be Date: Tue, 19 Mar 2024 00:27:35 +0100 Subject: [PATCH 40/40] quick fix for getUserProjects API --- frontend/src/API/API.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index cab3b6b..8fd66d3 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -42,10 +42,7 @@ interface API { token: string, ): Promise>; /** Gets all the projects of a user*/ - getUserProjects( - username: string, - token: string, - ): Promise>; + getUserProjects(token: string): Promise>; /** Gets a project from id*/ getProject(id: number): Promise>; }