404 lines
11 KiB
C#
404 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using xCommons.Extensions;
|
|
using xModels.Dtos;
|
|
using xPushService.Constants;
|
|
using xPushService.Interfaces;
|
|
using xPushService.Models;
|
|
|
|
namespace xPushService.Base {
|
|
/// <summary>
|
|
/// a base class for implementing Hubs ...
|
|
/// </summary>
|
|
public abstract class XBaseHub : Hub, IXBaseHub
|
|
{
|
|
//
|
|
#region Props ...
|
|
protected readonly IXPushGroupStore groupStore;
|
|
protected readonly IXPushConnectionStore connectionStore;
|
|
#endregion
|
|
|
|
//
|
|
#region Constructor ...
|
|
public XBaseHub(
|
|
IXPushGroupStore groupStore,
|
|
IXPushConnectionStore connectionStore
|
|
) : base()
|
|
{
|
|
//
|
|
this.groupStore = groupStore;
|
|
this.connectionStore = connectionStore;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Abstract ...
|
|
public abstract XPushConnectionDto GetConnection();
|
|
#endregion
|
|
|
|
//
|
|
#region EnevtHandlers ...
|
|
#endregion
|
|
|
|
//
|
|
#region Overrides ...
|
|
public override Task OnConnectedAsync()
|
|
{
|
|
//
|
|
var connection = GetConnection();
|
|
if (!connection.IsNull())
|
|
{
|
|
//
|
|
connectionStore
|
|
.Add(connection)
|
|
.RunTask();
|
|
|
|
//
|
|
var count = connectionStore
|
|
.Count()
|
|
.RunTask();
|
|
|
|
//
|
|
Console.WriteLine($"Count After Coonected: {count}");
|
|
}
|
|
|
|
//
|
|
return base.OnConnectedAsync();
|
|
}
|
|
|
|
public override Task OnDisconnectedAsync(Exception exception)
|
|
{
|
|
//
|
|
var connection = GetConnection();
|
|
if (!connection.IsNull())
|
|
{
|
|
//
|
|
connectionStore
|
|
.RemoveByConnectionId(connection.Id)
|
|
.RunTask();
|
|
|
|
//
|
|
var count = connectionStore
|
|
.Count()
|
|
.RunTask();
|
|
|
|
//
|
|
Console.WriteLine($"Count After DisCoonected: {count}");
|
|
}
|
|
|
|
//
|
|
return base.OnDisconnectedAsync(exception);
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Actions ...
|
|
/// <summary>
|
|
/// Notify to all Other Clients which a new Connection is established ...
|
|
/// </summary>
|
|
/// <param name="connectionId"></param>
|
|
public Task NotifyNewConnection(string connectionId)
|
|
{
|
|
//
|
|
var actor = Context.User.Identity.Name;
|
|
var authType = Context.User.Identity.AuthenticationType;
|
|
var actorRole = Context?.User?.FindFirst("role")?.Value;
|
|
|
|
//
|
|
var pushMessage = new XPushMessage
|
|
{
|
|
//
|
|
Actor = actor,
|
|
Payload = connectionId,
|
|
TimeStamp = DateTime.UtcNow,
|
|
Type = XPushType.System.GetStringValue(),
|
|
Topic = XPushType.System.GetStringValue(),
|
|
Action = XBasePushAction.NotifyNewConnection.GetStringValue(),
|
|
Message = $"a new connection stablished by {connectionId} ...",
|
|
};
|
|
|
|
//
|
|
Console.WriteLine($"XPushServiceLog => ");
|
|
Console.WriteLine($"XPushServiceLog => NotifyNewConnection: User: {actor}/Role: {actorRole}/AuthType: {authType}/ConnectionId: {connectionId}/ConnectedAt: {DateTime.UtcNow}");
|
|
Console.WriteLine($"XPushServiceLog => ");
|
|
|
|
//
|
|
return Clients.Others.SendAsync(
|
|
XBasePushAction.PushMessage.GetStringValue(),
|
|
pushMessage
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update Last Seen ...
|
|
/// </summary>
|
|
public Task UpdateLastSeen()
|
|
{
|
|
var connectionId = Context.ConnectionId;
|
|
return connectionStore
|
|
.UpdateLastSeen(connectionId)
|
|
.ContinueWith(updateLastSeenTask =>
|
|
{
|
|
//
|
|
var updateLastSeen = updateLastSeenTask
|
|
.RunTask();
|
|
if (updateLastSeen)
|
|
{
|
|
//
|
|
var updatedConnection = connectionStore
|
|
.GetByConnectionId(connectionId)
|
|
.RunTask();
|
|
|
|
//
|
|
var count = connectionStore
|
|
.Count()
|
|
.RunTask();
|
|
|
|
//
|
|
Console.WriteLine($"Connection Last Seen Updated: {connectionId}: {updatedConnection.LastSeen}, Connection Count: {count} ...");
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// publicly Push a Message to Other Clients ...
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
/// <returns></returns>
|
|
public Task PushMessageAsync(XPushMessage message)
|
|
{
|
|
//
|
|
if (message.IsNull())
|
|
{
|
|
message = GetPushMessage();
|
|
}
|
|
else
|
|
{
|
|
message.TimeStamp = DateTime.UtcNow;
|
|
}
|
|
|
|
//
|
|
return Clients.Others.SendAsync(XBasePushAction.PushMessage.GetStringValue(), message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// publicly Push a Message to Other Clients ...
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
/// <returns></returns>
|
|
[Authorize]
|
|
public Task AuthorizedMessageAsync(XPushMessage message)
|
|
{
|
|
//
|
|
if (message.IsNull())
|
|
{
|
|
message = GetPushMessage();
|
|
}
|
|
else
|
|
{
|
|
message.TimeStamp = DateTime.UtcNow;
|
|
}
|
|
|
|
//
|
|
return Clients.Others.SendAsync(XBasePushAction.PushMessage.GetStringValue(), message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// push message to All connections ...
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
/// <returns></returns>
|
|
public Task PushMessageToAll(XPushMessage message)
|
|
{
|
|
//
|
|
// Normalize Message ...
|
|
if (message.IsNull())
|
|
{
|
|
message = GetPushMessage();
|
|
}
|
|
else
|
|
{
|
|
message.TimeStamp = DateTime.UtcNow;
|
|
}
|
|
|
|
//
|
|
return Clients
|
|
.All
|
|
.SendAsync(
|
|
XBasePushAction.PushMessage.GetStringValue(),
|
|
message
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// push message to specific connection ...
|
|
/// </summary>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="message"></param>
|
|
/// <returns></returns>
|
|
public Task PushMessageToConnection(
|
|
string connectionId,
|
|
XPushMessage message
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (connectionId.IsNullOrEmpty())
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
//
|
|
// Normalize Message ...
|
|
if (message.IsNull())
|
|
{
|
|
message = GetPushMessage();
|
|
}
|
|
else
|
|
{
|
|
message.TimeStamp = DateTime.UtcNow;
|
|
}
|
|
|
|
//
|
|
return Clients
|
|
.Client(connectionId)
|
|
.SendAsync(
|
|
XBasePushAction.PushMessage.GetStringValue(),
|
|
message
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// push message to specific connections ...
|
|
/// </summary>
|
|
/// <param name="connectionIds"></param>
|
|
/// <param name="message"></param>
|
|
/// <returns></returns>
|
|
public Task PushMessageToConnections(
|
|
IEnumerable<string> connectionIds,
|
|
XPushMessage message
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (!connectionIds.HasChild())
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
//
|
|
// Normalize Message ...
|
|
if (message.IsNull())
|
|
{
|
|
message = GetPushMessage();
|
|
}
|
|
else
|
|
{
|
|
message.TimeStamp = DateTime.UtcNow;
|
|
}
|
|
|
|
//
|
|
return Clients
|
|
.Clients(
|
|
connectionIds
|
|
.ToList()
|
|
.AsReadOnly()
|
|
)
|
|
.SendAsync(
|
|
XBasePushAction.PushMessage.GetStringValue(),
|
|
message
|
|
);
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Protected ...
|
|
/// <summary>
|
|
/// retrieve connected user name ...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected string GetUserName()
|
|
{
|
|
return Context?.User?.Identity?.Name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// retrieve connected user role ...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected string GetUserRole()
|
|
{
|
|
return Context?.User?.FindFirst("role")?.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve Empty Message ...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected XPushMessage GetPushMessage()
|
|
{
|
|
//
|
|
var timeStamp = DateTime.UtcNow;
|
|
var actor = Context.User.Identity.Name;
|
|
var connectionId = Context.ConnectionId;
|
|
|
|
//
|
|
var result = new XPushMessage
|
|
{
|
|
Actor = actor,
|
|
TimeStamp = timeStamp,
|
|
Payload = connectionId,
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// retrieve current connection id ...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected string GetConnectionId()
|
|
{
|
|
return Context.ConnectionId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve Connection Model from Context ...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected XPushConnectionDto GetBaseConnection()
|
|
{
|
|
//
|
|
var connectionId = Context.ConnectionId;
|
|
var userName = Context.User.Identity.Name;
|
|
var authenticationType = Context.User.Identity.AuthenticationType;
|
|
|
|
//
|
|
var httpContext = Context.GetHttpContext();
|
|
var deviceJson = httpContext.Request.Query["Option"].ToString();
|
|
var device = deviceJson.FromJSON<XDeviceDto>();
|
|
|
|
//
|
|
var result = new XPushConnectionDto
|
|
{
|
|
User = userName,
|
|
Device = device,
|
|
Id = connectionId,
|
|
LastSeen = DateTime.UtcNow
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Private ...
|
|
#endregion
|
|
}
|
|
} |