From 89d6f88b842fe7dd13c1e9751d59bf4dc1e182e8 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Wed, 19 Jul 2023 00:11:45 +0300 Subject: [PATCH 01/11] The blocked provider (director) has the possibility (besides the blocked deputy provider and the blocked provider admin ) to log in to the system. --- .../OutOfSchool.AuthCommon/Controllers/AuthController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs index 77d6927b13..740ebe1935 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs @@ -152,7 +152,7 @@ public async Task Login(LoginViewModel model) if (user != null) { - if (user.IsBlocked) + if (user.IsBlocked && (user.Role == Role.Provider.ToString().ToLower() && user.IsDerived)) { logger.LogInformation("User is blocked. Login was failed"); From 1cff5f98d53292abc1f33acf76a8716a18c9ce2a Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Thu, 20 Jul 2023 01:28:06 +0300 Subject: [PATCH 02/11] Forbidden the CRUD (w/o R) and Block operations for the blocked provider with workshops, parents, applications, and providers admins (also deputies). --- .../Controllers/V1/ApplicationController.cs | 25 +++++++++++++- .../V1/BlockedProviderParentController.cs | 30 +++++++++++++--- .../Controllers/V1/ProviderAdminController.cs | 34 +++++++++++++++++++ .../Controllers/V1/WorkshopController.cs | 33 ++++++++++++++---- .../Services/IUserService.cs | 7 ++++ .../Services/UserService.cs | 16 +++++++++ 6 files changed, 132 insertions(+), 13 deletions(-) diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs index 2a36662399..28dae60b0d 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Mvc; +using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models; using OutOfSchool.WebApi.Models.Application; +using OutOfSchool.WebApi.Services; namespace OutOfSchool.WebApi.Controllers.V1; @@ -16,6 +18,7 @@ public class ApplicationController : ControllerBase private readonly IProviderService providerService; private readonly IProviderAdminService providerAdminService; private readonly IWorkshopService workshopService; + private readonly IUserService userService; /// /// Initializes a new instance of the class. @@ -24,16 +27,19 @@ public class ApplicationController : ControllerBase /// Service for Provider model. /// Service for ProviderAdmin model. /// Service for Workshop model. + /// Service for operations with users. public ApplicationController( IApplicationService applicationService, IProviderService providerService, IProviderAdminService providerAdminService, - IWorkshopService workshopService) + IWorkshopService workshopService, + IUserService userService) { this.applicationService = applicationService; this.providerService = providerService; this.providerAdminService = providerAdminService; this.workshopService = workshopService; + this.userService = userService; } /// @@ -252,6 +258,11 @@ public async Task GetByProviderAdminId(Guid providerAdminId, [Fro [HttpPost] public async Task Create(ApplicationCreate applicationDto) { + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to create the application by the blocked provider."); + } + if (applicationDto == null) { return BadRequest("Application is null."); @@ -303,6 +314,11 @@ public async Task Create(ApplicationCreate applicationDto) [HttpPut] public async Task Update(ApplicationUpdate applicationDto) { + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to update the application by the blocked provider."); + } + if (applicationDto is null) { return BadRequest("Application data is not provided."); @@ -360,4 +376,11 @@ public async Task AllowedToReview(Guid parentId, Guid workshopId) { return Ok(await applicationService.AllowedToReview(parentId, workshopId).ConfigureAwait(false)); } + + private async Task IsCurrentUserBlocked() + { + var userId = GettingUserProperties.GetUserId(User); + + return await userService.IsBlocked(userId); + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs index 93c616e5bd..68ea5ff20e 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; using OutOfSchool.Common.PermissionsModule; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models.BlockedProviderParent; @@ -16,15 +17,21 @@ namespace OutOfSchool.WebApi.Controllers.V1; public class BlockedProviderParentController : ControllerBase { private readonly IBlockedProviderParentService blockedProviderParentService; + private readonly IUserService userService; + private string currentUserId; /// /// Initializes a new instance of the class. /// /// Service for BlockedProviderParent model. + /// Service for operations with users. public BlockedProviderParentController( - IBlockedProviderParentService blockedProviderParentService) + IBlockedProviderParentService blockedProviderParentService, + IUserService userService) { this.blockedProviderParentService = blockedProviderParentService; + this.userService = userService; + currentUserId = GettingUserProperties.GetUserId(User); } /// @@ -44,8 +51,12 @@ public BlockedProviderParentController( [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task Block(BlockedProviderParentBlockDto blockedProviderParentBlockDto) { - var userId = GettingUserProperties.GetUserId(HttpContext); - var result = await blockedProviderParentService.Block(blockedProviderParentBlockDto, userId).ConfigureAwait(false); + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to block the parent by the blocked provider."); + } + + var result = await blockedProviderParentService.Block(blockedProviderParentBlockDto, currentUserId).ConfigureAwait(false); if (!result.Succeeded) { @@ -77,8 +88,12 @@ public async Task Block(BlockedProviderParentBlockDto blockedProv [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task UnBlock(BlockedProviderParentUnblockDto blockedProviderParentUnblockDto) { - var userId = GettingUserProperties.GetUserId(HttpContext); - var result = await blockedProviderParentService.Unblock(blockedProviderParentUnblockDto, userId).ConfigureAwait(false); + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to unblock the parent by the blocked provider."); + } + + var result = await blockedProviderParentService.Unblock(blockedProviderParentUnblockDto, currentUserId).ConfigureAwait(false); if (!result.Succeeded) { @@ -110,4 +125,9 @@ public async Task GetBlock(Guid parentId, Guid providerId) { return Ok(await blockedProviderParentService.GetBlock(parentId, providerId).ConfigureAwait(false)); } + + private async Task IsCurrentUserBlocked() + { + return await userService.IsBlocked(currentUserId); + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs index 66a2b0802b..683c8746d3 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs @@ -6,6 +6,7 @@ using OutOfSchool.Services.Models; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models; +using OutOfSchool.WebApi.Services; namespace OutOfSchool.WebApi.Controllers; @@ -16,15 +17,18 @@ namespace OutOfSchool.WebApi.Controllers; public class ProviderAdminController : Controller { private readonly IProviderAdminService providerAdminService; + private readonly IUserService userService; private readonly ILogger logger; private string path; private string userId; public ProviderAdminController( IProviderAdminService providerAdminService, + IUserService userService, ILogger logger) { this.providerAdminService = providerAdminService; + this.userService = userService; this.logger = logger; } @@ -50,6 +54,11 @@ public async Task Create(CreateProviderAdminDto providerAdmin) { logger.LogDebug($"{path} started. User(id): {userId}."); + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to create the provider admin by the blocked provider."); + } + if (!ModelState.IsValid) { logger.LogError($"Input data was not valid for User(id): {userId}"); @@ -86,6 +95,11 @@ await HttpContext.GetTokenAsync("access_token").ConfigureAwait(false)) [HttpPut] public async Task Update(Guid providerId, UpdateProviderAdminDto providerAdminModel) { + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to update the provider admin by the blocked provider."); + } + if (!ModelState.IsValid) { return BadRequest(ModelState); @@ -133,6 +147,11 @@ public async Task Delete(string providerAdminId, Guid providerId) { logger.LogDebug($"{path} started. User(id): {userId}."); + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to delete the provider admin by the blocked provider."); + } + var response = await providerAdminService.DeleteProviderAdminAsync( providerAdminId, userId, @@ -166,6 +185,11 @@ public async Task Block(string providerAdminId, Guid providerId, b return BadRequest("IsBlocked parameter is required"); } + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to block the provider admin by the blocked provider."); + } + var response = await providerAdminService.BlockProviderAdminAsync( providerAdminId, userId, @@ -293,6 +317,11 @@ public async Task Reinvite(string providerAdminId) { logger.LogDebug($"{path} started. User(id): {userId}."); + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to reinvite the provider admin by the blocked provider."); + } + var response = await providerAdminService.ReinviteProviderAdminAsync( providerAdminId, userId, @@ -313,4 +342,9 @@ await HttpContext.GetTokenAsync("access_token").ConfigureAwait(false)) return Ok(); }); } + + private async Task IsCurrentUserBlocked() + { + return await userService.IsBlocked(userId); + } } diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs index 90245b596c..14116ab73b 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs @@ -19,6 +19,7 @@ public class WorkshopController : ControllerBase private readonly IWorkshopServicesCombiner combinedWorkshopService; private readonly IProviderService providerService; private readonly IProviderAdminService providerAdminService; + private readonly IUserService userService; private readonly IStringLocalizer localizer; private readonly AppDefaultsConfig options; @@ -28,12 +29,14 @@ public class WorkshopController : ControllerBase /// Service for operations with Workshops. /// Service for Provider model. /// Service for ProviderAdmin model. + /// Service for operations with users. /// Localizer. /// Application default values. public WorkshopController( IWorkshopServicesCombiner combinedWorkshopService, IProviderService providerService, IProviderAdminService providerAdminService, + IUserService userService, IStringLocalizer localizer, IOptions options) { @@ -41,6 +44,7 @@ public WorkshopController( this.combinedWorkshopService = combinedWorkshopService; this.providerAdminService = providerAdminService; this.providerService = providerService; + this.userService = userService; this.options = options.Value; } @@ -257,6 +261,11 @@ public async Task Create(WorkshopDTO dto) return BadRequest(ModelState); } + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to create the workshop by the blocked provider."); + } + var userHasRights = await this.IsUserProvidersOwnerOrAdmin(dto.ProviderId).ConfigureAwait(false); if (!userHasRights) { @@ -326,6 +335,11 @@ public async Task Update(WorkshopDTO dto) return BadRequest(ModelState); } + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to update the workshop by the blocked provider."); + } + var userHasRights = await this.IsUserProvidersOwnerOrAdmin(dto.ProviderId, dto.Id).ConfigureAwait(false); if (!userHasRights) @@ -355,6 +369,11 @@ public async Task Update(WorkshopDTO dto) [HttpPut] public async Task UpdateStatus([FromBody] WorkshopStatusDto request) { + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to update the workshop by the blocked provider."); + } + var providerId = await providerService.GetProviderIdForWorkshopById(request.WorkshopId).ConfigureAwait(false); if (await providerService.IsProviderBlocked(providerId).ConfigureAwait(false)) @@ -402,13 +421,6 @@ public async Task UpdateStatus([FromBody] WorkshopStatusDto reque [HttpDelete("{id}")] public async Task Delete(Guid id) { - var providerId = await providerService.GetProviderIdForWorkshopById(id).ConfigureAwait(false); - - if (await providerService.IsProviderBlocked(providerId).ConfigureAwait(false)) - { - return StatusCode(403, "It is forbidden to delete workshops at blocked providers"); - } - var workshop = await combinedWorkshopService.GetById(id).ConfigureAwait(false); if (workshop is null) @@ -458,4 +470,11 @@ private async Task IsUserProvidersOwnerOrAdmin(Guid providerId, Guid works return false; } + + private async Task IsCurrentUserBlocked() + { + var userId = GettingUserProperties.GetUserId(User); + + return await userService.IsBlocked(userId); + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/IUserService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/IUserService.cs index 241c34ba85..83543ebc3e 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/IUserService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/IUserService.cs @@ -25,4 +25,11 @@ public interface IUserService /// User entity to add. /// A representing the result of the asynchronous operation. Task Update(ShortUserDto dto); + + /// + /// Check if entity is blocked. + /// + /// Key in the table. + /// . + Task IsBlocked(string id); } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/UserService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/UserService.cs index fa8dc4fa81..f45faa1af4 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/UserService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/UserService.cs @@ -99,4 +99,20 @@ public async Task Update(ShortUserDto dto) throw; } } + + public async Task IsBlocked(string id) + { + logger.LogInformation("Checking if the User is blocked was started. Getting user by Id = {id}.", id); + + var user = await repository.GetById(id).ConfigureAwait(false); + + if (user is null) + { + throw new ArgumentException(localizer["There is no User in the Db with such an id"], nameof(id)); + } + + logger.LogInformation("Successfully got the User with Id = {id}.", id); + + return user.IsBlocked; + } } \ No newline at end of file From b2eda3ad14ffdec5fd0842051e92457fd3f15a81 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Thu, 20 Jul 2023 01:31:58 +0300 Subject: [PATCH 03/11] Fix some tests. --- .../Controllers/ApplicationControllerTests.cs | 5 ++++- .../Controllers/WorkshopControllerTests.cs | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ApplicationControllerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ApplicationControllerTests.cs index 776a30dde2..fb9918cbb8 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ApplicationControllerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ApplicationControllerTests.cs @@ -31,6 +31,7 @@ public class ApplicationControllerTests private Mock workshopService; private Mock providerService; private Mock providerAdminService; + private Mock userService; private string userId; private Guid providerId; @@ -50,6 +51,7 @@ public void Setup() workshopService = new Mock(); providerService = new Mock(); providerAdminService = new Mock(); + userService = new Mock(); userId = Guid.NewGuid().ToString(); @@ -61,7 +63,8 @@ public void Setup() applicationService.Object, providerService.Object, providerAdminService.Object, - workshopService.Object) + workshopService.Object, + userService.Object) { ControllerContext = new ControllerContext() { HttpContext = httpContext.Object }, }; diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs index b3eddc10bf..38ca7027e0 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs @@ -43,6 +43,7 @@ public class WorkshopControllerTests private Mock providerServiceMoq; private Mock providerAdminService; private Mock> localizer; + private Mock userServiceMoq; private string userId; private Mock httpContextMoq; @@ -82,11 +83,13 @@ public void Setup() providerAdminService = new Mock(); localizer = new Mock>(); providerAdminService = new Mock(); + userServiceMoq = new Mock(); controller = new WorkshopController( workshopServiceMoq.Object, providerServiceMoq.Object, providerAdminService.Object, + userServiceMoq.Object, localizer.Object, options.Object) { From 11f3bd28fcc4e713879fe67cd521368275eeb744 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Wed, 26 Jul 2023 01:37:57 +0300 Subject: [PATCH 04/11] Added the blocking the provider admins and deputies after the blocking the provider. --- .../Controllers/ProviderAdminController.cs | 11 +++++ .../Interfaces/IProviderAdminService.cs | 6 +++ .../Services/ProviderAdminService.cs | 48 +++++++++++++++++-- .../Controllers/V1/ProviderController.cs | 5 +- .../Communication/CommunicationConstants.cs | 2 + .../Services/IProviderAdminService.cs | 6 +++ .../Services/IProviderService.cs | 2 +- .../Services/ProviderAdminService.cs | 38 +++++++++++++++ .../Services/ProviderService.cs | 13 ++++- 9 files changed, 124 insertions(+), 7 deletions(-) diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/ProviderAdminController.cs b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/ProviderAdminController.cs index e6de1f1cdb..c2c74c7359 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/ProviderAdminController.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/ProviderAdminController.cs @@ -82,6 +82,17 @@ public async Task Block(string providerAdminId, bool isBlocked) .BlockProviderAdminAsync(providerAdminId, userId, Request.Headers["X-Request-ID"], isBlocked); } + [HttpPut("{providerId}/{isBlocked}")] + [HasPermission(Permissions.ProviderBlock)] + public async Task BlockByProvider(Guid providerId, bool isBlocked) + { + logger.LogDebug($"Received request " + + $"{Request.Headers["X-Request-ID"]}. {path} started. User(id): {userId}"); + + return await providerAdminService + .BlockProviderAdminsAndDeputiesByProviderAsync(providerId, userId, Request.Headers["X-Request-ID"], isBlocked); + } + [HttpPut("{providerAdminId}")] [HasPermission(Permissions.ProviderRemove)] public async Task Reinvite(string providerAdminId) diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Services/Interfaces/IProviderAdminService.cs b/OutOfSchool/OutOfSchool.AuthCommon/Services/Interfaces/IProviderAdminService.cs index f1f2eb5ef8..10c8898ed5 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Services/Interfaces/IProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Services/Interfaces/IProviderAdminService.cs @@ -27,6 +27,12 @@ Task BlockProviderAdminAsync( string requestId, bool isBlocked); + Task BlockProviderAdminsAndDeputiesByProviderAsync( + Guid providerId, + string userId, + string requestId, + bool isBlocked); + Task ReinviteProviderAdminAsync( string providerAdminId, string userId, diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs index afec52a985..e0a409b772 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs @@ -7,6 +7,7 @@ using OutOfSchool.Common.Models; using OutOfSchool.RazorTemplatesData.Models.Emails; using OutOfSchool.Services.Enums; +using OutOfSchool.Services.Models; namespace OutOfSchool.AuthCommon.Services; @@ -493,11 +494,50 @@ await providerAdminChangesLogService.SaveChangesLogAsync(providerAdmin, userId, } } + public async Task BlockProviderAdminsAndDeputiesByProviderAsync( + Guid providerId, + string userId, + string requestId, + bool isBlocked) + { + var mainResponse = new ResponseDto() { IsSuccess = true, HttpStatusCode = HttpStatusCode.OK, Message = string.Empty }; + + var providerAdmins = await providerAdminRepository.GetByFilter(x => x.ProviderId == providerId).ConfigureAwait(false); + + foreach (var providerAdmin in providerAdmins) + { + var response = await BlockProviderAdminAsync(providerAdmin.UserId, userId, requestId, isBlocked); + + if (response.IsSuccess) + { + logger.LogInformation( + "ProviderAdmin(id):{providerAdminId} was successfully blocked by User(id): {userId}. Request(id): {requestId}", + providerAdmin.UserId, + userId, + requestId); + } + else + { + mainResponse.IsSuccess = false; + mainResponse.Message = string.Concat(mainResponse.Message, providerAdmin.UserId, " ", response.HttpStatusCode.ToString(), " "); + + logger.LogInformation( + "ProviderAdmin(id):{providerAdminId} wasn't blocked by User(id): {userId}. Reason {ResponseHttpStatusCode}. Request(id): {requestId}", + providerAdmin.UserId, + userId, + response.HttpStatusCode, + requestId); + } + } + + return mainResponse; + } + public async Task ReinviteProviderAdminAsync( - string providerAdminId, - string userId, - IUrlHelper url, - string requestId) + string providerAdminId, + string userId, + IUrlHelper url, + string requestId) { var executionStrategy = context.Database.CreateExecutionStrategy(); var result = await executionStrategy.Execute(async () => diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderController.cs index 98cb778304..972ed232fb 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderController.cs @@ -1,3 +1,4 @@ +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; using OutOfSchool.WebApi.Common; @@ -223,7 +224,9 @@ public async Task Update(ProviderUpdateDto providerModel) [HttpPut] public async Task Block([FromBody] ProviderBlockDto providerBlockDto) { - var result = await providerService.Block(providerBlockDto); + var result = await providerService.Block( + providerBlockDto, + await HttpContext.GetTokenAsync("access_token").ConfigureAwait(false)); if (!result.IsSuccess) { diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Communication/CommunicationConstants.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Communication/CommunicationConstants.cs index ab292b7710..bafd1d0476 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Communication/CommunicationConstants.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Communication/CommunicationConstants.cs @@ -10,6 +10,8 @@ public static class CommunicationConstants public const string BlockProviderAdmin = "provideradmin/block/"; + public const string BlockProviderAdminByProvider = "provideradmin/blockbyprovider/"; + public const string ReinviteProviderAdmin = "provideradmin/reinvite/"; public const string CreateMinistryAdmin = "ministryadmin/create"; diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/IProviderAdminService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/IProviderAdminService.cs index 4904eeffd5..d49fa9a49d 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/IProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/IProviderAdminService.cs @@ -30,6 +30,12 @@ Task> BlockProviderAdminAsync( string token, bool isBlocked); + Task> BlockProviderAdminsAndDeputiesByProviderAsync( + Guid providerId, + string userId, + string token, + bool isBlocked); + Task GiveAssistantAccessToWorkshop(string userId, Guid workshopId); /// diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs index dd61cb72ca..8e12fc760b 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs @@ -90,7 +90,7 @@ public interface IProviderService /// /// Provider to block/unblock. /// A representing the asynchronous operation. - Task Block(ProviderBlockDto providerBlockDto); + Task Block(ProviderBlockDto providerBlockDto, string token = default); /// /// Get blocked/unblocked status for provider. diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs index 4defed92cd..01b7964670 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs @@ -3,8 +3,11 @@ using AutoMapper; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using MongoDB.Bson.Serialization.IdGenerators; +using MongoDB.Driver; using Nest; using Newtonsoft.Json; +using NuGet.Common; using OutOfSchool.Common.Models; using OutOfSchool.Services.Models; using OutOfSchool.Services.Repository; @@ -295,6 +298,41 @@ public async Task> BlockProviderAdminAsync( : null); } + public async Task> BlockProviderAdminsAndDeputiesByProviderAsync( + Guid providerId, + string userId, + string token, + bool isBlocked) + { + var request = new Request() + { + HttpMethodType = HttpMethodType.Put, + Url = new Uri(identityServerConfig.Authority, string.Concat( + CommunicationConstants.BlockProviderAdminByProvider, + providerId, + new PathString("/"), + isBlocked)), + Token = token, + RequestId = Guid.NewGuid(), + }; + + var response = await SendRequest(request) + .ConfigureAwait(false); + + return response + .FlatMap(r => r.IsSuccess + ? r + : new ErrorResponse + { + HttpStatusCode = r.HttpStatusCode, + Message = r.Message, + }) + .Map(result => result.Result is not null + ? JsonConvert + .DeserializeObject(result.Result.ToString()) + : null); + } + public async Task IsAllowedCreateAsync(Guid providerId, string userId, bool isDeputy) { bool providerAdminDeputy = await providerAdminRepository diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs index e3ee9e0a67..5d56b4751a 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs @@ -5,15 +5,18 @@ using System.Linq.Expressions; using System.Threading.Tasks; using AutoMapper; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OutOfSchool.Common.Enums; using OutOfSchool.Common.Extensions; +using OutOfSchool.Common.Models; using OutOfSchool.Services.Enums; using OutOfSchool.Services.Models; using OutOfSchool.Services.Repository; using OutOfSchool.WebApi.Common; +using OutOfSchool.WebApi.Config; using OutOfSchool.WebApi.Models; using OutOfSchool.WebApi.Models.Providers; using OutOfSchool.WebApi.Services.AverageRatings; @@ -303,7 +306,7 @@ public async Task UpdateStatus(ProviderStatusDto dto, string } /// - public async Task Block(ProviderBlockDto providerBlockDto) + public async Task Block(ProviderBlockDto providerBlockDto, string token = default) { logger.LogInformation($"Block/Unblock Provider by Id started."); @@ -365,7 +368,15 @@ await SendNotification( false, false); + logger.LogInformation($"Block/Unblock the particular provider admins and deputy providers belonging to the Provider starts."); + + var providerAdminsResponse = await providerAdminService + .BlockProviderAdminsAndDeputiesByProviderAsync(provider.Id, currentUserService.UserId, token, providerBlockDto.IsBlocked); + + logger.LogInformation($"Block/Unblock the particular provider admins and deputy providers belonging to the Provider finished."); + var blockedStatus = providerBlockDto.IsBlocked ? "blocked" : "unblocked"; + return new ResponseDto() { Result = providerBlockDto, From 342db541b8f43c02ea2d0cab53e13e7933c94918 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Mon, 14 Aug 2023 01:00:31 +0300 Subject: [PATCH 05/11] Added BlockingType model (manually or automatically deleting). Updated ProviderAdmin model. Changed ProviderAdminService. Changed AuthController. Blocked provider, deputy and provideradmin can log in. --- .../Controllers/AuthController.cs | 3 ++- .../OutOfSchool.Common/Enums/BlockingType.cs | 12 +++++++++++ .../Models/ProviderAdmin.cs | 5 ++++- .../Services/ProviderAdminService.cs | 21 +++++++++++++++++-- 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 OutOfSchool/OutOfSchool.Common/Enums/BlockingType.cs diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs index 740ebe1935..091533d99d 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs @@ -152,7 +152,8 @@ public async Task Login(LoginViewModel model) if (user != null) { - if (user.IsBlocked && (user.Role == Role.Provider.ToString().ToLower() && user.IsDerived)) + //if (user.IsBlocked && (user.Role == Role.Provider.ToString().ToLower() && user.IsDerived)) + if (user.IsBlocked && !(user.Role == Role.Provider.ToString().ToLower())) { logger.LogInformation("User is blocked. Login was failed"); diff --git a/OutOfSchool/OutOfSchool.Common/Enums/BlockingType.cs b/OutOfSchool/OutOfSchool.Common/Enums/BlockingType.cs new file mode 100644 index 0000000000..1733c63315 --- /dev/null +++ b/OutOfSchool/OutOfSchool.Common/Enums/BlockingType.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace OutOfSchool.Common.Enums; + +[JsonConverter(typeof(StringEnumConverter))] +public enum BlockingType +{ + None, + Manually, + Automatically, +} diff --git a/OutOfSchool/OutOfSchool.DataAccess/Models/ProviderAdmin.cs b/OutOfSchool/OutOfSchool.DataAccess/Models/ProviderAdmin.cs index aa742d5092..9814a6c6ba 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Models/ProviderAdmin.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Models/ProviderAdmin.cs @@ -1,4 +1,5 @@ -using System; +using OutOfSchool.Common.Enums; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; @@ -18,6 +19,8 @@ public class ProviderAdmin : IKeyedEntity<(string, Guid)> // "false" executes further inspection into admins-to-workshops relations public bool IsDeputy { get; set; } + public BlockingType BlockingType { get; set; } + public virtual List ManagedWorkshops { get; set; } [NotMapped] diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs index 01b7964670..7914f20f93 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs @@ -8,6 +8,7 @@ using Nest; using Newtonsoft.Json; using NuGet.Common; +using OutOfSchool.Common.Enums; using OutOfSchool.Common.Models; using OutOfSchool.Services.Models; using OutOfSchool.Services.Repository; @@ -249,10 +250,10 @@ public async Task> BlockProviderAdminAsync( }; } - var provideradmin = await providerAdminRepository.GetByIdAsync(providerAdminId, providerId) + var providerAdmin = await providerAdminRepository.GetByIdAsync(providerAdminId, providerId) .ConfigureAwait(false); - if (provideradmin is null) + if (providerAdmin is null) { Logger.LogError("ProviderAdmin(id) {ProviderAdminId} not found. User(id): {UserId}", providerAdminId, userId); @@ -262,6 +263,9 @@ public async Task> BlockProviderAdminAsync( }; } + providerAdmin.BlockingType = isBlocked ? BlockingType.Manually : BlockingType.None; + providerAdmin = await providerAdminRepository.Update(providerAdmin).ConfigureAwait(false); + var request = new Request() { HttpMethodType = HttpMethodType.Put, @@ -304,6 +308,19 @@ public async Task> BlockProviderAdminsAndDep string token, bool isBlocked) { + var providerAdmins = await providerAdminRepository.GetByFilter(x => x.ProviderId == providerId).ConfigureAwait(false); + + var blockingType = isBlocked ? BlockingType.Automatically : BlockingType.None; + + foreach (var providerAdmin in providerAdmins) + { + if (providerAdmin.BlockingType != BlockingType.Manually) + { + providerAdmin.BlockingType = blockingType; + _ = await providerAdminRepository.Update(providerAdmin).ConfigureAwait(false); + } + } + var request = new Request() { HttpMethodType = HttpMethodType.Put, From 5f6f992aba6d27cb558bed71cfbda9029900159c Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Tue, 22 Aug 2023 01:32:12 +0300 Subject: [PATCH 06/11] Forbidden the CRUD (w/o R) and Block operations at the blocked provider. --- .../Services/ProviderAdminService.cs | 5 +- .../Controllers/ProviderControllerTests.cs | 6 ++- .../Controllers/V1/AchievementController.cs | 6 +-- .../Controllers/V1/ApplicationController.cs | 32 +++++++++-- .../V1/BlockedProviderParentController.cs | 26 +++++++-- .../Controllers/V1/ProviderAdminController.cs | 33 ++++++++++-- .../Controllers/V1/WorkshopController.cs | 53 ++++++++++++------- .../Services/Database/IWorkshopService.cs | 7 +++ .../Services/Database/WorkshopService.cs | 5 ++ .../Services/IProviderService.cs | 2 +- .../Services/ProviderService.cs | 6 +-- 11 files changed, 139 insertions(+), 42 deletions(-) diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs index e0a409b772..d196b190f3 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs @@ -4,6 +4,7 @@ using OutOfSchool.AuthCommon.Config; using OutOfSchool.AuthCommon.Config.ExternalUriModels; using OutOfSchool.AuthCommon.Services.Password; +using OutOfSchool.Common.Enums; using OutOfSchool.Common.Models; using OutOfSchool.RazorTemplatesData.Models.Emails; using OutOfSchool.Services.Enums; @@ -502,7 +503,9 @@ public async Task BlockProviderAdminsAndDeputiesByProviderAsync( { var mainResponse = new ResponseDto() { IsSuccess = true, HttpStatusCode = HttpStatusCode.OK, Message = string.Empty }; - var providerAdmins = await providerAdminRepository.GetByFilter(x => x.ProviderId == providerId).ConfigureAwait(false); + var providerAdmins = await providerAdminRepository + .GetByFilter(x => x.ProviderId == providerId && x.BlockingType != BlockingType.Manually) + .ConfigureAwait(false); foreach (var providerAdmin in providerAdmins) { diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs index a2fdaa50c6..1be7b35c6f 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs @@ -398,6 +398,7 @@ public async Task LicenseStatusUpdate_WhenInvalidRequest_ReturnsBadRequestObject } [Test] + [Ignore("Until mock HttpContext.GetTokenAsync()")] public async Task Block_ReturnsProviderBlockDto_IfProviderExist() { // Arrange @@ -416,7 +417,7 @@ public async Task Block_ReturnsProviderBlockDto_IfProviderExist() IsSuccess = true, }; - providerService.Setup(x => x.Block(providerBlockDto)) + providerService.Setup(x => x.Block(providerBlockDto, It.IsAny())) .ReturnsAsync(responseDto); // Act @@ -427,6 +428,7 @@ public async Task Block_ReturnsProviderBlockDto_IfProviderExist() } [Test] + [Ignore("Until mock HttpContext.GetTokenAsync()")] public async Task Block_ReturnsNotFoundResult_IfIdDoesNotExist() { // Arrange @@ -448,7 +450,7 @@ public async Task Block_ReturnsNotFoundResult_IfIdDoesNotExist() var expected = new NotFoundObjectResult(responseDto.Message); - providerService.Setup(x => x.Block(providerBlockDto)) + providerService.Setup(x => x.Block(providerBlockDto, It.IsAny())) .ReturnsAsync(responseDto); // Act diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/AchievementController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/AchievementController.cs index 4353a28920..553280a059 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/AchievementController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/AchievementController.cs @@ -102,7 +102,7 @@ public async Task Create(AchievementCreateDTO achievementDto) { var providerId = await providerService.GetProviderIdForWorkshopById(achievementDto.WorkshopId).ConfigureAwait(false); - if (await providerService.IsProviderBlocked(providerId).ConfigureAwait(false)) + if (await providerService.IsBlocked(providerId).ConfigureAwait(false)) { return StatusCode(403, "It is forbidden to add achievements to workshops at blocked providers"); } @@ -157,7 +157,7 @@ public async Task Update(AchievementCreateDTO achievementDto) { var providerId = await providerService.GetProviderIdForWorkshopById(achievementDto.WorkshopId).ConfigureAwait(false); - if (await providerService.IsProviderBlocked(providerId).ConfigureAwait(false)) + if (await providerService.IsBlocked(providerId).ConfigureAwait(false)) { return StatusCode(403, "It is forbidden to update the workshops achievements at blocked providers"); } @@ -210,7 +210,7 @@ public async Task Delete(Guid id) var providerId = await providerService.GetProviderIdForWorkshopById(achievement.WorkshopId).ConfigureAwait(false); - if (await providerService.IsProviderBlocked(providerId).ConfigureAwait(false)) + if (await providerService.IsBlocked(providerId).ConfigureAwait(false)) { return StatusCode(403, "It is forbidden to delete the workshops achievements at blocked providers"); } diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs index 28dae60b0d..fdd6859009 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using OutOfSchool.Services.Models; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models; using OutOfSchool.WebApi.Models.Application; @@ -258,11 +259,6 @@ public async Task GetByProviderAdminId(Guid providerAdminId, [Fro [HttpPost] public async Task Create(ApplicationCreate applicationDto) { - if (await IsCurrentUserBlocked()) - { - return StatusCode(403, "Forbidden to create the application by the blocked provider."); - } - if (applicationDto == null) { return BadRequest("Application is null."); @@ -273,6 +269,16 @@ public async Task Create(ApplicationCreate applicationDto) return BadRequest(ModelState); } + if (await IsWorkshopOrProviderBlocked(applicationDto.WorkshopId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to create the application at the blocked workshop/provider"); + } + + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to create the application by the blocked provider."); + } + try { var applicationWithAdditionalData = await applicationService.Create(applicationDto).ConfigureAwait(false); @@ -314,6 +320,11 @@ public async Task Create(ApplicationCreate applicationDto) [HttpPut] public async Task Update(ApplicationUpdate applicationDto) { + if (await IsWorkshopOrProviderBlocked(applicationDto.WorkshopId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to update the application at the blocked workshop/provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to update the application by the blocked provider."); @@ -383,4 +394,15 @@ private async Task IsCurrentUserBlocked() return await userService.IsBlocked(userId); } + + private async Task IsWorkshopOrProviderBlocked(Guid workshopId) + { + var isWorkshopBlocked = await workshopService.isBlocked(workshopId).ConfigureAwait(false); + + var providerId = await providerService.GetProviderIdForWorkshopById(workshopId).ConfigureAwait(false); + + var isProviderBlocked = await providerService.IsBlocked(providerId).ConfigureAwait(false); + + return isWorkshopBlocked || isProviderBlocked; + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs index 68ea5ff20e..f03a831c83 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using OutOfSchool.Common.PermissionsModule; +using OutOfSchool.Services.Models; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models.BlockedProviderParent; using OutOfSchool.WebApi.Services; @@ -18,6 +19,7 @@ public class BlockedProviderParentController : ControllerBase { private readonly IBlockedProviderParentService blockedProviderParentService; private readonly IUserService userService; + private readonly IProviderService providerService; private string currentUserId; /// @@ -25,13 +27,16 @@ public class BlockedProviderParentController : ControllerBase /// /// Service for BlockedProviderParent model. /// Service for operations with users. + /// Service for operations with providers. public BlockedProviderParentController( IBlockedProviderParentService blockedProviderParentService, - IUserService userService) + IUserService userService, + IProviderService providerService) { this.blockedProviderParentService = blockedProviderParentService; this.userService = userService; currentUserId = GettingUserProperties.GetUserId(User); + this.providerService = providerService; } /// @@ -51,6 +56,11 @@ public BlockedProviderParentController( [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task Block(BlockedProviderParentBlockDto blockedProviderParentBlockDto) { + if (await IsProviderBlocked(blockedProviderParentBlockDto.ProviderId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to block the parent at the blocked provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to block the parent by the blocked provider."); @@ -88,6 +98,11 @@ public async Task Block(BlockedProviderParentBlockDto blockedProv [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task UnBlock(BlockedProviderParentUnblockDto blockedProviderParentUnblockDto) { + if (await IsProviderBlocked(blockedProviderParentUnblockDto.ProviderId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to unblock the parent at the blocked provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to unblock the parent by the blocked provider."); @@ -126,8 +141,9 @@ public async Task GetBlock(Guid parentId, Guid providerId) return Ok(await blockedProviderParentService.GetBlock(parentId, providerId).ConfigureAwait(false)); } - private async Task IsCurrentUserBlocked() - { - return await userService.IsBlocked(currentUserId); - } + private async Task IsCurrentUserBlocked() => + await userService.IsBlocked(currentUserId); + + private async Task IsProviderBlocked(Guid providerId) => + await providerService.IsBlocked(providerId).ConfigureAwait(false); } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs index 683c8746d3..feceb44f33 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs @@ -18,6 +18,7 @@ public class ProviderAdminController : Controller { private readonly IProviderAdminService providerAdminService; private readonly IUserService userService; + private readonly IProviderService providerService; private readonly ILogger logger; private string path; private string userId; @@ -25,10 +26,12 @@ public class ProviderAdminController : Controller public ProviderAdminController( IProviderAdminService providerAdminService, IUserService userService, + IProviderService providerService, ILogger logger) { this.providerAdminService = providerAdminService; this.userService = userService; + this.providerService = providerService; this.logger = logger; } @@ -54,6 +57,11 @@ public async Task Create(CreateProviderAdminDto providerAdmin) { logger.LogDebug($"{path} started. User(id): {userId}."); + if (await IsProviderBlocked(providerAdmin.ProviderId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to create the provider admin at the blocked provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to create the provider admin by the blocked provider."); @@ -95,6 +103,11 @@ await HttpContext.GetTokenAsync("access_token").ConfigureAwait(false)) [HttpPut] public async Task Update(Guid providerId, UpdateProviderAdminDto providerAdminModel) { + if (await IsProviderBlocked(providerId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to update the provider admin at the blocked provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to update the provider admin by the blocked provider."); @@ -147,6 +160,11 @@ public async Task Delete(string providerAdminId, Guid providerId) { logger.LogDebug($"{path} started. User(id): {userId}."); + if (await IsProviderBlocked(providerId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to delete the provider admin at the blocked provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to delete the provider admin by the blocked provider."); @@ -185,6 +203,11 @@ public async Task Block(string providerAdminId, Guid providerId, b return BadRequest("IsBlocked parameter is required"); } + if (await IsProviderBlocked(providerId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to block the provider admin at the blocked provider"); + } + if (await IsCurrentUserBlocked()) { return StatusCode(403, "Forbidden to block the provider admin by the blocked provider."); @@ -343,8 +366,10 @@ await HttpContext.GetTokenAsync("access_token").ConfigureAwait(false)) }); } - private async Task IsCurrentUserBlocked() - { - return await userService.IsBlocked(userId); - } + private async Task IsCurrentUserBlocked() => + await userService.IsBlocked(userId); + + private async Task IsProviderBlocked(Guid providerId) => + await providerService.IsBlocked(providerId).ConfigureAwait(false); + } diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs index 14116ab73b..fd0309c3a2 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs @@ -251,19 +251,19 @@ public async Task GetByFilter([FromQuery] WorkshopFilter filter, [HttpPost] public async Task Create(WorkshopDTO dto) { - if (await providerService.IsProviderBlocked(dto.ProviderId).ConfigureAwait(false)) + if (await IsProviderBlocked(default, dto.ProviderId).ConfigureAwait(false)) { - return StatusCode(403, "It is forbidden to create workshops at blocked providers"); + return StatusCode(403, "Forbidden to create workshops at blocked providers"); } - if (!ModelState.IsValid) + if (await IsCurrentUserBlocked()) { - return BadRequest(ModelState); + return StatusCode(403, "Forbidden to create the workshop by the blocked provider."); } - if (await IsCurrentUserBlocked()) + if (!ModelState.IsValid) { - return StatusCode(403, "Forbidden to create the workshop by the blocked provider."); + return BadRequest(ModelState); } var userHasRights = await this.IsUserProvidersOwnerOrAdmin(dto.ProviderId).ConfigureAwait(false); @@ -325,19 +325,19 @@ public async Task Create(WorkshopDTO dto) [HttpPut] public async Task Update(WorkshopDTO dto) { - if (await providerService.IsProviderBlocked(dto.ProviderId).ConfigureAwait(false)) + if (await IsProviderBlocked(default, dto.ProviderId).ConfigureAwait(false)) { - return StatusCode(403, "It is forbidden to update workshops at blocked providers"); + return StatusCode(403, "Forbidden to update workshops at blocked providers"); } - if (!ModelState.IsValid) + if (await IsCurrentUserBlocked()) { - return BadRequest(ModelState); + return StatusCode(403, "Forbidden to update the workshop by the blocked provider."); } - if (await IsCurrentUserBlocked()) + if (!ModelState.IsValid) { - return StatusCode(403, "Forbidden to update the workshop by the blocked provider."); + return BadRequest(ModelState); } var userHasRights = await this.IsUserProvidersOwnerOrAdmin(dto.ProviderId, dto.Id).ConfigureAwait(false); @@ -369,16 +369,14 @@ public async Task Update(WorkshopDTO dto) [HttpPut] public async Task UpdateStatus([FromBody] WorkshopStatusDto request) { - if (await IsCurrentUserBlocked()) + if (await IsProviderBlocked(request.WorkshopId).ConfigureAwait(false)) { - return StatusCode(403, "Forbidden to update the workshop by the blocked provider."); + return StatusCode(403, "Forbidden to update workshops statuses at blocked providers"); } - var providerId = await providerService.GetProviderIdForWorkshopById(request.WorkshopId).ConfigureAwait(false); - - if (await providerService.IsProviderBlocked(providerId).ConfigureAwait(false)) + if (await IsCurrentUserBlocked()) { - return StatusCode(403, "It is forbidden to update workshops statuses at blocked providers"); + return StatusCode(403, "Forbidden to update the workshop by the blocked provider."); } var workshop = await combinedWorkshopService.GetById(request.WorkshopId).ConfigureAwait(false); @@ -428,6 +426,16 @@ public async Task Delete(Guid id) return NoContent(); } + if (await IsProviderBlocked(default, workshop.ProviderId).ConfigureAwait(false)) + { + return StatusCode(403, "Forbidden to delete workshops at blocked providers"); + } + + if (await IsCurrentUserBlocked()) + { + return StatusCode(403, "Forbidden to delete the workshop by the blocked provider."); + } + var userHasRights = await this.IsUserProvidersOwnerOrAdmin(workshop.ProviderId).ConfigureAwait(false); if (!userHasRights) { @@ -477,4 +485,13 @@ private async Task IsCurrentUserBlocked() return await userService.IsBlocked(userId); } + + private async Task IsProviderBlocked(Guid workshopId = default, Guid providerId = default) + { + providerId = providerId == default ? + await providerService.GetProviderIdForWorkshopById(workshopId).ConfigureAwait(false) : + providerId; + + return await providerService.IsBlocked(providerId).ConfigureAwait(false); + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs index dfc651fe19..1a71fb6017 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs @@ -145,4 +145,11 @@ Task> GetByProviderId(Guid id, ExcludeIdFilter filter) /// WorkshopId for which we need to get provider owner entity. /// A representing the result of the asynchronous operation. Task GetWorkshopProviderOwnerIdAsync(Guid workshopId); + + /// + /// Returns isBlocked status of the workshop. + /// + /// WorkshopId for which we need to get status. + /// A representing the result of the asynchronous operation. + Task isBlocked(Guid workshopId); } diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs index 939b51ceec..3a257cd79b 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs @@ -610,6 +610,11 @@ public async Task GetWorkshopProviderOwnerIdAsync(Guid workshopId) .ConfigureAwait(false)).ProviderId; } + public async Task isBlocked(Guid workshopId) + { + return (await workshopRepository.GetById(workshopId).ConfigureAwait(false)).IsBlocked; + } + private static void ValidateExcludedIdFilter(ExcludeIdFilter filter) => ModelValidationHelper.ValidateExcludedIdFilter(filter); diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs index 8e12fc760b..571b5124cd 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/IProviderService.cs @@ -97,5 +97,5 @@ public interface IProviderService /// /// Key of the Provider entity in the table. /// A representing the asynchronous operation. - Task IsProviderBlocked(Guid providerId); + Task IsBlocked(Guid providerId); } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs index 5d56b4751a..2437b178c0 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs @@ -368,12 +368,12 @@ await SendNotification( false, false); - logger.LogInformation($"Block/Unblock the particular provider admins and deputy providers belonging to the Provider starts."); + logger.LogInformation("Block/Unblock the particular provider admins and deputy providers belonging to the Provider starts."); var providerAdminsResponse = await providerAdminService .BlockProviderAdminsAndDeputiesByProviderAsync(provider.Id, currentUserService.UserId, token, providerBlockDto.IsBlocked); - logger.LogInformation($"Block/Unblock the particular provider admins and deputy providers belonging to the Provider finished."); + logger.LogInformation("Block/Unblock the particular provider admins and deputy providers belonging to the Provider finished."); var blockedStatus = providerBlockDto.IsBlocked ? "blocked" : "unblocked"; @@ -386,7 +386,7 @@ await SendNotification( }; } - public async Task IsProviderBlocked(Guid providerId) + public async Task IsBlocked(Guid providerId) { return (await providerRepository.GetById(providerId).ConfigureAwait(false)).IsBlocked; } From e110e8e9cbf9b3476cedf2fcd050025d0e2d3b0c Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Tue, 22 Aug 2023 01:32:34 +0300 Subject: [PATCH 07/11] Add migration --- ...gTypePropToProviderAdminEntity.Designer.cs | 2893 +++++++++++++++++ ...ddBlockingTypePropToProviderAdminEntity.cs | 25 + .../OutOfSchoolDbContextModelSnapshot.cs | 3 + 3 files changed, 2921 insertions(+) create mode 100644 OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.Designer.cs create mode 100644 OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.cs diff --git a/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.Designer.cs b/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.Designer.cs new file mode 100644 index 0000000000..c837ed2f8c --- /dev/null +++ b/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.Designer.cs @@ -0,0 +1,2893 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using OutOfSchool.Services; + +#nullable disable + +namespace OutOfSchool.Migrations.Data.Migrations.OutOfSchoolMigrations +{ + [DbContext(typeof(OutOfSchoolDbContext))] + [Migration("20230821212942_AddBlockingTypePropToProviderAdminEntity")] + partial class AddBlockingTypePropToProviderAdminEntity + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("AchievementChild", b => + { + b.Property("AchievementsId") + .HasColumnType("binary(16)"); + + b.Property("ChildrenId") + .HasColumnType("binary(16)"); + + b.HasKey("AchievementsId", "ChildrenId"); + + b.HasIndex("ChildrenId"); + + b.ToTable("AchievementChild"); + }); + + modelBuilder.Entity("ChildSocialGroup", b => + { + b.Property("ChildrenId") + .HasColumnType("binary(16)"); + + b.Property("SocialGroupsId") + .HasColumnType("bigint"); + + b.HasKey("ChildrenId", "SocialGroupsId"); + + b.HasIndex("SocialGroupsId"); + + b.ToTable("ChildSocialGroup"); + }); + + modelBuilder.Entity("DirectionInstitutionHierarchy", b => + { + b.Property("DirectionsId") + .HasColumnType("bigint"); + + b.Property("InstitutionHierarchiesId") + .HasColumnType("binary(16)"); + + b.HasKey("DirectionsId", "InstitutionHierarchiesId"); + + b.HasIndex("InstitutionHierarchiesId"); + + b.ToTable("DirectionInstitutionHierarchy"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("FriendlyName") + .HasColumnType("longtext"); + + b.Property("Xml") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Achievement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("AchievementDate") + .HasColumnType("date"); + + b.Property("AchievementTypeId") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Title") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("varchar(2000)"); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("AchievementTypeId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Achievements"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.AchievementTeacher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AchievementId") + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("AchievementId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("AchievementTeachers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.AchievementType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("TitleEn") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("AchievementTypes"); + + b.HasData( + new + { + Id = 1L, + Title = "Переможці міжнародних та всеукраїнських спортивних змагань (індивідуальних та командних)", + TitleEn = "Winners of international and all-Ukrainian sports competitions (individual and team)" + }, + new + { + Id = 2L, + Title = "Призери та учасники міжнародних, всеукраїнських та призери регіональних конкурсів і виставок наукових, технічних, дослідницьких, інноваційних, ІТ проектів", + TitleEn = "Winners and participants of international, all-Ukrainian and regional contests and exhibitions of scientific, technical, research, innovation, IT projects" + }, + new + { + Id = 3L, + Title = "Реципієнти міжнародних грантів", + TitleEn = "Recipients of international grants" + }, + new + { + Id = 4L, + Title = "Призери міжнародних культурних конкурсів та фестивалів", + TitleEn = "Winners of international cultural competitions and festivals" + }, + new + { + Id = 5L, + Title = "Соціально активні категорії учнів", + TitleEn = "Socially active categories of students" + }, + new + { + Id = 6L, + Title = "Цифрові інструменти Google для закладів вищої та фахової передвищої освіти", + TitleEn = "Google digital tools for institutions of higher and professional pre-higher education" + }, + new + { + Id = 7L, + Title = "Переможці та учасники олімпіад міжнародного та всеукраїнського рівнів", + TitleEn = "Winners and participants of olympiads at the international and all-Ukrainian levels" + }); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("BuildingNumber") + .IsRequired() + .HasMaxLength(15) + .HasColumnType("varchar(15)"); + + b.Property("CATOTTGId") + .HasColumnType("bigint"); + + b.Property("GeoHash") + .HasColumnType("bigint unsigned"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Latitude") + .HasColumnType("double"); + + b.Property("Longitude") + .HasColumnType("double"); + + b.Property("Street") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("CATOTTGId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Application", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("ApprovedTime") + .HasColumnType("datetime(6)"); + + b.Property("ChildId") + .HasColumnType("binary(16)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("IsBlocked") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ParentId") + .HasColumnType("binary(16)"); + + b.Property("RejectionMessage") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Status") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(1); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("ChildId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.AreaAdmin", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("CATOTTGId") + .HasColumnType("bigint"); + + b.Property("InstitutionId") + .HasColumnType("binary(16)"); + + b.HasKey("UserId"); + + b.HasIndex("CATOTTGId"); + + b.HasIndex("InstitutionId"); + + b.ToTable("AreaAdmins"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.AverageRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("EntityId") + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Rate") + .HasColumnType("float"); + + b.Property("RateQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EntityId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("AverageRatings"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.BlockedProviderParent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("DateTimeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateTimeTo") + .HasColumnType("datetime(6)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ParentId") + .HasColumnType("binary(16)"); + + b.Property("ProviderId") + .HasColumnType("binary(16)"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("UserIdBlock") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserIdUnblock") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.HasIndex("ProviderId"); + + b.ToTable("BlockedProviderParents"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.CATOTTG", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Category") + .HasMaxLength(3) + .HasColumnType("varchar(3)"); + + b.Property("Code") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("GeoHash") + .HasColumnType("bigint unsigned"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("IsTop") + .HasColumnType("tinyint(1)"); + + b.Property("Latitude") + .HasColumnType("double"); + + b.Property("Longitude") + .HasColumnType("double"); + + b.Property("Name") + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("NeedCheck") + .HasColumnType("tinyint(1)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.ToTable("CATOTTGs"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChangesLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("EntityIdGuid") + .HasColumnType("binary(16)"); + + b.Property("EntityIdLong") + .HasColumnType("bigint"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("NewValue") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("OldValue") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UpdatedDate") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ChangesLog"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatWorkshop.ChatMessageWorkshop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("ChatRoomId") + .HasColumnType("binary(16)"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ReadDateTime") + .HasColumnType("datetime(6)"); + + b.Property("SenderRoleIsProvider") + .HasColumnType("tinyint(1)"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ChatRoomId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("ChatMessageWorkshops"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatWorkshop.ChatRoomWorkshop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("IsBlocked") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ParentId") + .HasColumnType("binary(16)"); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.HasIndex("WorkshopId"); + + b.ToTable("ChatRoomWorkshops"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Child", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("DateOfBirth") + .IsRequired() + .HasColumnType("date"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("Gender") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("IsParent") + .HasColumnType("tinyint(1)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("MiddleName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("ParentId") + .HasColumnType("binary(16)"); + + b.Property("PlaceOfStudy") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.ToTable("Children"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.CompanyInformation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("CompanyInformation"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.CompanyInformationItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("CompanyInformationId") + .HasColumnType("binary(16)"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("SectionName") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyInformationId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("CompanyInformationItems"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.DateTimeRange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("Workdays") + .HasColumnType("tinyint unsigned"); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("WorkshopId"); + + b.ToTable("DateTimeRanges"); + + b.HasCheckConstraint("CK_DateTimeRanges_EndTimeIsAfterStartTime", "EndTime >= StartTime"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Direction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("Directions"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ElasticsearchSyncRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("Entity") + .HasColumnType("int"); + + b.Property("Operation") + .HasColumnType("int"); + + b.Property("OperationDate") + .HasColumnType("datetime(6)"); + + b.Property("RecordId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.ToTable("ElasticsearchSyncRecords"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Favorite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("UserId"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Favorites"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.FileInDb", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ContentType") + .HasColumnType("longtext"); + + b.Property("Data") + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("FilesInDb"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Images.Image", b => + { + b.Property("EntityId") + .HasColumnType("binary(16)"); + + b.Property("ExternalStorageId") + .HasColumnType("varchar(255)"); + + b.HasKey("EntityId", "ExternalStorageId"); + + b.ToTable("ProviderImages"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Images.Image", b => + { + b.Property("EntityId") + .HasColumnType("binary(16)"); + + b.Property("ExternalStorageId") + .HasColumnType("varchar(255)"); + + b.HasKey("EntityId", "ExternalStorageId"); + + b.ToTable("WorkshopImages"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.InstitutionAdmin", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("InstitutionId") + .HasColumnType("binary(16)"); + + b.HasKey("UserId"); + + b.HasIndex("InstitutionId"); + + b.ToTable("InstitutionAdmins"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.InstitutionStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("InstitutionStatuses"); + + b.HasData( + new + { + Id = 1L, + IsDeleted = false, + Name = "Працює" + }, + new + { + Id = 2L, + IsDeleted = false, + Name = "Перебуває в стані реорганізації" + }, + new + { + Id = 3L, + IsDeleted = false, + Name = "Має намір на реорганізацію" + }, + new + { + Id = 4L, + IsDeleted = false, + Name = "Відсутній" + }); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("Action") + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("GroupedData") + .HasColumnType("longtext"); + + b.Property("ObjectId") + .HasColumnType("binary(16)"); + + b.Property("ReadDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.OperationWithObject", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("EntityId") + .HasColumnType("binary(16)"); + + b.Property("EntityType") + .HasColumnType("int"); + + b.Property("EventDateTime") + .HasColumnType("datetime(6)"); + + b.Property("OperationType") + .HasColumnType("int"); + + b.Property("RowSeparator") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("EntityId"); + + b.HasIndex("EntityType"); + + b.HasIndex("OperationType"); + + b.HasIndex("RowSeparator"); + + b.ToTable("OperationsWithObjects"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Parent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("DateOfBirth") + .IsRequired() + .HasColumnType("date"); + + b.Property("Gender") + .HasColumnType("int"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("UserId"); + + b.ToTable("Parents"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.PermissionsForRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Description") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("PackedPermissions") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("Id"); + + b.ToTable("PermissionsForRoles"); + + b.HasData( + new + { + Id = 1L, + Description = "techadmin permissions", + PackedPermissions = "def\n \r  !()+432578>== + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("ActualAddressId") + .HasColumnType("bigint"); + + b.Property("BlockReason") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("CoverImageId") + .HasColumnType("longtext"); + + b.Property("Director") + .IsRequired() + .HasMaxLength(50) + .IsUnicode(true) + .HasColumnType("varchar(50)"); + + b.Property("DirectorDateOfBirth") + .IsRequired() + .HasColumnType("Date"); + + b.Property("EdrpouIpn") + .IsRequired() + .HasMaxLength(12) + .HasColumnType("varchar(12)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Facebook") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Founder") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("FullTitle") + .IsRequired() + .HasMaxLength(60) + .IsUnicode(true) + .HasColumnType("varchar(60)"); + + b.Property("Instagram") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("InstitutionId") + .HasColumnType("binary(16)"); + + b.Property("InstitutionStatusId") + .HasColumnType("bigint"); + + b.Property("InstitutionType") + .HasColumnType("int"); + + b.Property("IsBlocked") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("LegalAddressId") + .HasColumnType("bigint"); + + b.Property("License") + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("LicenseStatus") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("Ownership") + .HasColumnType("int"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(15) + .HasColumnType("varchar(15)"); + + b.Property("ShortTitle") + .IsRequired() + .HasMaxLength(60) + .IsUnicode(true) + .HasColumnType("varchar(60)"); + + b.Property("Status") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(10); + + b.Property("StatusReason") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("TypeId") + .HasColumnType("bigint"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Website") + .HasMaxLength(256) + .IsUnicode(true) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("ActualAddressId") + .IsUnique(); + + b.HasIndex("EdrpouIpn"); + + b.HasIndex("InstitutionId"); + + b.HasIndex("InstitutionStatusId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("LegalAddressId") + .IsUnique(); + + b.HasIndex("TypeId"); + + b.HasIndex("UserId"); + + b.ToTable("Providers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderAdmin", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("BlockingType") + .HasColumnType("int"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("IsDeputy") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderId") + .HasColumnType("binary(16)"); + + b.HasKey("UserId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderAdmins"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderAdminChangesLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("ManagedWorkshopId") + .HasColumnType("binary(16)"); + + b.Property("OperationDate") + .HasColumnType("datetime(6)"); + + b.Property("OperationType") + .HasColumnType("int"); + + b.Property("ProviderAdminUserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("binary(16)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("ManagedWorkshopId"); + + b.HasIndex("ProviderAdminUserId"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId"); + + b.ToTable("ProviderAdminChangesLog"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderSectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ProviderId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderSectionItems"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Name") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.HasKey("Id"); + + b.ToTable("ProviderTypes"); + + b.HasData( + new + { + Id = 1L, + Name = "Дитячо-юнацькі спортивні школи: комплексні дитячо-юнацькі спортивні школи, дитячо-юнацькі спортивні школи з видів спорту, дитячо-юнацькі спортивні школи для осіб з інвалідністю, спеціалізовані дитячо-юнацькі школи олімпійського резерву, спеціалізовані дитячо-юнацькі спортивні школи для осіб з інвалідністю паралімпійського та дефлімпійського резерву" + }, + new + { + Id = 2L, + Name = "Клуби: військово-патріотичного виховання, дитячо-юнацькі (моряків, річковиків, авіаторів, космонавтів, парашутистів, десантників, прикордонників, радистів, пожежників, автолюбителів, краєзнавців, туристів, етнографів, фольклористів, фізичної підготовки та інших напрямів)" + }, + new + { + Id = 3L, + Name = "Мала академія мистецтв (народних ремесел)" + }, + new + { + Id = 4L, + Name = "Мала академія наук учнівської молоді" + }, + new + { + Id = 5L, + Name = "Оздоровчі заклади для дітей та молоді: дитячо-юнацькі табори (містечка, комплекси): оздоровчі, заміські, профільні, праці та відпочинку, санаторного типу, з денним перебуванням; туристські бази" + }, + new + { + Id = 6L, + Name = "Мистецькі школи: музична, художня, хореографічна, хорова, школа мистецтв тощо" + }, + new + { + Id = 7L, + Name = "Центр, палац, будинок, клуб художньої творчості дітей, юнацтва та молоді, художньо-естетичної творчості учнівської молоді, дитячої та юнацької творчості, естетичного виховання" + }, + new + { + Id = 8L, + Name = "Центр, будинок, клуб еколого-натуралістичної творчості учнівської молоді, станція юних натуралістів" + }, + new + { + Id = 9L, + Name = "Центр, будинок, клуб науково-технічної творчості учнівської молоді, станція юних техніків" + }, + new + { + Id = 10L, + Name = "Центр, будинок, клуб, бюро туризму, краєзнавства, спорту та екскурсій учнівської молоді, туристсько-краєзнавчої творчості учнівської молоді, станція юних туристів" + }, + new + { + Id = 11L, + Name = "Центри: військово-патріотичного та інших напрямів позашкільної освіти" + }, + new + { + Id = 12L, + Name = "Дитяча бібліотека, дитяча флотилія моряків і річковиків, дитячий парк, дитячий стадіон, дитячо-юнацька картинна галерея, дитячо-юнацька студія (хорова, театральна, музична, фольклорна тощо), кімната школяра, курси, студії, школи мистецтв, освітньо-культурні центри національних меншин" + }, + new + { + Id = 13L, + Name = "Інше" + }); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.QuartzJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("LastSuccessLaunch") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("QuartzJobs"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("EntityId") + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ParentId") + .HasColumnType("binary(16)"); + + b.Property("Rate") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EntityId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.RegionAdmin", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("CATOTTGId") + .HasColumnType("bigint"); + + b.Property("InstitutionId") + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.HasKey("UserId"); + + b.HasIndex("CATOTTGId"); + + b.HasIndex("InstitutionId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("RegionAdmins"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SocialGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("NameEn") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("SocialGroups"); + + b.HasData( + new + { + Id = 1L, + Name = "Діти із багатодітних сімей", + NameEn = "Children from large families" + }, + new + { + Id = 2L, + Name = "Діти із малозабезпечених сімей", + NameEn = "Children from low-income families" + }, + new + { + Id = 3L, + Name = "Діти з інвалідністю", + NameEn = "Children with disabilities" + }, + new + { + Id = 4L, + Name = "Діти-сироти", + NameEn = "Orphans" + }, + new + { + Id = 5L, + Name = "Діти, позбавлені батьківського піклування", + NameEn = "Children deprived of parental care" + }); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.StatisticReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("ExternalStorageId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReportDataType") + .HasColumnType("int"); + + b.Property("ReportType") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("varchar(250)"); + + b.HasKey("Id"); + + b.ToTable("StatisticReports"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.StatisticReportCSV", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ApplicationsAmount") + .HasColumnType("int"); + + b.Property("ApplicationsApproved") + .HasColumnType("int"); + + b.Property("CATOTTGCategory") + .HasColumnType("longtext"); + + b.Property("CATOTTGCode") + .HasColumnType("longtext"); + + b.Property("ChildrenStudying") + .HasColumnType("int"); + + b.Property("ChildrenStudyingAchievementsInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("ChildrenStudyingDisabilityInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("ChildrenStudyingFemale") + .HasColumnType("int"); + + b.Property("ChildrenStudyingFemaleInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("ChildrenStudyingInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("ChildrenStudyingLargeFamilyInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("ChildrenStudyingLess18") + .HasColumnType("int"); + + b.Property("ChildrenStudyingOrphanInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("ChildrenStudyingPoorFamilyInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("Complex") + .HasColumnType("longtext"); + + b.Property("EDRPOU") + .HasColumnType("longtext"); + + b.Property("InstitutionTitle") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("binary(16)"); + + b.Property("ProviderName") + .HasColumnType("longtext"); + + b.Property("ProviderType") + .HasColumnType("longtext"); + + b.Property("Region") + .HasColumnType("longtext"); + + b.Property("Settlement") + .HasColumnType("longtext"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Teachers") + .HasColumnType("int"); + + b.Property("TeachersFrom31To40InstitutionHierarchy") + .HasColumnType("int"); + + b.Property("TeachersFrom41To50InstitutionHierarchy") + .HasColumnType("int"); + + b.Property("TeachersFrom51To55InstitutionHierarchy") + .HasColumnType("int"); + + b.Property("TeachersFrom55InstitutionHierarchy") + .HasColumnType("int"); + + b.Property("TeachersInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("TeachersLess30InstitutionHierarchy") + .HasColumnType("int"); + + b.Property("TerritorialCommunity") + .HasColumnType("longtext"); + + b.Property("WorkshopsAmount") + .HasColumnType("int"); + + b.Property("WorkshopsAmountInstitutionHierarchy") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("StatisticReportsCSV"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SubordinationStructure.Institution", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("IsGovernment") + .HasColumnType("tinyint(1)"); + + b.Property("NumberOfHierarchyLevels") + .HasColumnType("int"); + + b.Property("Title") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.ToTable("Institutions"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SubordinationStructure.InstitutionFieldDescription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("HierarchyLevel") + .HasColumnType("int"); + + b.Property("InstitutionId") + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Title") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("InstitutionId"); + + b.HasIndex("IsDeleted"); + + b.ToTable("InstitutionFieldDescriptions"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SubordinationStructure.InstitutionHierarchy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("HierarchyLevel") + .HasColumnType("int"); + + b.Property("InstitutionId") + .HasColumnType("binary(16)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ParentId") + .HasColumnType("binary(16)"); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("InstitutionId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ParentId"); + + b.ToTable("InstitutionHierarchies"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Teacher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("CoverImageId") + .HasColumnType("longtext"); + + b.Property("DateOfBirth") + .HasColumnType("date"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("Gender") + .HasColumnType("int"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("MiddleName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Teachers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.User", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("CreatingTime") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("IsBlocked") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("IsDerived") + .HasColumnType("tinyint(1)"); + + b.Property("IsRegistered") + .HasColumnType("tinyint(1)"); + + b.Property("LastLogin") + .HasColumnType("datetime(6)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MiddleName") + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("MustChangePassword") + .HasColumnType("tinyint(1)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasMaxLength(84) + .IsUnicode(false) + .HasColumnType("char(84)") + .IsFixedLength(); + + b.Property("PhoneNumber") + .HasMaxLength(15) + .IsUnicode(false) + .HasColumnType("varchar(15)") + .IsFixedLength(false); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("Role") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(36) + .IsUnicode(false) + .HasColumnType("varchar(36)") + .IsFixedLength(false); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Workshop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("AvailableSeats") + .HasColumnType("int unsigned"); + + b.Property("CompetitiveSelection") + .HasColumnType("tinyint(1)"); + + b.Property("CompetitiveSelectionDescription") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("CoverImageId") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DisabilityOptionsDesc") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Facebook") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Instagram") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("InstitutionHierarchyId") + .HasColumnType("binary(16)"); + + b.Property("IsBlocked") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Keywords") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("MaxAge") + .HasColumnType("int"); + + b.Property("MinAge") + .HasColumnType("int"); + + b.Property("PayRate") + .HasColumnType("int"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(15) + .HasColumnType("varchar(15)"); + + b.Property("Price") + .HasColumnType("decimal(18,2)"); + + b.Property("ProviderId") + .HasColumnType("binary(16)"); + + b.Property("ProviderOwnership") + .HasColumnType("int"); + + b.Property("ProviderTitle") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("varchar(60)"); + + b.Property("Website") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("WithDisabilityOptions") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("InstitutionHierarchyId"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("ProviderId"); + + b.ToTable("Workshops"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.WorkshopDescriptionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("varchar(2000)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("SectionName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("WorkshopId") + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("IsDeleted"); + + b.HasIndex("WorkshopId"); + + b.ToTable("WorkshopDescriptionItems"); + }); + + modelBuilder.Entity("ProviderAdminWorkshop", b => + { + b.Property("ManagedWorkshopsId") + .HasColumnType("binary(16)"); + + b.Property("ProviderAdminsUserId") + .HasColumnType("varchar(255)"); + + b.HasKey("ManagedWorkshopsId", "ProviderAdminsUserId"); + + b.HasIndex("ProviderAdminsUserId"); + + b.ToTable("ProviderAdminWorkshop"); + }); + + modelBuilder.Entity("AchievementChild", b => + { + b.HasOne("OutOfSchool.Services.Models.Achievement", null) + .WithMany() + .HasForeignKey("AchievementsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Child", null) + .WithMany() + .HasForeignKey("ChildrenId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ChildSocialGroup", b => + { + b.HasOne("OutOfSchool.Services.Models.Child", null) + .WithMany() + .HasForeignKey("ChildrenId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SocialGroup", null) + .WithMany() + .HasForeignKey("SocialGroupsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DirectionInstitutionHierarchy", b => + { + b.HasOne("OutOfSchool.Services.Models.Direction", null) + .WithMany() + .HasForeignKey("DirectionsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.InstitutionHierarchy", null) + .WithMany() + .HasForeignKey("InstitutionHierarchiesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Achievement", b => + { + b.HasOne("OutOfSchool.Services.Models.AchievementType", "AchievementType") + .WithMany() + .HasForeignKey("AchievementTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany() + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AchievementType"); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.AchievementTeacher", b => + { + b.HasOne("OutOfSchool.Services.Models.Achievement", "Achievement") + .WithMany("Teachers") + .HasForeignKey("AchievementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Achievement"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Address", b => + { + b.HasOne("OutOfSchool.Services.Models.CATOTTG", "CATOTTG") + .WithMany() + .HasForeignKey("CATOTTGId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("CATOTTG"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Application", b => + { + b.HasOne("OutOfSchool.Services.Models.Child", "Child") + .WithMany() + .HasForeignKey("ChildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany() + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("Applications") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Child"); + + b.Navigation("Parent"); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.AreaAdmin", b => + { + b.HasOne("OutOfSchool.Services.Models.CATOTTG", "CATOTTG") + .WithMany() + .HasForeignKey("CATOTTGId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.Institution", "Institution") + .WithMany() + .HasForeignKey("InstitutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CATOTTG"); + + b.Navigation("Institution"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.BlockedProviderParent", b => + { + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany() + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.CATOTTG", b => + { + b.HasOne("OutOfSchool.Services.Models.CATOTTG", "Parent") + .WithMany() + .HasForeignKey("ParentId"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChangesLog", b => + { + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatWorkshop.ChatMessageWorkshop", b => + { + b.HasOne("OutOfSchool.Services.Models.ChatWorkshop.ChatRoomWorkshop", "ChatRoom") + .WithMany("ChatMessages") + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChatRoom"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatWorkshop.ChatRoomWorkshop", b => + { + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany("ChatRooms") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("ChatRooms") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Child", b => + { + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.CompanyInformationItem", b => + { + b.HasOne("OutOfSchool.Services.Models.CompanyInformation", "CompanyInformation") + .WithMany("CompanyInformationItems") + .HasForeignKey("CompanyInformationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CompanyInformation"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.DateTimeRange", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", null) + .WithMany("DateTimeRanges") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Favorite", b => + { + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany() + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Images.Image", b => + { + b.HasOne("OutOfSchool.Services.Models.Provider", "Entity") + .WithMany("Images") + .HasForeignKey("EntityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Entity"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Images.Image", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", "Entity") + .WithMany("Images") + .HasForeignKey("EntityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Entity"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.InstitutionAdmin", b => + { + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.Institution", "Institution") + .WithMany() + .HasForeignKey("InstitutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Institution"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Parent", b => + { + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Provider", b => + { + b.HasOne("OutOfSchool.Services.Models.Address", "ActualAddress") + .WithOne() + .HasForeignKey("OutOfSchool.Services.Models.Provider", "ActualAddressId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.Institution", "Institution") + .WithMany("RelatedProviders") + .HasForeignKey("InstitutionId"); + + b.HasOne("OutOfSchool.Services.Models.InstitutionStatus", "InstitutionStatus") + .WithMany("Providers") + .HasForeignKey("InstitutionStatusId"); + + b.HasOne("OutOfSchool.Services.Models.Address", "LegalAddress") + .WithOne() + .HasForeignKey("OutOfSchool.Services.Models.Provider", "LegalAddressId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.ProviderType", "Type") + .WithMany("Providers") + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ActualAddress"); + + b.Navigation("Institution"); + + b.Navigation("InstitutionStatus"); + + b.Navigation("LegalAddress"); + + b.Navigation("Type"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderAdmin", b => + { + b.HasOne("OutOfSchool.Services.Models.Provider", "Provider") + .WithMany("ProviderAdmins") + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderAdminChangesLog", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", "ManagedWorkshop") + .WithMany() + .HasForeignKey("ManagedWorkshopId"); + + b.HasOne("OutOfSchool.Services.Models.User", "ProviderAdminUser") + .WithMany() + .HasForeignKey("ProviderAdminUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ManagedWorkshop"); + + b.Navigation("Provider"); + + b.Navigation("ProviderAdminUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderSectionItem", b => + { + b.HasOne("OutOfSchool.Services.Models.Provider", "Provider") + .WithMany("ProviderSectionItems") + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Rating", b => + { + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany() + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.RegionAdmin", b => + { + b.HasOne("OutOfSchool.Services.Models.CATOTTG", "CATOTTG") + .WithMany() + .HasForeignKey("CATOTTGId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.Institution", "Institution") + .WithMany() + .HasForeignKey("InstitutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CATOTTG"); + + b.Navigation("Institution"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SubordinationStructure.InstitutionFieldDescription", b => + { + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.Institution", "Institution") + .WithMany() + .HasForeignKey("InstitutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Institution"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SubordinationStructure.InstitutionHierarchy", b => + { + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.Institution", "Institution") + .WithMany() + .HasForeignKey("InstitutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.InstitutionHierarchy", "Parent") + .WithMany() + .HasForeignKey("ParentId"); + + b.Navigation("Institution"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Teacher", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("Teachers") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Workshop", b => + { + b.HasOne("OutOfSchool.Services.Models.Address", "Address") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SubordinationStructure.InstitutionHierarchy", "InstitutionHierarchy") + .WithMany() + .HasForeignKey("InstitutionHierarchyId"); + + b.HasOne("OutOfSchool.Services.Models.Provider", "Provider") + .WithMany("Workshops") + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Address"); + + b.Navigation("InstitutionHierarchy"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.WorkshopDescriptionItem", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("WorkshopDescriptionItems") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("ProviderAdminWorkshop", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", null) + .WithMany() + .HasForeignKey("ManagedWorkshopsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.ProviderAdmin", null) + .WithMany() + .HasForeignKey("ProviderAdminsUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Achievement", b => + { + b.Navigation("Teachers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatWorkshop.ChatRoomWorkshop", b => + { + b.Navigation("ChatMessages"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.CompanyInformation", b => + { + b.Navigation("CompanyInformationItems"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.InstitutionStatus", b => + { + b.Navigation("Providers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Parent", b => + { + b.Navigation("ChatRooms"); + + b.Navigation("Children"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Provider", b => + { + b.Navigation("Images"); + + b.Navigation("ProviderAdmins"); + + b.Navigation("ProviderSectionItems"); + + b.Navigation("Workshops"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ProviderType", b => + { + b.Navigation("Providers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SubordinationStructure.Institution", b => + { + b.Navigation("RelatedProviders"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Workshop", b => + { + b.Navigation("Applications"); + + b.Navigation("ChatRooms"); + + b.Navigation("DateTimeRanges"); + + b.Navigation("Images"); + + b.Navigation("Teachers"); + + b.Navigation("WorkshopDescriptionItems"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.cs b/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.cs new file mode 100644 index 0000000000..d401d0c848 --- /dev/null +++ b/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/20230821212942_AddBlockingTypePropToProviderAdminEntity.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace OutOfSchool.Migrations.Data.Migrations.OutOfSchoolMigrations; + +public partial class AddBlockingTypePropToProviderAdminEntity : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "BlockingType", + table: "ProviderAdmins", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "BlockingType", + table: "ProviderAdmins"); + } +} diff --git a/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs b/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs index 345903891e..1357335868 100644 --- a/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs +++ b/OutOfSchool/OutOfSchool.Migrations/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs @@ -1352,6 +1352,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("UserId") .HasColumnType("varchar(255)"); + b.Property("BlockingType") + .HasColumnType("int"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("tinyint(1)") From faebb383b0554bfc05b42639078b88d15b919152 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Tue, 22 Aug 2023 09:20:25 +0300 Subject: [PATCH 08/11] Fixed code smells. --- .../Controllers/AuthController.cs | 3 +-- .../Services/ProviderAdminService.cs | 4 ++-- .../V1/BlockedProviderParentController.cs | 2 +- .../Controllers/V1/WorkshopController.cs | 12 ++++++------ .../Services/ProviderAdminService.cs | 2 +- .../OutOfSchool.WebApi/Services/ProviderService.cs | 2 +- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs index 091533d99d..d51b31a61c 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Controllers/AuthController.cs @@ -152,8 +152,7 @@ public async Task Login(LoginViewModel model) if (user != null) { - //if (user.IsBlocked && (user.Role == Role.Provider.ToString().ToLower() && user.IsDerived)) - if (user.IsBlocked && !(user.Role == Role.Provider.ToString().ToLower())) + if (user.IsBlocked && !user.Role.Equals(Role.Provider.ToString(), StringComparison.InvariantCultureIgnoreCase)) { logger.LogInformation("User is blocked. Login was failed"); diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs index d196b190f3..7aa7360a9c 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs @@ -507,7 +507,7 @@ public async Task BlockProviderAdminsAndDeputiesByProviderAsync( .GetByFilter(x => x.ProviderId == providerId && x.BlockingType != BlockingType.Manually) .ConfigureAwait(false); - foreach (var providerAdmin in providerAdmins) + providerAdmins.Select(async providerAdmin => { var response = await BlockProviderAdminAsync(providerAdmin.UserId, userId, requestId, isBlocked); @@ -531,7 +531,7 @@ public async Task BlockProviderAdminsAndDeputiesByProviderAsync( response.HttpStatusCode, requestId); } - } + }); return mainResponse; } diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs index f03a831c83..b531f912af 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs @@ -20,7 +20,7 @@ public class BlockedProviderParentController : ControllerBase private readonly IBlockedProviderParentService blockedProviderParentService; private readonly IUserService userService; private readonly IProviderService providerService; - private string currentUserId; + private readonly string currentUserId; /// /// Initializes a new instance of the class. diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs index fd0309c3a2..b865cb47e8 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs @@ -251,7 +251,7 @@ public async Task GetByFilter([FromQuery] WorkshopFilter filter, [HttpPost] public async Task Create(WorkshopDTO dto) { - if (await IsProviderBlocked(default, dto.ProviderId).ConfigureAwait(false)) + if (await IsProviderBlocked(dto.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to create workshops at blocked providers"); } @@ -325,7 +325,7 @@ public async Task Create(WorkshopDTO dto) [HttpPut] public async Task Update(WorkshopDTO dto) { - if (await IsProviderBlocked(default, dto.ProviderId).ConfigureAwait(false)) + if (await IsProviderBlocked(dto.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to update workshops at blocked providers"); } @@ -369,7 +369,7 @@ public async Task Update(WorkshopDTO dto) [HttpPut] public async Task UpdateStatus([FromBody] WorkshopStatusDto request) { - if (await IsProviderBlocked(request.WorkshopId).ConfigureAwait(false)) + if (await IsProviderBlocked(Guid.Empty, request.WorkshopId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to update workshops statuses at blocked providers"); } @@ -426,7 +426,7 @@ public async Task Delete(Guid id) return NoContent(); } - if (await IsProviderBlocked(default, workshop.ProviderId).ConfigureAwait(false)) + if (await IsProviderBlocked(workshop.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to delete workshops at blocked providers"); } @@ -486,9 +486,9 @@ private async Task IsCurrentUserBlocked() return await userService.IsBlocked(userId); } - private async Task IsProviderBlocked(Guid workshopId = default, Guid providerId = default) + private async Task IsProviderBlocked(Guid providerId, Guid workshopId = default) { - providerId = providerId == default ? + providerId = providerId == Guid.Empty ? await providerService.GetProviderIdForWorkshopById(workshopId).ConfigureAwait(false) : providerId; diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs index 7914f20f93..226509e06c 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderAdminService.cs @@ -264,7 +264,7 @@ public async Task> BlockProviderAdminAsync( } providerAdmin.BlockingType = isBlocked ? BlockingType.Manually : BlockingType.None; - providerAdmin = await providerAdminRepository.Update(providerAdmin).ConfigureAwait(false); + _ = await providerAdminRepository.Update(providerAdmin).ConfigureAwait(false); var request = new Request() { diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs index 2437b178c0..0005c1a732 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs @@ -370,7 +370,7 @@ await SendNotification( logger.LogInformation("Block/Unblock the particular provider admins and deputy providers belonging to the Provider starts."); - var providerAdminsResponse = await providerAdminService + _ = await providerAdminService .BlockProviderAdminsAndDeputiesByProviderAsync(provider.Id, currentUserService.UserId, token, providerBlockDto.IsBlocked); logger.LogInformation("Block/Unblock the particular provider admins and deputy providers belonging to the Provider finished."); From 63881593bcc89acc673bfda541eef83b99f528d2 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Tue, 22 Aug 2023 09:55:14 +0300 Subject: [PATCH 09/11] Fixed bug --- .../OutOfSchool.AuthCommon/Services/ProviderAdminService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs index 7aa7360a9c..d196b190f3 100644 --- a/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs +++ b/OutOfSchool/OutOfSchool.AuthCommon/Services/ProviderAdminService.cs @@ -507,7 +507,7 @@ public async Task BlockProviderAdminsAndDeputiesByProviderAsync( .GetByFilter(x => x.ProviderId == providerId && x.BlockingType != BlockingType.Manually) .ConfigureAwait(false); - providerAdmins.Select(async providerAdmin => + foreach (var providerAdmin in providerAdmins) { var response = await BlockProviderAdminAsync(providerAdmin.UserId, userId, requestId, isBlocked); @@ -531,7 +531,7 @@ public async Task BlockProviderAdminsAndDeputiesByProviderAsync( response.HttpStatusCode, requestId); } - }); + } return mainResponse; } From bf72facfb916488b342e5a28fd6c896ea441e283 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Tue, 22 Aug 2023 21:54:42 +0300 Subject: [PATCH 10/11] Added TODO to the tests at ProviderControlleTests. --- .../Controllers/ProviderControllerTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs index 1be7b35c6f..225f453af9 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ProviderControllerTests.cs @@ -401,6 +401,8 @@ public async Task LicenseStatusUpdate_WhenInvalidRequest_ReturnsBadRequestObject [Ignore("Until mock HttpContext.GetTokenAsync()")] public async Task Block_ReturnsProviderBlockDto_IfProviderExist() { + // TODO: it's nessesary to mock HttpContext.GetTokenAsync() to run this test. + // Arrange var providerBlockDto = new ProviderBlockDto() { @@ -431,6 +433,8 @@ public async Task Block_ReturnsProviderBlockDto_IfProviderExist() [Ignore("Until mock HttpContext.GetTokenAsync()")] public async Task Block_ReturnsNotFoundResult_IfIdDoesNotExist() { + // TODO: it's needed to mock HttpContext.GetTokenAsync() to run this test. + // Arrange var nonExistentProviderId = Guid.NewGuid(); var providerBlockDto = new ProviderBlockDto() From c1947956b9d07a210d30f651b45536da836ec892 Mon Sep 17 00:00:00 2001 From: Andrii Tsylia Date: Thu, 24 Aug 2023 23:43:37 +0300 Subject: [PATCH 11/11] Code review comments. --- .../Controllers/V1/ApplicationController.cs | 36 ++++++++----------- .../V1/BlockedProviderParentController.cs | 11 ++++++ .../Controllers/V1/ProviderAdminController.cs | 11 ++++++ .../Controllers/V1/WorkshopController.cs | 16 +++++++++ .../Services/Database/IWorkshopService.cs | 2 +- .../Services/Database/WorkshopService.cs | 2 +- .../Services/ProviderService.cs | 1 + 7 files changed, 55 insertions(+), 24 deletions(-) diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs index fdd6859009..26e344e213 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ApplicationController.cs @@ -264,19 +264,19 @@ public async Task Create(ApplicationCreate applicationDto) return BadRequest("Application is null."); } - if (!ModelState.IsValid) + if (await IsWorkshopBlocked(applicationDto.WorkshopId).ConfigureAwait(false)) { - return BadRequest(ModelState); + return StatusCode(403, "Forbidden to create the application at the blocked workshop."); } - if (await IsWorkshopOrProviderBlocked(applicationDto.WorkshopId).ConfigureAwait(false)) + if (await IsCurrentUserBlocked()) { - return StatusCode(403, "Forbidden to create the application at the blocked workshop/provider"); + return StatusCode(403, "Forbidden to create the application by the blocked user."); } - if (await IsCurrentUserBlocked()) + if (!ModelState.IsValid) { - return StatusCode(403, "Forbidden to create the application by the blocked provider."); + return BadRequest(ModelState); } try @@ -320,19 +320,19 @@ public async Task Create(ApplicationCreate applicationDto) [HttpPut] public async Task Update(ApplicationUpdate applicationDto) { - if (await IsWorkshopOrProviderBlocked(applicationDto.WorkshopId).ConfigureAwait(false)) + if (applicationDto is null) { - return StatusCode(403, "Forbidden to update the application at the blocked workshop/provider"); + return BadRequest("Application data is not provided."); } - if (await IsCurrentUserBlocked()) + if (await IsWorkshopBlocked(applicationDto.WorkshopId).ConfigureAwait(false)) { - return StatusCode(403, "Forbidden to update the application by the blocked provider."); + return StatusCode(403, "Forbidden to update the application at the blocked workshop."); } - if (applicationDto is null) + if (await IsCurrentUserBlocked()) { - return BadRequest("Application data is not provided."); + return StatusCode(403, "Forbidden to update the application by the blocked user."); } var workshop = await workshopService.GetById(applicationDto.WorkshopId).ConfigureAwait(false); @@ -395,14 +395,6 @@ private async Task IsCurrentUserBlocked() return await userService.IsBlocked(userId); } - private async Task IsWorkshopOrProviderBlocked(Guid workshopId) - { - var isWorkshopBlocked = await workshopService.isBlocked(workshopId).ConfigureAwait(false); - - var providerId = await providerService.GetProviderIdForWorkshopById(workshopId).ConfigureAwait(false); - - var isProviderBlocked = await providerService.IsBlocked(providerId).ConfigureAwait(false); - - return isWorkshopBlocked || isProviderBlocked; - } + private async Task IsWorkshopBlocked(Guid workshopId) => + await workshopService.IsBlocked(workshopId).ConfigureAwait(false); } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs index b531f912af..1e30bd7c91 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/BlockedProviderParentController.cs @@ -7,6 +7,7 @@ using OutOfSchool.Common.PermissionsModule; using OutOfSchool.Services.Models; using OutOfSchool.WebApi.Common; +using OutOfSchool.WebApi.Models.Application; using OutOfSchool.WebApi.Models.BlockedProviderParent; using OutOfSchool.WebApi.Services; @@ -56,6 +57,11 @@ public BlockedProviderParentController( [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task Block(BlockedProviderParentBlockDto blockedProviderParentBlockDto) { + if (blockedProviderParentBlockDto == null) + { + return BadRequest("ProviderParent is null."); + } + if (await IsProviderBlocked(blockedProviderParentBlockDto.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to block the parent at the blocked provider"); @@ -98,6 +104,11 @@ public async Task Block(BlockedProviderParentBlockDto blockedProv [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task UnBlock(BlockedProviderParentUnblockDto blockedProviderParentUnblockDto) { + if (blockedProviderParentUnblockDto == null) + { + return BadRequest("ProviderParent is null."); + } + if (await IsProviderBlocked(blockedProviderParentUnblockDto.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to unblock the parent at the blocked provider"); diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs index feceb44f33..d69a2fd870 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ProviderAdminController.cs @@ -6,6 +6,7 @@ using OutOfSchool.Services.Models; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models; +using OutOfSchool.WebApi.Models.Application; using OutOfSchool.WebApi.Services; namespace OutOfSchool.WebApi.Controllers; @@ -57,6 +58,11 @@ public async Task Create(CreateProviderAdminDto providerAdmin) { logger.LogDebug($"{path} started. User(id): {userId}."); + if (providerAdmin == null) + { + return BadRequest("ProviderAdmin is null."); + } + if (await IsProviderBlocked(providerAdmin.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to create the provider admin at the blocked provider"); @@ -103,6 +109,11 @@ await HttpContext.GetTokenAsync("access_token").ConfigureAwait(false)) [HttpPut] public async Task Update(Guid providerId, UpdateProviderAdminDto providerAdminModel) { + if (providerAdminModel == null) + { + return BadRequest("ProviderAdmin is null."); + } + if (await IsProviderBlocked(providerId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to update the provider admin at the blocked provider"); diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs index b865cb47e8..dc49bbbe1f 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs @@ -4,6 +4,7 @@ using OutOfSchool.Services.Enums; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models; +using OutOfSchool.WebApi.Models.BlockedProviderParent; using OutOfSchool.WebApi.Models.Workshop; namespace OutOfSchool.WebApi.Controllers.V1; @@ -251,6 +252,11 @@ public async Task GetByFilter([FromQuery] WorkshopFilter filter, [HttpPost] public async Task Create(WorkshopDTO dto) { + if (dto == null) + { + return BadRequest("Workshop is null."); + } + if (await IsProviderBlocked(dto.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to create workshops at blocked providers"); @@ -325,6 +331,11 @@ public async Task Create(WorkshopDTO dto) [HttpPut] public async Task Update(WorkshopDTO dto) { + if (dto == null) + { + return BadRequest("Workshop is null."); + } + if (await IsProviderBlocked(dto.ProviderId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to update workshops at blocked providers"); @@ -369,6 +380,11 @@ public async Task Update(WorkshopDTO dto) [HttpPut] public async Task UpdateStatus([FromBody] WorkshopStatusDto request) { + if (request == null) + { + return BadRequest("WorkshopStatus is null."); + } + if (await IsProviderBlocked(Guid.Empty, request.WorkshopId).ConfigureAwait(false)) { return StatusCode(403, "Forbidden to update workshops statuses at blocked providers"); diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs index 1a71fb6017..1743f43f1e 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Database/IWorkshopService.cs @@ -151,5 +151,5 @@ Task> GetByProviderId(Guid id, ExcludeIdFilter filter) /// /// WorkshopId for which we need to get status. /// A representing the result of the asynchronous operation. - Task isBlocked(Guid workshopId); + Task IsBlocked(Guid workshopId); } diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs index 3a257cd79b..d50bb97183 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs @@ -610,7 +610,7 @@ public async Task GetWorkshopProviderOwnerIdAsync(Guid workshopId) .ConfigureAwait(false)).ProviderId; } - public async Task isBlocked(Guid workshopId) + public async Task IsBlocked(Guid workshopId) { return (await workshopRepository.GetById(workshopId).ConfigureAwait(false)).IsBlocked; } diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs index 0005c1a732..7cf25266cf 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs @@ -370,6 +370,7 @@ await SendNotification( logger.LogInformation("Block/Unblock the particular provider admins and deputy providers belonging to the Provider starts."); + // TODO: It's need to consider how we might use the result of the blocking provider admins and deputies who belong to the provider. _ = await providerAdminService .BlockProviderAdminsAndDeputiesByProviderAsync(provider.Id, currentUserService.UserId, token, providerBlockDto.IsBlocked);