bba9c1d1d8
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 6m18s
- SitePageSettingsService: new gRPC client for simplified page settings - Licenses.razor: new page showing license certificates from CMS - RouteConstants: added Licenses route - Footer + MainLayout: added Licenses navigation link - Proto NuGet updated to 0.0.180
191 lines
10 KiB
C#
191 lines
10 KiB
C#
using Blazored.LocalStorage;
|
|
using Grpc.Core;
|
|
using Grpc.Net.Client.Web;
|
|
using Grpc.Net.Client;
|
|
using MudBlazor.Services;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
// Updated imports to use CMS protobuf instead of FrontOffice.BFF
|
|
using CMSMicroservice.Protobuf.Protos.Category;
|
|
using CMSMicroservice.Protobuf.Protos.City;
|
|
using CMSMicroservice.Protobuf.Protos.Package;
|
|
using CMSMicroservice.Protobuf.Protos.Products;
|
|
using CMSMicroservice.Protobuf.Protos.Transactions;
|
|
using CMSMicroservice.Protobuf.Protos.User;
|
|
using CMSMicroservice.Protobuf.Protos.UserCarts;
|
|
using CMSMicroservice.Protobuf.Protos.UserOrder;
|
|
using CMSMicroservice.Protobuf.Protos.UserWallet;
|
|
using CMSMicroservice.Protobuf.Protos.UserWalletChangeLog;
|
|
using CMSMicroservice.Protobuf.Protos.UserAddress;
|
|
using CMSMicroservice.Protobuf.Protos.Configuration;
|
|
using CMSMicroservice.Protobuf.Protos.NetworkMembership;
|
|
using CMSMicroservice.Protobuf.Protos.Commission;
|
|
using CMSMicroservice.Protobuf.Protos.AppVersion;
|
|
using CMSMicroservice.Protobuf.Protos.SitePage;
|
|
using CMSMicroservice.Protobuf.Protos.SitePageSettings;
|
|
using CMSMicroservice.Protobuf.Protos.BlogPost;
|
|
using CMSMicroservice.Protobuf.Protos.BlogCategory;
|
|
using CMSMicroservice.Protobuf.Protos.DiscountProduct;
|
|
using CMSMicroservice.Protobuf.Protos.DiscountCategory;
|
|
using CMSMicroservice.Protobuf.Protos.DiscountShoppingCart;
|
|
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
|
|
using FrontOffice.Main.Utilities;
|
|
|
|
namespace Microsoft.Extensions.DependencyInjection;
|
|
|
|
public static class ConfigureServices
|
|
{
|
|
public static IServiceCollection AddCommonServices(this IServiceCollection services)
|
|
{
|
|
services.AddMudServices();
|
|
services.AddBlazoredLocalStorage(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;
|
|
});
|
|
|
|
// Access HttpContext for User-Agent
|
|
services.AddHttpContextAccessor();
|
|
|
|
// Register custom services
|
|
services.AddSingleton<UserAuthInfo>();
|
|
services.AddScoped<AuthService>();
|
|
services.AddScoped<AuthDialogService>();
|
|
// Storefront services
|
|
services.AddScoped<CartService>();
|
|
services.AddScoped<ProductService>();
|
|
services.AddScoped<CategoryService>();
|
|
services.AddScoped<OrderService>();
|
|
services.AddScoped<WalletService>();
|
|
services.AddScoped<VATService>(); // Singleton برای cache روزانه
|
|
// Package service
|
|
services.AddScoped<PackageService>();
|
|
// New services for Club, Network, Commission
|
|
services.AddScoped<ClubMembershipService>();
|
|
services.AddScoped<ClubConfigurationService>();
|
|
services.AddScoped<NetworkMembershipService>();
|
|
services.AddScoped<CommissionService>();
|
|
// App Version Service for cache invalidation
|
|
services.AddScoped<AppVersionService>();
|
|
// Main Service for core functionality
|
|
services.AddScoped<MainService>();
|
|
// Site Page service for dynamic content (About, Contact)
|
|
services.AddScoped<SitePageService>();
|
|
// Blog Post service for landing page latest posts & blog pages
|
|
services.AddScoped<BlogPostService>();
|
|
// Blog Category service for blog sidebar filters
|
|
services.AddScoped<BlogCategoryService>();
|
|
// Discount Store services
|
|
services.AddScoped<DiscountProductService>();
|
|
services.AddScoped<DiscountCartService>();
|
|
services.AddScoped<DiscountOrderService>();
|
|
// Site Page Settings Service (simplified page management)
|
|
services.AddScoped<SitePageSettingsService>();
|
|
// Device detection: very light, dependency-free
|
|
services.AddTransient<IDeviceDetector, DeviceDetector>();
|
|
// PDF generation (Chromium only)
|
|
services.AddSingleton<FrontOffice.Main.Utilities.Pdf.IChromiumPdfService, FrontOffice.Main.Utilities.Pdf.ChromiumPdfService>();
|
|
|
|
// SignalR Token Notification Service
|
|
services.AddScoped<TokenNotificationService>();
|
|
|
|
return services;
|
|
}
|
|
|
|
public static IServiceCollection AddGrpcServices(this IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
var baseUrl = configuration["GwUrl"];
|
|
|
|
// Register optimized HttpClient for gRPC
|
|
services.AddScoped(sp =>
|
|
{
|
|
var handler = new HttpClientHandler
|
|
{
|
|
MaxConnectionsPerServer = 10,
|
|
AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate
|
|
};
|
|
|
|
return new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, handler))
|
|
{
|
|
Timeout = TimeSpan.FromMinutes(10),
|
|
BaseAddress = new Uri(baseUrl)
|
|
};
|
|
});
|
|
|
|
// Register gRPC clients with authentication - Updated for CMS
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.Package.PackageContract.PackageContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.User.UserContract.UserContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.UserOrder.UserOrderContract.UserOrderContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.UserWallet.UserWalletContract.UserWalletContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.Category.CategoryContract.CategoryContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.Products.ProductsContract.ProductsContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.Transactions.TransactionsContract.TransactionsContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.UserCarts.UserCartsContract.UserCartsContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.City.CityContract.CityContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.UserAddress.UserAddressContract.UserAddressContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.UserWalletChangeLog.UserWalletChangeLogContract.UserWalletChangeLogContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.ClubMembership.ClubMembershipContract.ClubMembershipContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.OtpToken.OtpTokenContract.OtpTokenContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.Configuration.ConfigurationContract.ConfigurationContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.NetworkMembership.NetworkMembershipContract.NetworkMembershipContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.Commission.CommissionContract.CommissionContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.AppVersion.AppVersionContract.AppVersionContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.SitePage.SitePageContract.SitePageContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<SitePageSettingsContract.SitePageSettingsContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.BlogPost.BlogPostContract.BlogPostContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.BlogCategory.BlogCategoryContract.BlogCategoryContractClient>);
|
|
// Image Resolver Service
|
|
services.AddScoped(CreateAuthenticatedClient<CMSMicroservice.Protobuf.Protos.ImageResolver.ImageResolverContract.ImageResolverContractClient>);
|
|
services.AddScoped<ImageCacheService>();
|
|
// Discount Store gRPC clients
|
|
services.AddScoped(CreateAuthenticatedClient<DiscountProductContract.DiscountProductContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<DiscountCategoryContract.DiscountCategoryContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<DiscountShoppingCartContract.DiscountShoppingCartContractClient>);
|
|
services.AddScoped(CreateAuthenticatedClient<DiscountOrderContract.DiscountOrderContractClient>);
|
|
|
|
return services;
|
|
}
|
|
|
|
private static TClient CreateAuthenticatedClient<TClient>(IServiceProvider sp)
|
|
where TClient : class
|
|
{
|
|
var httpClient = sp.GetRequiredService<HttpClient>();
|
|
var localStorage = sp.GetRequiredService<ILocalStorageService>();
|
|
var baseUrl = httpClient.BaseAddress?.ToString() ?? throw new InvalidOperationException("Base URL not configured");
|
|
|
|
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
|
|
{
|
|
try
|
|
{
|
|
var token = await localStorage.GetItemAsync<string>("auth:token");
|
|
if (!string.IsNullOrWhiteSpace(token))
|
|
{
|
|
metadata.Add("Authorization", $"Bearer {token}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
#if DEBUG
|
|
Console.WriteLine($"Token retrieval error: {ex.Message}");
|
|
#endif
|
|
}
|
|
});
|
|
|
|
var channel = GrpcChannel.ForAddress(baseUrl, 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 (TClient)Activator.CreateInstance(typeof(TClient), channel)!;
|
|
}
|
|
}
|