diff --git a/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Subtitle/GetById/GetSubtitleByIdHandler.cs b/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Subtitle/GetById/GetSubtitleByIdHandler.cs index 7ac406b46..45d0ffedd 100644 --- a/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Subtitle/GetById/GetSubtitleByIdHandler.cs +++ b/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Subtitle/GetById/GetSubtitleByIdHandler.cs @@ -33,7 +33,8 @@ public async Task> Handle(GetSubtitleByIdQuery request, Canc { string errorMsg = _stringLocalizerCannotFind["CannotFindSubtitleWithCorrespondingId", request.Id].Value; _logger.LogError(request, errorMsg); - return Result.Fail(new Error(errorMsg)); + var returner = Result.Fail(new Error(errorMsg)); + return returner; } return Result.Ok(_mapper.Map(subtitle)); diff --git a/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Tag/GetByStreetcodeId/GetTagByStreetcodeIdHandler.cs b/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Tag/GetByStreetcodeId/GetTagByStreetcodeIdHandler.cs index dca718fc1..730e1bb75 100644 --- a/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Tag/GetByStreetcodeId/GetTagByStreetcodeIdHandler.cs +++ b/Streetcode/Streetcode.BLL/MediatR/AdditionalContent/Tag/GetByStreetcodeId/GetTagByStreetcodeIdHandler.cs @@ -34,7 +34,7 @@ public async Task>> Handle(GetTagByStreetco t => t.StreetcodeId == request.StreetcodeId, include: q => q.Include(t => t.Tag)); - if (tagIndexed is null) + if (tagIndexed is null || request.StreetcodeId < 1) { string errorMsg = _stringLocalizerCannotFind?["CannotFindAnyTagByTheStreetcodeId", request.StreetcodeId].Value; _logger.LogError(request, errorMsg); diff --git a/Streetcode/Streetcode.BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtsByStreetcodeIdHandler.cs b/Streetcode/Streetcode.BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtsByStreetcodeIdHandler.cs index be242a541..e1e8714be 100644 --- a/Streetcode/Streetcode.BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtsByStreetcodeIdHandler.cs +++ b/Streetcode/Streetcode.BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtsByStreetcodeIdHandler.cs @@ -48,7 +48,7 @@ public async Task>> Handle(GetArtsByStreetcodeIdQuery include: scl => scl .Include(sc => sc.Image) !); - if (arts is null) + if (arts is null || request.StreetcodeId < 1) { string errorMsg = _stringLocalizerCannotFind["CannotFindAnyArtWithCorrespondingStreetcodeId", request.StreetcodeId].Value; _logger.LogError(request, errorMsg); diff --git a/Streetcode/Streetcode.BLL/MediatR/Media/Image/GetByStreetcodeId/GetImageByStreetcodeIdHandler.cs b/Streetcode/Streetcode.BLL/MediatR/Media/Image/GetByStreetcodeId/GetImageByStreetcodeIdHandler.cs index 80e494ff2..15482634c 100644 --- a/Streetcode/Streetcode.BLL/MediatR/Media/Image/GetByStreetcodeId/GetImageByStreetcodeIdHandler.cs +++ b/Streetcode/Streetcode.BLL/MediatR/Media/Image/GetByStreetcodeId/GetImageByStreetcodeIdHandler.cs @@ -46,7 +46,7 @@ public async Task>> Handle(GetImageByStreetcodeIdQu f => f.Streetcodes.Any(s => s.Id == request.StreetcodeId), include: q => q.Include(img => img.ImageDetails))).OrderBy(img => img.ImageDetails?.Alt); - if (images is null || images.Count() == 0) + if (images is null || request.StreetcodeId < 1) { string errorMsg = _stringLocalizerCannotFind["CannotFindAnImageWithTheCorrespondingStreetcodeId", request.StreetcodeId].Value; _logger.LogError(request, errorMsg); diff --git a/Streetcode/Streetcode.BLL/MediatR/Media/StreetcodeArt/GetByStreetcodeId/GetStreetcodeArtByStreetcodeIdHandler.cs b/Streetcode/Streetcode.BLL/MediatR/Media/StreetcodeArt/GetByStreetcodeId/GetStreetcodeArtByStreetcodeIdHandler.cs index 4097c3c51..2c68bc90d 100644 --- a/Streetcode/Streetcode.BLL/MediatR/Media/StreetcodeArt/GetByStreetcodeId/GetStreetcodeArtByStreetcodeIdHandler.cs +++ b/Streetcode/Streetcode.BLL/MediatR/Media/StreetcodeArt/GetByStreetcodeId/GetStreetcodeArtByStreetcodeIdHandler.cs @@ -52,7 +52,7 @@ public async Task>> Handle(GetStreetcodeArt .Include(a => a.Art) .Include(i => i.Art.Image) !); - if (art is null) + if (art is null || request.StreetcodeId < 1) { string errorMsg = _stringLocalizerCannotFind["CannotFindAnyArtWithCorrespondingStreetcodeId", request.StreetcodeId].Value; _logger.LogError(request, errorMsg); diff --git a/Streetcode/Streetcode.BLL/Services/BlobStorageService/BlobService.cs b/Streetcode/Streetcode.BLL/Services/BlobStorageService/BlobService.cs index 20cb2a9fb..fe7c38330 100644 --- a/Streetcode/Streetcode.BLL/Services/BlobStorageService/BlobService.cs +++ b/Streetcode/Streetcode.BLL/Services/BlobStorageService/BlobService.cs @@ -61,7 +61,7 @@ public string SaveFileInStorage(string base64, string name, string extension) public void SaveFileInStorageBase64(string base64, string name, string extension) { - byte[] imageBytes = Convert.FromBase64String(base64); + byte[] imageBytes = Convert.FromBase64String(base64.Trim()); Directory.CreateDirectory(_blobPath); EncryptFile(imageBytes, extension, name); } @@ -87,26 +87,6 @@ public string UpdateFileInStorage( return hashBlobStorageName; } - public async Task CleanBlobStorage() - { - var base64Files = GetAllBlobNames(); - - var existingImagesInDatabase = await _repositoryWrapper.ImageRepository.GetAllAsync(); - var existingAudiosInDatabase = await _repositoryWrapper.AudioRepository.GetAllAsync(); - - List existingMedia = new (); - existingMedia.AddRange(existingImagesInDatabase.Select(img => img.BlobName)); - existingMedia.AddRange(existingAudiosInDatabase.Select(img => img.BlobName)); - - var filesToRemove = base64Files.Except(existingMedia).ToList(); - - foreach (var file in filesToRemove) - { - Console.WriteLine($"Deleting {file}..."); - DeleteFileInStorage(file); - } - } - private IEnumerable GetAllBlobNames() { var paths = Directory.EnumerateFiles(_blobPath); diff --git a/Streetcode/Streetcode.BLL/Services/CacheService/CacheService.cs b/Streetcode/Streetcode.BLL/Services/CacheService/CacheService.cs index abbccade1..144359f76 100644 --- a/Streetcode/Streetcode.BLL/Services/CacheService/CacheService.cs +++ b/Streetcode/Streetcode.BLL/Services/CacheService/CacheService.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; using Streetcode.BLL.Interfaces.Cache; using Streetcode.BLL.Interfaces.Logging; @@ -14,54 +15,58 @@ namespace Streetcode.BLL.Services.CacheService public class CacheService : ICacheService { private readonly IMemoryCache _cache; - private readonly ILoggerService _logger; + private readonly IServiceScopeFactory _serviceScopeFactory; private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); - public CacheService(IMemoryCache cache, ILoggerService logger) + public CacheService(IMemoryCache cache, IServiceScopeFactory serviceScopeFactory ) { _cache = cache; - _logger = logger; + _serviceScopeFactory = serviceScopeFactory; } public async Task GetOrSetAsync(string key, Func> getItemCallback, TimeSpan cacheDuration) { - _logger.LogInformation(key + "GetOrSetAsync function start!"); - if (_cache.TryGetValue(key, out T cachedItem)) + using (var scope = _serviceScopeFactory.CreateAsyncScope()) { - _logger.LogInformation(key + "TryGetValue function true"); - return cachedItem; - } - - _logger.LogInformation(key + "TryGetValue function false"); - SemaphoreSlim mylock = _locks.GetOrAdd(key, k => new SemaphoreSlim(1, 1)); - - await mylock.WaitAsync(); - - try - { - if (_cache.TryGetValue(key, out cachedItem)) + var logger = scope.ServiceProvider.GetRequiredService(); + logger.LogInformation(key + "GetOrSetAsync function start!"); + if (_cache.TryGetValue(key, out T cachedItem)) { - _logger.LogInformation(key + "TryGetValue function true"); + logger.LogInformation(key + "TryGetValue function true"); return cachedItem; } - _logger.LogInformation(key + "TryGetValue function false"); - T item = await getItemCallback(); + logger.LogInformation(key + "TryGetValue function false"); + SemaphoreSlim mylock = _locks.GetOrAdd(key, k => new SemaphoreSlim(1, 1)); + + await mylock.WaitAsync(); - var cacheEntryOptions = new MemoryCacheEntryOptions + try { - AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30), - SlidingExpiration = cacheDuration, - Priority = CacheItemPriority.Normal, - }; + if (_cache.TryGetValue(key, out cachedItem)) + { + logger.LogInformation(key + "TryGetValue function true"); + return cachedItem; + } - _cache.Set(key, item, cacheEntryOptions); - _logger.LogInformation(key + "Set function true"); - return item; - } - finally - { - mylock.Release(); + logger.LogInformation(key + "TryGetValue function false"); + T item = await getItemCallback(); + + var cacheEntryOptions = new MemoryCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30), + SlidingExpiration = cacheDuration, + Priority = CacheItemPriority.Normal, + }; + + _cache.Set(key, item, cacheEntryOptions); + logger.LogInformation(key + "Set function true"); + return item; + } + finally + { + mylock.Release(); + } } } diff --git a/Streetcode/Streetcode.BLL/Util/DateToStringConverter.cs b/Streetcode/Streetcode.BLL/Util/DateToStringConverter.cs deleted file mode 100644 index 3f07d982a..000000000 --- a/Streetcode/Streetcode.BLL/Util/DateToStringConverter.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Streetcode.DAL.Enums; - -namespace Streetcode.BLL.Util -{ - public class DateToStringConverter - { - public static string FromDateToString(DateTime date, DateViewPattern pattern) - { - return pattern switch - { - DateViewPattern.Year => date.ToString("yyyy"), - DateViewPattern.MonthYear => date.ToString("yyyy, MMMM"), - DateViewPattern.SeasonYear => $"{GetSeason(date)} {date.Year}", - DateViewPattern.DateMonthYear => date.ToString("yyyy, d MMMM"), - _ =>"" - }; - } - - private static string GetSeason(DateTime dateTime) - { - if (dateTime.Month < 3 || dateTime.Month == 12) - { - return "зима"; - } - else if (dateTime.Month >= 3 && dateTime.Month < 6) - { - return "весна"; - } - else if(dateTime.Month >= 6 && dateTime.Month < 9) - { - return "літо"; - } - else - { - return "осінь"; - } - } - } -} diff --git a/Streetcode/Streetcode.BLL/Util/IdComparer.cs b/Streetcode/Streetcode.BLL/Util/IdComparer.cs deleted file mode 100644 index 758d754b6..000000000 --- a/Streetcode/Streetcode.BLL/Util/IdComparer.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Streetcode.DAL.Entities.Partners; - -namespace Streetcode.BLL.Util -{ - public class IdComparer : IEqualityComparer - { - public bool Equals(PartnerSourceLink? x, PartnerSourceLink? y) - { - if(x == null || y == null) - { - return false; - } - - return x.Id == y.Id; - } - - public int GetHashCode([DisallowNull] PartnerSourceLink obj) - { - return obj.Id.GetHashCode(); - } - } -} diff --git a/Streetcode/Streetcode.DAL/Streetcode.DAL.csproj b/Streetcode/Streetcode.DAL/Streetcode.DAL.csproj index a5023d288..635e4acf8 100644 --- a/Streetcode/Streetcode.DAL/Streetcode.DAL.csproj +++ b/Streetcode/Streetcode.DAL/Streetcode.DAL.csproj @@ -10,14 +10,14 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Streetcode/Streetcode.WebApi/Attributes/AuthorizeRoles.cs b/Streetcode/Streetcode.WebApi/Attributes/AuthorizeRoles.cs deleted file mode 100644 index c7d07d832..000000000 --- a/Streetcode/Streetcode.WebApi/Attributes/AuthorizeRoles.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Streetcode.DAL.Enums; -namespace Streetcode.WebApi.Attributes -{ - public class AuthorizeRoles : AuthorizeAttribute - { - public AuthorizeRoles(params UserRole[] userRoles) - { - Roles = string.Join(",", userRoles.Select(r => r.ToString()).ToArray()); - } - } -} diff --git a/Streetcode/Streetcode.WebApi/Controllers/BaseApiController.cs b/Streetcode/Streetcode.WebApi/Controllers/BaseApiController.cs index b51430095..1c0c2e19d 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/BaseApiController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/BaseApiController.cs @@ -1,8 +1,6 @@ -using System.Resources; -using FluentResults; +using FluentResults; using MediatR; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Localization; using Streetcode.BLL.MediatR.ResultVariations; namespace Streetcode.WebApi.Controllers; @@ -11,12 +9,7 @@ namespace Streetcode.WebApi.Controllers; [Route("api/[controller]/[action]")] public class BaseApiController : ControllerBase { - private readonly IStringLocalizer _stringLocalizer; private IMediator? _mediator; - public BaseApiController(IStringLocalizer stringLocalizer) - { - _stringLocalizer = stringLocalizer; - } public BaseApiController() { @@ -28,21 +21,14 @@ protected ActionResult HandleResult(Result result) { if (result.IsSuccess) { - if(result is NullResult) + if (result is NullResult) { return Ok(result.Value); } return (result.Value is null) ? - NotFound(_stringLocalizer?["NotFound"].Value) : Ok(result.Value); - } - foreach (var item in result.Reasons) - { - if (item.Message.Contains(_stringLocalizer?["NotFound"].Value)) - { - return Ok(); - } + NotFound("Not Found") : Ok(result.Value); } return BadRequest(result.Reasons); diff --git a/Streetcode/Streetcode.WebApi/Controllers/Media/AudioController.cs b/Streetcode/Streetcode.WebApi/Controllers/Media/AudioController.cs index ae19e3918..90fa93a86 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Media/AudioController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Media/AudioController.cs @@ -10,7 +10,6 @@ using Streetcode.BLL.MediatR.Media.Audio.Update; using Streetcode.BLL.MediatR.Media.Image.GetByStreetcodeId; using Streetcode.DAL.Enums; -using Streetcode.WebApi.Attributes; namespace Streetcode.WebApi.Controllers.Media; diff --git a/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ArtController.cs b/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ArtController.cs index 713044b2f..365b40389 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ArtController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ArtController.cs @@ -22,7 +22,7 @@ public async Task GetById([FromRoute] int id) } [HttpGet("{streetcodeId:int}")] - public async Task GetAllByStreetcodeId([FromRoute] int streetcodeId) + public async Task GetArtsByStreetcodeId([FromRoute] int streetcodeId) { return HandleResult(await Mediator.Send(new GetArtsByStreetcodeIdQuery(streetcodeId))); } diff --git a/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ImageController.cs b/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ImageController.cs index 867b280c0..60bb6d8b2 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ImageController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Media/Images/ImageController.cs @@ -7,7 +7,6 @@ using Streetcode.BLL.MediatR.Media.Image.Create; using Streetcode.BLL.MediatR.Media.Image.Delete; using Streetcode.BLL.MediatR.Media.Image.Update; -using Streetcode.WebApi.Attributes; using Streetcode.DAL.Enums; using Microsoft.Net.Http.Headers; diff --git a/Streetcode/Streetcode.WebApi/Controllers/Partners/PartnersController.cs b/Streetcode/Streetcode.WebApi/Controllers/Partners/PartnersController.cs index e7845935d..6d551fd5f 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Partners/PartnersController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Partners/PartnersController.cs @@ -10,7 +10,6 @@ using Streetcode.BLL.MediatR.Partners.GetByStreetcodeIdToUpdate; using Streetcode.DAL.Entities.Partners; using Streetcode.DAL.Enums; -using Streetcode.WebApi.Attributes; namespace Streetcode.WebApi.Controllers.Partners; diff --git a/Streetcode/Streetcode.WebApi/Controllers/Source/SourcesController.cs b/Streetcode/Streetcode.WebApi/Controllers/Source/SourcesController.cs index 6936f6bdd..3e246c69d 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Source/SourcesController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Source/SourcesController.cs @@ -6,7 +6,6 @@ using Streetcode.BLL.MediatR.Sources.SourceLink.Update; using Streetcode.BLL.MediatR.Sources.SourceLink.Delete; using Streetcode.DAL.Enums; -using Streetcode.WebApi.Attributes; using Streetcode.BLL.MediatR.Sources.SourceLinkCategory.GetAll; using Streetcode.BLL.MediatR.Sources.SourceLinkCategory.GetCategoryContentByStreetcodeId; diff --git a/Streetcode/Streetcode.WebApi/Controllers/Streetcode/TextContent/FactController.cs b/Streetcode/Streetcode.WebApi/Controllers/Streetcode/TextContent/FactController.cs index ad9215920..3e082da34 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Streetcode/TextContent/FactController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Streetcode/TextContent/FactController.cs @@ -7,7 +7,6 @@ using Streetcode.BLL.MediatR.Streetcode.Fact.GetByStreetcodeId; using Streetcode.BLL.MediatR.Streetcode.Fact.Update; using Streetcode.DAL.Enums; -using Streetcode.WebApi.Attributes; namespace Streetcode.WebApi.Controllers.Streetcode.TextContent; diff --git a/Streetcode/Streetcode.WebApi/Controllers/Team/TeamController.cs b/Streetcode/Streetcode.WebApi/Controllers/Team/TeamController.cs index dcfed564b..a5d5d28e1 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Team/TeamController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Team/TeamController.cs @@ -8,7 +8,6 @@ using Streetcode.BLL.MediatR.Team.GetByRoleId; using Streetcode.BLL.MediatR.Team.Update; using Streetcode.DAL.Enums; -using Streetcode.WebApi.Attributes; namespace Streetcode.WebApi.Controllers.Team { diff --git a/Streetcode/Streetcode.WebApi/Controllers/Users/UserController.cs b/Streetcode/Streetcode.WebApi/Controllers/Users/UserController.cs index 50f7ca5db..a2cea0419 100644 --- a/Streetcode/Streetcode.WebApi/Controllers/Users/UserController.cs +++ b/Streetcode/Streetcode.WebApi/Controllers/Users/UserController.cs @@ -4,7 +4,6 @@ using Streetcode.BLL.MediatR.Users.Login; using Streetcode.BLL.MediatR.Users.RefreshToken; using Streetcode.DAL.Enums; -using Streetcode.WebApi.Attributes; namespace Streetcode.WebApi.Controllers.Users { diff --git a/Streetcode/Streetcode.WebApi/Extensions/RecurringJobExtensions.cs b/Streetcode/Streetcode.WebApi/Extensions/RecurringJobExtensions.cs index e6d5eadee..d7b54f094 100644 --- a/Streetcode/Streetcode.WebApi/Extensions/RecurringJobExtensions.cs +++ b/Streetcode/Streetcode.WebApi/Extensions/RecurringJobExtensions.cs @@ -1,4 +1,5 @@ using Hangfire; +using Microsoft.Extensions.DependencyInjection; using Streetcode.BLL.Interfaces.Audio; using Streetcode.BLL.Interfaces.Image; @@ -8,23 +9,33 @@ public static class RecurringJobExtensions { public static void AddCleanAudiosJob(this WebApplication app) { - var recurringJobManager = app.Services.GetService(); + var serviceScopeFactory = app.Services.GetService(); + using (var scope = serviceScopeFactory.CreateScope()) + { + var recurringJobManager = scope.ServiceProvider.GetService(); + var audioService = scope.ServiceProvider.GetService(); - recurringJobManager.AddOrUpdate( - "Clean audio that are not used in streetcodes", - () => app.Services.GetService().CleanUnusedAudiosAsync(), - app.Configuration.GetSection("RecurringJobs")["AudioCleaningFrequency"], - TimeZoneInfo.Utc); + recurringJobManager.AddOrUpdate( + "Clean audio that are not used in streetcodes", + () => audioService.CleanUnusedAudiosAsync(), + app.Configuration.GetSection("RecurringJobs")["AudioCleaningFrequency"], + TimeZoneInfo.Utc); + } } public static void AddCleanImagesJob(this WebApplication app) { - var recurringJobManager = app.Services.GetService(); + var serviceScopeFactory = app.Services.GetService(); + using (var scope = serviceScopeFactory.CreateScope()) + { + var recurringJobManager = scope.ServiceProvider.GetService(); + var imageService = scope.ServiceProvider.GetService(); - recurringJobManager.AddOrUpdate( - "Clean images that are not used", - () => app.Services.GetService().CleanUnusedImagesAsync(), - app.Configuration.GetSection("RecurringJobs")["ImageCleaningFrequency"], - TimeZoneInfo.Utc); + recurringJobManager.AddOrUpdate( + "Clean images that are not used", + () => imageService.CleanUnusedImagesAsync(), + app.Configuration.GetSection("RecurringJobs")["ImageCleaningFrequency"], + TimeZoneInfo.Utc); + } } } \ No newline at end of file diff --git a/Streetcode/Streetcode.WebApi/Hangfire/HangfireDashboardAuthorizationFilter.cs b/Streetcode/Streetcode.WebApi/Hangfire/HangfireDashboardAuthorizationFilter.cs index 31369e899..0577b798e 100644 --- a/Streetcode/Streetcode.WebApi/Hangfire/HangfireDashboardAuthorizationFilter.cs +++ b/Streetcode/Streetcode.WebApi/Hangfire/HangfireDashboardAuthorizationFilter.cs @@ -1,3 +1,4 @@ +using System.Security.Claims; using Hangfire.Dashboard; using Streetcode.DAL.Enums; @@ -5,12 +6,21 @@ namespace Streetcode.BLL.Services.Hangfire; public class HangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter { - public bool Authorize(DashboardContext context) - { - var user = context.GetHttpContext().User; + public bool Authorize(DashboardContext context) + { + var user = GetUser(context); + var isMainAdministrator = IsMainAdministrator(user); - var isAdministrator = user.IsInRole(UserRole.MainAdministrator.ToString()); + return isMainAdministrator; + } - return isAdministrator; - } + public bool IsMainAdministrator(ClaimsPrincipal user) + { + return user.IsInRole(UserRole.MainAdministrator.ToString()); + } + + public virtual ClaimsPrincipal GetUser(DashboardContext context) + { + return context.GetHttpContext().User; + } } \ No newline at end of file diff --git a/Streetcode/Streetcode.WebApi/Program.cs b/Streetcode/Streetcode.WebApi/Program.cs index 86f211c7b..b36fe685f 100644 --- a/Streetcode/Streetcode.WebApi/Program.cs +++ b/Streetcode/Streetcode.WebApi/Program.cs @@ -4,6 +4,7 @@ using Streetcode.WebApi.Extensions; using Microsoft.AspNetCore.Localization; using Streetcode.BLL.Services.Hangfire; +using Microsoft.AspNetCore.HttpOverrides; var builder = WebApplication.CreateBuilder(args); @@ -18,8 +19,16 @@ builder.Services.ConfigureInstagram(builder); builder.Services.ConfigureSerilog(builder); builder.Services.ConfigureRateLimitMiddleware(builder); +builder.Services.Configure(options => +{ + options.ForwardedHeaders = + ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; +}); var app = builder.Build(); + +app.UseForwardedHeaders(); + var supportedCulture = new[] { new CultureInfo("en-US"), diff --git a/Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj b/Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj index e04a3f4e5..c05015e04 100644 --- a/Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj +++ b/Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj @@ -18,16 +18,16 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Streetcode/Streetcode.WebApi/appsettings.Local.json b/Streetcode/Streetcode.WebApi/appsettings.Local.json index 14b44479d..0fe7bd709 100644 --- a/Streetcode/Streetcode.WebApi/appsettings.Local.json +++ b/Streetcode/Streetcode.WebApi/appsettings.Local.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=127.0.0.1;Database=StreetcodeDb;User Id=sa;Password=Admin@1234;MultipleActiveResultSets=true" + "DefaultConnection": "Server=127.0.0.1;Database=StreetcodeDb;User Id=sa;Password=Admin@1234;MultipleActiveResultSets=true" }, "CORS": { "AllowedOrigins": [ "http://localhost:3000" ], diff --git a/Streetcode/Streetcode.WebApi/appsettings.json b/Streetcode/Streetcode.WebApi/appsettings.json index c66f7473d..73350553e 100644 --- a/Streetcode/Streetcode.WebApi/appsettings.json +++ b/Streetcode/Streetcode.WebApi/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=127.0.0.1;Database=StreetcodeDb;User Id=sa;Password=Admin@1234;MultipleActiveResultSets=true" + "DefaultConnection": "Server=127.0.0.1;Database=StreetcodeDb;User Id=sa;Password=Admin@1234;MultipleActiveResultSets=true" }, "EmailConfiguration": { "From": "streetcodefordev@gmail.com", diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/SubtitleControllerTests.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/SubtitleControllerTests.cs index ae2e6cb3c..3005adfef 100644 --- a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/SubtitleControllerTests.cs +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/SubtitleControllerTests.cs @@ -48,6 +48,7 @@ public async Task GetById_Incorrect_ReturnBadRequest() { int incorrectId = -100; var response = await this.client.GetByIdAsync(incorrectId); + Assert.Multiple( () => Assert.False(response.IsSuccessStatusCode), () => Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode)); diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/TagControllerTests.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/TagControllerTests.cs index fd18b84e1..e28dfa36b 100644 --- a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/TagControllerTests.cs +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/AdditionalContent/TagControllerTests.cs @@ -59,6 +59,7 @@ public async Task GetByIdIncorrect_ReturnBadRequest() [ExtractTestTag] public async Task GetByStreetcodeId_ReturnSuccessStatusCode() { + StreetcodeTagIndexSetup.Setup(ExtractTestStreetcode.StreetcodeForTest, ExtractTestTag.TagForTest); int streetcodeId = ExtractTestStreetcode.StreetcodeForTest.Id; var response = await client.GetByStreetcodeId(streetcodeId); var returnedValue = CaseIsensitiveJsonDeserializer.Deserialize>(response.Content); diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Media/Images/ArtControllerTests.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Media/Images/ArtControllerTests.cs index add60c2b3..4fdda4f68 100644 --- a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Media/Images/ArtControllerTests.cs +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Media/Images/ArtControllerTests.cs @@ -17,7 +17,7 @@ public ArtControllerTests(CustomWebApplicationFactory factory) [Fact] public async Task GetAll_ReturnSuccessStatusCode() { - var response = await client.GetAllAsync(); + var response = await this.client.GetAllAsync(); var returnedValue = CaseIsensitiveJsonDeserializer.Deserialize>(response.Content); Assert.True(response.IsSuccessStatusCode); @@ -45,7 +45,7 @@ public async Task GetById_ReturnSuccessStatusCode() public async Task GetById_Incorrect_ReturnBadRequest() { int id = -100; - var response = await client.GetByIdAsync(id); + var response = await this.client.GetByIdAsync(id); Assert.Multiple( () => Assert.Equal(System.Net.HttpStatusCode.BadRequest, response.StatusCode), @@ -54,10 +54,10 @@ public async Task GetById_Incorrect_ReturnBadRequest() [Fact] [ExtractTestStreetcode] - public async Task GetByStreetcodeId_ReturnSuccessStatusCode() + public async Task GetArtsByStreetcodeId_ReturnSuccessStatusCode() { int streetcodeId = ExtractTestStreetcode.StreetcodeForTest.Id; - var response = await client.GetByStreetcodeId(streetcodeId); + var response = await this.client.GetArtsByStreetcodeId(streetcodeId); var returnedValue = CaseIsensitiveJsonDeserializer.Deserialize>(response.Content); Assert.True(response.IsSuccessStatusCode); @@ -65,11 +65,11 @@ public async Task GetByStreetcodeId_ReturnSuccessStatusCode() } [Fact] - public async Task GetByStreetcodeId_Incorrect_BadResult() + public async Task GetArtsByStreetcodeId_Incorrect_BadResult() { int streetcodeId = -100; - var response = await this.client.GetByStreetcodeId(streetcodeId); + var response = await this.client.GetArtsByStreetcodeId(streetcodeId); Assert.Multiple( () => Assert.Equal(System.Net.HttpStatusCode.BadRequest, response.StatusCode), diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/ExtractTestTag.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/ExtractTestTag.cs index 65c6c8352..33d3b63b2 100644 --- a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/ExtractTestTag.cs +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/ExtractTestTag.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using Streetcode.DAL.Entities.AdditionalContent; +using System.Reflection; using Xunit.Sdk; namespace Streetcode.XIntegrationTest.ControllerTests.Utils.BeforeAndAfterTestAtribute.AdditionalContent.Tag @@ -17,7 +18,7 @@ public override void Before(MethodInfo methodUnderTest) TagForTest = sqlDbHelper.AddNewItem( new DAL.Entities.AdditionalContent.Tag() { - Title = "TagTitle", + Title = "TagTitle_NEW!!!", }); sqlDbHelper.SaveChanges(); } diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/StreetcodeTagIndexSetup.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/StreetcodeTagIndexSetup.cs new file mode 100644 index 000000000..41f223b91 --- /dev/null +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/AdditionalContent/Tag/StreetcodeTagIndexSetup.cs @@ -0,0 +1,26 @@ +using Streetcode.DAL.Entities.AdditionalContent; +using Streetcode.DAL.Entities.Streetcode; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Streetcode.XIntegrationTest.ControllerTests.Utils.BeforeAndAfterTestAtribute.AdditionalContent.Tag +{ + public class StreetcodeTagIndexSetup + { + public static void Setup(StreetcodeContent streetcodeForTest, DAL.Entities.AdditionalContent.Tag tagForTest) + { + var sqlDbHelper = BaseControllerTests.GetSqlDbHelper(); + var existingIndex = sqlDbHelper.GetExistItem( + index => index.StreetcodeId == streetcodeForTest.Id && index.TagId == tagForTest.Id); + if (existingIndex == null) + { + var streetcodeTagIndex = new StreetcodeTagIndex { TagId = tagForTest.Id, StreetcodeId = streetcodeForTest.Id }; + sqlDbHelper.AddNewItem(streetcodeTagIndex); + sqlDbHelper.SaveChanges(); + } + } + } +} diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/Streetcode/ExtractTestStreetcode.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/Streetcode/ExtractTestStreetcode.cs index 32f16ad51..4d7546b39 100644 --- a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/Streetcode/ExtractTestStreetcode.cs +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/BeforeAndAfterTestAtribute/Streetcode/ExtractTestStreetcode.cs @@ -1,4 +1,5 @@ -using Streetcode.DAL.Entities.Streetcode; +using Streetcode.DAL.Entities.AdditionalContent; +using Streetcode.DAL.Entities.Streetcode; using System.Reflection; using Xunit.Sdk; diff --git a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/StreetcodeClient.cs b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/StreetcodeClient.cs index a58f0fd5d..97e3eee4c 100644 --- a/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/StreetcodeClient.cs +++ b/Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/StreetcodeClient.cs @@ -10,7 +10,7 @@ public class StreetcodeClient public string SecondPartUrl { get; } - public StreetcodeClient(HttpClient client, string secondPartUrl = "") + public StreetcodeClient(HttpClient client, string secondPartUrl = "") { this.Client = new RestClient(client) { AcceptedContentTypes=ContentType.JsonAccept }; this.SecondPartUrl = secondPartUrl; @@ -31,13 +31,18 @@ public async Task GetByStreetcodeId(int id) return await this.GetResponse($"/getByStreetcodeId/{id}"); } + public async Task GetArtsByStreetcodeId(int id) + { + return await this.GetResponse($"/getArtsByStreetcodeId/{id}"); + } + public async Task GetResponse(string requestString) { var request = new RestRequest($"{this.SecondPartUrl}{requestString}"); request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; }; request.AddHeader("content-type", "application/json"); - - return await this.Client.ExecuteGetAsync(request); + var returns = await this.Client.ExecuteGetAsync(request); + return returns; } } diff --git a/Streetcode/Streetcode.XIntegrationTest/ServiceTests/BlobServiceTests/CleanBlobTest/CleanBlobServiceTests.cs b/Streetcode/Streetcode.XIntegrationTest/ServiceTests/BlobServiceTests/CleanBlobTest/CleanBlobServiceTests.cs deleted file mode 100644 index 0369dc5a3..000000000 --- a/Streetcode/Streetcode.XIntegrationTest/ServiceTests/BlobServiceTests/CleanBlobTest/CleanBlobServiceTests.cs +++ /dev/null @@ -1,49 +0,0 @@ -//using Streetcode.DAL.Entities.Media.Images; -//using Streetcode.XIntegrationTest.Base; -//using Streetcode.XIntegrationTest.ServiceTests.BlobServiceTests.Utils; -//using Xunit; - -//namespace Streetcode.XIntegrationTest.ServiceTests.BlobServiceTests.CleanBlobTest -//{ -// public class CleanBlobServiceTests : BlobServiceTestBase, IClassFixture -// { -// private TestDBFixture DbFixture { get; } - -// public CleanBlobServiceTests(TestDBFixture fixture) : base(new BlobStorageFixture()) -// { -// DbFixture = fixture; -// } - -// [Theory] -// [InlineData("ED_kNMjZkMDz6_syM5klb8HGDyfU72Q6Sdz_Y4DmCJ8=.png")] -// public async Task ShouldRemoveUnusedFilesFromBlobStorage(string blobName) -// { -// // Arrange -// await _fixture.DbAndStorageSeeding(); -// Image imgToRemove = _fixture.TestDbContext.Images.FirstOrDefault(x => x.BlobName == blobName); -// _fixture.TestDbContext.Images.Remove(imgToRemove); -// await _fixture.TestDbContext.SaveChangesAsync(); - -// // Act -// await _fixture.blobService.CleanBlobStorage(); - -// // Assert -// Assert.False(File.Exists(_fixture.blobPath + blobName)); -// } - -// [Theory] -// [InlineData("ED_kNMjZkMDz6_syM5klb8HGDyfU72Q6Sdz_Y4DmCJ8=.png")] -// public async Task NothingToRemoveFromBlobStorage(string blobName) -// { -// // Arrange -// await _fixture.DbAndStorageSeeding(); -// Image imgToRemove = _fixture.TestDbContext.Images.FirstOrDefault(x => x.BlobName == blobName); - -// // Act -// await _fixture.blobService.CleanBlobStorage(); - -// // Assert -// Assert.True(File.Exists(_fixture.blobPath + blobName)); -// } -// } -//} diff --git a/Streetcode/Streetcode.XIntegrationTest/Streetcode.XIntegrationTest.csproj b/Streetcode/Streetcode.XIntegrationTest/Streetcode.XIntegrationTest.csproj index 8758e2555..460f80ab3 100644 --- a/Streetcode/Streetcode.XIntegrationTest/Streetcode.XIntegrationTest.csproj +++ b/Streetcode/Streetcode.XIntegrationTest/Streetcode.XIntegrationTest.csproj @@ -13,9 +13,13 @@ - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -47,4 +51,8 @@ + + + + diff --git a/Streetcode/Streetcode.XUnitTest/Factories/Streetcode/StreetcodeFactoryTests.cs b/Streetcode/Streetcode.XUnitTest/Factories/Streetcode/StreetcodeFactoryTests.cs new file mode 100644 index 000000000..92f1f1814 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/Factories/Streetcode/StreetcodeFactoryTests.cs @@ -0,0 +1,35 @@ +using Streetcode.BLL.Factories.Streetcode; +using Xunit; +using Streetcode.DAL.Enums; +using Streetcode.DAL.Entities.Streetcode.Types; + +namespace Streetcode.XUnitTest.Factories.Streetcode; + +public class StreetcodeFactoryTests +{ + [Fact] + public void CreateStreetcode_StreetcodeTypePerson_ReturnsPersonStreetcode() + { + // Arrange + var streetcodeTypePerson = StreetcodeType.Person; + + // Act + var streetcode = StreetcodeFactory.CreateStreetcode(streetcodeTypePerson); + + // Assert + Assert.IsType(streetcode); + } + + [Fact] + public void CreateStreetcode_StreetcodeTypeEvent_ReturnsEventStreetcode() + { + // Arrange + var streetcodeTypeEvent = StreetcodeType.Event; + + // Act + var streetcode = StreetcodeFactory.CreateStreetcode(streetcodeTypeEvent); + + // Assert + Assert.IsType(streetcode); + } +} \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/Hangfire/HangfireAuthorizationFilterTests.cs b/Streetcode/Streetcode.XUnitTest/Hangfire/HangfireAuthorizationFilterTests.cs new file mode 100644 index 000000000..0756524b8 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/Hangfire/HangfireAuthorizationFilterTests.cs @@ -0,0 +1,102 @@ +using System.Security.Claims; +using Hangfire; +using Hangfire.Annotations; +using Hangfire.Dashboard; +using Moq; +using Streetcode.BLL.Services.Hangfire; +using Streetcode.DAL.Enums; +using Xunit; + +namespace Streetcode.XUnitTest.Hangfire; + +public class HangfireAuthorizationFilterTests +{ + public static IEnumerable NonMainAdministratorRoles => + new List + { + new object[] { UserRole.Administrator.ToString() }, + new object[] { UserRole.Moderator.ToString() }, + new object[] { string.Empty }, + }; + + private class MockDashboardContext : DashboardContext + { + public MockDashboardContext([NotNull] JobStorage storage, [NotNull] DashboardOptions options) + : base(storage, options) + { + } + } + + public class MockHangfireDashboardAuthorizationFilter : HangfireDashboardAuthorizationFilter + { + private readonly string _userRole; + + public MockHangfireDashboardAuthorizationFilter(string userRole) + { + this._userRole = userRole; + } + + public override ClaimsPrincipal GetUser(DashboardContext context) + { + return new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Role, _userRole) })); + } + } + + [Fact] + public void IsMainAdministrator_UserIsMainAdministrator_ReturnsTrue() + { + // Arrange + var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Role, UserRole.MainAdministrator.ToString()) })); + var filter = new HangfireDashboardAuthorizationFilter(); + + // Act + bool result = filter.IsMainAdministrator(user); + + // Assert + Assert.True(result); + } + + [Theory] + [MemberData(nameof(NonMainAdministratorRoles))] + public void IsMainAdministrator_UserIsNotMainAdministrator_ReturnsFalse(string role) + { + // Arrange + var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Role, role) })); + var filter = new HangfireDashboardAuthorizationFilter(); + + // Act + bool result = filter.IsMainAdministrator(user); + + // Assert + Assert.False(result); + } + + [Fact] + public void Authorize_UserIsMainAdministrator_ReturnsTrue() + { + // Arrange + var mockDashboardContext = new MockDashboardContext(new Mock().Object, new Mock().Object); + var mockFilter = new MockHangfireDashboardAuthorizationFilter(UserRole.MainAdministrator.ToString()); + + // Act + bool result = mockFilter.Authorize(mockDashboardContext); + + // Assert + Assert.True(result); + } + + [Theory] + [MemberData(nameof(NonMainAdministratorRoles))] + public void Authorize_UserIsNotMainAdministrator_ReturnsFalse(string role) + { + // Arrange + var mockDashboardContext = new MockDashboardContext(new Mock().Object, new Mock().Object); + var mockFilter = new MockHangfireDashboardAuthorizationFilter(role); + + // Act + bool result = mockFilter.Authorize(mockDashboardContext); + + // Assert + Assert.False(result); + } +} \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj b/Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj index 7a9e61659..efb7c1e0f 100644 --- a/Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj +++ b/Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj @@ -17,6 +17,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -44,6 +45,7 @@ + \ No newline at end of file