Skip to content

feat: implement token based authentication and authorization #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bd9aa77
Register automapper in Program.cs
osm-Jatin Feb 27, 2025
3728219
Modify the UpdateRole method to return Role object
osm-Jatin Mar 2, 2025
0b8705e
Refactor the ModelValidationBadRequest class to generate model valida…
osm-Jatin Mar 2, 2025
331b280
Add BaseResponse in Role controller
osm-Jatin Mar 2, 2025
731a3c6
Modify the service and repo layers to return the UserDto
osm-Jatin Mar 2, 2025
2e75997
Add BaseResponse in User controller
osm-Jatin Mar 2, 2025
a3dac78
Remove the duplicate using directive
osm-Jatin Mar 11, 2025
b3fb0c3
Update the PaginationMetadata
osm-Jatin Mar 4, 2025
43c6a73
Add pagination in /GET All APIs of User and Role controllers
osm-Jatin Mar 4, 2025
292728d
Add packages for JWT authentication and swagger annotations
osm-Jatin Mar 4, 2025
a85e8e0
Add JWT Configuration in appsettings.json
osm-Jatin Mar 4, 2025
88b9f10
Modify Program.cs to configure authentication and allow swagger to pa…
osm-Jatin Mar 4, 2025
e0c09ee
Create a token service to generate JWT tokens
osm-Jatin Mar 4, 2025
e12fca5
Modify UserService to Generate JWT Tokens
osm-Jatin Mar 4, 2025
8ce7858
Create DTO for Login Request
osm-Jatin Mar 4, 2025
f999e63
Modify UserController to create a login endpoint and secure APIs usin…
osm-Jatin Mar 4, 2025
c578b10
Add validation attributes to LoginRequestDto
osm-Jatin Mar 4, 2025
b92bfab
Improve error handling for missing JWT configuration
osm-Jatin Mar 4, 2025
df1fda1
Add placeholders for JWT configuration
osm-Jatin Mar 4, 2025
54c78e7
Add checks for JWT config values.
osm-Jatin Apr 22, 2025
a1c6ae3
Align JWT package versions for compatibility with JwtBearer
osm-Jatin Apr 22, 2025
1c0287c
Resolve package downgrade by aligning System.IdentityModel.Tokens.Jwt…
osm-Jatin Apr 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Api/Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.2" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.13">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -21,6 +22,8 @@
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.1.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.2.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
</ItemGroup>

<ItemGroup>
Expand Down
170 changes: 137 additions & 33 deletions src/Api/Controllers/RoleController.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Api.Models.Common;
using Api.Models.Enums;
using Core.Entities.DTOs;
using Core.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -16,67 +18,169 @@ public RoleController(IRoleService roleService)
}

[HttpGet("{id}")]
public async Task<IActionResult> GetRoleById(int id)
public async Task<ActionResult<BaseResponse<RoleResponseDto>>> GetRoleById(int id)
{
RoleResponseDto? role = await _roleService.GetRoleByIdAsync(id).ConfigureAwait(false);
if (role == null)
BaseResponse<RoleResponseDto> response = new(ResponseStatus.Fail)
{
return NotFound(new { message = "Role not found" });
}
Message = "Role not found"
};
try
{
RoleResponseDto? role = await _roleService.GetRoleByIdAsync(id).ConfigureAwait(false);
if (role != null)
{
response.Status = ResponseStatus.Success;
response.Data = role;
response.Message = "Role retrieved successfully";
}

return Ok(role);
return role == null ? NotFound(response) : Ok(response);
}
catch (Exception ex)
{
response.Status = ResponseStatus.Error;
response.Message = "An unexpected error occurred.";
response.StackTrace = ex.StackTrace;
return StatusCode(500, response);
}
}

[HttpGet]
public async Task<IActionResult> GetAllRoles()
public async Task<ActionResult<BaseResponse<IEnumerable<RoleResponseDto>>>> GetAllRoles([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10)
{
IEnumerable<RoleResponseDto> roles = await _roleService.GetAllRolesAsync().ConfigureAwait(false);
return Ok(roles);
BaseResponse<IEnumerable<RoleResponseDto>> response = new(ResponseStatus.Fail)
{
Message = "No roles found"
};
try
{
IEnumerable<RoleResponseDto> roles = await _roleService.GetAllRolesAsync(pageNumber, pageSize).ConfigureAwait(false);
int totalCount = await _roleService.GetTotalRolesCountAsync().ConfigureAwait(false);
if (roles.Any())
{
int totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

response.Status = ResponseStatus.Success;
response.Data = roles;
response.Message = "Roles retrieved successfully";
response.Pagination = new PaginationMetadata
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalCount = totalCount,
TotalPages = totalPages,
HasPreviousPage = pageNumber > 1,
HasNextPage = pageNumber < totalPages
};
}

return roles.Any() ? Ok(response) : NotFound(response);
}
catch (Exception ex)
{
response.Status = ResponseStatus.Error;
response.Message = "An unexpected error occurred.";
response.StackTrace = ex.StackTrace;
return StatusCode(500, response);
}
}

[HttpPost]
public async Task<IActionResult> CreateRole([FromBody] RoleCreateDto roleDto)
public async Task<ActionResult<BaseResponse<RoleResponseDto?>>> CreateRole([FromBody] RoleCreateDto roleDto)
{
if (!ModelState.IsValid)
BaseResponse<RoleResponseDto> response = new(ResponseStatus.Fail)
{
return BadRequest(ModelState);
}
Message = "Failed to create role"
};
try
{
if (!ModelState.IsValid)
{
return ModelValidationBadRequest.GenerateErrorResponse(ModelState);
}

RoleResponseDto? createdRole = await _roleService.CreateRoleAsync(roleDto).ConfigureAwait(false);
if (createdRole != null)
{
response.Status = ResponseStatus.Success;
response.Data = createdRole;
response.Message = "Role created successfully";
}

RoleResponseDto? createdRole = await _roleService.CreateRoleAsync(roleDto).ConfigureAwait(false);
if (createdRole == null)
return createdRole == null ? BadRequest(response) : Ok(response);
}
catch (Exception ex)
{
return BadRequest(new { message = "Failed to create role" });
response.Status = ResponseStatus.Error;
response.Message = "An unexpected error occurred.";
response.StackTrace = ex.StackTrace;
return StatusCode(500, response);
}

return CreatedAtAction(nameof(GetRoleById), new { id = createdRole.Id }, createdRole);
}

[HttpPut("{id}")]
public async Task<IActionResult> UpdateRole(int id, [FromBody] RoleUpdateDto roleDto)
public async Task<ActionResult<BaseResponse<RoleResponseDto>>> UpdateRole(int id, [FromBody] RoleUpdateDto roleDto)
{
if (!ModelState.IsValid)
BaseResponse<RoleResponseDto> response = new(ResponseStatus.Fail)
{
return BadRequest(ModelState);
}
Message = "Role update failed"
};

bool success = await _roleService.UpdateRoleAsync(id, roleDto).ConfigureAwait(false);
if (!success)
try
{
return NotFound(new { message = "Role not found or update failed" });
}
if (!ModelState.IsValid)
{
return ModelValidationBadRequest.GenerateErrorResponse(ModelState);
}

return NoContent();
RoleResponseDto? updatedRole = await _roleService.UpdateRoleAsync(id, roleDto).ConfigureAwait(false);
if (updatedRole == null)
{
return NotFound(new { message = "Role not found" });
}

response.Status = ResponseStatus.Success;
response.Data = updatedRole;
response.Message = "Role updated successfully";
return Ok(response);
}
catch (Exception ex)
{
response.Status = ResponseStatus.Error;
response.Message = "An unexpected error occurred.";
response.StackTrace = ex.StackTrace;
return StatusCode(500, response);
}
}

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteRole(int id)
public async Task<ActionResult<BaseResponse<bool>>> DeleteRole(int id)
{
bool success = await _roleService.DeleteRoleAsync(id).ConfigureAwait(false);
if (!success)
BaseResponse<bool> response = new(ResponseStatus.Fail)
{
return NotFound(new { message = "Role not found or deletion failed" });
}
Message = "Role deletion failed"
};

try
{
bool isDeleted = await _roleService.DeleteRoleAsync(id).ConfigureAwait(false);
if (!isDeleted)
{
response.Message = "Role not found";
return NotFound(response);
}

return NoContent();
response.Status = ResponseStatus.Success;
response.Data = true;
response.Message = "Role deleted successfully";
return Ok(response);
}
catch (Exception ex)
{
response.Status = ResponseStatus.Error;
response.Message = "An unexpected error occurred.";
response.StackTrace = ex.StackTrace;
return StatusCode(500, response);
}
}
}
Loading