Spaces:
Sleeping
Sleeping
Commit ·
97af519
1
Parent(s): 24fa936
chore: remove backend project files and configurations for Library Management System
Browse files- LibraryManagement.Backend/Features/Auth/AuthController.cs +0 -59
- LibraryManagement.Backend/Features/Auth/AuthModels.cs +0 -26
- LibraryManagement.Backend/Features/Auth/AuthService.cs +0 -110
- LibraryManagement.Backend/Features/Books/BookController.cs +0 -67
- LibraryManagement.Backend/Features/Books/BookService.cs +0 -150
- LibraryManagement.Backend/Features/Borrowing/BorrowingController.cs +0 -72
- LibraryManagement.Backend/Features/Borrowing/BorrowingModels.cs +0 -24
- LibraryManagement.Backend/Features/Borrowing/BorrowingService.cs +0 -166
- LibraryManagement.Backend/Features/Categories/CategoryController.cs +0 -49
- LibraryManagement.Backend/Features/Categories/CategoryService.cs +0 -69
- LibraryManagement.Backend/Features/Subscriptions/SubscriptionController.cs +0 -84
- LibraryManagement.Backend/Features/Subscriptions/SubscriptionModels.cs +0 -38
- LibraryManagement.Backend/Features/Subscriptions/SubscriptionService.cs +0 -96
- LibraryManagement.Backend/Features/Users/UserController.cs +0 -77
- LibraryManagement.Backend/Features/Users/UserService.cs +0 -182
- LibraryManagement.Backend/LibraryManagement.Backend.csproj +0 -20
- LibraryManagement.Backend/LibraryManagement.Backend.http +0 -6
- LibraryManagement.Backend/Program.cs +0 -91
- LibraryManagement.Backend/Properties/launchSettings.json +0 -41
- LibraryManagement.Backend/WeatherForecast.cs +0 -13
- LibraryManagement.Backend/appsettings.Development.json +0 -8
- LibraryManagement.Backend/appsettings.json +0 -18
LibraryManagement.Backend/Features/Auth/AuthController.cs
DELETED
|
@@ -1,59 +0,0 @@
|
|
| 1 |
-
using Microsoft.AspNetCore.Authorization;
|
| 2 |
-
using Microsoft.AspNetCore.Mvc;
|
| 3 |
-
using System.Security.Claims;
|
| 4 |
-
|
| 5 |
-
namespace LibraryManagement.Backend.Features.Auth
|
| 6 |
-
{
|
| 7 |
-
[ApiController]
|
| 8 |
-
[Route("api/auth")]
|
| 9 |
-
public class AuthController : ControllerBase
|
| 10 |
-
{
|
| 11 |
-
private readonly IAuthService _authService;
|
| 12 |
-
|
| 13 |
-
public AuthController(IAuthService authService)
|
| 14 |
-
{
|
| 15 |
-
_authService = authService;
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
[HttpPost("register")]
|
| 19 |
-
public async Task<ActionResult<AuthResponse>> Register([FromBody] RegisterRequest request)
|
| 20 |
-
{
|
| 21 |
-
try
|
| 22 |
-
{
|
| 23 |
-
var response = await _authService.Register(request);
|
| 24 |
-
return Ok(response);
|
| 25 |
-
}
|
| 26 |
-
catch (Exception ex)
|
| 27 |
-
{
|
| 28 |
-
return BadRequest(new { message = ex.Message });
|
| 29 |
-
}
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
[HttpPost("login")]
|
| 33 |
-
public async Task<ActionResult<AuthResponse>> Login([FromBody] LoginRequest request)
|
| 34 |
-
{
|
| 35 |
-
try
|
| 36 |
-
{
|
| 37 |
-
var response = await _authService.Login(request);
|
| 38 |
-
return Ok(response);
|
| 39 |
-
}
|
| 40 |
-
catch (Exception ex)
|
| 41 |
-
{
|
| 42 |
-
return Unauthorized(new { message = ex.Message });
|
| 43 |
-
}
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
-
[HttpGet("me")]
|
| 47 |
-
[Authorize]
|
| 48 |
-
public IActionResult GetCurrentUser()
|
| 49 |
-
{
|
| 50 |
-
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();
|
| 51 |
-
return Ok(new
|
| 52 |
-
{
|
| 53 |
-
IsAuthenticated = User.Identity?.IsAuthenticated,
|
| 54 |
-
Name = User.Identity?.Name,
|
| 55 |
-
Claims = claims
|
| 56 |
-
});
|
| 57 |
-
}
|
| 58 |
-
}
|
| 59 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Auth/AuthModels.cs
DELETED
|
@@ -1,26 +0,0 @@
|
|
| 1 |
-
namespace LibraryManagement.Backend.Features.Auth
|
| 2 |
-
{
|
| 3 |
-
public class RegisterRequest
|
| 4 |
-
{
|
| 5 |
-
public string FullName { get; set; } = string.Empty;
|
| 6 |
-
public string Email { get; set; } = string.Empty;
|
| 7 |
-
public string Password { get; set; } = string.Empty;
|
| 8 |
-
public string? PhoneNumber { get; set; }
|
| 9 |
-
public string? Address { get; set; }
|
| 10 |
-
public string? StudentId { get; set; }
|
| 11 |
-
}
|
| 12 |
-
|
| 13 |
-
public class LoginRequest
|
| 14 |
-
{
|
| 15 |
-
public string Email { get; set; } = string.Empty;
|
| 16 |
-
public string Password { get; set; } = string.Empty;
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
public class AuthResponse
|
| 20 |
-
{
|
| 21 |
-
public string Token { get; set; } = string.Empty;
|
| 22 |
-
public string FullName { get; set; } = string.Empty;
|
| 23 |
-
public string Role { get; set; } = string.Empty;
|
| 24 |
-
public DateTime Expiry { get; set; }
|
| 25 |
-
}
|
| 26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Auth/AuthService.cs
DELETED
|
@@ -1,110 +0,0 @@
|
|
| 1 |
-
using Database.Models;
|
| 2 |
-
using Microsoft.EntityFrameworkCore;
|
| 3 |
-
using Microsoft.IdentityModel.Tokens;
|
| 4 |
-
using System.IdentityModel.Tokens.Jwt;
|
| 5 |
-
using System.Security.Claims;
|
| 6 |
-
using System.Text;
|
| 7 |
-
|
| 8 |
-
using LibraryManagement.Backend.Features.Subscriptions;
|
| 9 |
-
|
| 10 |
-
namespace LibraryManagement.Backend.Features.Auth
|
| 11 |
-
{
|
| 12 |
-
public interface IAuthService
|
| 13 |
-
{
|
| 14 |
-
Task<AuthResponse> Register(RegisterRequest request);
|
| 15 |
-
Task<AuthResponse> Login(LoginRequest request);
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
public class AuthService : IAuthService
|
| 19 |
-
{
|
| 20 |
-
private readonly LibraryManagementContext _context;
|
| 21 |
-
private readonly IConfiguration _configuration;
|
| 22 |
-
private readonly ISubscriptionService _subscriptionService;
|
| 23 |
-
|
| 24 |
-
public AuthService(LibraryManagementContext context, IConfiguration configuration, ISubscriptionService subscriptionService)
|
| 25 |
-
{
|
| 26 |
-
_context = context;
|
| 27 |
-
_configuration = configuration;
|
| 28 |
-
_subscriptionService = subscriptionService;
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
public async Task<AuthResponse> Register(RegisterRequest request)
|
| 32 |
-
{
|
| 33 |
-
if (await _context.Users.AnyAsync(u => u.Email == request.Email))
|
| 34 |
-
{
|
| 35 |
-
throw new Exception("User already exists with this email.");
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
var user = new User
|
| 39 |
-
{
|
| 40 |
-
FullName = request.FullName,
|
| 41 |
-
Email = request.Email,
|
| 42 |
-
PhoneNumber = request.PhoneNumber,
|
| 43 |
-
Address = request.Address,
|
| 44 |
-
StudentId = request.StudentId,
|
| 45 |
-
PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password),
|
| 46 |
-
Role = "Member", // Default role
|
| 47 |
-
IsActive = true,
|
| 48 |
-
CreatedAt = DateTime.UtcNow
|
| 49 |
-
};
|
| 50 |
-
|
| 51 |
-
_context.Users.Add(user);
|
| 52 |
-
await _context.SaveChangesAsync();
|
| 53 |
-
|
| 54 |
-
if (!string.IsNullOrEmpty(user.StudentId))
|
| 55 |
-
{
|
| 56 |
-
await _subscriptionService.SubscribeUserAsync(user.Id, 3); // 3 is "Basic Yearly"
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
-
return await AuthenticateUser(user);
|
| 60 |
-
}
|
| 61 |
-
|
| 62 |
-
public async Task<AuthResponse> Login(LoginRequest request)
|
| 63 |
-
{
|
| 64 |
-
var user = await _context.Users.FirstOrDefaultAsync(u => u.Email == request.Email);
|
| 65 |
-
|
| 66 |
-
if (user == null || !BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
|
| 67 |
-
{
|
| 68 |
-
throw new Exception("Invalid email or password.");
|
| 69 |
-
}
|
| 70 |
-
|
| 71 |
-
if (!user.IsActive)
|
| 72 |
-
{
|
| 73 |
-
throw new Exception("User account is deactivated.");
|
| 74 |
-
}
|
| 75 |
-
|
| 76 |
-
return await AuthenticateUser(user);
|
| 77 |
-
}
|
| 78 |
-
|
| 79 |
-
private async Task<AuthResponse> AuthenticateUser(User user)
|
| 80 |
-
{
|
| 81 |
-
var tokenHandler = new JwtSecurityTokenHandler();
|
| 82 |
-
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Secret"] ?? "YourSuperSecretKeyForLibraryManagementSystem_AtLeast32CharsLong");
|
| 83 |
-
|
| 84 |
-
var tokenDescriptor = new SecurityTokenDescriptor
|
| 85 |
-
{
|
| 86 |
-
Subject = new ClaimsIdentity(new[]
|
| 87 |
-
{
|
| 88 |
-
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
| 89 |
-
new Claim(ClaimTypes.Email, user.Email),
|
| 90 |
-
new Claim(ClaimTypes.Name, user.FullName),
|
| 91 |
-
new Claim(ClaimTypes.Role, user.Role)
|
| 92 |
-
}),
|
| 93 |
-
Expires = DateTime.UtcNow.AddDays(7),
|
| 94 |
-
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
|
| 95 |
-
Issuer = _configuration["Jwt:Issuer"],
|
| 96 |
-
Audience = _configuration["Jwt:Audience"]
|
| 97 |
-
};
|
| 98 |
-
|
| 99 |
-
var token = tokenHandler.CreateToken(tokenDescriptor);
|
| 100 |
-
|
| 101 |
-
return new AuthResponse
|
| 102 |
-
{
|
| 103 |
-
Token = tokenHandler.WriteToken(token),
|
| 104 |
-
FullName = user.FullName,
|
| 105 |
-
Role = user.Role,
|
| 106 |
-
Expiry = tokenDescriptor.Expires.Value
|
| 107 |
-
};
|
| 108 |
-
}
|
| 109 |
-
}
|
| 110 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Books/BookController.cs
DELETED
|
@@ -1,67 +0,0 @@
|
|
| 1 |
-
using Microsoft.AspNetCore.Authorization;
|
| 2 |
-
using Microsoft.AspNetCore.Mvc;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Books
|
| 5 |
-
{
|
| 6 |
-
[ApiController]
|
| 7 |
-
[Route("api/books")]
|
| 8 |
-
public class BookController : ControllerBase
|
| 9 |
-
{
|
| 10 |
-
private readonly IBookService _bookService;
|
| 11 |
-
|
| 12 |
-
public BookController(IBookService bookService)
|
| 13 |
-
{
|
| 14 |
-
_bookService = bookService;
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
[HttpGet]
|
| 18 |
-
//[Authorize]
|
| 19 |
-
public async Task<ActionResult<IEnumerable<BookDto>>> GetBooks()
|
| 20 |
-
{
|
| 21 |
-
var books = await _bookService.GetAllBooksAsync();
|
| 22 |
-
return Ok(books);
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
[HttpGet("{id}")]
|
| 26 |
-
//[Authorize]
|
| 27 |
-
public async Task<ActionResult<BookDto>> GetBook(int id)
|
| 28 |
-
{
|
| 29 |
-
var book = await _bookService.GetBookByIdAsync(id);
|
| 30 |
-
if (book == null) return NotFound();
|
| 31 |
-
return Ok(book);
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
[HttpPost]
|
| 35 |
-
//[Authorize(Roles = "Librarian")]
|
| 36 |
-
public async Task<ActionResult<BookDto>> CreateBook([FromBody] BookCreateRequest request)
|
| 37 |
-
{
|
| 38 |
-
try
|
| 39 |
-
{
|
| 40 |
-
var book = await _bookService.CreateBookAsync(request);
|
| 41 |
-
return CreatedAtAction(nameof(GetBook), new { id = book.Id }, book);
|
| 42 |
-
}
|
| 43 |
-
catch (Exception ex)
|
| 44 |
-
{
|
| 45 |
-
return BadRequest(new { message = ex.Message });
|
| 46 |
-
}
|
| 47 |
-
}
|
| 48 |
-
|
| 49 |
-
[HttpPut("{id}")]
|
| 50 |
-
//[Authorize(Roles = "Librarian")]
|
| 51 |
-
public async Task<ActionResult<BookDto>> UpdateBook(int id, [FromBody] BookUpdateRequest request)
|
| 52 |
-
{
|
| 53 |
-
var updatedBook = await _bookService.UpdateBookAsync(id, request);
|
| 54 |
-
if (updatedBook == null) return NotFound();
|
| 55 |
-
return Ok(updatedBook);
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
[HttpDelete("{id}")]
|
| 59 |
-
//[Authorize(Roles = "Librarian")]
|
| 60 |
-
public async Task<IActionResult> DeleteBook(int id)
|
| 61 |
-
{
|
| 62 |
-
var success = await _bookService.DeleteBookAsync(id);
|
| 63 |
-
if (!success) return NotFound();
|
| 64 |
-
return NoContent();
|
| 65 |
-
}
|
| 66 |
-
}
|
| 67 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Books/BookService.cs
DELETED
|
@@ -1,150 +0,0 @@
|
|
| 1 |
-
using Database.Models;
|
| 2 |
-
using Microsoft.EntityFrameworkCore;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Books
|
| 5 |
-
{
|
| 6 |
-
public interface IBookService
|
| 7 |
-
{
|
| 8 |
-
Task<IEnumerable<BookDto>> GetAllBooksAsync();
|
| 9 |
-
Task<BookDto?> GetBookByIdAsync(int id);
|
| 10 |
-
Task<BookDto> CreateBookAsync(BookCreateRequest request);
|
| 11 |
-
Task<BookDto?> UpdateBookAsync(int id, BookUpdateRequest request);
|
| 12 |
-
Task<bool> DeleteBookAsync(int id);
|
| 13 |
-
}
|
| 14 |
-
|
| 15 |
-
public class BookService : IBookService
|
| 16 |
-
{
|
| 17 |
-
private readonly LibraryManagementContext _context;
|
| 18 |
-
|
| 19 |
-
public BookService(LibraryManagementContext context)
|
| 20 |
-
{
|
| 21 |
-
_context = context;
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
-
public async Task<IEnumerable<BookDto>> GetAllBooksAsync()
|
| 25 |
-
{
|
| 26 |
-
return await _context.Books
|
| 27 |
-
.Where(b => b.IsActive)
|
| 28 |
-
.Select(b => MapToDto(b))
|
| 29 |
-
.ToListAsync();
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
public async Task<BookDto?> GetBookByIdAsync(int id)
|
| 33 |
-
{
|
| 34 |
-
var book = await _context.Books.FindAsync(id);
|
| 35 |
-
if (book == null || !book.IsActive) return null;
|
| 36 |
-
return MapToDto(book);
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
public async Task<BookDto> CreateBookAsync(BookCreateRequest request)
|
| 40 |
-
{
|
| 41 |
-
if (await _context.Books.AnyAsync(b => b.Isbn == request.Isbn))
|
| 42 |
-
{
|
| 43 |
-
throw new Exception("A book with this ISBN already exists.");
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
-
var book = new Book
|
| 47 |
-
{
|
| 48 |
-
Title = request.Title,
|
| 49 |
-
Isbn = request.Isbn,
|
| 50 |
-
Author = request.Author,
|
| 51 |
-
Description = request.Description,
|
| 52 |
-
TotalCopies = request.TotalCopies,
|
| 53 |
-
AvailableCopies = request.TotalCopies,
|
| 54 |
-
Status = request.TotalCopies > 0 ? "Available" : "Out Of Stock",
|
| 55 |
-
IsActive = true,
|
| 56 |
-
CreatedAt = DateTime.UtcNow
|
| 57 |
-
};
|
| 58 |
-
|
| 59 |
-
_context.Books.Add(book);
|
| 60 |
-
await _context.SaveChangesAsync();
|
| 61 |
-
|
| 62 |
-
return MapToDto(book);
|
| 63 |
-
}
|
| 64 |
-
|
| 65 |
-
public async Task<BookDto?> UpdateBookAsync(int id, BookUpdateRequest request)
|
| 66 |
-
{
|
| 67 |
-
var book = await _context.Books.FindAsync(id);
|
| 68 |
-
if (book == null || !book.IsActive) return null;
|
| 69 |
-
|
| 70 |
-
book.Title = request.Title;
|
| 71 |
-
book.Author = request.Author;
|
| 72 |
-
book.Description = request.Description;
|
| 73 |
-
|
| 74 |
-
// Basic logic to sync availability when total copies change
|
| 75 |
-
int difference = request.TotalCopies - book.TotalCopies;
|
| 76 |
-
book.TotalCopies = request.TotalCopies;
|
| 77 |
-
book.AvailableCopies += difference;
|
| 78 |
-
|
| 79 |
-
if (book.AvailableCopies < 0) book.AvailableCopies = 0;
|
| 80 |
-
book.Status = book.AvailableCopies > 0 ? "Available" : "Out Of Stock";
|
| 81 |
-
|
| 82 |
-
book.UpdatedAt = DateTime.UtcNow;
|
| 83 |
-
|
| 84 |
-
await _context.SaveChangesAsync();
|
| 85 |
-
return MapToDto(book);
|
| 86 |
-
}
|
| 87 |
-
|
| 88 |
-
public async Task<bool> DeleteBookAsync(int id)
|
| 89 |
-
{
|
| 90 |
-
var book = await _context.Books.FindAsync(id);
|
| 91 |
-
if (book == null) return false;
|
| 92 |
-
|
| 93 |
-
book.IsActive = false;
|
| 94 |
-
book.UpdatedAt = DateTime.UtcNow;
|
| 95 |
-
|
| 96 |
-
await _context.SaveChangesAsync();
|
| 97 |
-
return true;
|
| 98 |
-
}
|
| 99 |
-
|
| 100 |
-
private static BookDto MapToDto(Book book)
|
| 101 |
-
{
|
| 102 |
-
return new BookDto
|
| 103 |
-
{
|
| 104 |
-
Id = book.Id,
|
| 105 |
-
Title = book.Title,
|
| 106 |
-
Isbn = book.Isbn,
|
| 107 |
-
Author = book.Author,
|
| 108 |
-
Status = book.Status,
|
| 109 |
-
IsActive = book.IsActive,
|
| 110 |
-
Description = book.Description,
|
| 111 |
-
TotalCopies = book.TotalCopies,
|
| 112 |
-
AvailableCopies = book.AvailableCopies,
|
| 113 |
-
CreatedAt = book.CreatedAt,
|
| 114 |
-
UpdatedAt = book.UpdatedAt
|
| 115 |
-
};
|
| 116 |
-
}
|
| 117 |
-
}
|
| 118 |
-
|
| 119 |
-
public class BookDto
|
| 120 |
-
{
|
| 121 |
-
public int Id { get; set; }
|
| 122 |
-
public string Title { get; set; } = string.Empty;
|
| 123 |
-
public string Isbn { get; set; } = string.Empty;
|
| 124 |
-
public string Author { get; set; } = string.Empty;
|
| 125 |
-
public string Status { get; set; } = string.Empty;
|
| 126 |
-
public bool IsActive { get; set; }
|
| 127 |
-
public string? Description { get; set; }
|
| 128 |
-
public int TotalCopies { get; set; }
|
| 129 |
-
public int AvailableCopies { get; set; }
|
| 130 |
-
public DateTime CreatedAt { get; set; }
|
| 131 |
-
public DateTime? UpdatedAt { get; set; }
|
| 132 |
-
}
|
| 133 |
-
|
| 134 |
-
public class BookCreateRequest
|
| 135 |
-
{
|
| 136 |
-
public string Title { get; set; } = string.Empty;
|
| 137 |
-
public string Isbn { get; set; } = string.Empty;
|
| 138 |
-
public string Author { get; set; } = string.Empty;
|
| 139 |
-
public string? Description { get; set; }
|
| 140 |
-
public int TotalCopies { get; set; }
|
| 141 |
-
}
|
| 142 |
-
|
| 143 |
-
public class BookUpdateRequest
|
| 144 |
-
{
|
| 145 |
-
public string Title { get; set; } = string.Empty;
|
| 146 |
-
public string Author { get; set; } = string.Empty;
|
| 147 |
-
public string? Description { get; set; }
|
| 148 |
-
public int TotalCopies { get; set; }
|
| 149 |
-
}
|
| 150 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Borrowing/BorrowingController.cs
DELETED
|
@@ -1,72 +0,0 @@
|
|
| 1 |
-
using Microsoft.AspNetCore.Authorization;
|
| 2 |
-
using Microsoft.AspNetCore.Mvc;
|
| 3 |
-
using System.Security.Claims;
|
| 4 |
-
|
| 5 |
-
namespace LibraryManagement.Backend.Features.Borrowings
|
| 6 |
-
{
|
| 7 |
-
[ApiController]
|
| 8 |
-
[Route("api/borrowings")]
|
| 9 |
-
public class BorrowingController : ControllerBase
|
| 10 |
-
{
|
| 11 |
-
private readonly IBorrowingService _borrowingService;
|
| 12 |
-
|
| 13 |
-
public BorrowingController(IBorrowingService borrowingService)
|
| 14 |
-
{
|
| 15 |
-
_borrowingService = borrowingService;
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
[HttpPost("borrow")]
|
| 19 |
-
//[Authorize]
|
| 20 |
-
public async Task<ActionResult<BorrowingDto>> BorrowBook([FromBody] BorrowRequest request)
|
| 21 |
-
{
|
| 22 |
-
try
|
| 23 |
-
{
|
| 24 |
-
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
| 25 |
-
if (string.IsNullOrEmpty(userIdStr)) return Unauthorized();
|
| 26 |
-
|
| 27 |
-
var userId = int.Parse(userIdStr);
|
| 28 |
-
var borrowing = await _borrowingService.BorrowBookAsync(userId, request.BookId);
|
| 29 |
-
return Ok(borrowing);
|
| 30 |
-
}
|
| 31 |
-
catch (Exception ex)
|
| 32 |
-
{
|
| 33 |
-
return BadRequest(new { message = ex.Message });
|
| 34 |
-
}
|
| 35 |
-
}
|
| 36 |
-
|
| 37 |
-
[HttpPost("return/{id}")]
|
| 38 |
-
//[Authorize(Roles = "Librarian")]
|
| 39 |
-
public async Task<ActionResult<BorrowingDto>> ReturnBook(int id)
|
| 40 |
-
{
|
| 41 |
-
try
|
| 42 |
-
{
|
| 43 |
-
var borrowing = await _borrowingService.ReturnBookAsync(id);
|
| 44 |
-
return Ok(borrowing);
|
| 45 |
-
}
|
| 46 |
-
catch (Exception ex)
|
| 47 |
-
{
|
| 48 |
-
return BadRequest(new { message = ex.Message });
|
| 49 |
-
}
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
[HttpGet("me")]
|
| 53 |
-
//[Authorize]
|
| 54 |
-
public async Task<ActionResult<IEnumerable<BorrowingDto>>> GetMyBorrowings()
|
| 55 |
-
{
|
| 56 |
-
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
| 57 |
-
if (string.IsNullOrEmpty(userIdStr)) return Unauthorized();
|
| 58 |
-
|
| 59 |
-
var userId = int.Parse(userIdStr);
|
| 60 |
-
var borrowings = await _borrowingService.GetUserBorrowingsAsync(userId);
|
| 61 |
-
return Ok(borrowings);
|
| 62 |
-
}
|
| 63 |
-
|
| 64 |
-
[HttpGet]
|
| 65 |
-
//[Authorize(Roles = "Librarian")]
|
| 66 |
-
public async Task<ActionResult<IEnumerable<BorrowingDto>>> GetAllBorrowings()
|
| 67 |
-
{
|
| 68 |
-
var borrowings = await _borrowingService.GetAllBorrowingsAsync();
|
| 69 |
-
return Ok(borrowings);
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Borrowing/BorrowingModels.cs
DELETED
|
@@ -1,24 +0,0 @@
|
|
| 1 |
-
using System;
|
| 2 |
-
|
| 3 |
-
namespace LibraryManagement.Backend.Features.Borrowings
|
| 4 |
-
{
|
| 5 |
-
public class BorrowingDto
|
| 6 |
-
{
|
| 7 |
-
public int Id { get; set; }
|
| 8 |
-
public int UserId { get; set; }
|
| 9 |
-
public string UserEmail { get; set; } = string.Empty;
|
| 10 |
-
public int BookId { get; set; }
|
| 11 |
-
public string BookTitle { get; set; } = string.Empty;
|
| 12 |
-
public DateTime BorrowDate { get; set; }
|
| 13 |
-
public DateTime DueDate { get; set; }
|
| 14 |
-
public DateTime? ReturnDate { get; set; }
|
| 15 |
-
public string Status { get; set; } = string.Empty;
|
| 16 |
-
public decimal FineAmount { get; set; }
|
| 17 |
-
public bool IsFinePaid { get; set; }
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
public class BorrowRequest
|
| 21 |
-
{
|
| 22 |
-
public int BookId { get; set; }
|
| 23 |
-
}
|
| 24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Borrowing/BorrowingService.cs
DELETED
|
@@ -1,166 +0,0 @@
|
|
| 1 |
-
using Database.Models;
|
| 2 |
-
using Microsoft.EntityFrameworkCore;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Borrowings
|
| 5 |
-
{
|
| 6 |
-
public interface IBorrowingService
|
| 7 |
-
{
|
| 8 |
-
Task<BorrowingDto> BorrowBookAsync(int userId, int bookId);
|
| 9 |
-
Task<BorrowingDto> ReturnBookAsync(int borrowingId);
|
| 10 |
-
Task<IEnumerable<BorrowingDto>> GetUserBorrowingsAsync(int userId);
|
| 11 |
-
Task<IEnumerable<BorrowingDto>> GetAllBorrowingsAsync();
|
| 12 |
-
}
|
| 13 |
-
|
| 14 |
-
public class BorrowingService : IBorrowingService
|
| 15 |
-
{
|
| 16 |
-
private readonly LibraryManagementContext _context;
|
| 17 |
-
private const decimal FinePerDay = 500;
|
| 18 |
-
|
| 19 |
-
public BorrowingService(LibraryManagementContext context)
|
| 20 |
-
{
|
| 21 |
-
_context = context;
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
-
public async Task<BorrowingDto> BorrowBookAsync(int userId, int bookId)
|
| 25 |
-
{
|
| 26 |
-
// 1. Check for Active Membership
|
| 27 |
-
var subscription = await _context.UserSubscriptions
|
| 28 |
-
.Include(s => s.Membership)
|
| 29 |
-
.Where(s => s.UserId == userId && s.IsActive && s.ExpiryDate > DateTime.UtcNow)
|
| 30 |
-
.FirstOrDefaultAsync();
|
| 31 |
-
|
| 32 |
-
if (subscription == null)
|
| 33 |
-
{
|
| 34 |
-
throw new Exception("Active membership required to borrow books.");
|
| 35 |
-
}
|
| 36 |
-
|
| 37 |
-
// 2. Check for Overdue Books or Unpaid Fines
|
| 38 |
-
var hasBlockers = await _context.Borrowings
|
| 39 |
-
.AnyAsync(b => b.UserId == userId &&
|
| 40 |
-
((b.Status == "Borrowed" && b.DueDate < DateTime.UtcNow) || (b.FineAmount > 0 && !b.IsFinePaid)));
|
| 41 |
-
|
| 42 |
-
if (hasBlockers)
|
| 43 |
-
{
|
| 44 |
-
throw new Exception("Borrowing blocked: You have overdue books or unpaid fines.");
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
// 3. Check MaxBooks limit
|
| 48 |
-
var activeBorrowCount = await _context.Borrowings
|
| 49 |
-
.CountAsync(b => b.UserId == userId && b.Status == "Borrowed");
|
| 50 |
-
|
| 51 |
-
if (activeBorrowCount >= subscription.Membership.MaxBooks)
|
| 52 |
-
{
|
| 53 |
-
throw new Exception($"Borrowing limit reached: You can only borrow {subscription.Membership.MaxBooks} books at a time.");
|
| 54 |
-
}
|
| 55 |
-
|
| 56 |
-
// 4. Check Book Availability
|
| 57 |
-
var book = await _context.Books.FindAsync(bookId);
|
| 58 |
-
if (book == null || !book.IsActive || book.AvailableCopies <= 0)
|
| 59 |
-
{
|
| 60 |
-
throw new Exception("Book is currently unavailable.");
|
| 61 |
-
}
|
| 62 |
-
|
| 63 |
-
// 5. Create Borrowing Record
|
| 64 |
-
var borrowing = new Borrowing
|
| 65 |
-
{
|
| 66 |
-
UserId = userId,
|
| 67 |
-
BookId = bookId,
|
| 68 |
-
BorrowDate = DateTime.UtcNow,
|
| 69 |
-
DueDate = DateTime.UtcNow.AddDays(subscription.Membership.BorrowingDays),
|
| 70 |
-
Status = "Borrowed",
|
| 71 |
-
FineAmount = 0,
|
| 72 |
-
IsFinePaid = false
|
| 73 |
-
};
|
| 74 |
-
|
| 75 |
-
// 6. Update Book Stock
|
| 76 |
-
book.AvailableCopies--;
|
| 77 |
-
if (book.AvailableCopies == 0)
|
| 78 |
-
{
|
| 79 |
-
book.Status = "Out Of Stock";
|
| 80 |
-
}
|
| 81 |
-
|
| 82 |
-
_context.Borrowings.Add(borrowing);
|
| 83 |
-
await _context.SaveChangesAsync();
|
| 84 |
-
|
| 85 |
-
// Load relations for mapping
|
| 86 |
-
await _context.Entry(borrowing).Reference(b => b.Book).LoadAsync();
|
| 87 |
-
await _context.Entry(borrowing).Reference(b => b.User).LoadAsync();
|
| 88 |
-
|
| 89 |
-
return MapToDto(borrowing);
|
| 90 |
-
}
|
| 91 |
-
|
| 92 |
-
public async Task<BorrowingDto> ReturnBookAsync(int borrowingId)
|
| 93 |
-
{
|
| 94 |
-
var borrowing = await _context.Borrowings
|
| 95 |
-
.Include(b => b.Book)
|
| 96 |
-
.Include(b => b.User)
|
| 97 |
-
.FirstOrDefaultAsync(b => b.Id == borrowingId);
|
| 98 |
-
|
| 99 |
-
if (borrowing == null) throw new Exception("Borrowing record not found.");
|
| 100 |
-
if (borrowing.Status == "Returned") throw new Exception("Book has already been returned.");
|
| 101 |
-
|
| 102 |
-
var now = DateTime.UtcNow;
|
| 103 |
-
borrowing.ReturnDate = now;
|
| 104 |
-
borrowing.Status = "Returned";
|
| 105 |
-
|
| 106 |
-
// Calculate Fine
|
| 107 |
-
if (now > borrowing.DueDate)
|
| 108 |
-
{
|
| 109 |
-
var overdueDays = (now.Date - borrowing.DueDate.Date).Days;
|
| 110 |
-
if (overdueDays > 0)
|
| 111 |
-
{
|
| 112 |
-
borrowing.FineAmount = overdueDays * FinePerDay;
|
| 113 |
-
}
|
| 114 |
-
}
|
| 115 |
-
|
| 116 |
-
// Update Book Stock
|
| 117 |
-
var book = borrowing.Book;
|
| 118 |
-
book.AvailableCopies++;
|
| 119 |
-
book.Status = "Available";
|
| 120 |
-
|
| 121 |
-
await _context.SaveChangesAsync();
|
| 122 |
-
return MapToDto(borrowing);
|
| 123 |
-
}
|
| 124 |
-
|
| 125 |
-
public async Task<IEnumerable<BorrowingDto>> GetUserBorrowingsAsync(int userId)
|
| 126 |
-
{
|
| 127 |
-
var borrowings = await _context.Borrowings
|
| 128 |
-
.Include(b => b.Book)
|
| 129 |
-
.Include(b => b.User)
|
| 130 |
-
.Where(b => b.UserId == userId)
|
| 131 |
-
.OrderByDescending(b => b.BorrowDate)
|
| 132 |
-
.ToListAsync();
|
| 133 |
-
|
| 134 |
-
return borrowings.Select(MapToDto);
|
| 135 |
-
}
|
| 136 |
-
|
| 137 |
-
public async Task<IEnumerable<BorrowingDto>> GetAllBorrowingsAsync()
|
| 138 |
-
{
|
| 139 |
-
var borrowings = await _context.Borrowings
|
| 140 |
-
.Include(b => b.Book)
|
| 141 |
-
.Include(b => b.User)
|
| 142 |
-
.OrderByDescending(b => b.BorrowDate)
|
| 143 |
-
.ToListAsync();
|
| 144 |
-
|
| 145 |
-
return borrowings.Select(MapToDto);
|
| 146 |
-
}
|
| 147 |
-
|
| 148 |
-
private static BorrowingDto MapToDto(Borrowing b)
|
| 149 |
-
{
|
| 150 |
-
return new BorrowingDto
|
| 151 |
-
{
|
| 152 |
-
Id = b.Id,
|
| 153 |
-
UserId = b.UserId,
|
| 154 |
-
UserEmail = b.User?.Email ?? "Unknown",
|
| 155 |
-
BookId = b.BookId,
|
| 156 |
-
BookTitle = b.Book?.Title ?? "Unknown",
|
| 157 |
-
BorrowDate = b.BorrowDate,
|
| 158 |
-
DueDate = b.DueDate,
|
| 159 |
-
ReturnDate = b.ReturnDate,
|
| 160 |
-
Status = b.Status,
|
| 161 |
-
FineAmount = b.FineAmount,
|
| 162 |
-
IsFinePaid = b.IsFinePaid
|
| 163 |
-
};
|
| 164 |
-
}
|
| 165 |
-
}
|
| 166 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Categories/CategoryController.cs
DELETED
|
@@ -1,49 +0,0 @@
|
|
| 1 |
-
using Microsoft.AspNetCore.Authorization;
|
| 2 |
-
using Microsoft.AspNetCore.Mvc;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Categories
|
| 5 |
-
{
|
| 6 |
-
[ApiController]
|
| 7 |
-
[Route("api/categories")]
|
| 8 |
-
public class CategoryController : ControllerBase
|
| 9 |
-
{
|
| 10 |
-
private readonly ICategoryService _categoryService;
|
| 11 |
-
|
| 12 |
-
public CategoryController(ICategoryService categoryService)
|
| 13 |
-
{
|
| 14 |
-
_categoryService = categoryService;
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
[HttpGet]
|
| 18 |
-
//[Authorize] // Accessible by both Librarian and Member
|
| 19 |
-
public async Task<ActionResult<IEnumerable<CategoryDto>>> GetCategories()
|
| 20 |
-
{
|
| 21 |
-
var categories = await _categoryService.GetAllCategoriesAsync();
|
| 22 |
-
return Ok(categories);
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
[HttpPost]
|
| 26 |
-
//[Authorize(Roles = "Librarian")]
|
| 27 |
-
public async Task<ActionResult<CategoryDto>> CreateCategory([FromBody] CategoryCreateRequest request)
|
| 28 |
-
{
|
| 29 |
-
try
|
| 30 |
-
{
|
| 31 |
-
var category = await _categoryService.CreateCategoryAsync(request);
|
| 32 |
-
return CreatedAtAction(nameof(GetCategories), category);
|
| 33 |
-
}
|
| 34 |
-
catch (Exception ex)
|
| 35 |
-
{
|
| 36 |
-
return BadRequest(new { message = ex.Message });
|
| 37 |
-
}
|
| 38 |
-
}
|
| 39 |
-
|
| 40 |
-
[HttpDelete("{id}")]
|
| 41 |
-
//[Authorize(Roles = "Librarian")]
|
| 42 |
-
public async Task<IActionResult> DeleteCategory(int id)
|
| 43 |
-
{
|
| 44 |
-
var success = await _categoryService.DeleteCategoryAsync(id);
|
| 45 |
-
if (!success) return NotFound();
|
| 46 |
-
return NoContent();
|
| 47 |
-
}
|
| 48 |
-
}
|
| 49 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Categories/CategoryService.cs
DELETED
|
@@ -1,69 +0,0 @@
|
|
| 1 |
-
using Database.Models;
|
| 2 |
-
using Microsoft.EntityFrameworkCore;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Categories
|
| 5 |
-
{
|
| 6 |
-
public interface ICategoryService
|
| 7 |
-
{
|
| 8 |
-
Task<IEnumerable<CategoryDto>> GetAllCategoriesAsync();
|
| 9 |
-
Task<CategoryDto> CreateCategoryAsync(CategoryCreateRequest request);
|
| 10 |
-
Task<bool> DeleteCategoryAsync(int id);
|
| 11 |
-
}
|
| 12 |
-
|
| 13 |
-
public class CategoryService : ICategoryService
|
| 14 |
-
{
|
| 15 |
-
private readonly LibraryManagementContext _context;
|
| 16 |
-
|
| 17 |
-
public CategoryService(LibraryManagementContext context)
|
| 18 |
-
{
|
| 19 |
-
_context = context;
|
| 20 |
-
}
|
| 21 |
-
|
| 22 |
-
public async Task<IEnumerable<CategoryDto>> GetAllCategoriesAsync()
|
| 23 |
-
{
|
| 24 |
-
return await _context.Categories
|
| 25 |
-
.Select(c => new CategoryDto { Id = c.Id, Name = c.Name })
|
| 26 |
-
.ToListAsync();
|
| 27 |
-
}
|
| 28 |
-
|
| 29 |
-
public async Task<CategoryDto> CreateCategoryAsync(CategoryCreateRequest request)
|
| 30 |
-
{
|
| 31 |
-
if (await _context.Categories.AnyAsync(c => c.Name == request.Name))
|
| 32 |
-
{
|
| 33 |
-
throw new Exception("Category with this name already exists.");
|
| 34 |
-
}
|
| 35 |
-
|
| 36 |
-
var category = new Category
|
| 37 |
-
{
|
| 38 |
-
Name = request.Name
|
| 39 |
-
};
|
| 40 |
-
|
| 41 |
-
_context.Categories.Add(category);
|
| 42 |
-
await _context.SaveChangesAsync();
|
| 43 |
-
|
| 44 |
-
return new CategoryDto { Id = category.Id, Name = category.Name };
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
public async Task<bool> DeleteCategoryAsync(int id)
|
| 48 |
-
{
|
| 49 |
-
var category = await _context.Categories.FindAsync(id);
|
| 50 |
-
if (category == null) return false;
|
| 51 |
-
|
| 52 |
-
// Note: EF automatically handles removing associations in many-to-many join tables
|
| 53 |
-
_context.Categories.Remove(category);
|
| 54 |
-
await _context.SaveChangesAsync();
|
| 55 |
-
return true;
|
| 56 |
-
}
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
-
public class CategoryDto
|
| 60 |
-
{
|
| 61 |
-
public int Id { get; set; }
|
| 62 |
-
public string Name { get; set; } = string.Empty;
|
| 63 |
-
}
|
| 64 |
-
|
| 65 |
-
public class CategoryCreateRequest
|
| 66 |
-
{
|
| 67 |
-
public string Name { get; set; } = string.Empty;
|
| 68 |
-
}
|
| 69 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Subscriptions/SubscriptionController.cs
DELETED
|
@@ -1,84 +0,0 @@
|
|
| 1 |
-
using Microsoft.AspNetCore.Authorization;
|
| 2 |
-
using Microsoft.AspNetCore.Mvc;
|
| 3 |
-
using System.Security.Claims;
|
| 4 |
-
|
| 5 |
-
namespace LibraryManagement.Backend.Features.Subscriptions
|
| 6 |
-
{
|
| 7 |
-
[ApiController]
|
| 8 |
-
[Route("api")]
|
| 9 |
-
public class SubscriptionController : ControllerBase
|
| 10 |
-
{
|
| 11 |
-
private readonly ISubscriptionService _subscriptionService;
|
| 12 |
-
|
| 13 |
-
public SubscriptionController(ISubscriptionService subscriptionService)
|
| 14 |
-
{
|
| 15 |
-
_subscriptionService = subscriptionService;
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
[HttpGet("memberships")]
|
| 19 |
-
[AllowAnonymous]
|
| 20 |
-
public async Task<ActionResult<IEnumerable<MembershipDto>>> GetMemberships()
|
| 21 |
-
{
|
| 22 |
-
return Ok(await _subscriptionService.GetMembershipsAsync());
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
[HttpGet("subscriptions/me")]
|
| 26 |
-
[Authorize]
|
| 27 |
-
public async Task<ActionResult<SubscriptionDto>> GetMySubscription()
|
| 28 |
-
{
|
| 29 |
-
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
| 30 |
-
if (string.IsNullOrEmpty(userIdStr)) return Unauthorized();
|
| 31 |
-
|
| 32 |
-
var userId = int.Parse(userIdStr);
|
| 33 |
-
var subscription = await _subscriptionService.GetUserSubscriptionAsync(userId);
|
| 34 |
-
|
| 35 |
-
if (subscription == null) return NotFound(new { message = "No active subscription found." });
|
| 36 |
-
|
| 37 |
-
return Ok(subscription);
|
| 38 |
-
}
|
| 39 |
-
|
| 40 |
-
[HttpPost("subscriptions/subscribe")]
|
| 41 |
-
[Authorize]
|
| 42 |
-
public async Task<ActionResult<SubscriptionDto>> Subscribe([FromBody] SubscribeRequest request)
|
| 43 |
-
{
|
| 44 |
-
try
|
| 45 |
-
{
|
| 46 |
-
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
| 47 |
-
if (string.IsNullOrEmpty(userIdStr)) return Unauthorized();
|
| 48 |
-
|
| 49 |
-
var userId = int.Parse(userIdStr);
|
| 50 |
-
var subscription = await _subscriptionService.SubscribeUserAsync(userId, request.MembershipId);
|
| 51 |
-
return Ok(subscription);
|
| 52 |
-
}
|
| 53 |
-
catch (Exception ex)
|
| 54 |
-
{
|
| 55 |
-
return BadRequest(new { message = ex.Message });
|
| 56 |
-
}
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
-
[HttpGet("subscriptions/user/{userId}")]
|
| 60 |
-
[Authorize(Roles = "Admin")]
|
| 61 |
-
public async Task<ActionResult<SubscriptionDto>> GetUserSubscription(int userId)
|
| 62 |
-
{
|
| 63 |
-
var subscription = await _subscriptionService.GetUserSubscriptionAsync(userId);
|
| 64 |
-
if (subscription == null) return NotFound(new { message = "No active subscription found." });
|
| 65 |
-
|
| 66 |
-
return Ok(subscription);
|
| 67 |
-
}
|
| 68 |
-
|
| 69 |
-
[HttpPost("subscriptions/admin-subscribe")]
|
| 70 |
-
[Authorize(Roles = "Admin")]
|
| 71 |
-
public async Task<ActionResult<SubscriptionDto>> AdminSubscribe([FromBody] AdminSubscribeRequest request)
|
| 72 |
-
{
|
| 73 |
-
try
|
| 74 |
-
{
|
| 75 |
-
var subscription = await _subscriptionService.SubscribeUserAsync(request.UserId, request.MembershipId);
|
| 76 |
-
return Ok(subscription);
|
| 77 |
-
}
|
| 78 |
-
catch (Exception ex)
|
| 79 |
-
{
|
| 80 |
-
return BadRequest(new { message = ex.Message });
|
| 81 |
-
}
|
| 82 |
-
}
|
| 83 |
-
}
|
| 84 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Subscriptions/SubscriptionModels.cs
DELETED
|
@@ -1,38 +0,0 @@
|
|
| 1 |
-
using System;
|
| 2 |
-
|
| 3 |
-
namespace LibraryManagement.Backend.Features.Subscriptions
|
| 4 |
-
{
|
| 5 |
-
public class MembershipDto
|
| 6 |
-
{
|
| 7 |
-
public int Id { get; set; }
|
| 8 |
-
public string Type { get; set; } = string.Empty;
|
| 9 |
-
public int MaxBooks { get; set; }
|
| 10 |
-
public int BorrowingDays { get; set; }
|
| 11 |
-
public decimal Price { get; set; }
|
| 12 |
-
public string Currency { get; set; } = "MMK";
|
| 13 |
-
public int DurationMonths { get; set; }
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
public class SubscriptionDto
|
| 17 |
-
{
|
| 18 |
-
public int Id { get; set; }
|
| 19 |
-
public int UserId { get; set; }
|
| 20 |
-
public int MembershipId { get; set; }
|
| 21 |
-
public string MembershipType { get; set; } = string.Empty;
|
| 22 |
-
public DateTime StartDate { get; set; }
|
| 23 |
-
public DateTime ExpiryDate { get; set; }
|
| 24 |
-
public bool IsActive { get; set; }
|
| 25 |
-
public bool IsExpired => DateTime.UtcNow > ExpiryDate;
|
| 26 |
-
}
|
| 27 |
-
|
| 28 |
-
public class SubscribeRequest
|
| 29 |
-
{
|
| 30 |
-
public int MembershipId { get; set; }
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
public class AdminSubscribeRequest
|
| 34 |
-
{
|
| 35 |
-
public int UserId { get; set; }
|
| 36 |
-
public int MembershipId { get; set; }
|
| 37 |
-
}
|
| 38 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Subscriptions/SubscriptionService.cs
DELETED
|
@@ -1,96 +0,0 @@
|
|
| 1 |
-
using Database.Models;
|
| 2 |
-
using Microsoft.EntityFrameworkCore;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Subscriptions
|
| 5 |
-
{
|
| 6 |
-
public interface ISubscriptionService
|
| 7 |
-
{
|
| 8 |
-
Task<IEnumerable<MembershipDto>> GetMembershipsAsync();
|
| 9 |
-
Task<SubscriptionDto?> GetUserSubscriptionAsync(int userId);
|
| 10 |
-
Task<SubscriptionDto> SubscribeUserAsync(int userId, int membershipId);
|
| 11 |
-
}
|
| 12 |
-
|
| 13 |
-
public class SubscriptionService : ISubscriptionService
|
| 14 |
-
{
|
| 15 |
-
private readonly LibraryManagementContext _context;
|
| 16 |
-
|
| 17 |
-
public SubscriptionService(LibraryManagementContext context)
|
| 18 |
-
{
|
| 19 |
-
_context = context;
|
| 20 |
-
}
|
| 21 |
-
|
| 22 |
-
public async Task<IEnumerable<MembershipDto>> GetMembershipsAsync()
|
| 23 |
-
{
|
| 24 |
-
return await _context.Memberships
|
| 25 |
-
.Select(m => new MembershipDto
|
| 26 |
-
{
|
| 27 |
-
Id = m.Id,
|
| 28 |
-
Type = m.Type,
|
| 29 |
-
MaxBooks = m.MaxBooks,
|
| 30 |
-
BorrowingDays = m.BorrowingDays,
|
| 31 |
-
Price = m.Price,
|
| 32 |
-
DurationMonths = m.DurationMonths
|
| 33 |
-
}).ToListAsync();
|
| 34 |
-
}
|
| 35 |
-
|
| 36 |
-
public async Task<SubscriptionDto?> GetUserSubscriptionAsync(int userId)
|
| 37 |
-
{
|
| 38 |
-
var subscription = await _context.UserSubscriptions
|
| 39 |
-
.Include(s => s.Membership)
|
| 40 |
-
.Where(s => s.UserId == userId && s.IsActive)
|
| 41 |
-
.OrderByDescending(s => s.StartDate)
|
| 42 |
-
.FirstOrDefaultAsync();
|
| 43 |
-
|
| 44 |
-
if (subscription == null) return null;
|
| 45 |
-
|
| 46 |
-
return MapToDto(subscription);
|
| 47 |
-
}
|
| 48 |
-
|
| 49 |
-
public async Task<SubscriptionDto> SubscribeUserAsync(int userId, int membershipId)
|
| 50 |
-
{
|
| 51 |
-
var membership = await _context.Memberships.FindAsync(membershipId);
|
| 52 |
-
if (membership == null) throw new Exception("Membership plan not found.");
|
| 53 |
-
|
| 54 |
-
// Deactivate any existing active subscriptions for this user
|
| 55 |
-
var activeSubscriptions = await _context.UserSubscriptions
|
| 56 |
-
.Where(s => s.UserId == userId && s.IsActive)
|
| 57 |
-
.ToListAsync();
|
| 58 |
-
|
| 59 |
-
foreach (var s in activeSubscriptions)
|
| 60 |
-
{
|
| 61 |
-
s.IsActive = false;
|
| 62 |
-
}
|
| 63 |
-
|
| 64 |
-
var subscription = new UserSubscription
|
| 65 |
-
{
|
| 66 |
-
UserId = userId,
|
| 67 |
-
MembershipId = membershipId,
|
| 68 |
-
StartDate = DateTime.UtcNow,
|
| 69 |
-
ExpiryDate = DateTime.UtcNow.AddMonths(membership.DurationMonths),
|
| 70 |
-
IsActive = true
|
| 71 |
-
};
|
| 72 |
-
|
| 73 |
-
_context.UserSubscriptions.Add(subscription);
|
| 74 |
-
await _context.SaveChangesAsync();
|
| 75 |
-
|
| 76 |
-
// Explicitly load the membership data for the DTO mapping
|
| 77 |
-
await _context.Entry(subscription).Reference(s => s.Membership).LoadAsync();
|
| 78 |
-
|
| 79 |
-
return MapToDto(subscription);
|
| 80 |
-
}
|
| 81 |
-
|
| 82 |
-
private static SubscriptionDto MapToDto(UserSubscription subscription)
|
| 83 |
-
{
|
| 84 |
-
return new SubscriptionDto
|
| 85 |
-
{
|
| 86 |
-
Id = subscription.Id,
|
| 87 |
-
UserId = subscription.UserId,
|
| 88 |
-
MembershipId = subscription.MembershipId,
|
| 89 |
-
MembershipType = subscription.Membership.Type,
|
| 90 |
-
StartDate = subscription.StartDate,
|
| 91 |
-
ExpiryDate = subscription.ExpiryDate,
|
| 92 |
-
IsActive = subscription.IsActive
|
| 93 |
-
};
|
| 94 |
-
}
|
| 95 |
-
}
|
| 96 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Users/UserController.cs
DELETED
|
@@ -1,77 +0,0 @@
|
|
| 1 |
-
using Microsoft.AspNetCore.Authorization;
|
| 2 |
-
using Microsoft.AspNetCore.Mvc;
|
| 3 |
-
|
| 4 |
-
namespace LibraryManagement.Backend.Features.Users
|
| 5 |
-
{
|
| 6 |
-
[ApiController]
|
| 7 |
-
[Route("api/users")]
|
| 8 |
-
public class UserController : ControllerBase
|
| 9 |
-
{
|
| 10 |
-
private readonly IUserService _userService;
|
| 11 |
-
|
| 12 |
-
public UserController(IUserService userService)
|
| 13 |
-
{
|
| 14 |
-
_userService = userService;
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
[HttpGet]
|
| 18 |
-
//[Authorize(Roles = "Librarian")]
|
| 19 |
-
public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers()
|
| 20 |
-
{
|
| 21 |
-
var users = await _userService.GetAllUsersAsync();
|
| 22 |
-
return Ok(users);
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
[HttpGet("{id}")]
|
| 26 |
-
//[Authorize(Roles = "Librarian")]
|
| 27 |
-
public async Task<ActionResult<UserDto>> GetUser(int id)
|
| 28 |
-
{
|
| 29 |
-
var user = await _userService.GetUserByIdAsync(id);
|
| 30 |
-
if (user == null) return NotFound();
|
| 31 |
-
return Ok(user);
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
[HttpPost]
|
| 35 |
-
[AllowAnonymous]
|
| 36 |
-
public async Task<ActionResult<UserDto>> CreateUser([FromBody] UserCreateRequest request)
|
| 37 |
-
{
|
| 38 |
-
try
|
| 39 |
-
{
|
| 40 |
-
var response = await _userService.CreateUserAsync(request);
|
| 41 |
-
return CreatedAtAction(nameof(GetUser), new { id = response.Id }, response);
|
| 42 |
-
}
|
| 43 |
-
catch (Exception ex)
|
| 44 |
-
{
|
| 45 |
-
return BadRequest(new { message = ex.Message });
|
| 46 |
-
}
|
| 47 |
-
}
|
| 48 |
-
|
| 49 |
-
[HttpPut("{id}")]
|
| 50 |
-
//[Authorize(Roles = "Librarian")]
|
| 51 |
-
public async Task<ActionResult<UserDto>> UpdateUser(int id, [FromBody] UserUpdateRequest request)
|
| 52 |
-
{
|
| 53 |
-
var updatedUser = await _userService.UpdateUserAsync(id, request);
|
| 54 |
-
if (updatedUser == null) return NotFound();
|
| 55 |
-
return Ok(updatedUser);
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
[HttpPatch("{id}/role")]
|
| 59 |
-
//[Authorize(Roles = "Librarian")]
|
| 60 |
-
public async Task<IActionResult> UpdateUserRole(int id, [FromBody] UserRoleUpdateRequest request)
|
| 61 |
-
{
|
| 62 |
-
var success = await _userService.UpdateUserRoleAsync(id, request.Role);
|
| 63 |
-
if (!success) return NotFound();
|
| 64 |
-
return NoContent();
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
[HttpDelete("{id}")]
|
| 68 |
-
//[Authorize(Roles = "Librarian")]
|
| 69 |
-
public async Task<IActionResult> DeleteUser(int id)
|
| 70 |
-
{
|
| 71 |
-
var success = await _userService.DeleteUserAsync(id);
|
| 72 |
-
if (!success) return NotFound();
|
| 73 |
-
return NoContent();
|
| 74 |
-
}
|
| 75 |
-
}
|
| 76 |
-
}
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Features/Users/UserService.cs
DELETED
|
@@ -1,182 +0,0 @@
|
|
| 1 |
-
using Database.Models;
|
| 2 |
-
using Microsoft.EntityFrameworkCore;
|
| 3 |
-
using LibraryManagement.Backend.Features.Subscriptions;
|
| 4 |
-
using System;
|
| 5 |
-
using System.Collections.Generic;
|
| 6 |
-
using System.Linq;
|
| 7 |
-
using System.Threading.Tasks;
|
| 8 |
-
|
| 9 |
-
namespace LibraryManagement.Backend.Features.Users
|
| 10 |
-
{
|
| 11 |
-
public interface IUserService
|
| 12 |
-
{
|
| 13 |
-
Task<IEnumerable<UserDto>> GetAllUsersAsync();
|
| 14 |
-
Task<UserDto?> GetUserByIdAsync(int id);
|
| 15 |
-
Task<UserDto> CreateUserAsync(UserCreateRequest request);
|
| 16 |
-
Task<UserDto?> UpdateUserAsync(int id, UserUpdateRequest request);
|
| 17 |
-
Task<bool> UpdateUserRoleAsync(int id, string role);
|
| 18 |
-
Task<bool> DeleteUserAsync(int id);
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
public class UserService : IUserService
|
| 22 |
-
{
|
| 23 |
-
private readonly LibraryManagementContext _context;
|
| 24 |
-
private readonly ISubscriptionService _subscriptionService;
|
| 25 |
-
|
| 26 |
-
public UserService(LibraryManagementContext context, ISubscriptionService subscriptionService)
|
| 27 |
-
{
|
| 28 |
-
_context = context;
|
| 29 |
-
_subscriptionService = subscriptionService;
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
public async Task<IEnumerable<UserDto>> GetAllUsersAsync()
|
| 33 |
-
{
|
| 34 |
-
var users = await _context.Users.ToListAsync();
|
| 35 |
-
return users.Select(MapToDto);
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
public async Task<UserDto?> GetUserByIdAsync(int id)
|
| 39 |
-
{
|
| 40 |
-
var user = await _context.Users.FindAsync(id);
|
| 41 |
-
return user == null ? null : MapToDto(user);
|
| 42 |
-
}
|
| 43 |
-
|
| 44 |
-
public async Task<UserDto> CreateUserAsync(UserCreateRequest request)
|
| 45 |
-
{
|
| 46 |
-
if (await _context.Users.AnyAsync(u => u.Email == request.Email))
|
| 47 |
-
{
|
| 48 |
-
throw new Exception("Email already registered.");
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
var user = new User
|
| 52 |
-
{
|
| 53 |
-
FullName = request.FullName,
|
| 54 |
-
Email = request.Email,
|
| 55 |
-
PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password),
|
| 56 |
-
PhoneNumber = request.PhoneNumber,
|
| 57 |
-
Address = request.Address,
|
| 58 |
-
StudentId = request.StudentId,
|
| 59 |
-
Role = "Member", // Default role
|
| 60 |
-
IsActive = true,
|
| 61 |
-
CreatedAt = DateTime.UtcNow
|
| 62 |
-
};
|
| 63 |
-
|
| 64 |
-
_context.Users.Add(user);
|
| 65 |
-
await _context.SaveChangesAsync();
|
| 66 |
-
|
| 67 |
-
if (!string.IsNullOrEmpty(user.StudentId))
|
| 68 |
-
{
|
| 69 |
-
await _subscriptionService.SubscribeUserAsync(user.Id, 3); // 3 is "Basic Yearly"
|
| 70 |
-
}
|
| 71 |
-
|
| 72 |
-
return MapToDto(user);
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
public async Task<UserDto?> UpdateUserAsync(int id, UserUpdateRequest request)
|
| 76 |
-
{
|
| 77 |
-
var user = await _context.Users.FindAsync(id);
|
| 78 |
-
if (user == null) return null;
|
| 79 |
-
|
| 80 |
-
bool isNewlyStudent = string.IsNullOrEmpty(user.StudentId) && !string.IsNullOrEmpty(request.StudentId);
|
| 81 |
-
|
| 82 |
-
user.FullName = request.FullName;
|
| 83 |
-
user.PhoneNumber = request.PhoneNumber;
|
| 84 |
-
user.Address = request.Address;
|
| 85 |
-
user.StudentId = request.StudentId;
|
| 86 |
-
user.UpdatedAt = DateTime.UtcNow;
|
| 87 |
-
|
| 88 |
-
await _context.SaveChangesAsync();
|
| 89 |
-
|
| 90 |
-
if (isNewlyStudent)
|
| 91 |
-
{
|
| 92 |
-
await _subscriptionService.SubscribeUserAsync(user.Id, 3);
|
| 93 |
-
}
|
| 94 |
-
|
| 95 |
-
return MapToDto(user);
|
| 96 |
-
}
|
| 97 |
-
|
| 98 |
-
public async Task<bool> UpdateUserRoleAsync(int id, string role)
|
| 99 |
-
{
|
| 100 |
-
var user = await _context.Users.FindAsync(id);
|
| 101 |
-
if (user == null) return false;
|
| 102 |
-
|
| 103 |
-
user.Role = role;
|
| 104 |
-
user.UpdatedAt = DateTime.UtcNow;
|
| 105 |
-
|
| 106 |
-
await _context.SaveChangesAsync();
|
| 107 |
-
return true;
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
public async Task<bool> DeleteUserAsync(int id)
|
| 111 |
-
{
|
| 112 |
-
var user = await _context.Users.FindAsync(id);
|
| 113 |
-
if (user == null) return false;
|
| 114 |
-
|
| 115 |
-
// Soft delete
|
| 116 |
-
user.IsActive = false;
|
| 117 |
-
user.UpdatedAt = DateTime.UtcNow;
|
| 118 |
-
|
| 119 |
-
await _context.SaveChangesAsync();
|
| 120 |
-
return true;
|
| 121 |
-
}
|
| 122 |
-
|
| 123 |
-
private static UserDto MapToDto(User user)
|
| 124 |
-
{
|
| 125 |
-
return new UserDto
|
| 126 |
-
{
|
| 127 |
-
Id = user.Id,
|
| 128 |
-
FullName = user.FullName,
|
| 129 |
-
Email = user.Email,
|
| 130 |
-
PhoneNumber = user.PhoneNumber,
|
| 131 |
-
Role = user.Role,
|
| 132 |
-
IsActive = user.IsActive,
|
| 133 |
-
StudentId = user.StudentId,
|
| 134 |
-
Address = user.Address,
|
| 135 |
-
CreatedAt = user.CreatedAt,
|
| 136 |
-
UpdatedAt = user.UpdatedAt,
|
| 137 |
-
BanStatus = user.BanStatus,
|
| 138 |
-
SuspensionEndDate = user.SuspensionEndDate
|
| 139 |
-
};
|
| 140 |
-
}
|
| 141 |
-
}
|
| 142 |
-
|
| 143 |
-
public class UserDto
|
| 144 |
-
{
|
| 145 |
-
public int Id { get; set; }
|
| 146 |
-
public string Name => FullName;
|
| 147 |
-
public string FullName { get; set; } = string.Empty;
|
| 148 |
-
public string Email { get; set; } = string.Empty;
|
| 149 |
-
public string? PhoneNumber { get; set; }
|
| 150 |
-
public string Role { get; set; } = string.Empty;
|
| 151 |
-
public bool IsActive { get; set; }
|
| 152 |
-
public string? StudentId { get; set; }
|
| 153 |
-
public string? Address { get; set; }
|
| 154 |
-
public DateTime CreatedAt { get; set; }
|
| 155 |
-
public DateTime? UpdatedAt { get; set; }
|
| 156 |
-
public bool? BanStatus { get; set; }
|
| 157 |
-
public DateTime? SuspensionEndDate { get; set; }
|
| 158 |
-
}
|
| 159 |
-
|
| 160 |
-
public class UserCreateRequest
|
| 161 |
-
{
|
| 162 |
-
public string FullName { get; set; } = string.Empty;
|
| 163 |
-
public string Email { get; set; } = string.Empty;
|
| 164 |
-
public string Password { get; set; } = string.Empty;
|
| 165 |
-
public string? PhoneNumber { get; set; }
|
| 166 |
-
public string? StudentId { get; set; }
|
| 167 |
-
public string? Address { get; set; }
|
| 168 |
-
}
|
| 169 |
-
|
| 170 |
-
public class UserUpdateRequest
|
| 171 |
-
{
|
| 172 |
-
public string FullName { get; set; } = string.Empty;
|
| 173 |
-
public string? PhoneNumber { get; set; }
|
| 174 |
-
public string? StudentId { get; set; }
|
| 175 |
-
public string? Address { get; set; }
|
| 176 |
-
}
|
| 177 |
-
|
| 178 |
-
public class UserRoleUpdateRequest
|
| 179 |
-
{
|
| 180 |
-
public string Role { get; set; } = string.Empty;
|
| 181 |
-
}
|
| 182 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/LibraryManagement.Backend.csproj
DELETED
|
@@ -1,20 +0,0 @@
|
|
| 1 |
-
<Project Sdk="Microsoft.NET.Sdk.Web">
|
| 2 |
-
|
| 3 |
-
<PropertyGroup>
|
| 4 |
-
<TargetFramework>net8.0</TargetFramework>
|
| 5 |
-
<Nullable>enable</Nullable>
|
| 6 |
-
<ImplicitUsings>enable</ImplicitUsings>
|
| 7 |
-
</PropertyGroup>
|
| 8 |
-
|
| 9 |
-
<ItemGroup>
|
| 10 |
-
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
|
| 11 |
-
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.13" />
|
| 12 |
-
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
| 13 |
-
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.17.0" />
|
| 14 |
-
</ItemGroup>
|
| 15 |
-
|
| 16 |
-
<ItemGroup>
|
| 17 |
-
<ProjectReference Include="..\Database\Database.csproj" />
|
| 18 |
-
</ItemGroup>
|
| 19 |
-
|
| 20 |
-
</Project>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/LibraryManagement.Backend.http
DELETED
|
@@ -1,6 +0,0 @@
|
|
| 1 |
-
@LibraryManagement.Backend_HostAddress = http://localhost:5199
|
| 2 |
-
|
| 3 |
-
GET {{LibraryManagement.Backend_HostAddress}}/weatherforecast/
|
| 4 |
-
Accept: application/json
|
| 5 |
-
|
| 6 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Program.cs
DELETED
|
@@ -1,91 +0,0 @@
|
|
| 1 |
-
using System.Text;
|
| 2 |
-
using Database.Models;
|
| 3 |
-
using LibraryManagement.Backend.Features.Auth;
|
| 4 |
-
using LibraryManagement.Backend.Features.Users;
|
| 5 |
-
using LibraryManagement.Backend.Features.Books;
|
| 6 |
-
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
| 7 |
-
using Microsoft.EntityFrameworkCore;
|
| 8 |
-
using Microsoft.IdentityModel.Tokens;
|
| 9 |
-
using Microsoft.OpenApi.Models;
|
| 10 |
-
using LibraryManagement.Backend.Features.Subscriptions;
|
| 11 |
-
using LibraryManagement.Backend.Features.Categories;
|
| 12 |
-
using LibraryManagement.Backend.Features.Borrowings;
|
| 13 |
-
|
| 14 |
-
var builder = WebApplication.CreateBuilder(args);
|
| 15 |
-
|
| 16 |
-
builder.Services.AddControllers();
|
| 17 |
-
builder.Services.AddAuthorization();
|
| 18 |
-
builder.Services.AddEndpointsApiExplorer();
|
| 19 |
-
builder.Services.AddSwaggerGen(c =>
|
| 20 |
-
{
|
| 21 |
-
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Library Management API", Version = "v1" });
|
| 22 |
-
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
| 23 |
-
{
|
| 24 |
-
Description = "JWT Authorization header using the Bearer scheme.",
|
| 25 |
-
Name = "Authorization",
|
| 26 |
-
In = ParameterLocation.Header,
|
| 27 |
-
Type = SecuritySchemeType.Http,
|
| 28 |
-
Scheme = "bearer",
|
| 29 |
-
BearerFormat = "JWT"
|
| 30 |
-
});
|
| 31 |
-
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
| 32 |
-
{
|
| 33 |
-
{
|
| 34 |
-
new OpenApiSecurityScheme
|
| 35 |
-
{
|
| 36 |
-
Reference = new OpenApiReference
|
| 37 |
-
{
|
| 38 |
-
Type = ReferenceType.SecurityScheme,
|
| 39 |
-
Id = "Bearer"
|
| 40 |
-
}
|
| 41 |
-
},
|
| 42 |
-
new string[] {}
|
| 43 |
-
}
|
| 44 |
-
});
|
| 45 |
-
});
|
| 46 |
-
|
| 47 |
-
builder.Services.AddDbContext<LibraryManagementContext>(options =>
|
| 48 |
-
options.UseSqlServer(builder.Configuration.GetConnectionString("MssqlConnection")));
|
| 49 |
-
|
| 50 |
-
// Register Services
|
| 51 |
-
builder.Services.AddScoped<IAuthService, AuthService>();
|
| 52 |
-
builder.Services.AddScoped<IUserService, UserService>();
|
| 53 |
-
builder.Services.AddScoped<IBookService, BookService>();
|
| 54 |
-
builder.Services.AddScoped<ISubscriptionService, SubscriptionService>();
|
| 55 |
-
builder.Services.AddScoped<ICategoryService, CategoryService>();
|
| 56 |
-
builder.Services.AddScoped<IBorrowingService, BorrowingService>();
|
| 57 |
-
|
| 58 |
-
// Configure JWT Authentication
|
| 59 |
-
var key = Encoding.ASCII.GetBytes(builder.Configuration["Jwt:Secret"] ?? "YourSuperSecretKeyForLibraryManagementSystem_AtLeast32CharsLong");
|
| 60 |
-
builder.Services.AddAuthentication(x =>
|
| 61 |
-
{
|
| 62 |
-
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
| 63 |
-
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
| 64 |
-
})
|
| 65 |
-
.AddJwtBearer(x =>
|
| 66 |
-
{
|
| 67 |
-
x.RequireHttpsMetadata = false;
|
| 68 |
-
x.SaveToken = true;
|
| 69 |
-
x.TokenValidationParameters = new TokenValidationParameters
|
| 70 |
-
{
|
| 71 |
-
ValidateIssuerSigningKey = true,
|
| 72 |
-
IssuerSigningKey = new SymmetricSecurityKey(key),
|
| 73 |
-
ValidateIssuer = true,
|
| 74 |
-
ValidateAudience = true,
|
| 75 |
-
ValidIssuer = builder.Configuration["Jwt:Issuer"],
|
| 76 |
-
ValidAudience = builder.Configuration["Jwt:Audience"],
|
| 77 |
-
ClockSkew = TimeSpan.Zero
|
| 78 |
-
};
|
| 79 |
-
});
|
| 80 |
-
|
| 81 |
-
var app = builder.Build();
|
| 82 |
-
|
| 83 |
-
app.UseSwagger();
|
| 84 |
-
app.UseSwaggerUI();
|
| 85 |
-
app.UseAuthentication();
|
| 86 |
-
app.UseAuthorization();
|
| 87 |
-
|
| 88 |
-
app.MapControllers();
|
| 89 |
-
|
| 90 |
-
app.Run();
|
| 91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/Properties/launchSettings.json
DELETED
|
@@ -1,41 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"$schema": "http://json.schemastore.org/launchsettings.json",
|
| 3 |
-
"iisSettings": {
|
| 4 |
-
"windowsAuthentication": false,
|
| 5 |
-
"anonymousAuthentication": true,
|
| 6 |
-
"iisExpress": {
|
| 7 |
-
"applicationUrl": "http://localhost:13110",
|
| 8 |
-
"sslPort": 44374
|
| 9 |
-
}
|
| 10 |
-
},
|
| 11 |
-
"profiles": {
|
| 12 |
-
"http": {
|
| 13 |
-
"commandName": "Project",
|
| 14 |
-
"dotnetRunMessages": true,
|
| 15 |
-
"launchBrowser": true,
|
| 16 |
-
"launchUrl": "swagger",
|
| 17 |
-
"applicationUrl": "http://localhost:5001",
|
| 18 |
-
"environmentVariables": {
|
| 19 |
-
"ASPNETCORE_ENVIRONMENT": "Development"
|
| 20 |
-
}
|
| 21 |
-
},
|
| 22 |
-
"https": {
|
| 23 |
-
"commandName": "Project",
|
| 24 |
-
"dotnetRunMessages": true,
|
| 25 |
-
"launchBrowser": true,
|
| 26 |
-
"launchUrl": "swagger",
|
| 27 |
-
"applicationUrl": "https://localhost:7028;http://localhost:5199",
|
| 28 |
-
"environmentVariables": {
|
| 29 |
-
"ASPNETCORE_ENVIRONMENT": "Development"
|
| 30 |
-
}
|
| 31 |
-
},
|
| 32 |
-
"IIS Express": {
|
| 33 |
-
"commandName": "IISExpress",
|
| 34 |
-
"launchBrowser": true,
|
| 35 |
-
"launchUrl": "swagger",
|
| 36 |
-
"environmentVariables": {
|
| 37 |
-
"ASPNETCORE_ENVIRONMENT": "Development"
|
| 38 |
-
}
|
| 39 |
-
}
|
| 40 |
-
}
|
| 41 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/WeatherForecast.cs
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
namespace LibraryManagement.Backend
|
| 2 |
-
{
|
| 3 |
-
public class WeatherForecast
|
| 4 |
-
{
|
| 5 |
-
public DateOnly Date { get; set; }
|
| 6 |
-
|
| 7 |
-
public int TemperatureC { get; set; }
|
| 8 |
-
|
| 9 |
-
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
| 10 |
-
|
| 11 |
-
public string? Summary { get; set; }
|
| 12 |
-
}
|
| 13 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/appsettings.Development.json
DELETED
|
@@ -1,8 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"Logging": {
|
| 3 |
-
"LogLevel": {
|
| 4 |
-
"Default": "Information",
|
| 5 |
-
"Microsoft.AspNetCore": "Warning"
|
| 6 |
-
}
|
| 7 |
-
}
|
| 8 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LibraryManagement.Backend/appsettings.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"Logging": {
|
| 3 |
-
"LogLevel": {
|
| 4 |
-
"Default": "Information",
|
| 5 |
-
"Microsoft.AspNetCore": "Warning"
|
| 6 |
-
}
|
| 7 |
-
},
|
| 8 |
-
"AllowedHosts": "*",
|
| 9 |
-
"ConnectionStrings": {
|
| 10 |
-
//"MssqlConnection": "Server=DESKTOP-BP9A061;Database=LibraryManagement;User Id=sa;Password=sasa@123;TrustServerCertificate=True;"
|
| 11 |
-
"MssqlConnection": "Server=.;Database=LibraryManagement;User Id=sa;Password=sasa@123;TrustServerCertificate=True;"
|
| 12 |
-
},
|
| 13 |
-
"Jwt": {
|
| 14 |
-
"Secret": "YourSuperSecretKeyForLibraryManagementSystem_AtLeast32CharsLong",
|
| 15 |
-
"Issuer": "LibraryManagementSystem",
|
| 16 |
-
"Audience": "LibraryManagementUsers"
|
| 17 |
-
}
|
| 18 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|