Spaces:
Sleeping
Sleeping
Yuyuqt commited on
Commit ·
798b4ec
1
Parent(s): 6469525
fix: authorization
Browse files
Backend/Features/Subscriptions/SubscriptionService.cs
CHANGED
|
@@ -310,15 +310,19 @@ namespace Backend.Features.Subscriptions
|
|
| 310 |
subscription.IsActive = true;
|
| 311 |
|
| 312 |
// Award points now
|
| 313 |
-
decimal
|
| 314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
|
| 316 |
await _loyaltyService.ProcessEventAsync(
|
| 317 |
externalUserId: subscription.UserId.ToString(),
|
| 318 |
eventKey: "SUBSCRIBE",
|
| 319 |
eventValue: (double)paidAmount,
|
| 320 |
referenceId: $"SUB-{subscription.Id}",
|
| 321 |
-
description: $"Membership Approved: {subscription.Membership.Type}",
|
| 322 |
email: subscription.User?.Email ?? "No Email",
|
| 323 |
mobile: subscription.User?.PhoneNumber ?? "0000000000"
|
| 324 |
);
|
|
@@ -353,7 +357,7 @@ namespace Backend.Features.Subscriptions
|
|
| 353 |
Id = subscription.Id,
|
| 354 |
UserId = subscription.UserId,
|
| 355 |
MembershipId = subscription.MembershipId,
|
| 356 |
-
MembershipType = subscription.Membership.Type,
|
| 357 |
UserEmail = subscription.User?.Email ?? "Unknown",
|
| 358 |
UserName = subscription.User?.FullName ?? "Unknown",
|
| 359 |
StartDate = subscription.StartDate,
|
|
|
|
| 310 |
subscription.IsActive = true;
|
| 311 |
|
| 312 |
// Award points now
|
| 313 |
+
decimal paidAmount = 0;
|
| 314 |
+
if (subscription.Membership != null)
|
| 315 |
+
{
|
| 316 |
+
decimal discount = 0; // Simplified for approval flow for now
|
| 317 |
+
paidAmount = subscription.Membership.Price - discount;
|
| 318 |
+
}
|
| 319 |
|
| 320 |
await _loyaltyService.ProcessEventAsync(
|
| 321 |
externalUserId: subscription.UserId.ToString(),
|
| 322 |
eventKey: "SUBSCRIBE",
|
| 323 |
eventValue: (double)paidAmount,
|
| 324 |
referenceId: $"SUB-{subscription.Id}",
|
| 325 |
+
description: $"Membership Approved: {subscription.Membership?.Type ?? "Unknown Plan"}",
|
| 326 |
email: subscription.User?.Email ?? "No Email",
|
| 327 |
mobile: subscription.User?.PhoneNumber ?? "0000000000"
|
| 328 |
);
|
|
|
|
| 357 |
Id = subscription.Id,
|
| 358 |
UserId = subscription.UserId,
|
| 359 |
MembershipId = subscription.MembershipId,
|
| 360 |
+
MembershipType = subscription.Membership?.Type ?? "Unknown",
|
| 361 |
UserEmail = subscription.User?.Email ?? "Unknown",
|
| 362 |
UserName = subscription.User?.FullName ?? "Unknown",
|
| 363 |
StartDate = subscription.StartDate,
|
Backend/Features/Wallet/WalletController.cs
CHANGED
|
@@ -38,7 +38,7 @@ namespace Backend.Features.Wallet
|
|
| 38 |
}
|
| 39 |
|
| 40 |
[HttpPost("topup")]
|
| 41 |
-
[Authorize(Roles = "Librarian
|
| 42 |
public async Task<IActionResult> TopUp([FromBody] TopUpRequest request)
|
| 43 |
|
| 44 |
{
|
|
|
|
| 38 |
}
|
| 39 |
|
| 40 |
[HttpPost("topup")]
|
| 41 |
+
[Authorize(Roles = "Librarian")]
|
| 42 |
public async Task<IActionResult> TopUp([FromBody] TopUpRequest request)
|
| 43 |
|
| 44 |
{
|
BlazorWebAssembly/Pages/Members.razor
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
@using LibraryManagement.Shared.Models
|
| 4 |
@using BlazorWebAssembly.Models
|
| 5 |
@using Microsoft.AspNetCore.Authorization
|
| 6 |
-
@attribute [Authorize(Roles = "Librarian
|
| 7 |
@inject LibraryApiClient ApiClient
|
| 8 |
@inject IJSRuntime JS
|
| 9 |
@inject NavigationManager Navigation
|
|
@@ -11,21 +11,21 @@
|
|
| 11 |
<div class="max-w-7xl mx-auto py-10 px-6 animate-fade">
|
| 12 |
<!-- Top Tabs Navigation -->
|
| 13 |
<div class="flex items-center gap-8 border-b border-border mb-10">
|
| 14 |
-
<button @onclick="() => SetTab(
|
| 15 |
Member Directory
|
| 16 |
-
@if (_activeTab ==
|
| 17 |
</button>
|
| 18 |
-
<button @onclick="() => SetTab(
|
| 19 |
Membership Approvals
|
| 20 |
@if (_pendingSubscriptions?.Any() == true)
|
| 21 |
{
|
| 22 |
<span class="ml-2 bg-red-500 text-white text-[10px] px-2 py-0.5 rounded-full">@_pendingSubscriptions.Count()</span>
|
| 23 |
}
|
| 24 |
-
@if (_activeTab ==
|
| 25 |
</button>
|
| 26 |
</div>
|
| 27 |
|
| 28 |
-
@if (_activeTab ==
|
| 29 |
{
|
| 30 |
@if (_currentView == ViewMode.List)
|
| 31 |
{
|
|
@@ -91,7 +91,7 @@
|
|
| 91 |
<div class="text-xs text-muted">@(string.IsNullOrEmpty(user.PhoneNumber) ? "No phone" : user.PhoneNumber)</div>
|
| 92 |
</td>
|
| 93 |
<td class="px-6 py-4">
|
| 94 |
-
<span class="inline-flex rounded-full px-3 py-1 text-[10px] font-black tracking-widest uppercase @(user.Role == "
|
| 95 |
@user.Role
|
| 96 |
</span>
|
| 97 |
</td>
|
|
@@ -191,7 +191,7 @@
|
|
| 191 |
@(_selectedUser.User.FullName?.Substring(0, Math.Min(2, _selectedUser.User.FullName.Length)).ToUpper() ?? "U")
|
| 192 |
</div>
|
| 193 |
<h2 class="text-2xl font-bold text-center mb-2">@_selectedUser.User.FullName</h2>
|
| 194 |
-
<div class="inline-flex rounded-full px-4 py-1.5 text-[10px] font-black uppercase tracking-widest @(_selectedUser.User.Role == "
|
| 195 |
@_selectedUser.User.Role
|
| 196 |
</div>
|
| 197 |
</div>
|
|
@@ -240,7 +240,7 @@
|
|
| 240 |
<button @onclick="() => ShowEdit(_selectedUser.User.Id)" class="bg-primary text-white py-3 px-8 rounded-xl font-bold hover:bg-primary-hover shadow-lg shadow-primary/20 transition-all">Edit Details</button>
|
| 241 |
|
| 242 |
<button @onclick="UpdateRole" class="bg-body border border-border text-main py-3 px-8 rounded-xl font-bold hover:bg-card transition-colors">
|
| 243 |
-
Make @(_selectedUser.User.Role == "
|
| 244 |
</button>
|
| 245 |
|
| 246 |
<button @onclick="DeleteUser" class="p-3 text-red-500 hover:text-red-600 hover:bg-red-500/10 rounded-xl transition-colors ml-auto border border-transparent hover:border-red-500/20">
|
|
@@ -417,7 +417,7 @@
|
|
| 417 |
</div>
|
| 418 |
}
|
| 419 |
}
|
| 420 |
-
else if (_activeTab ==
|
| 421 |
{
|
| 422 |
<div class="animate-fade">
|
| 423 |
<h1 class="text-4xl font-extrabold tracking-tight text-main mb-2">Membership Approvals</h1>
|
|
@@ -479,10 +479,10 @@
|
|
| 479 |
|
| 480 |
@code {
|
| 481 |
private enum ViewMode { List, Details, Create, Edit }
|
| 482 |
-
private enum
|
| 483 |
|
| 484 |
private ViewMode _currentView = ViewMode.List;
|
| 485 |
-
private
|
| 486 |
|
| 487 |
private IEnumerable<UserDto>? _allUsers;
|
| 488 |
private PagedResult<UserDto>? _pagedResult;
|
|
@@ -521,7 +521,7 @@
|
|
| 521 |
}
|
| 522 |
}
|
| 523 |
|
| 524 |
-
private async Task SetTab(
|
| 525 |
{
|
| 526 |
_activeTab = tab;
|
| 527 |
_currentView = ViewMode.List;
|
|
@@ -706,7 +706,7 @@
|
|
| 706 |
private async Task UpdateRole()
|
| 707 |
{
|
| 708 |
if (_selectedUser == null) return;
|
| 709 |
-
var newRole = _selectedUser.User.Role == "
|
| 710 |
try
|
| 711 |
{
|
| 712 |
var success = await ApiClient.UpdateUserRoleAsync(_selectedUser.User.Id, newRole);
|
|
|
|
| 3 |
@using LibraryManagement.Shared.Models
|
| 4 |
@using BlazorWebAssembly.Models
|
| 5 |
@using Microsoft.AspNetCore.Authorization
|
| 6 |
+
@attribute [Authorize(Roles = "Librarian")]
|
| 7 |
@inject LibraryApiClient ApiClient
|
| 8 |
@inject IJSRuntime JS
|
| 9 |
@inject NavigationManager Navigation
|
|
|
|
| 11 |
<div class="max-w-7xl mx-auto py-10 px-6 animate-fade">
|
| 12 |
<!-- Top Tabs Navigation -->
|
| 13 |
<div class="flex items-center gap-8 border-b border-border mb-10">
|
| 14 |
+
<button @onclick="() => SetTab(LibrarianTab.Directory)" class="pb-4 px-2 text-sm font-black uppercase tracking-widest transition-all relative @(_activeTab == LibrarianTab.Directory ? "text-primary" : "text-muted hover:text-main")">
|
| 15 |
Member Directory
|
| 16 |
+
@if (_activeTab == LibrarianTab.Directory) { <div class="absolute bottom-0 left-0 right-0 h-1 bg-primary rounded-t-full"></div> }
|
| 17 |
</button>
|
| 18 |
+
<button @onclick="() => SetTab(LibrarianTab.Approvals)" class="pb-4 px-2 text-sm font-black uppercase tracking-widest transition-all relative @(_activeTab == LibrarianTab.Approvals ? "text-primary" : "text-muted hover:text-main")">
|
| 19 |
Membership Approvals
|
| 20 |
@if (_pendingSubscriptions?.Any() == true)
|
| 21 |
{
|
| 22 |
<span class="ml-2 bg-red-500 text-white text-[10px] px-2 py-0.5 rounded-full">@_pendingSubscriptions.Count()</span>
|
| 23 |
}
|
| 24 |
+
@if (_activeTab == LibrarianTab.Approvals) { <div class="absolute bottom-0 left-0 right-0 h-1 bg-primary rounded-t-full"></div> }
|
| 25 |
</button>
|
| 26 |
</div>
|
| 27 |
|
| 28 |
+
@if (_activeTab == LibrarianTab.Directory)
|
| 29 |
{
|
| 30 |
@if (_currentView == ViewMode.List)
|
| 31 |
{
|
|
|
|
| 91 |
<div class="text-xs text-muted">@(string.IsNullOrEmpty(user.PhoneNumber) ? "No phone" : user.PhoneNumber)</div>
|
| 92 |
</td>
|
| 93 |
<td class="px-6 py-4">
|
| 94 |
+
<span class="inline-flex rounded-full px-3 py-1 text-[10px] font-black tracking-widest uppercase @(user.Role == "Librarian" ? "bg-amber-500/10 text-amber-500" : "bg-blue-500/10 text-blue-500")">
|
| 95 |
@user.Role
|
| 96 |
</span>
|
| 97 |
</td>
|
|
|
|
| 191 |
@(_selectedUser.User.FullName?.Substring(0, Math.Min(2, _selectedUser.User.FullName.Length)).ToUpper() ?? "U")
|
| 192 |
</div>
|
| 193 |
<h2 class="text-2xl font-bold text-center mb-2">@_selectedUser.User.FullName</h2>
|
| 194 |
+
<div class="inline-flex rounded-full px-4 py-1.5 text-[10px] font-black uppercase tracking-widest @(_selectedUser.User.Role == "Librarian" ? "bg-amber-500/10 text-amber-500 border border-amber-500/20" : "bg-blue-500/10 text-blue-500 border border-blue-500/20")">
|
| 195 |
@_selectedUser.User.Role
|
| 196 |
</div>
|
| 197 |
</div>
|
|
|
|
| 240 |
<button @onclick="() => ShowEdit(_selectedUser.User.Id)" class="bg-primary text-white py-3 px-8 rounded-xl font-bold hover:bg-primary-hover shadow-lg shadow-primary/20 transition-all">Edit Details</button>
|
| 241 |
|
| 242 |
<button @onclick="UpdateRole" class="bg-body border border-border text-main py-3 px-8 rounded-xl font-bold hover:bg-card transition-colors">
|
| 243 |
+
Make @(_selectedUser.User.Role == "Librarian" ? "Member" : "Librarian")
|
| 244 |
</button>
|
| 245 |
|
| 246 |
<button @onclick="DeleteUser" class="p-3 text-red-500 hover:text-red-600 hover:bg-red-500/10 rounded-xl transition-colors ml-auto border border-transparent hover:border-red-500/20">
|
|
|
|
| 417 |
</div>
|
| 418 |
}
|
| 419 |
}
|
| 420 |
+
else if (_activeTab == LibrarianTab.Approvals)
|
| 421 |
{
|
| 422 |
<div class="animate-fade">
|
| 423 |
<h1 class="text-4xl font-extrabold tracking-tight text-main mb-2">Membership Approvals</h1>
|
|
|
|
| 479 |
|
| 480 |
@code {
|
| 481 |
private enum ViewMode { List, Details, Create, Edit }
|
| 482 |
+
private enum LibrarianTab { Directory, Approvals }
|
| 483 |
|
| 484 |
private ViewMode _currentView = ViewMode.List;
|
| 485 |
+
private LibrarianTab _activeTab = LibrarianTab.Directory;
|
| 486 |
|
| 487 |
private IEnumerable<UserDto>? _allUsers;
|
| 488 |
private PagedResult<UserDto>? _pagedResult;
|
|
|
|
| 521 |
}
|
| 522 |
}
|
| 523 |
|
| 524 |
+
private async Task SetTab(LibrarianTab tab)
|
| 525 |
{
|
| 526 |
_activeTab = tab;
|
| 527 |
_currentView = ViewMode.List;
|
|
|
|
| 706 |
private async Task UpdateRole()
|
| 707 |
{
|
| 708 |
if (_selectedUser == null) return;
|
| 709 |
+
var newRole = _selectedUser.User.Role == "Librarian" ? "Member" : "Librarian";
|
| 710 |
try
|
| 711 |
{
|
| 712 |
var success = await ApiClient.UpdateUserRoleAsync(_selectedUser.User.Id, newRole);
|
BlazorWebAssembly/Services/LibraryApiClient.cs
CHANGED
|
@@ -405,7 +405,7 @@ namespace BlazorWebAssembly.Services
|
|
| 405 |
|
| 406 |
public async Task<bool> UpdateUserRoleAsync(Guid id, string role)
|
| 407 |
{
|
| 408 |
-
var response = await _httpClient.
|
| 409 |
return response.IsSuccessStatusCode;
|
| 410 |
}
|
| 411 |
|
|
|
|
| 405 |
|
| 406 |
public async Task<bool> UpdateUserRoleAsync(Guid id, string role)
|
| 407 |
{
|
| 408 |
+
var response = await _httpClient.PatchAsJsonAsync($"api/users/{id}/role", new UserRoleUpdateRequest { Role = role });
|
| 409 |
return response.IsSuccessStatusCode;
|
| 410 |
}
|
| 411 |
|