Files
xWebinarService/Providers/XWebinarProvider.cs
T
2025-12-19 00:27:06 +03:30

2214 lines
67 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using MongoDB.Driver;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Extensions;
using xExceptions.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityService.Extensions;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xPushService.Constants;
using xTagService.Models.Dtos;
using xWebinarService.Constants;
using xWebinarService.Hubs;
using xWebinarService.Interfaces;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;
using XFileDto = xFileService.Models.Dtos.XFileDto;
namespace xWebinarService.Providers
{
/// <summary>
/// Implement all Webinar Related Things here ...
/// </summary>
public class XWebinarProvider : IXWebinarProvider
{
//
#region Props ...
public IHubContext<XWebinarEntityHub> Hub { get; }
public IXIdentityProvider IdentityProvider { get; }
public IXWebinarRepository WebinarRepository { get; }
public IXWebinarTagProvider WebinarTagProvider { get; }
public IXWebinarFileProvider WebinarFileProvider { 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,
IXWebinarTagProvider webinarTagProvider,
IXWebinarFileProvider webinarFileProvider,
XDataServiceConfiguration dataSercviceConfiguration,
IXWebinarTitleResourceProvider titleResourceProvider,
IXWebinarSubscriberRepository webinarSubscriberRepository,
IXWebinarDescriptionResourceProvider descriptionResourceProvider,
IHubContext<XWebinarEntityHub> hub = null
)
{
//
Hub = hub;
IdentityProvider = identityProvider;
WebinarRepository = webinarRepository;
WebinarTagProvider = webinarTagProvider;
WebinarFileProvider = webinarFileProvider;
TitleResourceProvider = titleResourceProvider;
DataSercviceConfiguration = dataSercviceConfiguration;
WebinarSubscriberRepository = webinarSubscriberRepository;
DescriptionResourceProvider = descriptionResourceProvider;
}
#endregion
//
#region Tools ...
/// <summary>
/// Converts Specified XWebinar Entity to it's Corresponding Dto Presentation
/// and also Fill Owner and Title/Description Resources ...
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<XWebinarDto> 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,
Enabled = model.Enabled,
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 = 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;
}
/// <summary>
/// Converts Specified WebinarSubscriber Entity to it's Dto Presentation ...
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<XWebinarSubscriberDto> ToXWebinarSubscriberDto(XWebinarSubscriber model)
{
//
bool isValid =
!model.IsNull() &&
!model.SubscriberId.IsNullOrEmpty();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Retrieve User Info ...
var device = 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,
WebinarId = model.WebinarId,
SubscriberId = model.SubscriberId,
SubscribedOn = model.SubscribedOn,
Subscriber = userInfo.ToXPersonDto(),
};
//
return result;
}
#endregion
//
#region Actions ...
/// <summary>
/// Create Webinar ...
/// </summary>
/// <param name="item"></param>
/// <param name="tags"></param>
/// <param name="files"></param>
/// <param name="userInfo"></param>
/// <param name="connectionId"></param>
/// <returns></returns>
public async Task<XWebinarDto> CreateWebinar(
XWebinarDto item,
IEnumerable<string> tags = null,
IFormFileCollection files = null,
XUserClaimsInfoDto userInfo = null,
string connectionId = null
)
{
//
// Validate ...
bool isValid =
!item.IsNull() &&
!item.Title.IsNull() &&
!item.Description.IsNull() &&
!userInfo.IsNullOrDefault() &&
!item.OwnerId.IsNullOrEmpty() &&
userInfo.UserId == item.OwnerId;
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();
}
//
// Check For Files ...
isValid = !files.IsNull() && files.Count() > 0;
if (isValid)
{
//
try
{
//
await UploadFiles(
id: entity.Id,
files: files,
userInfo: userInfo
);
}
catch { }
}
//
// Check For Tags ...
isValid = !tags.IsNull() && tags.HasChild();
if (isValid)
{
//
try
{
//
await AttachTags(
id: entity.Id,
userInfo: userInfo,
forceAttachToFiles: true,
tags: tags.ToListString(),
connectionId: connectionId
);
}
catch { }
}
//
await SendPush(
action: XBaseEntityHubAction.Add.GetStringValue(),
payLoad: entity.ToJSON(camelCase: true),
connectionId: connectionId
);
//
// Convert Entity to Dto ...
var result = await ToXWebinarDto(entity);
return result;
}
/// <summary>
/// Update a Webinar ...
/// </summary>
/// <param name="item"></param>
/// <param name="userInfo"></param>
/// <param name="connectionId"></param>
/// <returns></returns>
public async Task<XWebinarDto> UpdateWebinar(
XWebinarDto item,
XUserClaimsInfoDto userInfo = null,
string connectionId = null
)
{
//
// Since Medias and Tags Manages Separatly, here
// we dont need to ensure that ...
//
// Validate ...
bool isValid =
!item.Id.IsNull() &&
!item.IsNullOrDefault() &&
!item.Id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault() &&
!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 Permissions ...
isValid = await HasPermission(item.Id, userInfo);
if (!isValid)
{
XException.NotAllowed.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);
}
//
// Check if Enabled Change Update it ...
if (entity.Enabled != item.Enabled)
{
//
entity.Enabled = item.Enabled;
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: item.Title.Locales
);
//
// Description ...
var descriptionAddedLocales = await DescriptionResourceProvider.AddOrUpdate(
resource: entity.Description,
locales: item.Description.Locales
);
//
entity = await WebinarRepository.GetAsync(entity.Id);
var result = await ToXWebinarDto(entity);
//
if (!result.IsNullOrDefault())
{
//
await SendPush(
action: XBaseEntityHubAction.Update.GetStringValue(),
payLoad: entity.ToJSON(camelCase: true),
connectionId: connectionId
);
}
//
return result;
}
/// <summary>
/// Retrieve Specified Webinar ...
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<XWebinarDto> GetWebinar(Guid id)
{
//
var entity = await WebinarRepository.GetAsync(id);
if (entity.IsNullOrDefault())
{
XException.NotFound.Throw();
}
//
var result = await ToXWebinarDto(entity);
return result;
}
/// <summary>
/// Retrieve all Exists Webinars ...
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<XWebinarDto>> GetWebinars()
{
//
var entities = WebinarRepository
.AsQueryable()
.ToList();
//
var result = new List<XWebinarDto>();
if (!entities.IsNull() && entities.HasChild())
{
//
foreach (var entity in entities)
{
//
var dto = await ToXWebinarDto(entity);
if (!dto.IsNullOrDefault())
{
result.Add(dto);
}
}
}
//
return result;
}
/// <summary>
/// Query Webinars ...
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public async Task<XQueryResult<XWebinarDto>> 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 list = new List<XWebinarDto>();
foreach (var entity in totalEntities)
{
//
var dto = await ToXWebinarDto(entity);
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<XWebinarDto>
{
Page = query.Page,
Items = items.ToList(),
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
/// <summary>
/// Conditional Query Webinars ...
/// </summary>
/// <param name="whereClause"></param>
/// <param name="query"></param>
/// <returns></returns>
public async Task<XQueryResult<XWebinarDto>> ConditionalQueryWebinars(
Expression<Func<XWebinarDto, bool>> 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<XWebinarDto>();
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<XWebinarDto>
{
Page = query.Page,
Items = items.ToList(),
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
/// <summary>
/// Query Owned Webinars ...
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public async Task<XQueryResult<XWebinarDto>> QueryOwnedWebinars(
XQuery query,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !query.IsNullOrDefault() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
Expression<Func<XWebinarDto, bool>> whereClause = d => d.OwnerId == userInfo.UserId;
var result = await ConditionalQueryWebinars(
query: query,
whereClause: whereClause
);
return result;
}
/// <summary>
/// Query Joinable Webinars ...
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public async Task<XQueryResult<XWebinarDto>> 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<Func<XWebinarDto, bool>> 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;
}
/// <summary>
/// Remove Specified Webinar ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="userInfo"></param>
/// <param name="connectionId"></param>
/// <returns></returns>
public async Task<bool> RemoveWebinar(
Guid webinarId,
XUserClaimsInfoDto userInfo = null,
string connectionId = null
)
{
//
bool result = false;
//
// Validate ...
result =
!webinarId.IsNull() &&
!webinarId.IsDefaultGuid();
if (!result)
{
return result;
}
//
// Check Permissions ...
result = await HasPermission(webinarId, userInfo);
if (!result)
{
XException.NotAllowed.Throw();
}
//
// Get Entity ...
var entity = await WebinarRepository.GetAsync(webinarId);
result = !entity.IsNullOrDefault();
if (!result)
{
return result;
}
//
// Handle Remove ...
var subscribers = await GetSubscribers(
webinarId: webinarId,
userInfo: userInfo
);
try
{
//
// Unsubscribe all Subscribers ...
await subscribers.SelectAsync(async s => await Unsubscribe(
webinarId: webinarId,
subscriberId: s.SubscriberId
));
//
// Detach Tags ...
await DetachTags(
tags: null, // Pass Null to Detach All Referenced Tags ...
id: entity.Id,
userInfo: userInfo,
connectionId: connectionId
);
//
// Detach Files ...
//
await DetachFiles(
ids: null, // Pass Null To Detach All Referenced Files ...
id: webinarId,
userInfo: userInfo,
connectionId: connectionId
);
//
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);
if (result)
{
//
await SendPush(
action: XBaseEntityHubAction.Delete.GetStringValue(),
payLoad: entity.ToJSON(camelCase: true),
connectionId: connectionId
);
}
//
return result;
}
#endregion
//
#region WebinarSubscriber ...
/// <summary>
/// Subscribe a User to Webinar ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="subscriberId"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<bool> Subscribe(
Guid webinarId,
string subscriberId,
string connectionId = null,
XUserClaimsInfoDto userInfo = null
)
{
//
var result = false;
//
// Validate ...
result =
!webinarId.IsNull() &&
!webinarId.IsDefaultGuid() &&
!subscriberId.IsNullOrEmpty() &&
!userInfo.IsNullOrDefault();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Check Webinar Exists ...
result = await WebinarRepository.IsExistsAsync(webinarId);
if (!result)
{
XException.NotFound.Throw();
}
//
// Retrieve Webinar Entity ...
var webinar = await WebinarRepository.GetAsync(webinarId);
result = !webinar.IsNullOrDefault();
if (!result)
{
XException.ActionFailed.Throw();
}
//
// Check Permissions ...
result =
userInfo.UserId == webinar.OwnerId ||
webinar.Type == XWebinarType.Public ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!result)
{
XException.NotAllowed.Throw();
}
//
// Check User Exists ...
var device = IdentityProvider.GetDevice();
XOpenActionUserInfoDto subscriber = null;
try
{
//
subscriber = await IdentityProvider.GetUserInfo(
device: device,
userSelectByParam: subscriberId
);
}
catch { }
result = !subscriber.IsNullOrDefault();
if (!result)
{
XException.NotFound.Throw();
}
//
// Create Subscription Model ...
var entity = new XWebinarSubscriber
{
WebinarId = webinarId,
SubscriberId = subscriberId,
SubscribedOn = DateTime.UtcNow,
};
entity = await WebinarSubscriberRepository.AddAsync(entity);
result = !entity.IsNullOrDefault();
if (result)
{
//
await SendPush(
action: XWebinarEntityHubAction.Subscribe.GetStringValue(),
payLoad: entity.ToJSON(camelCase: true),
connectionId: connectionId
);
}
//
return result;
}
/// <summary>
/// Check Specified User Subscribed on a Webinar or not ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="subscriberId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<bool> IsSubscribed(
Guid webinarId,
string subscriberId,
XUserClaimsInfoDto userInfo = null
)
{
//
bool result = false;
//
// Validate ...
result =
!webinarId.IsNull() &&
!webinarId.IsDefaultGuid() &&
!userInfo.IsNullOrDefault() &&
!subscriberId.IsNullOrEmpty();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Check Webinar Exists ...
var webinar = await WebinarRepository.GetAsync(webinarId);
result = !webinar.IsNullOrDefault();
if (!result)
{
XException.NotFound.Throw();
}
//
// Check Permission ...
result =
userInfo.UserId == subscriberId ||
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!result)
{
XException.NotAllowed.Throw();
}
//
// Check User Exists ...
var device = IdentityProvider.GetDevice();
XOpenActionUserInfoDto suscriber = null;
try
{
//
suscriber = await IdentityProvider.GetUserInfo(
device: device,
userSelectByParam: subscriberId
);
}
catch { }
result = !suscriber.IsNullOrDefault();
if (!result)
{
XException.NotFound.Throw();
}
//
result = !(await WebinarSubscriberRepository.FindOneAsync(ws =>
ws.WebinarId == webinarId &&
ws.SubscriberId == subscriberId
)).IsNull();
//
return result;
}
/// <summary>
/// Unsubscribe Specified User from a Specified Webinar ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="subscriberId"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<bool> Unsubscribe(
Guid webinarId,
string subscriberId,
string connectionId = null,
XUserClaimsInfoDto userInfo = null
)
{
//
var result = false;
//
// Validate ...
result =
!webinarId.IsNull() &&
!webinarId.IsDefaultGuid() &&
!userInfo.IsNullOrDefault() &&
!subscriberId.IsNullOrEmpty();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Check Subscription ...
result = await IsSubscribed(
webinarId: webinarId,
userInfo: userInfo,
subscriberId: subscriberId
);
if (!result)
{
XException.NotFound.Throw();
}
//
// Retrieve Webinar ...
var webinar = await WebinarRepository.GetAsync(webinarId);
result = !webinar.IsNullOrDefault();
if (!result)
{
XException.ActionFailed.Throw();
}
//
// Check Permissions ...
result =
userInfo.UserId == subscriberId ||
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!result)
{
XException.NotAllowed.Throw();
}
//
// Retrieve Subscription Entity ...
var entity = await WebinarSubscriberRepository.FindOneAsync(ws =>
ws.WebinarId == webinarId &&
ws.SubscriberId == subscriberId
);
entity = await WebinarSubscriberRepository.RemoveAsync(entity);
result = !entity.IsNullOrDefault();
if (result)
{
//
await SendPush(
action: XWebinarEntityHubAction.Unsubscribe.GetStringValue(),
payLoad: entity.ToJSON(camelCase: true),
connectionId: connectionId
);
}
//
return result;
}
/// <summary>
/// Retrieve Specified Subscriber ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="subscriberId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<XWebinarSubscriberDto> GetSubscriber(
Guid webinarId,
string subscriberId,
XUserClaimsInfoDto userInfo = 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();
}
//
// Check Permissions ...
isValid =
userInfo.UserId == subscriberId ||
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!isValid)
{
XException.NotAllowed.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();
}
//
// Converts to Subscriber Dto ...
var result = await ToXWebinarSubscriberDto(entity);
return result;
}
/// <summary>
/// Get all Specified Webinars Subscribers ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<IEnumerable<XWebinarSubscriberDto>> GetSubscribers(
Guid webinarId,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
bool isValid =
!webinarId.IsNull() &&
!userInfo.IsNullOrDefault() &&
!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 =
(await IsSubscribed(
userInfo: userInfo,
webinarId: webinarId,
subscriberId: userInfo.UserId
)) ||
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
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;
}
/// <summary>
/// Query Specified Webinar's Subscribers ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="query"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<XQueryResult<XWebinarSubscriberDto>> QuerySubscribers(
Guid webinarId,
XQuery query,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
bool isValid =
!query.IsNull() &&
!webinarId.IsNull() &&
!webinarId.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Normalize ...
query = query.NormalizeQuery(DataSercviceConfiguration);
//
// Check Webinar Exists ...
var webinar = await WebinarRepository.GetAsync(webinarId);
isValid = !webinar.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Check Permissions ...
isValid =
(await IsSubscribed(
userInfo: userInfo,
webinarId: webinarId,
subscriberId: userInfo.UserId
)) ||
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Retrieve all Items ...
var items = await GetSubscribers(
userInfo: userInfo,
webinarId: webinarId
);
var totalItemsCount = items.Count();
//
// Try Filter Items ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
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<XWebinarSubscriberDto>
{
Items = items,
Page = query.Page,
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
#endregion
//
#region File Actions ...
/// <summary>
/// Upload Files ...
/// </summary>
/// <param name="forProvidedId"></param>
/// <param name="files"></param>
/// <param name="userInfo"></param>
/// <param name="connectionId"></param>
/// <returns></returns>
public async Task<IEnumerable<XFileDto>> UploadFiles(
Guid id,
IFormFileCollection files,
XUserClaimsInfoDto userInfo = null,
string connectionId = null
)
{
//
// Validate ...
var isValid = !id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Permission ...
isValid = await HasPermission(id, userInfo);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var result = new List<XFileDto>();
try
{
//
result = (await WebinarFileProvider.Upload(
files: files,
forProvidedId: id,
userInfo: userInfo,
connectionId: connectionId
))
.ToList();
}
catch { }
//
return result;
}
/// <summary>
/// Get Webinar Files ...
/// </summary>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<IEnumerable<XFileDto>> GetFiles(
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid =
!id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Webinar Exists ...
var webinar = await WebinarRepository.GetAsync(id);
isValid = !webinar.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
var result = (await WebinarFileProvider
.GetAllReferences(id))
.ToList();
//
return result;
}
/// <summary>
/// Stream Specified File of Specified Webinar ...
/// </summary>
/// <param name="id"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public async Task<FileStreamResult> StreamFile(
Guid id,
Guid fileId
)
{
//
// Validate ...
var isValid = !id.IsNull() &&
!fileId.IsNull() &&
!id.IsDefaultGuid() &&
!fileId.IsDefaultGuid();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
var result = await WebinarFileProvider.Stream(fileId);
return result;
}
/// <summary>
/// Download Specified File of Specified Webinar ...
/// </summary>
/// <param name="id"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public async Task<PhysicalFileResult> DownloadFile(
Guid id,
Guid fileId
)
{
//
// Validate ...
var isValid = !id.IsNull() &&
!fileId.IsNull() &&
!id.IsDefaultGuid() &&
!fileId.IsDefaultGuid();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
var result = await WebinarFileProvider.Download(fileId);
return result;
}
/// <summary>
/// Attach Provided Files to Specified Webinar ...
/// </summary>
/// <param name="id"></param>
/// <param name="ids"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task AttachFiles(
Guid id,
string ids,
string connectionId = null,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !id.IsNull() &&
!id.IsDefaultGuid() &&
!ids.IsNullOrEmpty() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Parse Files ...
var idsList = ids.ParseListGuid();
isValid = !idsList.IsNull() && idsList.HasChild();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Retrieve Webinar ...
var webinar = await WebinarRepository.GetAsync(id);
isValid = !webinar.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Check Permissions ...
isValid =
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Refrieve all Webinar Refrenced File ...
var references = await WebinarFileProvider.GetAllReferences(id);
if (!references.IsNull() && references.HasChild())
{
//
// Filter ids which Exists in References ...
idsList =
idsList.Where(i => !references.Any(r => r.Id == i));
}
//
isValid = idsList.HasChild();
if (!isValid)
{
return;
}
//
foreach (var fileId in idsList)
{
//
// Check File Exists ...
var file = await WebinarFileProvider.FileProvider.Get(fileId);
isValid = !file.IsNullOrDefault();
if (isValid)
{
//
await WebinarFileProvider.AddReference(
model: file,
providedForId: id,
userInfo: userInfo,
connectionId: connectionId
);
}
}
}
/// <summary>
/// Detach Provided Files to Specified Webinar ...
/// </summary>
/// <param name="id"></param>
/// <param name="ids">if null, detach all files ...</param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task DetachFiles(
Guid id,
string ids,
string connectionId = null,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid =
!id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Webinar Exists ...
var webinar = await WebinarRepository.GetAsync(id);
isValid = !webinar.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Check Permissions ...
isValid =
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var references = await WebinarFileProvider.GetAllReferences(id);
isValid = !references.IsNull() && references.HasChild();
if (!isValid)
{
return;
}
//
// Parse IDS ...
if (!ids.IsNullOrEmpty())
{
//
var idsList = ids.ParseListGuid();
if (!idsList.IsNull() && idsList.HasChild())
{
//
// Filtere References based on IDS ...
references =
references.Where(r => idsList.Contains(r.Id));
}
}
//
if (references.HasChild())
{
//
foreach (var file in references)
{
//
await WebinarFileProvider.RemoveReference(
model: file,
providedForId: id,
userInfo: userInfo,
connectionId: connectionId
);
}
}
}
#endregion
//
#region Tags Actions ...
/// <summary>
/// Attach Tag to Specified File ...
/// </summary>
/// <param name="id"></param>
/// <param name="tag"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="forceAttachToFiles"></param>
/// <returns></returns>
public async Task AttachTag(
Guid id,
string tag,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
bool forceAttachToFiles = true
)
{
//
// Validate ...
var isValid =
!id.IsNull() &&
!id.IsDefaultGuid() &&
!tag.IsNullOrEmpty() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
//
// Attached Tag to Webinar ...
await WebinarTagProvider.AddReference(
tag: tag,
providedForId: id,
connectionId: connectionId
);
//
if (forceAttachToFiles)
{
//
var medias = await WebinarFileProvider.GetAllReferences(id);
isValid = !medias.IsNull() && medias.HasChild();
if (isValid)
{
//
foreach (var media in medias)
{
//
await WebinarFileProvider.FileProvider.AttachTag(
tag: tag,
id: media.Id,
userInfo: userInfo,
connectionId: connectionId
);
}
}
}
}
catch { }
}
/// <summary>
/// Detach Tag fro Specified File ...
/// </summary>
/// <param name="id"></param>
/// <param name="tag"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="forceAttachToFiles"></param>
/// <returns></returns>
public async Task DetachTag(
Guid id,
string tag,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
bool forceDetachFromFiles = true
)
{
//
// Validate ...
var isValid =
!id.IsNull() &&
!id.IsDefaultGuid() &&
!tag.IsNullOrEmpty() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
//
await WebinarTagProvider
.RemoveReference(
tag: tag,
providedForId: id,
connectionId: connectionId
);
//
if (forceDetachFromFiles)
{
//
var medias = await WebinarFileProvider.GetAllReferences(id);
isValid = !medias.IsNull() && medias.HasChild();
if (isValid)
{
//
foreach (var media in medias)
{
//
await WebinarFileProvider.FileProvider.DetachTag(
tag: tag,
id: media.Id,
userInfo: userInfo,
connectionId: connectionId
);
}
}
}
}
catch { }
}
/// <summary>
/// Attach Tags for Specified File ...
/// </summary>
/// <param name="id"></param>
/// <param name="tags"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="forceAttachToFiles"></param>
/// <returns></returns>
public async Task AttachTags(
Guid id,
string tags,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
bool forceAttachToFiles = true
)
{
//
// Validate ...
var isValid =
!id.IsNull() &&
!id.IsDefaultGuid() &&
!tags.IsNullOrEmpty() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
//
var tagsList = tags.ParseListString<string>();
foreach (var tag in tagsList)
{
//
await AttachTag(
id: id,
tag: tag,
userInfo: userInfo,
connectionId: connectionId,
forceAttachToFiles: forceAttachToFiles
);
}
}
catch { }
}
/// <summary>
/// Detach Tags for Specified File ...
/// </summary>
/// <param name="id"></param>
/// <param name="tags">if null, Detach All ...</param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="forceDetachFromFiles"></param>
/// <returns></returns>
public async Task DetachTags(
Guid id,
string tags,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
bool forceDetachFromFiles = true
)
{
//
// Validate ...
var isValid =
!id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
IEnumerable<string> tagsList;
if (!tags.IsNullOrEmpty())
{
//
// Only Detach Provided Tags ...
tagsList = tags.ParseListString<string>();
}
else
{
//
// Select all Referenced Tags ...
tagsList = (await WebinarTagProvider.GetAllReferences(id)).Select(t => t.Tag);
}
//
try
{
//
foreach (var tag in tagsList)
{
//
await DetachTag(
id: id,
tag: tag,
userInfo: userInfo,
connectionId: connectionId,
forceDetachFromFiles: forceDetachFromFiles
);
}
}
catch { }
}
/// <summary>
/// Retrieve Specified Webinar's Tags ...
/// </summary>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<IEnumerable<XTagDto>> GetTags(
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate Args ...
var isValid = !id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Webinar Wxists ...
var webinar = await WebinarRepository.GetAsync(id);
isValid = !webinar.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Checking Permissions ...
isValid =
(await IsSubscribed(
webinarId: id,
userInfo: userInfo,
subscriberId: userInfo.UserId
)) ||
userInfo.UserId == webinar.OwnerId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Reading Tags Dto List ...
var result = await WebinarTagProvider.GetAllReferences(id);
//
// var result = new List<string>();
// isValid = !tagsDtos.IsNull() && tagsDtos.HasChild();
// if (isValid)
// {
// //
// result = tagsDtos
// .Select(td => td.Tag)
// .ToList();
// }
//
return result;
}
#endregion
//
#region Hub Actions ...
/// <summary>
/// Send Custom Push Message ...
/// </summary>
/// <param name="action"></param>
/// <param name="payLoad"></param>
/// <param name="connectionId"></param>
/// <returns></returns>
public async Task SendPush(
string action,
string payLoad,
string connectionId = null
)
{
//
var actions = new List<string>
{
XBaseEntityHubAction.Add.GetStringValue(),
XBaseEntityHubAction.Update.GetStringValue(),
XBaseEntityHubAction.Delete.GetStringValue(),
XBaseEntityHubAction.AddMany.GetStringValue(),
XBaseEntityHubAction.DeleteMany.GetStringValue(),
XBaseEntityHubAction.UpdateMany.GetStringValue(),
XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
XWebinarEntityHubAction.Subscribe.GetStringValue(),
XWebinarEntityHubAction.Unsubscribe.GetStringValue(),
};
//
// Validate ...
var isValid =
!Hub.IsNull() &&
!action.IsNullOrEmpty() &&
actions.Contains(action);
if (!isValid)
{
return;
}
//
var clients = Hub.Clients.All;
if (!connectionId.IsNullOrEmpty())
{
clients = Hub.Clients.AllExcept(connectionId);
}
try
{
await clients.SendAsync(action, payLoad, connectionId);
}
catch { }
}
#endregion
//
#region Private ...
/// <summary>
/// Check Specified User Info Has Permissions for Specified Webinar ...
/// </summary>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
private async Task<bool> HasPermission(
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
var result = false;
//
// Validate ...
result = !id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Check Item Exists ...
var dto = await GetWebinar(id);
result = !dto.IsNullOrDefault();
if (!result)
{
XException.NotFound.Throw();
}
//
result =
dto.OwnerId == userInfo.UserId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
//
return result;
}
#endregion
}
}