From eb71b3aba19965bef263b219db2bcd409c01da8b Mon Sep 17 00:00:00 2001 From: Leni BEAULATON Date: Wed, 19 Mar 2025 10:23:51 +0100 Subject: [PATCH 1/3] Ajout et suppression user API --- WF_EF_Api/StubApi/UserService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WF_EF_Api/StubApi/UserService.cs b/WF_EF_Api/StubApi/UserService.cs index 4ce870b..2b812e7 100644 --- a/WF_EF_Api/StubApi/UserService.cs +++ b/WF_EF_Api/StubApi/UserService.cs @@ -36,7 +36,7 @@ namespace StubApi public async Task AddUser(UserDTO user) { - throw new NotImplementedException(); + _users.Add(user); } public async Task CountUser() @@ -94,7 +94,7 @@ namespace StubApi public async Task RemoveUser(UserDTO user) { - throw new NotImplementedException(); + _users.Remove(user); } public async Task SetAdminRole(bool isAdmin) From f726c7c7453b52b31ea95fecd25e7a48bfda69eb Mon Sep 17 00:00:00 2001 From: Leni BEAULATON Date: Wed, 19 Mar 2025 11:46:30 +0100 Subject: [PATCH 2/3] REST API + Documentation --- WF_EF_Api/Shared/IUserService.cs | 2 +- WF_EF_Api/StubApi/UserService.cs | 19 +- .../WfApi/Controllers/UsersController.cs | 414 ++++++++++++++++-- 3 files changed, 396 insertions(+), 39 deletions(-) diff --git a/WF_EF_Api/Shared/IUserService.cs b/WF_EF_Api/Shared/IUserService.cs index 29fe4bf..74bf04a 100644 --- a/WF_EF_Api/Shared/IUserService.cs +++ b/WF_EF_Api/Shared/IUserService.cs @@ -35,7 +35,7 @@ namespace Shared // Updates the details of an existing user identified by 'userId'. // 'userId' is the ID of the user to be updated, and 'user' contains the new user data. - Task UpdateUser(int userId, TUser user, TUser existingUser); + Task UpdateUser(int userId, TUser user); // Removes a user from the system based on their unique identifier ('userId'). // 'userId' is the unique identifier of the user to be removed. diff --git a/WF_EF_Api/StubApi/UserService.cs b/WF_EF_Api/StubApi/UserService.cs index 2b812e7..315d9a5 100644 --- a/WF_EF_Api/StubApi/UserService.cs +++ b/WF_EF_Api/StubApi/UserService.cs @@ -104,16 +104,19 @@ namespace StubApi - public async Task UpdateUser(int userId, UserDTO user, UserDTO existingUser) + public async Task UpdateUser(int userId, UserDTO user) { - + UserDTO userUpdate = new UserDTO(); + userUpdate = GetUserById(userId).Result; + // Update users properties - existingUser.Pseudo = user.Pseudo; - existingUser.Password = user.Password; - existingUser.Email = user.Email; - existingUser.date = user.date; - existingUser.ImageProfil = user.ImageProfil; - return existingUser; + userUpdate.Pseudo = user.Pseudo; + userUpdate.Password = user.Password; + userUpdate.Email = user.Email; + userUpdate.date = user.date; + userUpdate.ImageProfil = user.ImageProfil; + + return userUpdate; } } } diff --git a/WF_EF_Api/WfApi/Controllers/UsersController.cs b/WF_EF_Api/WfApi/Controllers/UsersController.cs index a60300f..400c835 100644 --- a/WF_EF_Api/WfApi/Controllers/UsersController.cs +++ b/WF_EF_Api/WfApi/Controllers/UsersController.cs @@ -21,8 +21,34 @@ namespace WfApi.Controllers } //===================================== ROUTE GET ===================================== - - [HttpGet("id/{id}")] // Indiquer que l'id est dans l'URL + /// + /// Gets a user by their unique identifier. + /// + /// The unique identifier of the user + /// + /// + /// ## **Sample request**: + /// + /// GET /users/{id} + /// + /// Where `{id}` is the unique identifier of the user you want to retrieve. + /// + /// ## **Returns** + /// + /// - **200 OK** : Returns the user data if the user with the given ID exists. + /// - **204 No Content** : No user found for the provided ID, or the operation failed. + /// - **500 Internal Server Error** : If there is an exception during the process. + /// + /// ## **Error Handling** + /// - In case of an internal server error (e.g., database issues), a `500 Internal Server Error` will be returned with an error message. + /// + /// Returns the user data corresponding to the provided ID + /// No content if no user is found or the operation fails + /// Internal server error in case of an exception + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [HttpGet("{id}")] // Indiquer que l'id est dans l'URL public async Task Get(int id) { try @@ -45,7 +71,35 @@ namespace WfApi.Controllers } - [HttpGet("all")] // Indiquer que l'id est dans l'URL + /// + /// Gets a list of users with pagination support. + /// + /// The index of the page to retrieve (default is 0) + /// The number of users to retrieve per page (default is 5) + /// + /// + /// ## **Sample request**: + /// + /// GET /users/all?index=0&count=5 + /// + /// The `index` parameter specifies the page number to retrieve (starting from 0), and the `count` parameter specifies how many users to return per page. + /// + /// ## **Returns** + /// + /// - **200 OK** : Returns a list of users if the operation is successful. + /// - **204 No Content** : If no users are found or the operation fails. + /// - **500 Internal Server Error** : If there is an exception during the execution of the request. + /// + /// ## **Error Handling** + /// - In case of an internal server error (e.g., database issues), a `500 Internal Server Error` is returned with an error message. + /// + /// Returns a list of users + /// No content if no users are found or the operation fails + /// Internal server error in case of an exception + [HttpGet("all")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetAllUsers(int index = 0, int count = 5) { try @@ -68,9 +122,45 @@ namespace WfApi.Controllers } - [HttpGet("hashpassword/{username}")] // Indiquer que l'id est dans l'URL - public async Task GetHashPassword(string username) + /// + /// Gets the hashed password for a given username. + /// + /// The username to retrieve the hashed password for + /// + /// + /// ## **Sample request**: + /// + /// GET /users/hashpassword?username=johndoe + /// + /// The `username` parameter specifies the username for which to retrieve the hashed password. + /// + /// ## **Returns** + /// + /// - **200 OK** : Returns the hashed password for the user if the username exists. + /// - **400 Bad Request** : If no username is provided or if the username is invalid. + /// - **204 No Content** : If no hashed password is found for the provided username. + /// - **500 Internal Server Error** : If an exception occurs while processing the request. + /// + /// ## **Error Handling** + /// - In case of a missing or invalid `username`, a `400 Bad Request` is returned with a relevant message. + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned. + /// + /// Returns the hashed password for the provided username + /// Bad request if no username is provided or invalid + /// No content if no hashed password is found + /// Internal server error in case of an exception + [HttpGet("hashpassword")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetHashPassword([FromQuery] string username) { + if (string.IsNullOrWhiteSpace(username)) + { + return BadRequest(new { message = "No user defined" }); + } + try { var result = _user.GetHashPassword(username); @@ -91,9 +181,45 @@ namespace WfApi.Controllers } - [HttpGet("username/{username}")] // Indiquer que l'id est dans l'URL - public async Task GetUserByUsername(string username) + /// + /// Gets a user by their username. + /// + /// The username to retrieve the user + /// + /// + /// ## **Sample request**: + /// + /// GET /users/username?username=johndoe + /// + /// The `username` parameter specifies the username of the user you want to retrieve. + /// + /// ## **Returns** + /// + /// - **200 OK** : Returns the user data if the username exists. + /// - **400 Bad Request** : If no username is provided or if the username is invalid. + /// - **204 No Content** : If no user is found with the provided username. + /// - **500 Internal Server Error** : If an exception occurs while processing the request. + /// + /// ## **Error Handling** + /// - In case of a missing or invalid `username`, a `400 Bad Request` is returned with a relevant message. + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned. + /// + /// Returns the user data for the provided username + /// Bad request if no username is provided or invalid + /// No content if no user is found with the provided username + /// Internal server error in case of an exception + [HttpGet("username")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetUserByUsername([FromQuery] string username) { + if (string.IsNullOrWhiteSpace(username)) + { + return BadRequest(new { message = "No user defined" }); + } + try { var result = _user.GetUserByUsername(username); @@ -112,9 +238,46 @@ namespace WfApi.Controllers return StatusCode((int)HttpStatusCode.InternalServerError, new { message = "Internal Server Error" }); } } - [HttpGet("email/{email}")] // Indiquer que l'id est dans l'URL - public async Task GetUserByEmail(string email) + + + /// + /// Gets a user by their email address. + /// + /// The email address of the user + /// + /// + /// ## **Sample request**: + /// + /// GET /users/email?email=johndoe@example.com + /// + /// The `email` parameter specifies the email address of the user you want to retrieve. + /// + /// ## **Returns** + /// + /// - **200 OK** : Returns the user data if the email exists. + /// - **400 Bad Request** : If no email is provided or if the email is invalid. + /// - **204 No Content** : If no user is found with the provided email. + /// - **500 Internal Server Error** : If an exception occurs while processing the request. + /// + /// ## **Error Handling** + /// - In case of a missing or invalid `email`, a `400 Bad Request` is returned with a relevant message. + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned. + /// + /// Returns the user data for the provided email + /// Bad request if no email is provided or invalid + /// No content if no user is found with the provided email + /// Internal server error in case of an exception + [HttpGet("email")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetUserByEmail([FromQuery] string email) { + if (string.IsNullOrWhiteSpace(email)) + { + return BadRequest(new { message = "No user email defined" }); + } try { var result = _user.GetUserByEmail(email); @@ -135,7 +298,33 @@ namespace WfApi.Controllers } - [HttpGet("countuser")] // Indiquer que l'id est dans l'URL + /// + /// Gets the total number of users. + /// + /// + /// + /// ## **Sample request**: + /// + /// GET /users/count + /// + /// This endpoint returns the total number of users present in the system. + /// + /// ## **Returns** + /// + /// - **200 OK** : Returns the total count of users. + /// - **204 No Content** : If no users are found or the operation fails. + /// - **500 Internal Server Error** : If an exception occurs while processing the request. + /// + /// ## **Error Handling** + /// - In case of an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned with a relevant message. + /// + /// Returns the total count of users + /// No content if the count could not be retrieved + /// Internal server error in case of an exception + [HttpGet("count")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetCountUser() { try @@ -159,9 +348,45 @@ namespace WfApi.Controllers - [HttpGet("existusername/{username}")] // Indiquer que l'id est dans l'URL - public async Task GetExistUsername(string username) + /// + /// Checks if a user exists by their username. + /// + /// The username to check for existence + /// + /// + /// ## **Sample request**: + /// + /// GET /users/existusername?username=johndoe + /// + /// The `username` parameter specifies the username to check if it exists in the system. + /// + /// ## **Returns** + /// + /// - **200 OK** : If the username exists, returns a success message. + /// - **400 Bad Request** : If no username is provided or if the username is invalid. + /// - **404 Not Found** : If the user with the specified username does not exist. + /// - **500 Internal Server Error** : If an exception occurs while processing the request. + /// + /// ## **Error Handling** + /// - In case of a missing or invalid `username`, a `400 Bad Request` is returned with a relevant message. + /// - If the user does not exist, a `404 Not Found` response is returned. + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned with an appropriate message. + /// + /// Returns a success message if the username exists + /// Bad request if no username is provided or invalid + /// Not found if the user with the provided username does not exist + /// Internal server error in case of an exception + [HttpGet("existusername")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetExistUsername([FromQuery] string username) { + if (string.IsNullOrWhiteSpace(username)) + { + return BadRequest(new { message = "No user defined" }); + } try { var result = _user.ExistUsername(username); @@ -172,7 +397,7 @@ namespace WfApi.Controllers } else { - return NoContent(); + return NotFound("User not found"); } } catch (Exception) @@ -182,9 +407,45 @@ namespace WfApi.Controllers } - [HttpGet("existemail/{email}")] // Indiquer que l'id est dans l'URL - public async Task GetExistEmail(string email) + /// + /// Checks if a user exists by their email address. + /// + /// The email address to check for existence + /// + /// + /// ## **Sample request**: + /// + /// GET /users/existemail?email=johndoe@example.com + /// + /// The `email` parameter specifies the email address to check if it exists in the system. + /// + /// ## **Returns** + /// + /// - **200 OK** : If the email exists, returns a success message. + /// - **400 Bad Request** : If no email is provided or if the email is invalid. + /// - **404 Not Found** : If the user with the specified email does not exist. + /// - **500 Internal Server Error** : If an exception occurs while processing the request. + /// + /// ## **Error Handling** + /// - In case of a missing or invalid `email`, a `400 Bad Request` is returned with a relevant message. + /// - If the user does not exist, a `404 Not Found` response is returned. + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned with an appropriate message. + /// + /// Returns a success message if the email exists + /// Bad request if no email is provided or invalid + /// Not found if the user with the provided email does not exist + /// Internal server error in case of an exception + [HttpGet("existemail")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetExistEmail([FromQuery] string email) { + if (string.IsNullOrWhiteSpace(email)) + { + return BadRequest(new { message = "No user email defined" }); + } try { var result = _user.ExistEmail(email); @@ -195,7 +456,7 @@ namespace WfApi.Controllers } else { - return NoContent(); + return NotFound("User email not found"); } } catch (Exception) @@ -207,7 +468,42 @@ namespace WfApi.Controllers //===================================== ROUTE PUT ===================================== + /// + /// Updates an existing user's data. + /// + /// The ID of the user to update + /// The updated user data + /// + /// + /// ## **Sample request**: + /// + /// PUT /users?id=1 + /// Body: + /// { + /// "username": "newusername", + /// "email": "newemail@example.com", + /// "fullName": "New Name" + /// } + /// + /// The `id` parameter specifies the user ID to be updated, and the body contains the updated user data. + /// + /// ## **Returns** + /// + /// - **200 OK** : If the user was successfully updated. + /// - **400 Bad Request** : If the provided user data is invalid or missing. + /// - **500 Internal Server Error** : If an error occurs while processing the update. + /// + /// ## **Error Handling** + /// - If the `updateduser` object is `null`, a `400 Bad Request` is returned with a message indicating that player data is required. + /// - If an exception occurs during the process (e.g., database errors), a `500 Internal Server Error` is returned with an appropriate message. + /// + /// Returns the updated user data + /// Bad request if no user data is provided or invalid + /// Internal server error in case of an exception [HttpPut()] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task UpdateUser([FromQuery] int id, [FromBody] UserDTO updateduser) { try @@ -217,18 +513,11 @@ namespace WfApi.Controllers return BadRequest(new { message = "Player data is required." }); } - - var existingUser = _user.GetUserById(id).Result; - if (existingUser == null) - { - return NotFound(new { message = "Player not found." }); - } - - var result = _user.UpdateUser(id,updateduser,existingUser); + var result = _user.UpdateUser(id,updateduser); return Ok(result); } - catch (Exception ex) + catch (Exception) { return StatusCode((int)HttpStatusCode.InternalServerError, new { message = "Internal server error." }); } @@ -238,8 +527,47 @@ namespace WfApi.Controllers //===================================== ROUTE POST ===================================== + /// + /// Creates a new user in the system. + /// + /// The user data to create the new user + /// + /// + /// ## **Sample request**: + /// + /// POST /users + /// Body: + /// { + /// "id": 123, + /// "username": "newuser", + /// "email": "newuser@example.com", + /// "fullName": "New User" + /// } + /// + /// The `newUser` parameter in the body contains the data of the new user to be created. + /// + /// ## **Returns** + /// + /// - **201 Created** : If the user was successfully created. The location of the created resource is returned in the response header. + /// - **400 Bad Request** : If the provided user data is invalid or missing. + /// - **409 Conflict** : If a user with the specified ID already exists. + /// - **500 Internal Server Error** : If an error occurs while processing the creation of the user. + /// + /// ## **Error Handling** + /// - If the `newUser` object is `null`, a `400 Bad Request` is returned with a message indicating that user data is required. + /// - If the user already exists (based on `Id`), a `409 Conflict` is returned with a message indicating that a user with this ID already exists. + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` is returned with an appropriate message. + /// + /// Returns the created user and its location + /// Bad request if no user data is provided or invalid + /// Conflict if a user with the same ID already exists + /// Internal server error in case of an exception [HttpPost] - public async Task CreatePlayer([FromBody] UserDTO newUser) + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task CreateUser([FromBody] UserDTO newUser) { try { @@ -258,7 +586,7 @@ namespace WfApi.Controllers return CreatedAtAction(nameof(GetAllUsers), new { id = newUser.Id }, newUser); } - catch (Exception ex) + catch (Exception) { return StatusCode((int)HttpStatusCode.InternalServerError, new { message = "Erreur interne du serveur." }); } @@ -268,7 +596,35 @@ namespace WfApi.Controllers //===================================== ROUTE DELETE ===================================== + /// + /// Deletes a player by their ID. + /// + /// The ID of the player to be deleted + /// + /// + /// ## **Sample request**: + /// + /// DELETE /api/v1/players?id=51 + /// + /// The `id` parameter specifies the ID of the player to be deleted. + /// + /// ## **Returns** + /// + /// - **200 OK** : If the player was successfully deleted, a success message is returned. + /// - **404 Not Found** : If no player with the given ID is found. + /// - **500 Internal Server Error** : If an error occurs while deleting the player. + /// + /// ## **Error Handling** + /// - If no player is found with the specified `id`, a `404 Not Found` response is returned with a message "Player not found." + /// - If there is an exception during the process (e.g., database errors), a `500 Internal Server Error` response is returned with a message "Internal server error." + /// + /// Returns a success message indicating the player was deleted + /// Not found if no player with the specified ID is found + /// Internal server error in case of an exception [HttpDelete] // /api/v1/players?id=51 + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task DeletePlayer([FromQuery] int id) { try @@ -284,12 +640,10 @@ namespace WfApi.Controllers return Ok(new { message = $"Player {id} deleted successfully." }); } - catch (Exception ex) + catch (Exception) { return StatusCode((int)HttpStatusCode.InternalServerError, new { message = "Internal server error." }); } } - - } } From 925592aa8163a6f474ee154c02b2eddc3f1b986c Mon Sep 17 00:00:00 2001 From: Leni BEAULATON Date: Wed, 19 Mar 2025 11:55:12 +0100 Subject: [PATCH 3/3] drone.yml --- .drone.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..6b39127 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,23 @@ +image: mcr.microsoft.com/dotnet/sdk:8.0 + +volumes: + - name: docs + path: /docs + +- dotnet new tool-manifest +- dotnet tool install NSwag.ConsoleCore +- dotnet nswag aspnetcore2openapi /output:/docs/swagger.json + +volumes: +- name: docs + temp: {} + +image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-docdeployer +volumes: + - name: docs + path: /docs + +commands: + - /entrypoint.sh + +depends_on: [ previous_job_name ] \ No newline at end of file