ChangeUserPassword Handler + API
This commit is contained in:
		
							parent
							
								
									47d4bda99b
								
							
						
					
					
						commit
						0176f78067
					
				
					 8 changed files with 163 additions and 7 deletions
				
			
		|  | @ -48,6 +48,7 @@ type Database interface { | |||
| 	UnsignWeeklyReport(reportId int, projectManagerId int) error | ||||
| 	DeleteReport(reportID int) error | ||||
| 	ChangeProjectName(projectName string, newProjectName string) error | ||||
| 	ChangeUserPassword(username string, password string) error | ||||
| } | ||||
| 
 | ||||
| // This struct is a wrapper type that holds the database connection | ||||
|  | @ -677,3 +678,8 @@ func (d *Db) ChangeProjectName(projectName string, newProjectName string) error | |||
| 	_, err := d.Exec("UPDATE projects SET name = ? WHERE name = ?", newProjectName, projectName) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (d *Db) ChangeUserPassword(username string, password string) error { | ||||
| 	_, err := d.Exec("UPDATE users SET password = ? WHERE username = ?", password, username) | ||||
| 	return err | ||||
| } | ||||
|  |  | |||
|  | @ -1120,3 +1120,25 @@ func TestChangeProjectName(t *testing.T) { | |||
| 		t.Error("ChangeProjectName failed: expected newprojectname, got", projects[0].Name) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestChangeUserPassword(t *testing.T) { | ||||
| 	db, err := setupState() | ||||
| 	if err != nil { | ||||
| 		t.Error("setupState failed:", err) | ||||
| 	} | ||||
| 
 | ||||
| 	// Add a user | ||||
| 	_ = db.AddUser("testuser", "password") | ||||
| 
 | ||||
| 	// Change user password | ||||
| 	err = db.ChangeUserPassword("testuser", "newpassword") | ||||
| 	if err != nil { | ||||
| 		t.Error("ChangeUserPassword failed:", err) | ||||
| 	} | ||||
| 
 | ||||
| 	// Check if the password was changed | ||||
| 	if !db.CheckUser("testuser", "newpassword") { | ||||
| 		t.Error("ChangeUserPassword failed: password not changed") | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -20,16 +20,17 @@ func ChangeProjectName(c *fiber.Ctx) error { | |||
| 	projectName := c.Params("projectName") | ||||
| 	newProjectName := c.Query("newProjectName") | ||||
| 
 | ||||
| 	// Check if user is project manager | ||||
| 	ismanager, err := db.GetDb(c).IsProjectManager(username, projectName) | ||||
| 	// Check if user is site admin | ||||
| 	issiteadmin, err := db.GetDb(c).IsSiteAdmin(username) | ||||
| 	if err != nil { | ||||
| 		log.Warn("Error checking if projectmanager:", err) | ||||
| 		log.Warn("Error checking if siteadmin:", err) | ||||
| 		return c.Status(500).SendString(err.Error()) | ||||
| 	} else if !ismanager { | ||||
| 		log.Warn("User is not projectmanager") | ||||
| 		return c.Status(401).SendString("User is not projectmanager") | ||||
| 	} else if !issiteadmin { | ||||
| 		log.Warn("User is not siteadmin") | ||||
| 		return c.Status(401).SendString("User is not siteadmin") | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	// Perform the project name change | ||||
| 	err = db.GetDb(c).ChangeProjectName(projectName, newProjectName) | ||||
| 	if err != nil { | ||||
|  |  | |||
							
								
								
									
										42
									
								
								backend/internal/handlers/users/ChangeUserPassword.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								backend/internal/handlers/users/ChangeUserPassword.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| package users | ||||
| 
 | ||||
| import ( | ||||
| 	db "ttime/internal/database" | ||||
| 
 | ||||
| 	"github.com/gofiber/fiber/v2" | ||||
| 	"github.com/gofiber/fiber/v2/log" | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| ) | ||||
| 
 | ||||
| // ChangeUserPassword is a handler that changes the password of a user | ||||
| func ChangeUserPassword(c *fiber.Ctx) error { | ||||
| 
 | ||||
| 	//Check token and get username of current user | ||||
| 	user := c.Locals("user").(*jwt.Token) | ||||
| 	claims := user.Claims.(jwt.MapClaims) | ||||
| 	admin := claims["name"].(string) | ||||
| 
 | ||||
| 	// Extract the necessary parameters from the request | ||||
| 	username := c.Params("username") | ||||
| 	newPassword := c.Query("newPassword") | ||||
| 
 | ||||
| 	// Check if user is site admin | ||||
| 	issiteadmin, err := db.GetDb(c).IsSiteAdmin(admin) | ||||
| 	if err != nil { | ||||
| 		log.Warn("Error checking if siteadmin:", err) | ||||
| 		return c.Status(500).SendString(err.Error()) | ||||
| 	} else if !issiteadmin { | ||||
| 		log.Warn("User is not siteadmin") | ||||
| 		return c.Status(401).SendString("User is not siteadmin") | ||||
| 	} | ||||
| 
 | ||||
| 	// Perform the password change | ||||
| 	err = db.GetDb(c).ChangeUserPassword(username, newPassword) | ||||
| 	if err != nil { | ||||
| 		log.Warn("Error changing password:", err) | ||||
| 		return c.Status(500).SendString(err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	// Return a success message | ||||
| 	return c.Status(200).SendString("Password changed successfully") | ||||
| } | ||||
|  | @ -110,6 +110,7 @@ func main() { | |||
| 	api.Post("/promoteToAdmin", users.PromoteToAdmin) | ||||
| 	api.Put("/changeUserName", users.ChangeUserName) | ||||
| 	api.Delete("/userdelete/:username", users.UserDelete) // Perhaps just use POST to avoid headaches | ||||
| 	api.Put("/changeUserPassword/:username", users.ChangeUserPassword) | ||||
| 
 | ||||
| 	// All project related routes | ||||
| 	// projectGroup := api.Group("/project") // Not currently in use | ||||
|  |  | |||
|  | @ -283,6 +283,18 @@ interface API { | |||
|     newProjectName: string, | ||||
|     token: string, | ||||
|   ): Promise<APIResponse<string>>; | ||||
| 
 | ||||
|   /** | ||||
|    * Changes the password of a user | ||||
|    * @param {string} username The username of the user | ||||
|    * @param {string} newPassword The new password | ||||
|    * @param {string} token The authentication token | ||||
|    */ | ||||
|   changeUserPassword( | ||||
|     username: string, | ||||
|     newPassword: string, | ||||
|     token: string, | ||||
|   ): Promise<APIResponse<string>>; | ||||
| } | ||||
| 
 | ||||
| /** An instance of the API */ | ||||
|  | @ -1041,4 +1053,31 @@ export const api: API = { | |||
|       return { success: false, message: "Failed to change project name" }; | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   async changeUserPassword( | ||||
|     username: string, | ||||
|     newPassword: string, | ||||
|     token: string, | ||||
|   ): Promise<APIResponse<string>> { | ||||
|     try { | ||||
|       const response = await fetch( | ||||
|         `/api/changePassword/${username}?newPassword=${newPassword}`, | ||||
|         { | ||||
|           method: "PUT", | ||||
|           headers: { | ||||
|             "Content-Type": "application/json", | ||||
|             Authorization: "Bearer " + token, | ||||
|           }, | ||||
|         }, | ||||
|       ); | ||||
| 
 | ||||
|       if (!response.ok) { | ||||
|         return { success: false, message: "Failed to change password" }; | ||||
|       } else { | ||||
|         return { success: true, message: "Password changed" }; | ||||
|       } | ||||
|     } catch (e) { | ||||
|       return { success: false, message: "Failed to change password" }; | ||||
|     } | ||||
|   }, | ||||
| }; | ||||
|  |  | |||
|  | @ -38,8 +38,9 @@ unsignReportPath = base_url + "/api/unsignReport" | |||
| deleteReportPath = base_url + "/api/deleteReport" | ||||
| getStatisticsPath = base_url + "/api/getStatistics" | ||||
| changeProjectNamePath = base_url + "/api/changeProjectName" | ||||
| changeUserPasswordPath = base_url + "/api/changeUserPassword" | ||||
| 
 | ||||
| debug_output = True | ||||
| debug_output = False | ||||
| 
 | ||||
| 
 | ||||
| def gprint(*args, **kwargs): | ||||
|  | @ -180,3 +181,11 @@ def changeProjectName(token: string, projectName: string, newProjectName: string | |||
|         params={"newProjectName": newProjectName} | ||||
|     ) | ||||
|     return response | ||||
| 
 | ||||
| def changeUserPassword(token: string, username: string, newPassword: string): | ||||
|     response = requests.put( | ||||
|         changeUserPasswordPath + "/" + username, | ||||
|         headers = {"Authorization": "Bearer " + token}, | ||||
|         params={"newPassword": newPassword} | ||||
|     ) | ||||
|     return response | ||||
|  | @ -675,6 +675,14 @@ def test_project_name_change(): | |||
| 
 | ||||
|     token = register_and_login(admin_username, admin_password) | ||||
| 
 | ||||
|     # Promote to admin | ||||
|     response = requests.post( | ||||
|         promoteToAdminPath, | ||||
|         json={"username": admin_username}, | ||||
|         headers={"Authorization": "Bearer " + token}, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
|     response = create_project(token, project_name) | ||||
|     assert response.status_code == 200, "Create project failed" | ||||
| 
 | ||||
|  | @ -703,8 +711,36 @@ def test_project_name_change(): | |||
|     assert response.status_code == 200, "Project name change failed" | ||||
|     gprint("test_projectNameChange successful") | ||||
| 
 | ||||
| def test_change_user_password(): | ||||
|     # Create admin | ||||
|     admin_username = randomString() | ||||
|     admin_password = randomString() | ||||
| 
 | ||||
|     user = randomString() | ||||
|     password = randomString() | ||||
| 
 | ||||
|     token = register_and_login(admin_username, admin_password) | ||||
| 
 | ||||
|     # Promote to admin | ||||
|     response = requests.post( | ||||
|         promoteToAdminPath, | ||||
|         json={"username": admin_username}, | ||||
|         headers={"Authorization": "Bearer " + token}, | ||||
|     ) | ||||
| 
 | ||||
|     _ = register_and_login(user, password) | ||||
| 
 | ||||
|     response = changeUserPassword(token, user, "new_password") | ||||
|     assert response.status_code == 200, "Change user password failed" | ||||
| 
 | ||||
|     response = login(user, "new_password") | ||||
|     assert response.status_code == 200, "Login failed with new password" | ||||
|      | ||||
|     gprint("test_change_user_password successful") | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     test_change_user_password() | ||||
|     test_project_name_change(); | ||||
|     test_delete_report() | ||||
|     test_unsign_report() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 al8763be
						al8763be