Restructured the rest of the features to their own environment

This commit is contained in:
Marcel Baumgartner
2024-01-26 13:53:34 +01:00
parent 63b2b40227
commit 12bc66a95b
91 changed files with 181 additions and 147 deletions

View File

@@ -1,7 +1,7 @@
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Event;
using Moonlight.Core.Event.Args;
using Moonlight.Features.ServiceManagement.Entities;
namespace Moonlight.Core.Services.Background;

View File

@@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Exceptions;
using Moonlight.Core.Helpers;
using Moonlight.Core.Models.Abstractions;

View File

@@ -1,29 +0,0 @@
using Microsoft.JSInterop;
using Moonlight.Core.Helpers;
namespace Moonlight.Core.Services.Interop;
public class AdBlockService
{
private readonly IJSRuntime JsRuntime;
public AdBlockService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async Task<bool> Detect()
{
try
{
return await JsRuntime.InvokeAsync<bool>("moonlight.utils.vendo"); // lat. vendo = advertisement xd
}
catch (Exception e)
{
Logger.Warn("An unexpected error occured while trying to detect possible ad blockers");
Logger.Warn(e);
return false;
}
}
}

View File

@@ -2,8 +2,9 @@
using Moonlight.Core.Event;
using Moonlight.Core.Extensions;
using Moonlight.Core.Helpers;
using Moonlight.Features.Theming.Services;
namespace Moonlight.Core.Services.Sys;
namespace Moonlight.Core.Services;
public class MoonlightService // This service can be used to perform strictly panel specific actions
{
@@ -12,7 +13,7 @@ public class MoonlightService // This service can be used to perform strictly pa
public WebApplication Application { get; set; } // Do NOT modify using a plugin
public string LogPath { get; set; } // Do NOT modify using a plugin
public MoonlightThemeService Theme => ServiceProvider.GetRequiredService<MoonlightThemeService>();
public ThemeService Theme => ServiceProvider.GetRequiredService<ThemeService>();
public MoonlightService(ConfigService configService, IServiceProvider serviceProvider)
{

View File

@@ -1,8 +1,8 @@
using System.Reflection;
using Moonlight.Core.Helpers;
using Moonlight.Core.Models.Abstractions.Services;
using Moonlight.Core.Plugins;
using Moonlight.Core.Plugins.Contexts;
using Moonlight.Features.ServiceManagement.Models.Abstractions;
namespace Moonlight.Core.Services;

View File

@@ -1,81 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Exceptions;
using Moonlight.Core.Repositories;
using Moonlight.Features.StoreSystem.Entities;
namespace Moonlight.Core.Services.ServiceManage;
public class ServiceAdminService
{
private readonly IServiceScopeFactory ServiceScopeFactory;
private readonly ServiceDefinitionService ServiceDefinitionService;
public ServiceAdminService(IServiceScopeFactory serviceScopeFactory, ServiceDefinitionService serviceDefinitionService)
{
ServiceScopeFactory = serviceScopeFactory;
ServiceDefinitionService = serviceDefinitionService;
}
public async Task<Service> Create(User u, Product p, Action<Service>? modifyService = null)
{
var impl = ServiceDefinitionService.Get(p);
// Load models in new scope
using var scope = ServiceScopeFactory.CreateScope();
var userRepo = scope.ServiceProvider.GetRequiredService<Repository<User>>();
var productRepo = scope.ServiceProvider.GetRequiredService<Repository<Product>>();
var serviceRepo = scope.ServiceProvider.GetRequiredService<Repository<Service>>();
var user = userRepo.Get().First(x => x.Id == u.Id);
var product = productRepo.Get().First(x => x.Id == p.Id);
// Create database model
var service = new Service()
{
Product = product,
Owner = user,
Suspended = false,
CreatedAt = DateTime.UtcNow
};
// Allow further modifications
if(modifyService != null)
modifyService.Invoke(service);
// Add new service in database
var finishedService = serviceRepo.Add(service);
// Call the action for the logic behind the service type
await impl.Actions.Create(scope.ServiceProvider, finishedService);
return finishedService;
}
public async Task Delete(Service s)
{
using var scope = ServiceScopeFactory.CreateScope();
var serviceRepo = scope.ServiceProvider.GetRequiredService<Repository<Service>>();
var serviceShareRepo = scope.ServiceProvider.GetRequiredService<Repository<ServiceShare>>();
var service = serviceRepo
.Get()
.Include(x => x.Shares)
.FirstOrDefault(x => x.Id == s.Id);
if (service == null)
throw new DisplayException("Service does not exist anymore");
var impl = ServiceDefinitionService.Get(service);
await impl.Actions.Delete(scope.ServiceProvider, service);
foreach (var share in service.Shares.ToArray())
{
serviceShareRepo.Delete(share);
}
serviceRepo.Delete(service);
}
}

View File

@@ -1,56 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Database.Enums;
using Moonlight.Core.Models.Abstractions.Services;
using Moonlight.Core.Repositories;
using Moonlight.Features.StoreSystem.Entities;
namespace Moonlight.Core.Services.ServiceManage;
public class ServiceDefinitionService
{
private readonly Dictionary<ServiceType, ServiceDefinition> ServiceImplementations = new();
private readonly IServiceScopeFactory ServiceScopeFactory;
public ServiceDefinitionService(IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
}
public void Register<T>(ServiceType type) where T : ServiceDefinition
{
var impl = Activator.CreateInstance<T>() as ServiceDefinition;
if (impl == null)
throw new ArgumentException("The provided type is not an service implementation");
if (ServiceImplementations.ContainsKey(type))
throw new ArgumentException($"An implementation for {type} has already been registered");
ServiceImplementations.Add(type, impl);
}
public ServiceDefinition Get(Service s)
{
using var scope = ServiceScopeFactory.CreateScope();
var serviceRepo = scope.ServiceProvider.GetRequiredService<Repository<Service>>();
var service = serviceRepo
.Get()
.Include(x => x.Product)
.First(x => x.Id == s.Id);
return Get(service.Product);
}
public ServiceDefinition Get(Product p) => Get(p.Type);
public ServiceDefinition Get(ServiceType type)
{
if (!ServiceImplementations.ContainsKey(type))
throw new ArgumentException($"No service implementation found for {type}");
return ServiceImplementations[type];
}
}

View File

@@ -1,61 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.Models.Enums;
using Moonlight.Core.Repositories;
namespace Moonlight.Core.Services.ServiceManage;
public class ServiceManageService
{
private readonly IServiceScopeFactory ServiceScopeFactory;
public ServiceManageService(IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
}
public Task<bool> CheckAccess(Service s, User user)
{
var permissionStorage = new PermissionStorage(user.Permissions);
// Is admin?
if(permissionStorage[Permission.AdminServices])
return Task.FromResult(true);
using var scope = ServiceScopeFactory.CreateScope();
var serviceRepo = scope.ServiceProvider.GetRequiredService<Repository<Service>>();
var service = serviceRepo
.Get()
.Include(x => x.Owner)
.Include(x => x.Shares)
.ThenInclude(x => x.User)
.First(x => x.Id == s.Id);
// Is owner?
if(service.Owner.Id == user.Id)
return Task.FromResult(true);
// Is shared user
if(service.Shares.Any(x => x.User.Id == user.Id))
return Task.FromResult(true);
// No match
return Task.FromResult(false);
}
public Task<bool> NeedsRenewal(Service s)
{
// We fetch the service in a new scope wo ensure that we are not caching
using var scope = ServiceScopeFactory.CreateScope();
var serviceRepo = scope.ServiceProvider.GetRequiredService<Repository<Service>>();
var service = serviceRepo
.Get()
.First(x => x.Id == s.Id);
return Task.FromResult(DateTime.UtcNow > service.RenewAt);
}
}

View File

@@ -1,114 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Exceptions;
using Moonlight.Core.Repositories;
namespace Moonlight.Core.Services.ServiceManage;
public class ServiceService // This service is used for managing services and create the connection to the actual logic behind a service type
{
private readonly IServiceProvider ServiceProvider;
private readonly Repository<Service> ServiceRepository;
private readonly Repository<User> UserRepository;
public ServiceAdminService Admin => ServiceProvider.GetRequiredService<ServiceAdminService>();
public ServiceDefinitionService Definition => ServiceProvider.GetRequiredService<ServiceDefinitionService>();
public ServiceManageService Manage => ServiceProvider.GetRequiredService<ServiceManageService>();
public ServiceService(IServiceProvider serviceProvider, Repository<Service> serviceRepository, Repository<User> userRepository)
{
ServiceProvider = serviceProvider;
ServiceRepository = serviceRepository;
UserRepository = userRepository;
}
public Task<Service[]> Get(User user)
{
var result = ServiceRepository
.Get()
.Include(x => x.Product)
.Where(x => x.Owner.Id == user.Id)
.ToArray();
return Task.FromResult(result);
}
public Task<Service[]> GetShared(User user)
{
var result = ServiceRepository
.Get()
.Include(x => x.Product)
.Include(x => x.Owner)
.Where(x => x.Shares.Any(y => y.User.Id == user.Id))
.ToArray();
return Task.FromResult(result);
}
public Task AddSharedUser(Service s, string username)
{
var userToAdd = UserRepository
.Get()
.FirstOrDefault(x => x.Username == username);
if (userToAdd == null)
throw new DisplayException("No user found with this username");
var service = ServiceRepository
.Get()
.Include(x => x.Owner)
.Include(x => x.Shares)
.ThenInclude(x => x.User)
.First(x => x.Id == s.Id);
if (service.Owner.Id == userToAdd.Id)
throw new DisplayException("The owner cannot be added as a shared user");
if (service.Shares.Any(x => x.User.Id == userToAdd.Id))
throw new DisplayException("The user has already access to this service");
service.Shares.Add(new ()
{
User = userToAdd
});
ServiceRepository.Update(service);
return Task.CompletedTask;
}
public Task<User[]> GetSharedUsers(Service s)
{
var service = ServiceRepository
.Get()
.Include(x => x.Shares)
.ThenInclude(x => x.User)
.First(x => x.Id == s.Id);
var result = service.Shares
.Select(x => x.User)
.ToArray();
return Task.FromResult(result);
}
public Task RemoveSharedUser(Service s, User user)
{
var service = ServiceRepository
.Get()
.Include(x => x.Shares)
.ThenInclude(x => x.User)
.First(x => x.Id == s.Id);
var shareToRemove = service.Shares.FirstOrDefault(x => x.User.Id == user.Id);
if (shareToRemove == null)
throw new DisplayException("This user does not have access to this service");
service.Shares.Remove(shareToRemove);
ServiceRepository.Update(service);
return Task.CompletedTask;
}
}

View File

@@ -1,51 +0,0 @@
using Mappy.Net;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.Repositories;
namespace Moonlight.Core.Services.Sys;
public class MoonlightThemeService
{
private readonly IServiceProvider ServiceProvider;
private readonly ConfigService ConfigService;
public MoonlightThemeService(IServiceProvider serviceProvider, ConfigService configService)
{
ServiceProvider = serviceProvider;
ConfigService = configService;
}
public Task<ApplicationTheme[]> GetInstalled()
{
using var scope = ServiceProvider.CreateScope();
var themeRepo = scope.ServiceProvider.GetRequiredService<Repository<Theme>>();
var themes = new List<ApplicationTheme>();
themes.AddRange(themeRepo
.Get()
.ToArray()
.Select(x => Mapper.Map<ApplicationTheme>(x)));
if (ConfigService.Get().Theme.EnableDefault)
{
themes.Insert(0, new()
{
Id = 0,
Name = "Moonlight Default",
Author = "MasuOwO",
Enabled = true,
CssUrl = "/css/theme.css",
DonateUrl = "https://ko-fi.com/masuowo"
});
}
return Task.FromResult(themes.ToArray());
}
public async Task<ApplicationTheme[]> GetEnabled() =>
(await GetInstalled())
.Where(x => x.Enabled)
.ToArray();
}

View File

@@ -1,10 +1,10 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Database.Entities.Store;
using Moonlight.Core.Repositories;
using Moonlight.Core.Services.ServiceManage;
using Moonlight.Features.Community.Entities;
using Moonlight.Features.Community.Services;
using Moonlight.Features.ServiceManagement.Entities;
using Moonlight.Features.ServiceManagement.Services;
using Moonlight.Features.StoreSystem.Entities;
using Moonlight.Features.Ticketing.Entities;