From 9eff1548015b85908ae70416f3f6b6737c38d1a8 Mon Sep 17 00:00:00 2001 From: dini_landy Date: Wed, 26 Feb 2025 13:09:35 +0200 Subject: [PATCH 1/3] Create the different entities in DAL and DTO. Create an API for the registration request. If a standard login API with username and password does not exist, create it as well. Create an API that allows the admin to view users who want to register. Create an API that allows the admin to approve a new user. Assign the appropriate permissions to all existing and new API calls. --- BLL/Interfaces/User.cs | 2 + BLL/Services/User.cs | 7 ++ DAL/Interfaces/User.cs | 1 + DAL/Models/User.cs | 13 ++- DAL/Repositories/User.cs | 6 ++ DTO/classes/User.cs | 5 +- WebApi/Controllers/UserController.cs | 113 ++++++++++++++++++++++++++- WebApi/Program.cs | 11 ++- 8 files changed, 148 insertions(+), 10 deletions(-) diff --git a/BLL/Interfaces/User.cs b/BLL/Interfaces/User.cs index af68fb5..75c2d81 100644 --- a/BLL/Interfaces/User.cs +++ b/BLL/Interfaces/User.cs @@ -15,5 +15,7 @@ public interface IUserService Task> GetAllUsersAsync(); Task GetByEmailAndByPasswordAsync(string Email, string Password); Task UpdateAsync(UserDTO User); + Task> GetPendingUsersAsync(); + } } diff --git a/BLL/Services/User.cs b/BLL/Services/User.cs index d5cda7a..8dc9312 100644 --- a/BLL/Services/User.cs +++ b/BLL/Services/User.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using DAL.Repositories; namespace BLL.Services { @@ -115,5 +116,11 @@ public async Task UpdateAsync(UserDTO e) throw; } } + public async Task> GetPendingUsersAsync() + { + var pendingUsers = await UserRepository.GetPendingUsersAsync(); + return mapper.Map>(pendingUsers); + } + } } diff --git a/DAL/Interfaces/User.cs b/DAL/Interfaces/User.cs index ab0894d..03b7937 100644 --- a/DAL/Interfaces/User.cs +++ b/DAL/Interfaces/User.cs @@ -15,5 +15,6 @@ public interface IUserRepository Task UpdateAsync(User entity); Task AddAsync(User entity); Task DeleteAsync(int id); + Task> GetPendingUsersAsync(); } } diff --git a/DAL/Models/User.cs b/DAL/Models/User.cs index 445e535..b462c65 100644 --- a/DAL/Models/User.cs +++ b/DAL/Models/User.cs @@ -18,8 +18,19 @@ public class User public string Email { get; set; } [Required] public string Password { get; set; } - + [Required] + public UserStatus Status { get; set; } public virtual ICollection Discussions { get; set; } public virtual ICollection Comments { get; set; } + } + public enum UserStatus + { + SimpleUser, // יכול רק לצפות + PendingApproval, // מילא טופס וממתין לאישור + Approved, // אושר ויכול להתחבר + LoggedIn, // מחובר ויכול להגיב וליצור דיונים + Admin // מנהל עם כל ההרשאות + } + } diff --git a/DAL/Repositories/User.cs b/DAL/Repositories/User.cs index 2f7fe43..3547909 100644 --- a/DAL/Repositories/User.cs +++ b/DAL/Repositories/User.cs @@ -121,5 +121,11 @@ public async Task UpdateAsync(User entity) throw; } } + public async Task> GetPendingUsersAsync() + { + return await context.Users.Where(u => u.Status == UserStatus.PendingApproval).ToListAsync(); + } + + } } diff --git a/DTO/classes/User.cs b/DTO/classes/User.cs index 0bd4785..6247b66 100644 --- a/DTO/classes/User.cs +++ b/DTO/classes/User.cs @@ -1,4 +1,5 @@ -using System; +using DAL.Models; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; @@ -13,6 +14,6 @@ public class UserDTO public required string Username { get; set; } public string Email { get; set; } public string Password { get; set; } - + public UserStatus Status { get; set; } } } diff --git a/WebApi/Controllers/UserController.cs b/WebApi/Controllers/UserController.cs index ff4ea1e..fd8c76e 100644 --- a/WebApi/Controllers/UserController.cs +++ b/WebApi/Controllers/UserController.cs @@ -6,6 +6,10 @@ using System.Collections.Generic; using System.Threading.Tasks; using System; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Authorization; +using DAL.Models; +using BLL.Services; namespace WebApi.Controllers { @@ -21,8 +25,9 @@ public UserController(IUserService service, ILogger logger) this.logger = logger; } - + // ( ) [HttpGet] + //[Authorize(Roles = "Admin")] public async Task GetAll() { try @@ -33,10 +38,25 @@ public async Task GetAll() catch (Exception ex) { logger.LogError("Failed to get all users: " + ex.Message); - return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error + return StatusCode(500, "Internal Server Error");// HTTP 500 Internal Server Error } } + //[HttpGet] + //public async Task GetAll() + //{ + // try + // { + // var users = await UserService.GetAllUsersAsync(); + // return Ok(users); // HTTP 200 OK + // } + // catch (Exception ex) + // { + // logger.LogError("Failed to get all users: " + ex.Message); + // return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error + // } + //} + [HttpGet("{id}")] public async Task GetById(int id) { @@ -62,10 +82,13 @@ public async Task GetByEmailAndPassword(string email, string pass try { var user = await UserService.GetByEmailAndByPasswordAsync(email, password); - if (user == null) + if (user == null || user.Status != UserStatus.Approved) { return NotFound("User not found with provided email and password"); // HTTP 404 Not Found } + + user.Status= UserStatus.LoggedIn; // + await UserService.UpdateAsync(user); return Ok(user); // HTTP 200 OK } catch (Exception ex) @@ -74,6 +97,24 @@ public async Task GetByEmailAndPassword(string email, string pass return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error } } + //[HttpGet("{email}/{password}")] + //public async Task GetByEmailAndPassword(string email, string password) + //{ + // try + // { + // var user = await UserService.GetByEmailAndByPasswordAsync(email, password); + // if (user == null) + // { + // return NotFound("User not found with provided email and password"); // HTTP 404 Not Found + // } + // return Ok(user); // HTTP 200 OK + // } + // catch (Exception ex) + // { + // logger.LogError($"Failed to get user with email {email}: " + ex.Message); + // return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error + // } + //} [HttpPost] public async Task Add([FromBody] UserDTO newUser) @@ -85,6 +126,7 @@ public async Task Add([FromBody] UserDTO newUser) return BadRequest("User cannot be null"); // HTTP 400 Bad Request } + newUser.Status = UserStatus.PendingApproval; await UserService.AddNewUserAsync(newUser); return CreatedAtAction(nameof(GetById), new { id = newUser.Id }, newUser); // HTTP 201 Created } @@ -99,6 +141,71 @@ public async Task Add([FromBody] UserDTO newUser) return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error } } + //[HttpPost] + //public async Task Add([FromBody] UserDTO newUser) + //{ + // try + // { + // if (newUser == null) + // { + // return BadRequest("User cannot be null"); // HTTP 400 Bad Request + // } + + // await UserService.AddNewUserAsync(newUser); + // return CreatedAtAction(nameof(GetById), new { id = newUser.Id }, newUser); // HTTP 201 Created + // } + // catch (ArgumentException ex) + // { + // logger.LogError("Invalid argument: " + ex.Message); + // return BadRequest(ex.Message); // HTTP 400 Bad Request + // } + // catch (Exception ex) + // { + // logger.LogError("Failed to add user: " + ex.Message); + // return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error + // } + //} + // ( ) + [HttpGet("pending")] + [Authorize(Roles = "Admin")] + public async Task GetPendingUsers() + { + try + { + var pendingUsers = await UserService.GetPendingUsersAsync(); + return Ok(pendingUsers); + } + catch (Exception ex) + { + logger.LogError("Failed to get pending users: " + ex.Message); + return StatusCode(500, "Internal Server Error"); + } + } + + // ( ) + [HttpPut("approve/{id}")] + [Authorize(Roles = "Admin")] + public async Task ApproveUser(int id) + { + try + { + var user = await UserService.GetByIdAsync(id); + if (user == null) + { + return NotFound($"User with ID {id} not found"); + } + + user.Status = UserStatus.Approved; // + await UserService.UpdateAsync(user); + return Ok($"User with ID {id} has been approved."); + } + catch (Exception ex) + { + logger.LogError($"Failed to approve user with ID {id}: " + ex.Message); + return StatusCode(500, "Internal Server Error"); + } + } + [HttpPut] public async Task Update([FromBody] UserDTO user) diff --git a/WebApi/Program.cs b/WebApi/Program.cs index 9de92a6..266b3b3 100644 --- a/WebApi/Program.cs +++ b/WebApi/Program.cs @@ -9,11 +9,14 @@ var builder = WebApplication.CreateBuilder(args); -//builder.Configuration.AddEnvironmentVariables(); -//DotEnv.Load(options: new DotEnvOptions(envFilePaths: ["../.env.local"])); +#if DEBUG +Env.Load("../.env.local"); +#endif -//builder.Services.AddDbContext(options => options.UseMySql("server=127.0.0.1;uid=root;pwd=1234;database=npm;SslMode=Required", new MySqlServerVersion(new Version(8, 0, 21)))); -//builder.Services.AddDbContext(options => options.UseMySql(Environment.GetEnvironmentVariable("DB_CONNECTION"), new MySqlServerVersion(new Version(8, 0, 21)))); +string clientUrl = Env.GetString("CLIENT_URL"); +Console.WriteLine($"CLIENT_URL: {clientUrl}"); + +// Configure DbContext builder.Services.AddDbContext(); From 841638f9422e05ee9acf91d165245ef794bedd02 Mon Sep 17 00:00:00 2001 From: dini_landy Date: Wed, 26 Feb 2025 13:10:18 +0200 Subject: [PATCH 2/3] [Authorize(Roles = "Admin")] --- WebApi/Controllers/UserController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebApi/Controllers/UserController.cs b/WebApi/Controllers/UserController.cs index fd8c76e..0ba5a78 100644 --- a/WebApi/Controllers/UserController.cs +++ b/WebApi/Controllers/UserController.cs @@ -27,7 +27,7 @@ public UserController(IUserService service, ILogger logger) // ( ) [HttpGet] - //[Authorize(Roles = "Admin")] + [Authorize(Roles = "Admin")] public async Task GetAll() { try From 9b7d0ec88768298c3317bfdb499d99334bf446a1 Mon Sep 17 00:00:00 2001 From: dini_landy Date: Mon, 3 Mar 2025 12:50:09 +0200 Subject: [PATCH 3/3] Remove the comments --- DAL/Models/User.cs | 14 +++---- WebApi/Controllers/UserController.cs | 61 +--------------------------- 2 files changed, 8 insertions(+), 67 deletions(-) diff --git a/DAL/Models/User.cs b/DAL/Models/User.cs index b462c65..328e976 100644 --- a/DAL/Models/User.cs +++ b/DAL/Models/User.cs @@ -24,13 +24,13 @@ public class User public virtual ICollection Comments { get; set; } } - public enum UserStatus - { - SimpleUser, // יכול רק לצפות - PendingApproval, // מילא טופס וממתין לאישור - Approved, // אושר ויכול להתחבר - LoggedIn, // מחובר ויכול להגיב וליצור דיונים - Admin // מנהל עם כל ההרשאות + public enum UserStatus + { + SimpleUser, + PendingApproval, + Approved, + LoggedIn, + Admin } } diff --git a/WebApi/Controllers/UserController.cs b/WebApi/Controllers/UserController.cs index 0ba5a78..ddbbed1 100644 --- a/WebApi/Controllers/UserController.cs +++ b/WebApi/Controllers/UserController.cs @@ -42,21 +42,6 @@ public async Task GetAll() } } - //[HttpGet] - //public async Task GetAll() - //{ - // try - // { - // var users = await UserService.GetAllUsersAsync(); - // return Ok(users); // HTTP 200 OK - // } - // catch (Exception ex) - // { - // logger.LogError("Failed to get all users: " + ex.Message); - // return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error - // } - //} - [HttpGet("{id}")] public async Task GetById(int id) { @@ -87,7 +72,7 @@ public async Task GetByEmailAndPassword(string email, string pass return NotFound("User not found with provided email and password"); // HTTP 404 Not Found } - user.Status= UserStatus.LoggedIn; // + user.Status= UserStatus.LoggedIn; await UserService.UpdateAsync(user); return Ok(user); // HTTP 200 OK } @@ -97,24 +82,6 @@ public async Task GetByEmailAndPassword(string email, string pass return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error } } - //[HttpGet("{email}/{password}")] - //public async Task GetByEmailAndPassword(string email, string password) - //{ - // try - // { - // var user = await UserService.GetByEmailAndByPasswordAsync(email, password); - // if (user == null) - // { - // return NotFound("User not found with provided email and password"); // HTTP 404 Not Found - // } - // return Ok(user); // HTTP 200 OK - // } - // catch (Exception ex) - // { - // logger.LogError($"Failed to get user with email {email}: " + ex.Message); - // return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error - // } - //} [HttpPost] public async Task Add([FromBody] UserDTO newUser) @@ -141,31 +108,6 @@ public async Task Add([FromBody] UserDTO newUser) return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error } } - //[HttpPost] - //public async Task Add([FromBody] UserDTO newUser) - //{ - // try - // { - // if (newUser == null) - // { - // return BadRequest("User cannot be null"); // HTTP 400 Bad Request - // } - - // await UserService.AddNewUserAsync(newUser); - // return CreatedAtAction(nameof(GetById), new { id = newUser.Id }, newUser); // HTTP 201 Created - // } - // catch (ArgumentException ex) - // { - // logger.LogError("Invalid argument: " + ex.Message); - // return BadRequest(ex.Message); // HTTP 400 Bad Request - // } - // catch (Exception ex) - // { - // logger.LogError("Failed to add user: " + ex.Message); - // return StatusCode(500, "Internal Server Error"); // HTTP 500 Internal Server Error - // } - //} - // ( ) [HttpGet("pending")] [Authorize(Roles = "Admin")] public async Task GetPendingUsers() @@ -182,7 +124,6 @@ public async Task GetPendingUsers() } } - // ( ) [HttpPut("approve/{id}")] [Authorize(Roles = "Admin")] public async Task ApproveUser(int id)