Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 27 additions & 0 deletions BookStore.Api/BookStore.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BookStore.Domain\BookStore.Domain.csproj" />
<ProjectReference Include="..\BookStore.Application\BookStore.Application.csproj" />
<ProjectReference Include="..\BookStore.Infrastructure\BookStore.Infrastructure.csproj" />
<ProjectReference Include="..\BookStore.Shared\BookStore.Shared.csproj" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions BookStore.Api/BookStore.Api.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@BookStore.Api_HostAddress = http://localhost:5186

GET {{BookStore.Api_HostAddress}}/weatherforecast/
Accept: application/json

###
79 changes: 79 additions & 0 deletions BookStore.Api/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using BookStore.Shared.DTOs;

namespace BookStore.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AccountController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IConfiguration _configuration;

public AccountController(UserManager<IdentityUser> userManager, IConfiguration configuration)
{
_userManager = userManager;
_configuration = configuration;
}

[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterDto model)
{
var user = new IdentityUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);

if (result.Succeeded)
{
return Ok(new { Message = "User created successfully" });
}

return BadRequest(result.Errors);
}

[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginDto model)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
var token = GenerateJwtToken(user);
return Ok(new UserDto
{
Email = user.Email,
Token = token
});
}

return Unauthorized();
}

private string GenerateJwtToken(IdentityUser user)
{
var jwtSettings = _configuration.GetSection("Jwt");
var key = Encoding.ASCII.GetBytes(jwtSettings["Key"]);

var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.UserName)
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Issuer = jwtSettings["Issuer"],
Audience = jwtSettings["Audience"]
};

var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
}
121 changes: 121 additions & 0 deletions BookStore.Api/Controllers/BooksController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using BookStore.Domain.Entities;
using BookStore.Domain.Interfaces;
using BookStore.Shared.DTOs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace BookStore.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly IBookRepository _bookRepository;

public BooksController(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}

[HttpGet]
public IActionResult GetBooks([FromQuery] string? category = null)
{
var books = _bookRepository.Books.AsQueryable();

if (!string.IsNullOrEmpty(category))
{
books = books.Where(b => b.Category.Name == category);
}

var result = books.Select(b => new BookDto
{
Id = b.Id,
Name = b.Name,
Author = b.Author,
Details = b.Details,
ImgUrl = b.ImgUrl,
Active = b.Active,
Price = b.Price,
PriceOffer = b.PriceOffer,
CategoryId = b.CategoryId,
CategoryName = b.Category.Name
}).ToList();

return Ok(result);
}

[HttpGet("{id}")]
public IActionResult GetBook(int id)
{
var b = _bookRepository.GetBookById(id);
if (b == null) return NotFound();

var result = new BookDto
{
Id = b.Id,
Name = b.Name,
Author = b.Author,
Details = b.Details,
ImgUrl = b.ImgUrl,
Active = b.Active,
Price = b.Price,
PriceOffer = b.PriceOffer,
CategoryId = b.CategoryId,
CategoryName = b.Category?.Name
};

return Ok(result);
}

[HttpPost]
[Authorize]
public IActionResult CreateBook([FromBody] BookDto bookDto)
{
var book = new Book
{
Name = bookDto.Name,
Author = bookDto.Author,
Details = bookDto.Details,
ImgUrl = bookDto.ImgUrl,
Active = bookDto.Active,
Price = bookDto.Price,
PriceOffer = bookDto.PriceOffer,
CategoryId = bookDto.CategoryId
};

_bookRepository.AddOrEdit(book);
return CreatedAtAction(nameof(GetBook), new { id = book.Id }, bookDto);
}

[HttpPut("{id}")]
[Authorize]
public IActionResult UpdateBook(int id, [FromBody] BookDto bookDto)
{
var book = _bookRepository.GetBookById(id);
if (book == null) return NotFound();

book.Name = bookDto.Name;
book.Author = bookDto.Author;
book.Details = bookDto.Details;
book.ImgUrl = bookDto.ImgUrl;
book.Active = bookDto.Active;
book.Price = bookDto.Price;
book.PriceOffer = bookDto.PriceOffer;
book.CategoryId = bookDto.CategoryId;

_bookRepository.AddOrEdit(book);
return NoContent();
}

[HttpDelete("{id}")]
[Authorize]
public IActionResult DeleteBook(int id)
{
var book = _bookRepository.GetBookById(id);
if (book == null) return NotFound();

_bookRepository.Delete(id);
return NoContent();
}
}
}
70 changes: 70 additions & 0 deletions BookStore.Api/Controllers/CategoriesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using BookStore.Domain.Entities;
using BookStore.Domain.Interfaces;
using BookStore.Shared.DTOs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace BookStore.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class CategoriesController : ControllerBase
{
private readonly ICategoryRepository _categoryRepository;

public CategoriesController(ICategoryRepository categoryRepository)
{
_categoryRepository = categoryRepository;
}

[HttpGet]
public IActionResult GetCategories()
{
var categories = _categoryRepository.Categories.Select(c => new CategoryDto
{
Id = c.Id,
Name = c.Name,
Description = c.Description
}).ToList();

return Ok(categories);
}

[HttpPost]
[Authorize]
public IActionResult CreateCategory([FromBody] CategoryDto categoryDto)
{
var category = new Category
{
Name = categoryDto.Name,
Description = categoryDto.Description
};
_categoryRepository.AddEdit(category);
return Ok(categoryDto);
}

[HttpPut("{id}")]
[Authorize]
public IActionResult UpdateCategory(int id, [FromBody] CategoryDto categoryDto)
{
var category = _categoryRepository.Categories.FirstOrDefault(c => c.Id == id);
if (category == null) return NotFound();

category.Name = categoryDto.Name;
category.Description = categoryDto.Description;
_categoryRepository.AddEdit(category);
return NoContent();
}

[HttpDelete("{id}")]
[Authorize]
public IActionResult DeleteCategory(int id)
{
var category = _categoryRepository.Categories.FirstOrDefault(c => c.Id == id);
if (category == null) return NotFound();

_categoryRepository.Delete(id);
return NoContent();
}
}
}
72 changes: 72 additions & 0 deletions BookStore.Api/Controllers/OrdersController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using BookStore.Domain.Entities;
using BookStore.Domain.Interfaces;
using BookStore.Shared.DTOs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace BookStore.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class OrdersController : ControllerBase
{
private readonly IOrderRepository _orderRepository;
private readonly IShoppingCart _shoppingCart;

public OrdersController(IOrderRepository orderRepository, IShoppingCart shoppingCart)
{
_orderRepository = orderRepository;
_shoppingCart = shoppingCart;
}

[HttpPost("checkout/{cartId}")]
public IActionResult Checkout(string cartId, [FromBody] OrderDto orderDto)
{
_shoppingCart.ShoppingCartId = cartId;
var items = _shoppingCart.GetShoppingCartItems();
_shoppingCart.ShoppingCartItems = items;

if (items.Count == 0)
{
return BadRequest("Your cart is empty");
}

var order = new Order
{
FirstName = orderDto.FirstName,
LastName = orderDto.LastName,
Address = orderDto.Address,
ZipCode = orderDto.ZipCode,
State = orderDto.State,
Country = orderDto.Country,
PhoneNumber = orderDto.PhoneNumber,
Email = orderDto.Email,
OrderTotal = _shoppingCart.GetShoppingCartTotal(),
OrderedPlaced = DateTime.Now
};

_orderRepository.CreateOrder(order);
_shoppingCart.ClearCart();

return Ok(new { Message = "Order placed successfully", OrderId = order.Id });
}

[HttpGet]
public IActionResult GetAllOrders()
{
var orders = _orderRepository.Orders.Select(o => new {
o.Id,
o.FirstName,
o.LastName,
o.Email,
o.OrderTotal,
o.OrderedPlaced,
o.Address
}).OrderByDescending(o => o.OrderedPlaced).ToList();

return Ok(orders);
}
}
}
Loading