From 0109abb961731212e18f486ce974feb8a7437503 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 9 Dec 2025 17:06:26 +0330 Subject: [PATCH] last works ... --- Controllers/XWebinarServiceControllerBase.cs | 295 ++++++++++++++++-- Interfaces/IXWebinarProvider.cs | 54 +++- .../IXWebinarServiceControllerActions.cs | 101 +++++- Providers/XWebinarProvider.cs | 251 +++++++++++++-- 4 files changed, 632 insertions(+), 69 deletions(-) diff --git a/Controllers/XWebinarServiceControllerBase.cs b/Controllers/XWebinarServiceControllerBase.cs index b1e1bb7..99c735b 100644 --- a/Controllers/XWebinarServiceControllerBase.cs +++ b/Controllers/XWebinarServiceControllerBase.cs @@ -13,6 +13,7 @@ using xIdentityService.Interfaces; using xModels.Dtos; using xWebinarService.Interfaces; using xWebinarService.Models.Dtos; +using Microsoft.AspNetCore.Http; namespace xWebinarService.Controllers { @@ -52,10 +53,14 @@ namespace xWebinarService.Controllers /// Create Webinar ... /// /// + /// + /// /// [HttpPost("Create")] public virtual async Task> CreateWebinar( - [FromBody] XWebinarDto item + [FromBody] XWebinarDto item, + [FromQuery] string tags = null, + [FromForm] IFormFileCollection files = null ) { // @@ -77,9 +82,12 @@ namespace xWebinarService.Controllers } // + var tagList = tags.ParseListString(); var result = await WebinarProvider .CreateWebinar( item: item, + files: files, + tags: tagList, connectionId: connectionId ); @@ -200,33 +208,6 @@ namespace xWebinarService.Controllers } } - /// - /// Retrieve all Exists Webinar Ids ... - /// - /// - [HttpGet("Ids")] - public virtual ActionResult> GetWebinarIds() - { - // - // Do ... - try - { - // - var result = WebinarProvider - .GetWebinarIds(); - - // - return Ok(result. - ToDynamicObject()); - } - catch (Exception ex) - { - // - var result = GetExceptionActionResult(ex); - return result; - } - } - /// /// Query Webinars ... /// @@ -258,12 +239,12 @@ namespace xWebinarService.Controllers } /// - /// Query Webinar Ids ... + /// Query Owned Webinars ... /// /// /// - [HttpGet("QueryIds")] - public virtual ActionResult> QueryWebinarIds( + [HttpGet("QueryOwned")] + public virtual async Task>> QueryOwnedWebinars( [FromQuery] XQuery query ) { @@ -272,8 +253,52 @@ namespace xWebinarService.Controllers try { // - var result = WebinarProvider - .QueryWebinarIds(query); + // Retrieve User Info ... + var userInfo = await GetUserInfo(); + + // + var result = await WebinarProvider + .QueryOwnedWebinars( + query: query, + userInfo: userInfo + ); + + // + return Ok(result. + ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Query Joinable Webinars ... + /// + /// + /// + [HttpGet("QueryJoinable")] + public virtual async Task>> QueryJoinableWebinars( + [FromQuery] XQuery query + ) + { + // + // Do ... + try + { + // + // Retrieve User Info ... + var userInfo = await GetUserInfo(); + + // + var result = await WebinarProvider + .QueryJoinableWebinars( + query: query, + userInfo: userInfo + ); // return Ok(result. @@ -708,5 +733,209 @@ namespace xWebinarService.Controllers } } #endregion + + // + #region File Actions ... + /// + /// Upload Specified Files for Specified Webinar ... + /// + /// + /// + /// + [HttpPost("{id}/Files")] + public virtual async Task>> Upload( + [FromRoute] Guid id, + [FromForm] IFormFileCollection files + ) + { + // + // Do ... + try + { + // + // Retrieve User Info ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await WebinarProvider + .Upload( + id: id, + files: files, + userInfo: userInfo, + connectionId: connectionId + ); + + // + return Ok(result. + ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Remove Specified (All) Files of Specified Webinar ... + /// + /// + /// + /// + [HttpDelete("{id}/Files")] + public virtual async Task>> Remove( + [FromRoute] Guid id, + [FromQuery] string ids = null + ) + { + // + // Do ... + try + { + // + // Retrieve User Info ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await WebinarProvider + .RemoveFiles( + id: id, + ids: ids, + userInfo: userInfo, + connectionId: connectionId + ); + + // + return Ok(result. + ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Retrieve Specified Webinar's Files ... + /// + /// + /// + [HttpGet("{id}/Files")] + public virtual async Task>> GetFiles( + [FromRoute] Guid id + ) + { + // + // Do ... + try + { + // + var result = await WebinarProvider + .GetFiles(id); + + // + return Ok(result. + ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + #endregion + + // + #region Tags Actions ... + /// + /// Attach Specified Tags To Specified Webinar ... + /// + /// + /// + /// + [HttpPost("{id}/Tags")] + public virtual async Task TagsAttach( + [FromRoute] Guid id, + [FromQuery] string tags + ) + { + // + // Do ... + try + { + // + // Retrieve User Info ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var tagsList = tags.ParseListString(); + await WebinarProvider + .TagsAttach( + id: id, + tags: tagsList, + userInfo: userInfo, + connectionId: connectionId + ); + + // + return Ok(); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Detach Specified Tags From Specified Webinar ... + /// + /// + /// + /// + [HttpDelete("{id}/Tags")] + public virtual async Task TagsDetach( + [FromRoute] Guid id, + [FromQuery] string tags + ) + { + // + // Do ... + try + { + // + // Retrieve User Info ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var tagsList = tags.ParseListString(); + await WebinarProvider + .TagsDetach( + id: id, + tags: tagsList, + userInfo: userInfo, + connectionId: connectionId + ); + + // + return Ok(); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + #endregion } } \ No newline at end of file diff --git a/Interfaces/IXWebinarProvider.cs b/Interfaces/IXWebinarProvider.cs index 71801fa..49c7747 100644 --- a/Interfaces/IXWebinarProvider.cs +++ b/Interfaces/IXWebinarProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.SignalR; @@ -106,6 +107,37 @@ namespace xWebinarService.Interfaces /// Task> QueryWebinars(XQuery query); + /// + /// Conditional Query Webinars ... + /// + /// + /// + /// + Task> ConditionalQueryWebinars( + Expression> whereClause, + XQuery query + ); + + /// + /// Query Owned Webinars ... + /// + /// + /// + Task> QueryOwnedWebinars( + XQuery query, + XUserClaimsInfoDto userInfo = null + ); + + /// + /// Query Joinable Webinars ... + /// + /// + /// + Task> QueryJoinableWebinars( + XQuery query, + XUserClaimsInfoDto userInfo = null + ); + /// /// Query Webinar Ids ... /// @@ -204,11 +236,13 @@ namespace xWebinarService.Interfaces /// /// /// + /// /// Task> Upload( Guid id, IFormFileCollection files, - XUserClaimsInfoDto userInfo = null + XUserClaimsInfoDto userInfo = null, + string connectionId = null ); /// @@ -217,11 +251,13 @@ namespace xWebinarService.Interfaces /// /// /// + /// /// Task> RemoveFiles( Guid id, string ids = null, - XUserClaimsInfoDto userInfo = null + XUserClaimsInfoDto userInfo = null, + string connectionId = null ); /// @@ -240,12 +276,14 @@ namespace xWebinarService.Interfaces /// /// /// + /// /// /// Task TagAttach( string tag, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceAttachToFiles = true ); @@ -255,12 +293,14 @@ namespace xWebinarService.Interfaces /// /// /// + /// /// /// Task TagDetach( string tag, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceDetachFromFiles = true ); @@ -270,12 +310,14 @@ namespace xWebinarService.Interfaces /// /// /// + /// /// /// Task TagsAttach( IEnumerable tags, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceAttachToFiles = true ); @@ -285,12 +327,14 @@ namespace xWebinarService.Interfaces /// /// /// + /// /// /// Task TagsDetach( IEnumerable tags, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceDetachFromFiles = true ); @@ -298,10 +342,14 @@ namespace xWebinarService.Interfaces /// Detach all Attached Tags for Specified File ... /// /// + /// + /// /// Task TagsDetach( Guid id, - XUserClaimsInfoDto userInfo = null + XUserClaimsInfoDto userInfo = null, + string connectionId = null, + bool forceDetachFromFiles = true ); #endregion } diff --git a/Interfaces/IXWebinarServiceControllerActions.cs b/Interfaces/IXWebinarServiceControllerActions.cs index f6a76d6..49a14a4 100644 --- a/Interfaces/IXWebinarServiceControllerActions.cs +++ b/Interfaces/IXWebinarServiceControllerActions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using xModels.Dtos; using xWebinarService.Models.Dtos; @@ -18,22 +19,32 @@ namespace xWebinarService.Interfaces /// Create Webinar ... /// /// + /// + /// /// - Task> CreateWebinar([FromBody] XWebinarDto item); + Task> CreateWebinar( + [FromBody] XWebinarDto item, + [FromQuery] string tags = null, + [FromForm] IFormFileCollection files = null + ); /// /// Update a Webinar ... /// /// /// - Task> UpdateWebinar([FromBody] XWebinarDto item); + Task> UpdateWebinar( + [FromBody] XWebinarDto item + ); /// /// Retrieve Specified Webinar ... /// /// /// - Task> GetWebinar([FromQuery] Guid id); + Task> GetWebinar( + [FromQuery] Guid id + ); /// /// Retrieve all Exists Webinars ... @@ -41,25 +52,32 @@ namespace xWebinarService.Interfaces /// Task>> GetWebinars(); - /// - /// Retrieve all Exists Webinar Ids ... - /// - /// - ActionResult> GetWebinarIds(); - /// /// Query Webinars ... /// /// /// - Task>> QueryWebinars([FromQuery] XQuery query); + Task>> QueryWebinars( + [FromQuery] XQuery query + ); /// - /// Query Webinar Ids ... + /// Query Owned Webinars ... /// /// /// - ActionResult> QueryWebinarIds([FromQuery] XQuery query); + Task>> QueryOwnedWebinars( + [FromQuery] XQuery query + ); + + /// + /// Query Joinable Webinars ... + /// + /// + /// + Task>> QueryJoinableWebinars( + [FromQuery] XQuery query + ); /// /// Remove Specified Webinar ... @@ -143,5 +161,64 @@ namespace xWebinarService.Interfaces [FromQuery] Guid webinarId ); #endregion + + // + #region File Actions ... + /// + /// Upload Specified Files for Specified Webinar ... + /// + /// + /// + /// + Task>> Upload( + [FromRoute] Guid id, + [FromForm] IFormFileCollection files + ); + + /// + /// Remove Specified (All) Files of Specified Webinar ... + /// + /// + /// + /// + Task>> Remove( + [FromRoute] Guid id, + [FromQuery] string ids = null + ); + + /// + /// Retrieve Specified Webinar's Files ... + /// + /// + /// + Task>> GetFiles( + [FromRoute] Guid id + ); + #endregion + + // + #region Tags Actions ... + /// + /// Attach Specified Tags To Specified Webinar ... + /// + /// + /// + /// + Task TagsAttach( + [FromRoute] Guid id, + [FromQuery] string tags + ); + + /// + /// Detach Specified Tags From Specified Webinar ... + /// + /// + /// + /// + Task TagsDetach( + [FromRoute] Guid id, + [FromQuery] string tags + ); + #endregion } } \ No newline at end of file diff --git a/Providers/XWebinarProvider.cs b/Providers/XWebinarProvider.cs index cad02da..1ca3435 100644 --- a/Providers/XWebinarProvider.cs +++ b/Providers/XWebinarProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.SignalR; @@ -334,6 +335,7 @@ namespace xWebinarService.Providers tags: tags, id: entity.Id, userInfo: userInfo, + connectionId: connectionId, true // ); } @@ -366,6 +368,10 @@ namespace xWebinarService.Providers string connectionId = null ) { + // + // Since Medias and Tags Manages Separatly, here + // we dont need to ensure that ... + // // Validate ... bool isValid = @@ -584,7 +590,6 @@ namespace xWebinarService.Providers // Since in Resourceable Entities we have to Search on Locales // we Must Implement Senario Custom ... var totalEntities = await WebinarRepository.GetAllAsync(); - Console.WriteLine($"Query Reading All ..."); // var list = new List(); @@ -596,7 +601,6 @@ namespace xWebinarService.Providers } var items = list.AsEnumerable(); var totalItemsCount = items.Count(); - Console.WriteLine($"Query Reading Item's Tasks ..."); // // Apply Filter ... @@ -605,9 +609,6 @@ namespace xWebinarService.Providers // items = items .ApplyFilter(query.Filter); - - // - Console.WriteLine($"Query Apply Filter ..."); } int filteredItemsCount = items.Count(); @@ -629,8 +630,6 @@ namespace xWebinarService.Providers query.SortBy, query.IsAscending ); - // - Console.WriteLine($"Query Apply Sorting ..."); // // Apply Paging ... @@ -640,8 +639,6 @@ namespace xWebinarService.Providers query.Page, query.PageSize ); - // - Console.WriteLine($"Query Apply Paging ..."); } // @@ -661,6 +658,170 @@ namespace xWebinarService.Providers return result; } + /// + /// Conditional Query Webinars ... + /// + /// + /// + /// + public async Task> ConditionalQueryWebinars( + Expression> whereClause, + XQuery query + ) + { + // + // Validate ... + if (query.IsNull() || whereClause.IsNull()) + { + XException.InvalidArgs.Throw(); + } + + // + // Normalize ... + query = query.NormalizeQuery(DataSercviceConfiguration); + + // + // Compile Expression ... + var whereFunc = whereClause.Compile(); + + // + // Since in Resourceable Entities we have to Search on Locales + // we Must Implement Senario Custom ... + var totalEntities = await WebinarRepository.GetAllAsync(); + + // + var list = new List(); + foreach (var entity in totalEntities) + { + // + var dto = await ToXWebinarDto(entity); + + // + // Validate and Check Conditions ... + if (!dto.IsNullOrDefault() && whereFunc(dto)) + { + list.Add(dto); + } + } + var items = list.AsEnumerable(); + 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 + .ToList() + .ApplySorting( + query.SortBy, + query.IsAscending + ); + + // + // Apply Paging ... + items = items + .ToList() + .ApplyPaging( + query.Page, + query.PageSize + ); + } + + // + // Prepare Result ... + var result = new XQueryResult + { + Page = query.Page, + Items = items.ToList(), + PageSize = query.PageSize, + TotalPages = totalPagesCount, + TotalItems = totalItemsCount, + TotalFilteredPages = filteredPagesCount, + TotalFilteredItems = filteredItemsCount + }; + + // + return result; + } + + /// + /// Query Owned Webinars ... + /// + /// + /// + public async Task> QueryOwnedWebinars( + XQuery query, + XUserClaimsInfoDto userInfo = null + ) + { + // + // Validate ... + var isValid = !query.IsNullOrDefault() && + !userInfo.IsNullOrDefault(); + if (!isValid) + { + XException.InvalidArgs.Throw(); + } + + // + Expression> whereClause = d => d.OwnerId == userInfo.UserId; + var result = await ConditionalQueryWebinars( + query: query, + whereClause: whereClause + ); + return result; + } + + /// + /// Query Joinable Webinars ... + /// + /// + /// + public async Task> QueryJoinableWebinars( + XQuery query, + XUserClaimsInfoDto userInfo = null + ) + { + // + // Validate ... + var isValid = !query.IsNullOrDefault() && + !userInfo.IsNullOrDefault(); + if (!isValid) + { + XException.InvalidArgs.Throw(); + } + + // + // Create an Expression to Check Specified Webinar is Joinable by Provided User Info or not ... + Expression> whereClause = d => + d.OwnerId == userInfo.UserId || + d.Type == XWebinarType.Public || + WebinarSubscriberRepository.AsQueryable().Any(ws => ws.WebinarId == d.Id && ws.SubscriberId == userInfo.UserId); + var result = await ConditionalQueryWebinars( + query: query, + whereClause: whereClause + ); + return result; + } + /// /// Query Webinar Ids ... /// @@ -1246,11 +1407,13 @@ namespace xWebinarService.Providers /// /// /// + /// /// public async Task> Upload( Guid id, IFormFileCollection files, - XUserClaimsInfoDto userInfo = null + XUserClaimsInfoDto userInfo = null, + string connectionId = null ) { // @@ -1279,7 +1442,8 @@ namespace xWebinarService.Providers result = (await WebinarFileProvider.Upload( files: files, forProvidedId: id, - userInfo: userInfo + userInfo: userInfo, + connectionId: connectionId )) .ToList(); } @@ -1295,11 +1459,13 @@ namespace xWebinarService.Providers /// /// /// + /// /// public async Task> RemoveFiles( Guid id, string ids = null, - XUserClaimsInfoDto userInfo = null + XUserClaimsInfoDto userInfo = null, + string connectionId = null ) { // @@ -1322,9 +1488,10 @@ namespace xWebinarService.Providers // var result = await WebinarFileProvider.Remove( - id, - ids, - userInfo + forProvidedId: id, + ids: ids, + userInfo: userInfo, + connectionId: connectionId ); return result; } @@ -1362,12 +1529,14 @@ namespace xWebinarService.Providers /// /// /// + /// /// /// public async Task TagAttach( string tag, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceAttachToFiles = true ) { @@ -1395,7 +1564,7 @@ namespace xWebinarService.Providers { // // Attached Tag to Webinar ... - await WebinarTagProvider.Attach(tag, id); + await WebinarTagProvider.Attach(tag, id, connectionId); // if (forceAttachToFiles) @@ -1408,7 +1577,13 @@ namespace xWebinarService.Providers // foreach (var media in medias) { - await WebinarFileProvider.Provider.TagAttach(tag, media.Id); + // + await WebinarFileProvider.Provider.TagAttach( + tag, + media.Id, + userInfo, + connectionId + ); } } } @@ -1423,12 +1598,14 @@ namespace xWebinarService.Providers /// /// /// + /// /// /// public async Task TagDetach( string tag, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceDetachFromFiles = true ) { @@ -1454,7 +1631,7 @@ namespace xWebinarService.Providers try { // - await WebinarTagProvider.Detach(tag, id); + await WebinarTagProvider.Detach(tag, id, connectionId); // if (forceDetachFromFiles) @@ -1467,7 +1644,13 @@ namespace xWebinarService.Providers // foreach (var media in medias) { - await WebinarFileProvider.Provider.TagDetach(tag, media.Id); + // + await WebinarFileProvider.Provider.TagDetach( + tag, + media.Id, + userInfo, + connectionId + ); } } } @@ -1482,12 +1665,14 @@ namespace xWebinarService.Providers /// /// /// + /// /// /// public async Task TagsAttach( IEnumerable tags, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceAttachToFiles = true ) { @@ -1521,6 +1706,7 @@ namespace xWebinarService.Providers tag, id, userInfo, + connectionId, forceAttachToFiles ); } @@ -1535,12 +1721,14 @@ namespace xWebinarService.Providers /// /// /// + /// /// /// public async Task TagsDetach( IEnumerable tags, Guid id, XUserClaimsInfoDto userInfo = null, + string connectionId = null, bool forceDetachFromFiles = true ) { @@ -1574,6 +1762,7 @@ namespace xWebinarService.Providers tag, id, userInfo, + connectionId, forceDetachFromFiles ); } @@ -1586,10 +1775,14 @@ namespace xWebinarService.Providers /// Detach all Attached Tags for Specified File ... /// /// + /// + /// /// public async Task TagsDetach( Guid id, - XUserClaimsInfoDto userInfo = null + XUserClaimsInfoDto userInfo = null, + string connectionId = null, + bool forceDetachFromFiles = true ) { // @@ -1612,7 +1805,23 @@ namespace xWebinarService.Providers try { // - var tags = await WebinarTagProvider.RemoveTagsFor(id); + var tags = await WebinarTagProvider.RemoveTagsFor(id, connectionId); + + // + if (forceDetachFromFiles) + { + // + var medias = await WebinarFileProvider.GetAllFor(id); + if (!medias.IsNull() && medias.HasChild()) + { + // + foreach (var media in medias) + { + // + await WebinarFileProvider.Provider.TagsDetach(media.Id, userInfo, connectionId); + } + } + } } catch { } }