PromoteToPm handler
This commit is contained in:
		
							parent
							
								
									9cca8edd9d
								
							
						
					
					
						commit
						61a2d1ce0c
					
				
					 4 changed files with 97 additions and 588 deletions
				
			
		
							
								
								
									
										51
									
								
								backend/internal/handlers/projects/PromoteToPm.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								backend/internal/handlers/projects/PromoteToPm.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,51 @@
 | 
				
			||||||
 | 
					package projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						db "ttime/internal/database"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gofiber/fiber/v2"
 | 
				
			||||||
 | 
						"github.com/gofiber/fiber/v2/log"
 | 
				
			||||||
 | 
						"github.com/golang-jwt/jwt/v5"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//	@Summary		Promote to project manager
 | 
				
			||||||
 | 
					//	@Description	Promote a user to project manager
 | 
				
			||||||
 | 
					//	@Tags			Auth
 | 
				
			||||||
 | 
					//	@Security		JWT
 | 
				
			||||||
 | 
					//	@Accept			plain
 | 
				
			||||||
 | 
					//	@Produce		plain
 | 
				
			||||||
 | 
					//	@Param			projectName	path	string	true	"Project name"
 | 
				
			||||||
 | 
					//	@Param			userName	query	string	true	"User name"
 | 
				
			||||||
 | 
					//	@Failure		500		{string}	string	"Internal server error"
 | 
				
			||||||
 | 
					//	@Failure		403		{string}	string	"Forbidden"
 | 
				
			||||||
 | 
					//	@Router			/promote/{projectName} [put]
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Login logs in a user and returns a JWT token
 | 
				
			||||||
 | 
					// Promote to project manager
 | 
				
			||||||
 | 
					func PromoteToPm(c *fiber.Ctx) error {
 | 
				
			||||||
 | 
						user := c.Locals("user").(*jwt.Token)
 | 
				
			||||||
 | 
						claims := user.Claims.(jwt.MapClaims)
 | 
				
			||||||
 | 
						pm_name := claims["name"].(string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						project := c.Params("projectName")
 | 
				
			||||||
 | 
						new_pm_name := c.Query("userName")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the user is a project manager
 | 
				
			||||||
 | 
						isPM, err := db.GetDb(c).IsProjectManager(pm_name, project)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Info("Error checking if user is project manager:", err)
 | 
				
			||||||
 | 
							return c.Status(500).SendString(err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !isPM {
 | 
				
			||||||
 | 
							log.Info("User: ", pm_name, " is not a project manager in project: ", project)
 | 
				
			||||||
 | 
							return c.Status(403).SendString("User is not a project manager")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add the user to the project with the specified role
 | 
				
			||||||
 | 
						err = db.GetDb(c).ChangeUserRole(new_pm_name, project, "project_manager")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return success message
 | 
				
			||||||
 | 
						log.Info("User : ", new_pm_name, " promoted to project manager in project: ", project)
 | 
				
			||||||
 | 
						return c.SendStatus(fiber.StatusOK)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -119,6 +119,8 @@ func main() {
 | 
				
			||||||
	api.Get("/getUsersProject/:projectName", projects.ListAllUsersProject)
 | 
						api.Get("/getUsersProject/:projectName", projects.ListAllUsersProject)
 | 
				
			||||||
	api.Post("/project", projects.CreateProject)
 | 
						api.Post("/project", projects.CreateProject)
 | 
				
			||||||
	api.Post("/ProjectRoleChange", projects.ProjectRoleChange)
 | 
						api.Post("/ProjectRoleChange", projects.ProjectRoleChange)
 | 
				
			||||||
 | 
						api.Put("/promoteToPm/:projectName", projects.PromoteToPm)
 | 
				
			||||||
 | 
						api.Put("/addUserToProject/:projectName", projects.AddUserToProjectHandler)
 | 
				
			||||||
	api.Delete("/removeProject/:projectName", projects.RemoveProject)
 | 
						api.Delete("/removeProject/:projectName", projects.RemoveProject)
 | 
				
			||||||
	api.Delete("/project/:projectID", projects.DeleteProject)
 | 
						api.Delete("/project/:projectID", projects.DeleteProject)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,7 +131,6 @@ func main() {
 | 
				
			||||||
	api.Get("/getWeeklyReportsUser/:projectName", reports.GetWeeklyReportsUserHandler)
 | 
						api.Get("/getWeeklyReportsUser/:projectName", reports.GetWeeklyReportsUserHandler)
 | 
				
			||||||
	api.Post("/submitWeeklyReport", reports.SubmitWeeklyReport)
 | 
						api.Post("/submitWeeklyReport", reports.SubmitWeeklyReport)
 | 
				
			||||||
	api.Put("/signReport/:reportId", reports.SignReport)
 | 
						api.Put("/signReport/:reportId", reports.SignReport)
 | 
				
			||||||
	api.Put("/addUserToProject", projects.AddUserToProjectHandler)
 | 
					 | 
				
			||||||
	api.Put("/updateWeeklyReport", reports.UpdateWeeklyReport)
 | 
						api.Put("/updateWeeklyReport", reports.UpdateWeeklyReport)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Announce the port we are listening on and start the server
 | 
						// Announce the port we are listening on and start the server
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,6 +209,19 @@ interface API {
 | 
				
			||||||
   * @param {string} token The authentication token
 | 
					   * @param {string} token The authentication token
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  signReport(reportId: number, token: string): Promise<APIResponse<string>>;
 | 
					  signReport(reportId: number, token: string): Promise<APIResponse<string>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Promotes a user to project manager within a project.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param {string} userName The username of the user to promote
 | 
				
			||||||
 | 
					   * @param {string} projectName The name of the project to promote the user in
 | 
				
			||||||
 | 
					   * @returns {Promise<APIResponse<string>} A promise resolving to an API response.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  promoteToPm(
 | 
				
			||||||
 | 
					    userName: string,
 | 
				
			||||||
 | 
					    projectName: string,
 | 
				
			||||||
 | 
					    token: string,
 | 
				
			||||||
 | 
					  ): Promise<APIResponse<string>>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** An instance of the API */
 | 
					/** An instance of the API */
 | 
				
			||||||
| 
						 | 
					@ -783,4 +796,35 @@ export const api: API = {
 | 
				
			||||||
      return { success: false, message: "Failed to sign report" };
 | 
					      return { success: false, message: "Failed to sign report" };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async promoteToPm(
 | 
				
			||||||
 | 
					    userName: string,
 | 
				
			||||||
 | 
					    projectName: string,
 | 
				
			||||||
 | 
					    token: string,
 | 
				
			||||||
 | 
					  ): Promise<APIResponse<string>> {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const response = await fetch(
 | 
				
			||||||
 | 
					        `/api/promoteToPm/${projectName}?userName=${userName}`,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          method: "PUT",
 | 
				
			||||||
 | 
					          headers: {
 | 
				
			||||||
 | 
					            "Content-Type": "application/json",
 | 
				
			||||||
 | 
					            Authorization: "Bearer " + token,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      if (!response.ok) {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          success: false,
 | 
				
			||||||
 | 
					          message: "Failed to promote user to project manager",
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        success: false,
 | 
				
			||||||
 | 
					        message: "Failed to promote user to project manager",
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return { success: true, message: "User promoted to project manager" };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										587
									
								
								testing.py
									
										
									
									
									
								
							
							
						
						
									
										587
									
								
								testing.py
									
										
									
									
									
								
							| 
						 | 
					@ -1,587 +0,0 @@
 | 
				
			||||||
import requests
 | 
					 | 
				
			||||||
import string
 | 
					 | 
				
			||||||
import random
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
debug_output = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def gprint(*args, **kwargs):
 | 
					 | 
				
			||||||
    print("\033[92m", *args, "\033[00m", **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
print("Running Tests...")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def dprint(*args, **kwargs):
 | 
					 | 
				
			||||||
    if debug_output:
 | 
					 | 
				
			||||||
        print(*args, **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def randomString(len=10):
 | 
					 | 
				
			||||||
    """Generate a random string of fixed length"""
 | 
					 | 
				
			||||||
    letters = string.ascii_lowercase
 | 
					 | 
				
			||||||
    return "".join(random.choice(letters) for i in range(len))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Defined once per test run
 | 
					 | 
				
			||||||
username = "user_" + randomString()
 | 
					 | 
				
			||||||
projectName = "project_" + randomString()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# The base URL of the API
 | 
					 | 
				
			||||||
base_url = "http://localhost:8080"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Endpoint to test
 | 
					 | 
				
			||||||
registerPath = base_url + "/api/register"
 | 
					 | 
				
			||||||
loginPath = base_url + "/api/login"
 | 
					 | 
				
			||||||
addProjectPath = base_url + "/api/project"
 | 
					 | 
				
			||||||
submitReportPath = base_url + "/api/submitWeeklyReport"
 | 
					 | 
				
			||||||
getWeeklyReportPath = base_url + "/api/getWeeklyReport"
 | 
					 | 
				
			||||||
getProjectPath = base_url + "/api/project"
 | 
					 | 
				
			||||||
signReportPath = base_url + "/api/signReport"
 | 
					 | 
				
			||||||
addUserToProjectPath = base_url + "/api/addUserToProject"
 | 
					 | 
				
			||||||
promoteToAdminPath = base_url + "/api/promoteToAdmin"
 | 
					 | 
				
			||||||
getUserProjectsPath = base_url + "/api/getUserProjects"
 | 
					 | 
				
			||||||
getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser"
 | 
					 | 
				
			||||||
checkIfProjectManagerPath = base_url + "/api/checkIfProjectManager"
 | 
					 | 
				
			||||||
ProjectRoleChangePath = base_url + "/api/ProjectRoleChange"
 | 
					 | 
				
			||||||
getUsersProjectPath = base_url + "/api/getUsersProject"
 | 
					 | 
				
			||||||
getUnsignedReportsPath = base_url + "/api/getUnsignedReports"
 | 
					 | 
				
			||||||
getChangeUserNamePath = base_url + "/api/changeUserName"
 | 
					 | 
				
			||||||
getUpdateWeeklyReportPath = base_url + "/api/updateWeeklyReport"
 | 
					 | 
				
			||||||
removeProjectPath = base_url + "/api/removeProject"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ta bort auth i handlern för att få testet att gå igenom
 | 
					 | 
				
			||||||
def test_ProjectRoleChange():
 | 
					 | 
				
			||||||
    dprint("Testing ProjectRoleChange")
 | 
					 | 
				
			||||||
    localUsername = randomString()
 | 
					 | 
				
			||||||
    localProjectName = randomString()
 | 
					 | 
				
			||||||
    register(localUsername, "username_password")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    token = login(localUsername, "username_password").json()[
 | 
					 | 
				
			||||||
        "token"
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Just checking since this test is built somewhat differently than the others
 | 
					 | 
				
			||||||
    assert token != None, "Login failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        addProjectPath,
 | 
					 | 
				
			||||||
        json={"name": localProjectName, "description": "This is a project"},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if response.status_code != 200:
 | 
					 | 
				
			||||||
        print("Add project failed")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        ProjectRoleChangePath,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
        json={
 | 
					 | 
				
			||||||
            "projectName": localProjectName,
 | 
					 | 
				
			||||||
            "role": "project_manager",
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "ProjectRoleChange failed"
 | 
					 | 
				
			||||||
    gprint("test_ProjectRoleChange successful")
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_get_user_projects():
 | 
					 | 
				
			||||||
    username = "user2"
 | 
					 | 
				
			||||||
    password = "123"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dprint("Testing get user projects")
 | 
					 | 
				
			||||||
    loginResponse = login(username, password) 
 | 
					 | 
				
			||||||
    # Check if the user is added to the project
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        getUserProjectsPath + "/" + username,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + loginResponse.json()["token"]},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    dprint(response.json())
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Get user projects failed"
 | 
					 | 
				
			||||||
    gprint("test_get_user_projects successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Posts the username and password to the register endpoint
 | 
					 | 
				
			||||||
def register(username: string, password: string):
 | 
					 | 
				
			||||||
    dprint("Registering with username: ", username, " and password: ", password)
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        registerPath, json={"username": username, "password": password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    return response
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Posts the username and password to the login endpoint
 | 
					 | 
				
			||||||
def login(username: string, password: string):
 | 
					 | 
				
			||||||
    dprint("Logging in with username: ", username, " and password: ", password)
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        loginPath, json={"username": username, "password": password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    return response
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Test function to login
 | 
					 | 
				
			||||||
def test_login():
 | 
					 | 
				
			||||||
    response = login(username, "always_same")
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Login failed"
 | 
					 | 
				
			||||||
    dprint("Login successful")
 | 
					 | 
				
			||||||
    gprint("test_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"
 | 
					 | 
				
			||||||
    gprint("test_create_user successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Test function to add a project
 | 
					 | 
				
			||||||
def test_add_project():
 | 
					 | 
				
			||||||
    loginResponse = login(username, "always_same")
 | 
					 | 
				
			||||||
    token = loginResponse.json()["token"]
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        addProjectPath,
 | 
					 | 
				
			||||||
        json={"name": projectName, "description": "This is a project"},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add project failed"
 | 
					 | 
				
			||||||
    gprint("test_add_project successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Test function to submit a report
 | 
					 | 
				
			||||||
def test_submit_report():
 | 
					 | 
				
			||||||
    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},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Submit report failed"
 | 
					 | 
				
			||||||
    gprint("test_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(
 | 
					 | 
				
			||||||
        getWeeklyReportPath,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
        params={"username": username, "projectName": projectName, "week": 1},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Get weekly report failed"
 | 
					 | 
				
			||||||
    gprint("test_get_weekly_report successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 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},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Get project failed"
 | 
					 | 
				
			||||||
    gprint("test_get_project successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 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"
 | 
					 | 
				
			||||||
    dprint(
 | 
					 | 
				
			||||||
        "Registering with username: ", admin_username, " and password: ", admin_password
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        registerPath, json={"username": admin_username, "password": admin_password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    admin_token = login(admin_username, admin_password).json()["token"]
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        promoteToAdminPath,
 | 
					 | 
				
			||||||
        json={"username": admin_username},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Promote to site admin failed"
 | 
					 | 
				
			||||||
    dprint("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},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add user to project failed"
 | 
					 | 
				
			||||||
    gprint("test_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"
 | 
					 | 
				
			||||||
    dprint(
 | 
					 | 
				
			||||||
        "Registering with username: ", admin_username, " and password: ", admin_password
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        registerPath, json={"username": admin_username, "password": admin_password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Log in as the admin
 | 
					 | 
				
			||||||
    admin_token = login(admin_username, admin_password).json()["token"]
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        promoteToAdminPath,
 | 
					 | 
				
			||||||
        json={"username": admin_username},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    response = requests.put(
 | 
					 | 
				
			||||||
        addUserToProjectPath + "/" + projectName,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
        params={"userName": project_manager}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add project manager to project failed"
 | 
					 | 
				
			||||||
    dprint("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": 2,
 | 
					 | 
				
			||||||
            "developmentTime": 10,
 | 
					 | 
				
			||||||
            "meetingTime": 5,
 | 
					 | 
				
			||||||
            "adminTime": 5,
 | 
					 | 
				
			||||||
            "ownWorkTime": 10,
 | 
					 | 
				
			||||||
            "studyTime": 10,
 | 
					 | 
				
			||||||
            "testingTime": 10,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Submit report failed"
 | 
					 | 
				
			||||||
    dprint("Submit report successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Retrieve the report ID
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        getWeeklyReportPath,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
        params={"username": username, "projectName": projectName, "week": 1},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    report_id = response.json()["reportId"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Sign the report as the project manager
 | 
					 | 
				
			||||||
    response = requests.put(
 | 
					 | 
				
			||||||
        signReportPath + "/" + str(report_id),
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + project_manager_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Sign report failed"
 | 
					 | 
				
			||||||
    dprint("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},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    gprint("test_sign_report successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Test function to get weekly reports for a user in a project
 | 
					 | 
				
			||||||
def test_get_weekly_reports_user():
 | 
					 | 
				
			||||||
    # Log in as the user
 | 
					 | 
				
			||||||
    token = login(username, "always_same").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Get weekly reports for the user in the project
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        getWeeklyReportsUserPath + "/" + projectName,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Get weekly reports for user failed"
 | 
					 | 
				
			||||||
    gprint("test_get_weekly_reports_user successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Test function to check if a user is a project manager
 | 
					 | 
				
			||||||
def test_check_if_project_manager():
 | 
					 | 
				
			||||||
    # Log in as the user
 | 
					 | 
				
			||||||
    token = login(username, "always_same").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Check if the user is a project manager for the project
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        checkIfProjectManagerPath + "/" + projectName,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Check if project manager failed"
 | 
					 | 
				
			||||||
    gprint("test_check_if_project_manager successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_ensure_manager_of_created_project():
 | 
					 | 
				
			||||||
    # Create a new user to add to the project
 | 
					 | 
				
			||||||
    newUser = "karen_" + randomString()
 | 
					 | 
				
			||||||
    newProject = "HR_" + randomString()
 | 
					 | 
				
			||||||
    register(newUser, "new_user_password")
 | 
					 | 
				
			||||||
    token = login(newUser, "new_user_password").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Create a new project
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        addProjectPath,
 | 
					 | 
				
			||||||
        json={"name": newProject, "description": "This is a project"},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add project failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        checkIfProjectManagerPath + "/" + newProject,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Check if project manager failed"
 | 
					 | 
				
			||||||
    assert response.json()["isProjectManager"] == True, "User is not project manager"
 | 
					 | 
				
			||||||
    gprint("test_ensure_admin_of_created_project successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_change_user_name():
 | 
					 | 
				
			||||||
    # Register a new user
 | 
					 | 
				
			||||||
    new_user = randomString()
 | 
					 | 
				
			||||||
    register(new_user, "password")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Log in as the new user
 | 
					 | 
				
			||||||
    token = login(new_user, "password").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Register a new admin
 | 
					 | 
				
			||||||
    admin_username = randomString()
 | 
					 | 
				
			||||||
    admin_password = "admin_password"
 | 
					 | 
				
			||||||
    dprint(
 | 
					 | 
				
			||||||
        "Registering with username: ", admin_username, " and password: ", admin_password
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        registerPath, json={"username": admin_username, "password": admin_password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    admin_token = login(admin_username, admin_password).json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Promote to admin 
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        promoteToAdminPath,
 | 
					 | 
				
			||||||
        json={"username": admin_username},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Change the user's name
 | 
					 | 
				
			||||||
    response = requests.put(
 | 
					 | 
				
			||||||
        getChangeUserNamePath,
 | 
					 | 
				
			||||||
        json={"prevName": new_user, "newName": randomString()},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Check if the change was successful
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Change user name failed"
 | 
					 | 
				
			||||||
    gprint("test_change_user_name successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_list_all_users_project():
 | 
					 | 
				
			||||||
    # Log in as a user who is a member of the project
 | 
					 | 
				
			||||||
    admin_username = randomString()
 | 
					 | 
				
			||||||
    admin_password = "admin_password2"
 | 
					 | 
				
			||||||
    dprint(
 | 
					 | 
				
			||||||
        "Registering with username: ", admin_username, " and password: ", admin_password
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        registerPath, json={"username": admin_username, "password": admin_password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Log in as the admin
 | 
					 | 
				
			||||||
    admin_token = login(admin_username, admin_password).json()["token"]
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        promoteToAdminPath,
 | 
					 | 
				
			||||||
        json={"username": admin_username},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Make a request to list all users associated with the project
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        getUsersProjectPath + "/" + projectName,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},    
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "List all users project failed"
 | 
					 | 
				
			||||||
    gprint("test_list_all_users_project sucessful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_update_weekly_report():
 | 
					 | 
				
			||||||
    # Log in as the user
 | 
					 | 
				
			||||||
    token = login(username, "always_same").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Prepare the JSON data for updating the weekly report
 | 
					 | 
				
			||||||
    update_data = {
 | 
					 | 
				
			||||||
        "projectName": projectName,
 | 
					 | 
				
			||||||
        "userName": username,
 | 
					 | 
				
			||||||
        "week": 1,
 | 
					 | 
				
			||||||
        "developmentTime": 8,
 | 
					 | 
				
			||||||
        "meetingTime": 6,
 | 
					 | 
				
			||||||
        "adminTime": 4,
 | 
					 | 
				
			||||||
        "ownWorkTime": 11,
 | 
					 | 
				
			||||||
        "studyTime": 8,
 | 
					 | 
				
			||||||
        "testingTime": 18,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Send a request to update the weekly report
 | 
					 | 
				
			||||||
    response = requests.put(
 | 
					 | 
				
			||||||
        getUpdateWeeklyReportPath,
 | 
					 | 
				
			||||||
        json=update_data,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Check if the update was successful
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Update weekly report failed"
 | 
					 | 
				
			||||||
    gprint("test_update_weekly_report successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_remove_project():
 | 
					 | 
				
			||||||
    admin_username = randomString()
 | 
					 | 
				
			||||||
    admin_password = "admin_password2"
 | 
					 | 
				
			||||||
    dprint(
 | 
					 | 
				
			||||||
        "Registering with username: ", admin_username, " and password: ", admin_password
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        registerPath, json={"username": admin_username, "password": admin_password}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    dprint(response.text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Log in as the admin
 | 
					 | 
				
			||||||
    admin_token = login(admin_username, admin_password).json()["token"]
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        promoteToAdminPath,
 | 
					 | 
				
			||||||
        json={"username": admin_username},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Create a new project
 | 
					 | 
				
			||||||
    new_project = randomString()
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        addProjectPath,
 | 
					 | 
				
			||||||
        json={"name": new_project, "description": "This is a project"},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add project failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Remove the project
 | 
					 | 
				
			||||||
    response = requests.delete(
 | 
					 | 
				
			||||||
        removeProjectPath + "/" + new_project,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + admin_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Remove project failed"
 | 
					 | 
				
			||||||
    gprint("test_remove_project successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_get_unsigned_reports():
 | 
					 | 
				
			||||||
    # Log in as the user
 | 
					 | 
				
			||||||
        token = login("user2", "123").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Make a request to get all unsigned reports
 | 
					 | 
				
			||||||
        response = requests.get(
 | 
					 | 
				
			||||||
            getUnsignedReportsPath + "/" + projectName,
 | 
					 | 
				
			||||||
            headers={"Authorization": "Bearer " + token},
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        assert response.status_code == 200, "Get unsigned reports failed"
 | 
					 | 
				
			||||||
        gprint("test_get_unsigned_reports successful")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_get_other_users_report_as_pm():
 | 
					 | 
				
			||||||
    # Create user
 | 
					 | 
				
			||||||
    user = randomString()
 | 
					 | 
				
			||||||
    register(user, "password")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Create project
 | 
					 | 
				
			||||||
    project = randomString()
 | 
					 | 
				
			||||||
    pm_token = login(user, "password").json()["token"]
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        addProjectPath,
 | 
					 | 
				
			||||||
        json={"name": project, "description": "This is a project"},
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + pm_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add project failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Create other user
 | 
					 | 
				
			||||||
    other_user = randomString()
 | 
					 | 
				
			||||||
    register(other_user, "password")
 | 
					 | 
				
			||||||
    user_token = login(other_user, "password").json()["token"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Add other user to project
 | 
					 | 
				
			||||||
    response = requests.put(
 | 
					 | 
				
			||||||
        addUserToProjectPath + "/" + project,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + pm_token}, # note pm_token
 | 
					 | 
				
			||||||
        params={"userName": other_user},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Add user to project failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Submit report as other user
 | 
					 | 
				
			||||||
    response = requests.post(
 | 
					 | 
				
			||||||
        submitReportPath,
 | 
					 | 
				
			||||||
        json={
 | 
					 | 
				
			||||||
            "projectName": project,
 | 
					 | 
				
			||||||
            "week": 1,
 | 
					 | 
				
			||||||
            "developmentTime": 10,
 | 
					 | 
				
			||||||
            "meetingTime": 5,
 | 
					 | 
				
			||||||
            "adminTime": 5,
 | 
					 | 
				
			||||||
            "ownWorkTime": 10,
 | 
					 | 
				
			||||||
            "studyTime": 10,
 | 
					 | 
				
			||||||
            "testingTime": 10,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + user_token},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Submit report failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Get report as project manager
 | 
					 | 
				
			||||||
    response = requests.get(
 | 
					 | 
				
			||||||
        getWeeklyReportPath,
 | 
					 | 
				
			||||||
        headers={"Authorization": "Bearer " + pm_token},
 | 
					 | 
				
			||||||
        params={"targetUser": other_user, "projectName": project, "week": 1},
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    assert response.status_code == 200, "Get weekly report failed"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    test_remove_project()
 | 
					 | 
				
			||||||
    test_get_user_projects()
 | 
					 | 
				
			||||||
    test_create_user()
 | 
					 | 
				
			||||||
    test_login()
 | 
					 | 
				
			||||||
    test_add_project()
 | 
					 | 
				
			||||||
    test_submit_report()
 | 
					 | 
				
			||||||
    test_get_weekly_report()
 | 
					 | 
				
			||||||
    test_get_project()
 | 
					 | 
				
			||||||
    test_sign_report()
 | 
					 | 
				
			||||||
    test_add_user_to_project()
 | 
					 | 
				
			||||||
    test_get_weekly_reports_user()
 | 
					 | 
				
			||||||
    test_check_if_project_manager()
 | 
					 | 
				
			||||||
    test_ProjectRoleChange()
 | 
					 | 
				
			||||||
    test_ensure_manager_of_created_project()
 | 
					 | 
				
			||||||
    test_get_unsigned_reports()
 | 
					 | 
				
			||||||
    test_list_all_users_project()
 | 
					 | 
				
			||||||
    test_change_user_name()
 | 
					 | 
				
			||||||
    test_update_weekly_report()
 | 
					 | 
				
			||||||
    test_get_other_users_report_as_pm()
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue