Skip to content

Commit

Permalink
feat:addedDbCon
Browse files Browse the repository at this point in the history
  • Loading branch information
moshdev2213 committed Sep 10, 2024
1 parent 28012cb commit 7b07cf0
Show file tree
Hide file tree
Showing 23 changed files with 456 additions and 47 deletions.
22 changes: 0 additions & 22 deletions Controllers/StatusController.cs

This file was deleted.

70 changes: 70 additions & 0 deletions Controllers/TestController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.AspNetCore.Mvc;
using apekade.Dto;
using Microsoft.AspNetCore.Authorization;

namespace apekade.Controllers;

[Route("api/[controller]")]
[ApiController]
// [Authorize]
public class TestController : ControllerBase
{

[HttpGet]
public IActionResult GetServerStatus()
{
var response = new ApiRes<object>{
Status = true,
Code= 200,
Data = new { Message = "Server Online" }
};
return Ok(response);

}
// Only SuperAdmin can access this endpoint
[Authorize(Roles = "SUPER_ADMIN")]
[HttpGet("superadmin")]
public IActionResult SuperAdminOnly()
{
return Ok("Only SuperAdmin can access this.");
}

// Only Seller can access this endpoint
[Authorize(Roles = "SELLER")]
[HttpGet("seller")]
public IActionResult SellerOnly()
{
return Ok("Only Sellers can access this.");
}

// Only Buyer can access this endpoint
[Authorize(Roles = "BUYER")]
[HttpGet("buyer")]
public IActionResult BuyerOnly()
{
return Ok("Only Buyers can access this.");
}

// Both Seller and Buyer can access this endpoint
[Authorize(Roles = "SELLER,BUYER")]
[HttpGet("seller-buyer")]
public IActionResult SellerAndBuyerAccess()
{
return Ok("Both Sellers and Buyers can access this.");
}

// Any authenticated user can access this endpoint
[Authorize]
[HttpGet("common")]
public IActionResult CommonAccess()
{
return Ok("Any authenticated user can access this.");
}

// Any one can access this endpoint
[HttpGet("open")]
public IActionResult OpenAccess()
{
return Ok("Any one can access this.");
}
}
23 changes: 23 additions & 0 deletions Controllers/UserController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Mvc;
using apekade.Enums;
using apekade.Services;
using apekade.Dto.UserDto;

namespace apekade.Controllers;

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase{
private readonly IUserService _userService;

public UserController(IUserService userService){
_userService = userService;
}

[HttpPost]
public async Task<IActionResult> CreateUser([FromBody] UserReqtDto userReqtDto){

var response = await _userService.CreateNewUser(userReqtDto);
return Ok(response);
}
}
8 changes: 8 additions & 0 deletions Enums/Role.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace apekade.Enums;

public enum Role
{
ADMIN,
SELLER,
BUYER
}
40 changes: 40 additions & 0 deletions Helpers/GenerateJwtToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using apekade.Models;

namespace apekade.Helpers;

public class GenerateJwtToken{
private readonly IConfiguration _configuration;

public GenerateJwtToken(IConfiguration configuration)
{
_configuration = configuration;
}
public string GenerateJwt(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();

var appSettingToken = _configuration.GetSection("AppSettings:Token").Value;
if (appSettingToken is null)
throw new Exception("AppSettings Token is null!");

var key = Encoding.UTF8.GetBytes(appSettingToken);

var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Role, user.Role.ToString())
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};

var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
19 changes: 19 additions & 0 deletions Helpers/HashPassword.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Security.Cryptography;

namespace apekade.Helpers;

public class HashPassword{
public static void CreatePasswordHash(string password, out string passwordHash, out string passwordSalt)
{
using var hmac = new HMACSHA512();
passwordSalt = Convert.ToBase64String(hmac.Key);
passwordHash = Convert.ToBase64String(hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)));
}

public static bool VerifyPasswordHash(string password, string storedHash, string storedSalt)
{
using var hmac = new HMACSHA512(Convert.FromBase64String(storedSalt));
var computedHash = Convert.ToBase64String(hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)));
return computedHash == storedHash;
}
}
18 changes: 18 additions & 0 deletions Models/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using apekade.Enums;

namespace apekade.Models;

public class User{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public required string Id { get; set; }
public required string FirstName { get; set; }
public string? LastName { get; set; }
public required string Email { get; set; }
public required string PasswordHash { get; set; }
public required string PasswordSalt { get; set; }
[BsonRepresentation((BsonType.String))]
public required Role Role { get; set; }
}
13 changes: 7 additions & 6 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
var builder = WebApplication.CreateBuilder(args);
using apekade.Configuration;
using apekade.Dto;

// Add services to the container.
builder.Services.AddEndpointsApiExplorer();
var builder = WebApplication.CreateBuilder(args);

//the service configs are handled
ServiceConfiguration.Configure(builder.Services,builder.Configuration);
ServiceConfiguration.Configure(builder.Services, builder.Configuration);

var app = builder.Build();

Expand All @@ -26,8 +26,9 @@
app.MapControllers();

// root server online status
app.MapGet("/",()=> new ApiRes<object>{
Status = "Success",
app.MapGet("/", () => new ApiRes<object>
{
Status = true,
Code = 200,
Data = new { Message = "Server_Online" }
});
Expand Down
19 changes: 19 additions & 0 deletions Repositories/UserRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using MongoDB.Driver;
using apekade.Models;

namespace apekade.Repositories;

public class UserRepository
{
private readonly IMongoCollection<User> _usersCollection;

public UserRepository(IMongoDatabase database)
{
_usersCollection = database.GetCollection<User>("Users");
}

public async Task save(User user)
{
await _usersCollection.InsertOneAsync(user);
}
}
9 changes: 9 additions & 0 deletions Services/IUserService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using apekade.Dto;
using apekade.Dto.UserDto;

namespace apekade.Services;

public interface IUserService
{
Task<ApiRes<UserTokenResDto>> CreateNewUser(UserReqtDto userReqtDto);
}
57 changes: 57 additions & 0 deletions Services/Impl/UserService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using AutoMapper;
using apekade.Models;
using apekade.Dto;
using apekade.Repositories;
using apekade.Helpers;
using apekade.Services.Impl;
using apekade.Dto.UserDto;

namespace apekade.Services.Impl;

public class UserService : IUserService
{
private readonly IMapper _mapper;

private readonly UserRepository _userRepository;

private readonly GenerateJwtToken _generateJwtToken;

public UserService(IMapper mapper, UserRepository userRepository, GenerateJwtToken generateJwtToken)
{
_mapper = mapper;
_userRepository = userRepository;
_generateJwtToken = generateJwtToken;
}

public async Task<ApiRes<UserTokenResDto>> CreateNewUser(UserReqtDto userRequestDto)
{
var response = new ApiRes<UserTokenResDto>();

try
{
var newUser = _mapper.Map<User>(userRequestDto);
HashPassword.CreatePasswordHash(userRequestDto.Password, out var passwordHash, out var passwordSalt);
newUser.PasswordHash = passwordHash;
newUser.PasswordSalt = passwordSalt;

await _userRepository.save(newUser);

var token = _generateJwtToken.GenerateJwt(newUser);

var userResponse = _mapper.Map<UserResDto>(newUser);

response.Status = true;
response.Code = 201;
response.Data = new UserTokenResDto { User = userResponse, Token = token };
response.Message = "User created successfully!";
}
catch (Exception ex)
{
response.Status = false;
response.Code = 500;
response.Message = ex.Message;
}

return response;
}
}
2 changes: 2 additions & 0 deletions apekade.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.28.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions configuration/CorsConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
namespace apekade.Configuration;

public static class CorsConfiguration
{
Expand Down
28 changes: 20 additions & 8 deletions configuration/DbContextConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using apekade.Data;

namespace apekade.Configuration;

public static class DbContextConfiguration
{
public static void ConfigureDbContextServices(IServiceCollection services, IConfiguration configuration)
{
// Register the DbSettings configuration
services.Configure<DbSettings>(configuration.GetSection(nameof(DbSettings)));
// Register the DbSettings configuration
services.Configure<DbSettings>(configuration.GetSection(nameof(DbSettings)));

// Register the MongoDB DbContext
// services.AddSingleton<DbContext>();

services.AddSingleton(provider =>{
var dbSettings = provider.GetService<IOptions<DbSettings>>() ?? throw new InvalidOperationException("MongoDbSettings is not configured properly");
// Register the MongoDB DbContext
// service is created once for all.
services.AddSingleton(provider =>
{
var dbSettings = provider.GetRequiredService<IOptions<DbSettings>>() ?? throw new InvalidOperationException("MongoDbSettings is not configured properly");
// Initialize DbContext with the DbSettings
return new DbContext(dbSettings);
return new DbContext(dbSettings);
});

// service is created once per HTTP request in web applications.
services.AddScoped(sp =>
{
var settings = sp.GetRequiredService<IOptions<DbSettings>>().Value;
var client = sp.GetRequiredService<IMongoClient>();
return client.GetDatabase(settings.DatabaseName);
});
}
}
Loading

0 comments on commit 7b07cf0

Please sign in to comment.