diff --git a/.gitignore b/.gitignore index 313b735..bdbfff8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,6 @@ dist/ .vscode/ .idea/ .DS_Store -.go.work.sum # Ignore configuration files .env diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index e2aa366..5cbb13f 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -32,7 +32,6 @@ 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 @@ -107,10 +106,7 @@ 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.Get(&project, "SELECT * FROM projects WHERE id = ?", projectId) - if err != nil { - println("Error getting project: ", err) - } + err := d.Select(&project, "SELECT * FROM projects WHERE id = ?") return project, err } @@ -317,26 +313,6 @@ 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 a7f3878..09de45b 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -536,33 +536,3 @@ 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 566d549..c8beb1c 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -17,9 +17,6 @@ type GlobalState interface { SubmitWeeklyReport(c *fiber.Ctx) error GetWeeklyReport(c *fiber.Ctx) error SignReport(c *fiber.Ctx) error - GetProject(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 3732249..6a430e9 100644 --- a/backend/internal/handlers/handlers_project_related.go +++ b/backend/internal/handlers/handlers_project_related.go @@ -66,10 +66,6 @@ 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) @@ -84,7 +80,6 @@ func (gs *GState) GetProject(c *fiber.Ctx) error { } // Return the project as JSON - println("Returning project: ", project.Name) return c.JSON(project) } @@ -101,45 +96,3 @@ 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_report_related.go b/backend/internal/handlers/handlers_report_related.go index 291d068..509bd67 100644 --- a/backend/internal/handlers/handlers_report_related.go +++ b/backend/internal/handlers/handlers_report_related.go @@ -64,42 +64,30 @@ 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) - projectManagerUsername := claims["name"].(string) + managerUsername := claims["name"].(string) - // Extract report ID from the request query parameters - // reportID := c.Query("reportId") - rid := new(ReportId) - if err := c.BodyParser(rid); err != nil { - return err + // 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") } - 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") - // } - // Get the project manager's ID - projectManagerID, err := gs.Db.GetUserId(projectManagerUsername) + // Call the database function to get the project manager ID + managerID, err := gs.Db.GetUserId(managerUsername) 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(rid.ReportId, projectManagerID) + err = gs.Db.SignWeeklyReport(reportID, managerID) if err != nil { - return c.Status(500).SendString(err.Error()) + return c.Status(500).SendString("Failed to sign the weekly report: " + err.Error()) } + // Return success response return c.Status(200).SendString("Weekly report signed successfully") } diff --git a/backend/internal/handlers/handlers_user_related.go b/backend/internal/handlers/handlers_user_related.go index 0f7c047..0619ea5 100644 --- a/backend/internal/handlers/handlers_user_related.go +++ b/backend/internal/handlers/handlers_user_related.go @@ -1,7 +1,6 @@ package handlers import ( - "fmt" "time" "ttime/internal/types" @@ -123,25 +122,3 @@ 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 3e2fb75..bc33942 100644 --- a/backend/main.go +++ b/backend/main.go @@ -78,11 +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) - 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)) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index e8566b6..ac0f531 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -46,7 +46,6 @@ interface API { username: string, token: string, ): Promise>; - getProject(id: number): Promise>; } // Export an instance of the API @@ -254,30 +253,4 @@ 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/go.work.sum b/go.work.sum index 087c85b..a58340b 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,28 +1,15 @@ -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/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= -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/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/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/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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= -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= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/testing.py b/testing.py index e342598..38d09cc 100644 --- a/testing.py +++ b/testing.py @@ -22,13 +22,6 @@ 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 @@ -50,20 +43,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"] @@ -76,7 +69,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( @@ -97,7 +90,6 @@ 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( @@ -106,135 +98,10 @@ 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" - -# 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() -<<<<<<< HEAD - test_get_project() -======= - test_sign_report() - test_add_user_to_project() ->>>>>>> 9ad89d60636ac6091d71b0bf307982becc9b89fe + test_get_weekly_report() \ No newline at end of file