diff --git a/Api/Controllers/PluginController.cs b/Api/Controllers/PluginController.cs index 1d60456..1e03444 100644 --- a/Api/Controllers/PluginController.cs +++ b/Api/Controllers/PluginController.cs @@ -31,12 +31,12 @@ public async Task> CreatePlugin([FromBody] PluginCreateRequ { string userId = GetUserId(); - if (await pluginRepository.HasReachedPluginQuota(userId)) + if (await pluginRepository.HasReachedPluginQuota(User)) return BadRequest("Max plugins reached"); var plugin = mapper.Map(request); plugin.UserId = userId; - var createdPlugin = await pluginRepository.Add(plugin, userId); + var createdPlugin = await pluginRepository.Add(plugin,User); return CreatedAtAction(nameof(CreatePlugin), new { userId = createdPlugin.UserId, pluginId = createdPlugin.Id }, createdPlugin); } @@ -48,7 +48,7 @@ public async Task> GetPlugins() var plugins = await pluginRepository.GetByUserId(userId); var result = mapper.Map(plugins); - result.MaxPlugins = await subscriptionRepository.IsUserPremium(userId) ? 3 : 1; + result.MaxPlugins = await pluginRepository.maxPlugins(userId, User); return Ok(result); } diff --git a/Api/Program.cs b/Api/Program.cs index 6ace094..a10ce5f 100644 --- a/Api/Program.cs +++ b/Api/Program.cs @@ -79,7 +79,7 @@ static void AddServices(WebApplicationBuilder builder, string version) var contactUrl = builder.Configuration.GetValue("ContactLogicApp:Url"); ArgumentNullException.ThrowIfNull(contactUrl); builder.Services.AddSingleton(new ContactSetting() { Url = contactUrl }); - + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -116,6 +116,13 @@ void AddConfigrations(WebApplicationBuilder builder) var gptSettings = new GPTSettings(); builder.Configuration.GetSection("GPTSettings").Bind(gptSettings); builder.Services.AddSingleton(gptSettings); + var AdminEmails = builder.Configuration.GetSection("AdminEmail").Get>(); + if (AdminEmails != null) + { + var adminWhitelist = new AdminWhitelist(); + adminWhitelist.emails = AdminEmails; + builder.Services.AddSingleton(adminWhitelist); + } builder.Services.AddSingleton(x => x.GetRequiredService().GetValue("FrontendDomain")!); //make this an obj } \ No newline at end of file diff --git a/Application/Plugins/AdminWhitelist.cs b/Application/Plugins/AdminWhitelist.cs new file mode 100644 index 0000000..f181c4f --- /dev/null +++ b/Application/Plugins/AdminWhitelist.cs @@ -0,0 +1,12 @@ +public class AdminWhitelist +{ + public List? emails { get; set; } + public bool Contains(string email) + { + if (email == null) + { + return false; + } + return this.emails != null && this.emails.Any(e => string.Equals(e, email, StringComparison.OrdinalIgnoreCase)); + } +} diff --git a/Application/Plugins/IPluginRepository.cs b/Application/Plugins/IPluginRepository.cs index 4fd59a9..8d087ea 100644 --- a/Application/Plugins/IPluginRepository.cs +++ b/Application/Plugins/IPluginRepository.cs @@ -1,3 +1,4 @@ +using System.Security.Claims; using AiPlugin.Application.common; using AiPlugin.Domain.Plugin; @@ -6,5 +7,6 @@ namespace AiPlugin.Application.Plugins; public interface IPluginRepository : IBaseRepository { public Task> GetByUserId(string userid, CancellationToken cancellationToken = default); - public Task HasReachedPluginQuota(string userId); + public Task HasReachedPluginQuota(ClaimsPrincipal user); + public Task maxPlugins(string userId, ClaimsPrincipal? user = null); } \ No newline at end of file diff --git a/Application/Plugins/PluginRepository.cs b/Application/Plugins/PluginRepository.cs index 0d1aee4..fa69b98 100644 --- a/Application/Plugins/PluginRepository.cs +++ b/Application/Plugins/PluginRepository.cs @@ -1,25 +1,28 @@ -using AiPlugin.Application.Plugins; +using System.Security.Claims; using System.Text.RegularExpressions; using AiPlugin.Domain.Plugin; using AiPlugin.Infrastructure; using Microsoft.EntityFrameworkCore; + namespace AiPlugin.Application.Plugins; public class PluginRepository : IPluginRepository { private readonly AiPluginDbContext dbContext; private readonly SubscriptionRepository subscriptionRepository; + private readonly AdminWhitelist adminWhitelist; - public PluginRepository(AiPluginDbContext dbContext, SubscriptionRepository subscriptionRepository) + public PluginRepository(AiPluginDbContext dbContext, SubscriptionRepository subscriptionRepository, AdminWhitelist adminWhitelist) { this.dbContext = dbContext; this.subscriptionRepository = subscriptionRepository; + this.adminWhitelist = adminWhitelist; } - public async Task Add(Plugin entity, string userId, CancellationToken cancellationToken = default) + public async Task Add(Plugin entity, ClaimsPrincipal user, CancellationToken cancellationToken = default) { CheckPlugin(entity); - if (await HasReachedPluginQuota(userId)) + if (await HasReachedPluginQuota(user)) { throw new Exception("Max plugins reached"); } @@ -70,16 +73,31 @@ public async Task Delete(Guid id, CancellationToken cancellationToken = default) await dbContext.SaveChangesAsync(cancellationToken); } - public async Task HasReachedPluginQuota(string userId) + public async Task HasReachedPluginQuota(ClaimsPrincipal user) { - var isPremium = await subscriptionRepository.IsUserPremium(userId); + var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new UnauthorizedAccessException("UserId not found"); + var userEmail = user?.FindFirst(ClaimTypes.Email)?.Value; + if (userEmail != null && adminWhitelist.Contains(userEmail)) + { + return false; + } return (await dbContext .Plugins .Include(x => x.Sections) .Where(x => !x.isDeleted) .CountAsync(x => x.UserId == userId) - ) >= (isPremium ? 3 : 1); + ) >= await maxPlugins(userId, user); + } + public async Task maxPlugins(string userId, ClaimsPrincipal? user = null) + { + var userEmail = user?.FindFirst(ClaimTypes.Email)?.Value; + if (userEmail != null && adminWhitelist.Contains(userEmail)) + { + return 10000; + } + var isPremium = await subscriptionRepository.IsUserPremium(userId); + return isPremium ? 3 : 1; } private void CheckPlugin(Plugin entity) { diff --git a/Application/common/IBaseRepository.cs b/Application/common/IBaseRepository.cs index 216705b..02ab195 100644 --- a/Application/common/IBaseRepository.cs +++ b/Application/common/IBaseRepository.cs @@ -1,3 +1,4 @@ +using System.Security.Claims; using AiPlugin.Domain.Common; using AiPlugin.Domain.Plugin; @@ -5,7 +6,7 @@ namespace AiPlugin.Application.common; public interface IBaseRepository where T : EntityBase { - public Task Add(T entity, string userId, CancellationToken cancellationToken = default); + public Task Add(T entity,ClaimsPrincipal user, CancellationToken cancellationToken = default); public Task Get(Guid id, CancellationToken cancellationToken = default); public Task Update(T entity, CancellationToken cancellationToken = default); public Task Delete(Guid id, CancellationToken cancellationToken = default);