using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using xCommons.Extensions; using xDataService.Configuration; using xDataService.Extensions; using xExceptions.Constants; using xIdentityModels.Dtos; using xIdentityService.Extensions; using xIdentityService.Interfaces; using xModels.Dtos; using xWebinarService.Constants; using xWebinarService.Interfaces; using xWebinarService.Interfaces.Entities; using xWebinarService.Models.Dtos; using xWebinarService.Models.Entities; namespace xWebinarService.Providers { /// /// Implement all Webinar Related Things here ... /// public class XWebinarProvider : IXWebinarProvider { // #region Props ... public IXIdentityProvider IdentityProvider { get; } public IXWebinarRepository WebinarRepository { get; } public XDataServiceConfiguration DataSercviceConfiguration { get; } public IXWebinarTitleResourceProvider TitleResourceProvider { get; } public IXWebinarSubscriberRepository WebinarSubscriberRepository { get; } public IXWebinarDescriptionResourceProvider DescriptionResourceProvider { get; } #endregion // #region Constructor ... public XWebinarProvider( IXIdentityProvider identityProvider, IXWebinarRepository webinarRepository, XDataServiceConfiguration dataSercviceConfiguration, IXWebinarTitleResourceProvider titleResourceProvider, IXWebinarSubscriberRepository webinarSubscriberRepository, IXWebinarDescriptionResourceProvider descriptionResourceProvider ) { // IdentityProvider = identityProvider; WebinarRepository = webinarRepository; DataSercviceConfiguration = dataSercviceConfiguration; TitleResourceProvider = titleResourceProvider; WebinarSubscriberRepository = webinarSubscriberRepository; DescriptionResourceProvider = descriptionResourceProvider; } #endregion // #region Tools ... /// /// Converts Specified XWebinar Entity to it's Corresponding Dto Presentation /// and also Fill Owner and Title/Description Resources ... /// /// /// public async Task ToXWebinarDto(XWebinar model) { // // Validate ... bool isValid = !model.IsNullOrDefault() && !model.Title.IsNullOrEmpty() && !model.OwnerId.IsNullOrEmpty() && !model.Description.IsNullOrEmpty(); if (!isValid) { XException.InvalidArgs.Throw(); } // var result = new XWebinarDto { // // Set Common Properties ... Id = model.Id, Type = model.Type, OwnerId = model.OwnerId, CreatedOn = model.CreatedOn, // // Fill Resources ... Title = await TitleResourceProvider.GetResource(model.Id.ToString()), Description = await DescriptionResourceProvider.GetResource(model.Id.ToString()) }; // // Prepare Inner API Providers Device Dto ... var device = await IdentityProvider.GetDevice(); var userInfo = await IdentityProvider.GetUserInfo( device: device, userSelectByParam: model.OwnerId ); isValid = !userInfo.IsNullOrDefault(); if (!isValid) { XException.NotFound.Throw(); } // result.Owner = userInfo.ToXPersonDto(); // return result; } /// /// Converts Specified WebinarSubscriber Entity to it's Dto Presentation ... /// /// /// public async Task ToXWebinarSubscriberDto(XWebinarSubscriber model) { // bool isValid = !model.IsNull() && !model.SubscriberId.IsNullOrEmpty(); if (!isValid) { XException.InvalidArgs.Throw(); } // // Retrieve User Info ... var device = await IdentityProvider.GetDevice(); var userInfo = await IdentityProvider.GetUserInfo( device: device, userSelectByParam: model.SubscriberId ); isValid = !userInfo.IsNullOrDefault(); if (!isValid) { XException.NotFound.Throw(); } // var result = new XWebinarSubscriberDto { Id = model.Id, SubscriberId = model.SubscriberId, SubscribedOn = model.SubscribedOn, Subscriber = userInfo.ToXPersonDto(), }; // return result; } #endregion // #region Actions ... /// /// Create Webinar ... /// /// /// public async Task CreateWebinar(XWebinarDto item) { // // Validate ... bool isValid = !item.IsNull() && !item.Title.IsNull() && !item.Description.IsNull() && !item.OwnerId.IsNullOrEmpty(); if (!isValid) { XException.InvalidArgs.Throw(); } // // Check Title and Descriptions Has Value ... isValid = item.Title.Locales.HasChild() && item.Description.Locales.HasChild() && item.Title.Locales.All(l => !l.Value.IsNullOrEmpty()) && item.Description.Locales.All(l => !l.Value.IsNullOrEmpty()); if (!isValid) { XException.InvalidArgs.Throw(); } // // Prepare Temp Webinar Entity ... string tmpValue = Guid.NewGuid().ToString(); var entity = new XWebinar { Type = item.Type, OwnerId = item.OwnerId, Title = "T_" + tmpValue, CreatedOn = DateTime.UtcNow, Description = "D_" + tmpValue, }; entity = await WebinarRepository.AddAsync(entity); isValid = !entity.IsNullOrDefault() && !entity.Id.IsDefaultGuid(); if (!isValid) { XException.ActionFailed.Throw(); } // // Use Entity ID as Resources Suffix ... Guid suffixGuid = entity.Id; string suffix = suffixGuid.ToString(); var titleResource = await TitleResourceProvider.AddResource( suffix: suffix, item: item.Title ); var descriptionResource = await DescriptionResourceProvider.AddResource( suffix: suffix, item: item.Description ); isValid = // // Title Resource Validation ... !titleResource.IsNullOrDefault() && titleResource.Locales.HasChild() && !titleResource.Resource.IsNullOrEmpty() && // // Description Resource Validation ... !descriptionResource.IsNullOrDefault() && descriptionResource.Locales.HasChild() && !descriptionResource.Resource.IsNullOrEmpty() ; if (!isValid) { // // Rollback ... try { // entity.Id = suffixGuid; await TitleResourceProvider.Remove(suffix); await WebinarRepository.RemoveAsync(entity); await DescriptionResourceProvider.Remove(suffix); } catch { } // XException.ActionFailed.Throw(); } // // Update Title/Description Resources ... entity.Title = titleResource.Resource; entity.Description = descriptionResource.Resource; entity = await WebinarRepository.UpdateAsync(entity.Id, entity); isValid = !entity.IsNullOrDefault(); if (!isValid) { // // Rollback ... try { // entity.Id = suffixGuid; await TitleResourceProvider.Remove(suffix); await WebinarRepository.RemoveAsync(entity); await DescriptionResourceProvider.Remove(suffix); } catch { } // XException.ActionFailed.Throw(); } // // Convert Entity to Dto ... var result = await ToXWebinarDto(entity); return result; } /// /// Update a Webinar ... /// /// /// public async Task UpdateWebinar(XWebinarDto item) { // // Validate ... bool isValid = !item.Id.IsNull() && !item.IsNullOrDefault() && !item.Id.IsDefaultGuid() && !item.OwnerId.IsNullOrEmpty() && !item.Title.IsNullOrDefault() && !item.Description.IsNullOrDefault() && // // Title Validation ... item.Title.Locales.HasChild() && !item.Title.Resource.IsNullOrEmpty() && item.Title.Locales.All(l => !l.IsNullOrDefault() && !l.Value.IsNullOrEmpty() && !l.Language.IsNullOrEmpty()) && // // Description Validation ... item.Description.Locales.HasChild() && !item.Description.Resource.IsNullOrEmpty() && item.Description.Locales.All(l => !l.IsNullOrDefault() && !l.Value.IsNullOrEmpty() && !l.Language.IsNullOrEmpty()) ; if (!isValid) { XException.InvalidArgs.Throw(); } // // Check Item Exists ... isValid = await WebinarRepository.IsExistsAsync(item.Id); if (!isValid) { XException.NotFound.Throw(); } // // Retrieve Entity ... var entity = await WebinarRepository.GetAsync(item.Id); // // Check if Type Change Update it ... if (entity.Type != item.Type) { // entity.Type = item.Type; entity = await WebinarRepository.UpdateAsync(entity.Id, entity); } // // Retrieve Entity Dto ... var entityDto = await ToXWebinarDto(entity); // // Exclude Must Remove items ... var mustRemoveTitleLocals = entityDto.Title.Locales.Where(e => !item.Title.Locales.Any(l => l.Language.ToNormalString() == e.Language.ToNormalString()) ); var mustRemoveDescriptionLocals = entityDto.Description.Locales.Where(e => !item.Description.Locales.Any(l => l.Language.ToNormalString() == e.Language.ToNormalString()) ); // // Remove Specified Locales ... // // Titles ... foreach (var locale in mustRemoveTitleLocals) { // try { // await TitleResourceProvider.Remove( resource: entity.Title, language: locale.Language ); } catch { } } // // Descriptions ... foreach (var locale in mustRemoveDescriptionLocals) { // try { // await DescriptionResourceProvider.Remove( resource: entity.Description, language: locale.Language ); } catch { } } // // Add Or Update Locales ... // // Title ... var titleAddedLocales = await TitleResourceProvider.AddOrUpdate( resource: entity.Title, locales: entityDto.Title.Locales ); // // Description ... var descriptionAddedLocales = await DescriptionResourceProvider.AddOrUpdate( resource: entity.Description, locales: entityDto.Description.Locales ); // var result = await ToXWebinarDto(entity); // return result; } /// /// Retrieve Specified Webinar ... /// /// /// public async Task GetWebinar(Guid id) { // var entity = await WebinarRepository.GetAsync(id); if (entity.IsNullOrDefault()) { XException.NotFound.Throw(); } // var result = await ToXWebinarDto(entity); return result; } /// /// Retrieve all Exists Webinars ... /// /// public async Task> GetWebinars() { // var list = await WebinarRepository.GetAllAsync(); var result = await list.SelectAsync(async l => await ToXWebinarDto(l)); // return result; } /// /// Query Webinars ... /// /// /// public async Task> QueryWebinars(XQuery query) { // // Validate ... if (query.IsNull()) { XException.InvalidArgs.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataSercviceConfiguration); // // Since in Resourceable Entities we have to Search on Locales // we Must Implement Senario Custom ... var totalEntities = await WebinarRepository.GetAllAsync(); var items = await totalEntities.SelectAsync(async e => await ToXWebinarDto(e)); var totalItemsCount = items.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { // items = items .ApplyFilter(query.Filter); } int filteredItemsCount = items.Count(); // // Count Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Paging and Sorting ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items.ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items.ApplyPaging( query.Page, query.PageSize ); } // // Prepare Result ... var result = new XQueryResult { Items = items, Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return result; } /// /// Remove Specified Webinar ... /// /// /// /// public async Task RemoveWebinar( Guid webinarId, string requesterUserSelectByParam = null ) { // bool result = false; // // Validate ... result = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!result) { return result; } // // Get Entity ... var entity = await WebinarRepository.GetAsync(webinarId); result = !entity.IsNullOrDefault(); if (!result) { return result; } // // Check Permissions ... result = entity.OwnerId == requesterUserSelectByParam; if (!result) { return result; } // // Handle Remove ... var subscribers = await GetSubscribers( webinarId: webinarId, requesterUserSelectByParam: requesterUserSelectByParam ); try { // await subscribers.SelectAsync(async s => await Unsubscribe( webinarId: webinarId, subscriberId: s.SubscriberId, requesterUserSelectByParam: requesterUserSelectByParam )); // string resourceID = webinarId.ToString(); await TitleResourceProvider.Remove(resourceID); await DescriptionResourceProvider.Remove(resourceID); // await WebinarRepository.RemoveAsync(webinarId); } catch { } // // Check Entity Removed ... result = !await WebinarRepository.IsExistsAsync(webinarId); // return result; } #endregion // #region WebinarSubscriber ... /// /// Subscribe a User to Webinar ... /// /// /// /// /// public async Task Subscribe( Guid webinarId, string subscriberId, string requesterUserSelectByParam = null ) { // var result = false; // // Validate ... result = !webinarId.IsNull() && !webinarId.IsDefaultGuid() && !subscriberId.IsNullOrEmpty(); if (!result) { return result; } // // Check Webinar Exists ... result = await WebinarRepository.IsExistsAsync(webinarId); if (!result) { return result; } // // Retrieve Webinar Entity ... var webinar = await WebinarRepository.GetAsync(webinarId); // // Check Webinar Enabled ... result = webinar.Enabled || requesterUserSelectByParam == webinar.OwnerId; if (!result) { return result; } // // Check Webinar Type ... result = webinar.Type == XWebinarType.Public || requesterUserSelectByParam == webinar.OwnerId; if (!result) { return result; } // // Check User Exists ... var device = await IdentityProvider.GetDevice(); XOpenActionUserInfoDto userInfo = null; try { // userInfo = await IdentityProvider.GetUserInfo( device: device, userSelectByParam: subscriberId ); } catch { } result = !userInfo.IsNullOrDefault(); if (!result) { return result; } // // Create Subscription Model ... var entity = new XWebinarSubscriber { WebinarId = webinarId, SubscriberId = subscriberId, SubscribedOn = DateTime.UtcNow, }; entity = await WebinarSubscriberRepository.AddAsync(entity); result = !entity.IsNullOrDefault(); // return result; } /// /// Check Specified User Subscribed on a Webinar or not ... /// /// /// /// public async Task IsSubscribed( Guid webinarId, string subscriberId ) { // bool result = false; // // Validate ... result = !webinarId.IsNull() && !webinarId.IsDefaultGuid() && !subscriberId.IsNullOrEmpty(); if (!result) { return result; } // // Check Webinar Exists ... result = await WebinarRepository.IsExistsAsync(webinarId); if (!result) { return result; } // // Check User Exists ... var device = await IdentityProvider.GetDevice(); XOpenActionUserInfoDto userInfo = null; try { // userInfo = await IdentityProvider.GetUserInfo( device: device, userSelectByParam: subscriberId ); } catch { } result = !userInfo.IsNullOrDefault(); if (!result) { return result; } // result = !(await WebinarSubscriberRepository.FindOneAsync(ws => ws.WebinarId == webinarId && ws.SubscriberId == subscriberId )).IsNull(); // return result; } /// /// Unsubscribe Specified User from a Specified Webinar ... /// /// /// /// /// public async Task Unsubscribe( Guid webinarId, string subscriberId, string requesterUserSelectByParam = null ) { // var result = false; // // Validate ... result = !webinarId.IsNull() && !webinarId.IsDefaultGuid() && !subscriberId.IsNullOrEmpty(); if (!result) { return result; } // // Check Subscription .. result = await IsSubscribed( webinarId: webinarId, subscriberId: subscriberId ); if (!result) { return result; } // // Retrieve Webinar ... var webinar = await WebinarRepository.GetAsync(webinarId); // // Check Permission ... result = requesterUserSelectByParam == subscriberId || requesterUserSelectByParam == webinar.OwnerId; if (!result) { return result; } // // Retrieve Subscription Entity ... var entity = await WebinarSubscriberRepository.FindOneAsync(ws => ws.WebinarId == webinarId && ws.SubscriberId == subscriberId ); entity = await WebinarSubscriberRepository.RemoveAsync(entity); result = !entity.IsNullOrDefault(); // return result; } /// /// Retrieve Specified Subscriber ... /// /// /// /// /// public async Task GetSubscriber( Guid webinarId, string subscriberId, string requesterUserSelectByParam = null ) { // // Validate ... bool isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid() && !subscriberId.IsNullOrEmpty(); if (!isValid) { XException.InvalidArgs.Throw(); } // // Retrieve Webinar and Validate it ... var webinar = await WebinarRepository.GetAsync(webinarId); isValid = !webinar.IsNullOrDefault(); if (!isValid) { XException.NotFound.Throw(); } // // Retrieve Entity and Validate it ... var entity = await WebinarSubscriberRepository.FindOneAsync(e => e.WebinarId == webinarId && e.SubscriberId == subscriberId ); isValid = !entity.IsNullOrDefault(); if (!isValid) { XException.NotFound.Throw(); } // // Check Permissions ... isValid = subscriberId == requesterUserSelectByParam || webinar.OwnerId == requesterUserSelectByParam; if (!isValid) { XException.NotAllowed.Throw(); } // // Converts to Subscriber Dto ... var result = await ToXWebinarSubscriberDto(entity); return result; } /// /// Get all Specified Webinars Subscribers ... /// /// /// /// public async Task> GetSubscribers( Guid webinarId, string requesterUserSelectByParam = null ) { // // Validate ... bool isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { XException.InvalidArgs.Throw(); } // // Retrieve and Validate Webinar Entity ... var webinar = await WebinarRepository.GetAsync(webinarId); isValid = !webinar.IsNullOrDefault(); if (!isValid) { XException.NotFound.Throw(); } // // Check Permissions ... isValid = webinar.OwnerId == requesterUserSelectByParam; if (!isValid) { XException.NotAllowed.Throw(); } // var subscribers = await WebinarSubscriberRepository.FindManyAsync(e => e.WebinarId == webinarId ); // // Prepare Result ... var result = await subscribers .SelectAsync(async s => await ToXWebinarSubscriberDto(s)); // return result; } /// /// Query Specified Webinar's Subscribers ... /// /// /// /// /// public async Task> QuerySubscribers( Guid webinarId, XQuery query, string requesterUserSelectByParam = null ) { // // Validate ... bool isValid = !query.IsNull() && !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { XException.InvalidArgs.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataSercviceConfiguration); // // Check Webinar Exists ... isValid = await WebinarRepository.IsExistsAsync(webinarId); if (!isValid) { XException.NotFound.Throw(); } // // Retrieve all Items ... var items = await GetSubscribers( webinarId: webinarId, requesterUserSelectByParam: requesterUserSelectByParam ); var totalItemsCount = items.Count(); // // Try Filter Items ... if (!query.Filter.IsNullOrEmpty()) { // var filteredItems = new List(); // // Implement Filtering Senario ... // items = filteredItems.AsEnumerable(); } var filteredItemsCount = items.Count(); // // Counting Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Sorting and Paging ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items.ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items.ApplyPaging( query.Page, query.PageSize ); } // // Prepare Result ... var result = new XQueryResult { Items = items, Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return result; } #endregion } }