Files
BackOffice/src/BackOffice/Common/Configure/ConfigureService.cs
masoodafar-web 5cec4e9313 feat: Implement role-based access control and manual payment management
- Added role-based permission checks in NavMenu for dashboard and management links.
- Created ManualPaymentDialog for creating and managing manual payments.
- Implemented TransactionDetailsDialog for displaying transaction details.
- Developed Transactions page for viewing and filtering transactions.
- Introduced RolePermissionsDialog for managing role permissions.
- Established AuthorizationService to handle permission checks and user roles.
- Enhanced UI components with MudBlazor for better user experience.
2025-12-05 17:27:23 +03:30

156 lines
8.1 KiB
C#

using BackOffice.BFF.Otp.Protobuf.Protos.Otp;
using BackOffice.BFF.Package.Protobuf.Protos.Package;
using BackOffice.BFF.Role.Protobuf.Protos.Role;
using BackOffice.BFF.Products.Protobuf.Protos.Products;
using BackOffice.BFF.User.Protobuf.Protos.User;
using BackOffice.BFF.UserAddress.Protobuf.Protos.UserAddress;
using BackOffice.BFF.UserOrder.Protobuf.Protos.UserOrder;
using BackOffice.BFF.UserRole.Protobuf.Protos.UserRole;
using BackOffice.BFF.Category.Protobuf.Protos.Category;
using BackOffice.BFF.Commission.Protobuf;
using BackOffice.BFF.NetworkMembership.Protobuf;
using BackOffice.BFF.ClubMembership.Protobuf;
using BackOffice.BFF.Configuration.Protobuf;
using BackOffice.BFF.Health.Protobuf;
using BackOffice.BFF.DiscountProduct.Protobuf.Protos.DiscountProduct;
using BackOffice.BFF.DiscountCategory.Protobuf.Protos.DiscountCategory;
using BackOffice.BFF.DiscountOrder.Protobuf.Protos.DiscountOrder;
using BackOffice.BFF.Tag.Protobuf.Protos.Tag;
using BackOffice.BFF.ProductTag.Protobuf.Protos.ProductTag;
using BackOffice.BFF.PublicMessage.Protobuf.Protos.PublicMessage;
using BackOffice.Common.Utilities;
using BackOffice.Services.DiscountProduct;
using BackOffice.Services.DiscountCategory;
using BackOffice.Services.DiscountOrder;
using BackOffice.Services.PublicMessage;
using BackOffice.Services.Tag;
using Blazored.LocalStorage;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Grpc.Net.Client;
using Grpc.Net.Client.Web;
using Microsoft.AspNetCore.Components.Authorization;
using MudBlazor.Services;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.Extensions.DependencyInjection;
public static class ConfigureServices
{
public static IServiceCollection AddCommonServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddBlazoredLocalStorageAsSingleton(config =>
{
config.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
config.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
config.JsonSerializerOptions.IgnoreReadOnlyProperties = true;
config.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
config.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
config.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
config.JsonSerializerOptions.WriteIndented = false;
});
services.AddAuthorizationCore();
services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>();
services.AddSingleton<ITokenProvider, AppTokenProvider>();
services.AddSingleton<ITokenHandler, TokenHandler>();
services.AddMudServices();
services.AddGrpcServices(configuration);
// Application Services
services.AddScoped<BackOffice.Services.Authorization.IAuthorizationService, BackOffice.Services.Authorization.AuthorizationService>();
services.AddScoped<IDiscountProductService, DiscountProductService>();
services.AddScoped<IDiscountCategoryService, DiscountCategoryService>();
services.AddScoped<IDiscountOrderService, DiscountOrderService>();
services.AddScoped<IPublicMessageService, PublicMessageService>();
services.AddScoped<ITagService, TagService>();
return services;
}
public static IServiceCollection AddGrpcServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<CallInvoker>(sp =>
{
var config = sp.GetRequiredService<IConfiguration>();
var baseUri = config["GwUrl"];
if (string.IsNullOrWhiteSpace(baseUri))
{
throw new InvalidOperationException("Configuration value 'GwUrl' is missing or empty.");
}
var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()))
{
Timeout = TimeSpan.FromMinutes(10)
};
return CreateAuthenticatedChannel(baseUri, httpClient, sp);
});
services.AddTransient(sp => new OtpContract.OtpContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new PackageContract.PackageContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new ProductsContract.ProductsContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new RoleContract.RoleContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new UserContract.UserContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new UserAddressContract.UserAddressContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new UserOrderContract.UserOrderContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new UserRoleContract.UserRoleContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new CategoryContract.CategoryContractClient(sp.GetRequiredService<CallInvoker>()));
// CMS Services (Commission, Network, Club, Configuration, Health)
services.AddTransient(sp => new CommissionContract.CommissionContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new NetworkMembershipContract.NetworkMembershipContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new ClubMembershipContract.ClubMembershipContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new ConfigurationContract.ConfigurationContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new HealthContract.HealthContractClient(sp.GetRequiredService<CallInvoker>()));
// Discount Shop Services
services.AddTransient(sp => new DiscountProductsContract.DiscountProductsContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new DiscountCategoriesContract.DiscountCategoriesContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new DiscountOrdersContract.DiscountOrdersContractClient(sp.GetRequiredService<CallInvoker>()));
// Public Message Service
services.AddTransient(sp => new PublicMessagesContract.PublicMessagesContractClient(sp.GetRequiredService<CallInvoker>()));
// Tag Management Services
services.AddTransient(sp => new TagContract.TagContractClient(sp.GetRequiredService<CallInvoker>()));
services.AddTransient(sp => new ProductTagContract.ProductTagContractClient(sp.GetRequiredService<CallInvoker>()));
return services;
}
private static CallInvoker CreateAuthenticatedChannel(string address, HttpClient httpClient, IServiceProvider serviceProvider)
{
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
var provider = serviceProvider.GetRequiredService<ITokenProvider>();
// var accessToken = await provider.RequestAccessToken();
// accessToken.TryGetToken(out var token);
var token = await provider.GetTokenAsync();
if (!string.IsNullOrEmpty(token))
{
// Console.WriteLine($"Authorization Bearer {token.Value}");
metadata.Add("Authorization", $"Bearer {token}");
}
await Task.CompletedTask;
});
// SslCredentials is used here because this channel is using TLS.
// CallCredentials can't be used with ChannelCredentials.Insecure on non-TLS channels.
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
UnsafeUseInsecureChannelCallCredentials = true,
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials),
HttpClient = httpClient,
MaxReceiveMessageSize = 1000 * 1024 * 1024, // 1 GB
MaxSendMessageSize = 1000 * 1024 * 1024 // 1 GB
});
return channel.Intercept(new ErrorHandlerInterceptor());
}
}