This commit is contained in:
Marcel Baumgartner 2023-03-12 19:53:31 +01:00
commit 45defd7903
7 changed files with 182 additions and 8 deletions

View file

@ -0,0 +1,146 @@
using System.Net.WebSockets;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database.Entities.Notification;
using Moonlight.App.Models.Notifications;
using Moonlight.App.Repositories;
using Moonlight.App.Services;
using Moonlight.App.Services.Notifications;
using Moonlight.App.Services.Sessions;
using Newtonsoft.Json;
namespace Moonlight.App.Http.Controllers.Api.Moonlight.Notifications;
public class ListenController : ControllerBase
{
internal WebSocket ws;
private bool active = true;
private bool isAuth = false;
private NotificationClient Client;
private readonly IdentityService IdentityService;
private readonly NotificationRepository NotificationRepository;
private readonly OneTimeJwtService OneTimeJwtService;
private readonly NotificationClientService NotificationClientService;
private readonly NotificationServerService NotificationServerService;
public ListenController(IdentityService identityService,
NotificationRepository notificationRepository,
OneTimeJwtService oneTimeJwtService,
NotificationClientService notificationClientService,
NotificationServerService notificationServerService)
{
IdentityService = identityService;
NotificationRepository = notificationRepository;
OneTimeJwtService = oneTimeJwtService;
NotificationClientService = notificationClientService;
NotificationServerService = notificationServerService;
}
[Route("/api/moonlight/notifications/listen")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
ws = webSocket;
await Echo();
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
}
}
private async Task Echo()
{
while (active)
{
byte[] bytes = new byte[1024 * 16];
var asg = new ArraySegment<byte>(bytes);
var res = await ws.ReceiveAsync(asg, CancellationToken.None);
var text = Encoding.UTF8.GetString(bytes).Trim('\0');
var obj = JsonConvert.DeserializeObject<BasicWSModel>(text);
if (!string.IsNullOrWhiteSpace(obj.Action))
{
await HandleRequest(text, obj.Action);
}
active = ws.State == WebSocketState.Open;
}
}
private async Task HandleRequest(string text, string action)
{
if (!isAuth && action == "login")
await Login(text);
else if (!isAuth)
await ws.SendAsync(Encoding.UTF8.GetBytes("{\"error\": \"Unauthorised\"}"), WebSocketMessageType.Text,
WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
else switch (action)
{
case "received":
await Received(text);
break;
case "read":
await Read(text);
break;
default:
break;
}
}
private async Task Login(string json)
{
var jwt = JsonConvert.DeserializeObject<Login>(json).token;
var dict = await OneTimeJwtService.Validate(jwt);
if (dict == null)
{
string error = "{\"status\":false}";
var bytes = Encoding.UTF8.GetBytes(error);
await ws.SendAsync(bytes, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
return;
}
var _clientId = dict["clientId"];
var clientId = int.Parse(_clientId);
var client = NotificationRepository.GetClients().Include(x => x.User).First(x => x.Id == clientId);
Client = client;
await InitWebsocket();
string success = "{\"status\":true}";
var byt = Encoding.UTF8.GetBytes(success);
await ws.SendAsync(byt, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
}
private async Task InitWebsocket()
{
NotificationClientService.listenController = this;
NotificationClientService.WebsocketReady(Client);
isAuth = true;
}
private async Task Received(string json)
{
var id = JsonConvert.DeserializeObject<NotificationById>(json).notification;
//TODO: Implement ws notification received
}
private async Task Read(string json)
{
var id = JsonConvert.DeserializeObject<NotificationById>(json).notification;
await NotificationServerService.SendAction(NotificationClientService.User,
JsonConvert.SerializeObject(new NotificationById() {Action = "hide", notification = id}));
}
}

View file

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Moonlight.App.Models.Notifications;
public class BasicWSModel
{
[JsonProperty("action")]
public string Action { get; set; }
}

View file

@ -0,0 +1,6 @@
namespace Moonlight.App.Models.Notifications;
public class Login : BasicWSModel
{
public string token { get; set; }
}

View file

@ -0,0 +1,6 @@
namespace Moonlight.App.Models.Notifications;
public class NotificationById : BasicWSModel
{
public int notification { get; set; }
}

View file

@ -1,5 +1,8 @@
using Moonlight.App.Database.Entities;
using System.Net.WebSockets;
using System.Text;
using Moonlight.App.Database.Entities;
using Moonlight.App.Database.Entities.Notification;
using Moonlight.App.Http.Controllers.Api.Moonlight.Notifications;
using Moonlight.App.Repositories;
using Moonlight.App.Services.Sessions;
@ -9,6 +12,7 @@ public class NotificationClientService
{
private readonly NotificationRepository NotificationRepository;
private readonly NotificationServerService NotificationServerService;
internal ListenController listenController;
public NotificationClientService(NotificationRepository notificationRepository, NotificationServerService notificationServerService)
{
@ -20,9 +24,10 @@ public class NotificationClientService
public NotificationClient NotificationClient { get; set; }
public void SendAction(string action)
public async Task SendAction(string action)
{
throw new NotImplementedException();
await listenController.ws.SendAsync(Encoding.UTF8.GetBytes(action), WebSocketMessageType.Text,
WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
}
public void WebsocketReady(NotificationClient client)

View file

@ -1,4 +1,5 @@
using Moonlight.App.Database.Entities;
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database.Entities;
using Moonlight.App.Database.Entities.Notification;
using Moonlight.App.Repositories;
@ -40,9 +41,9 @@ public class NotificationServerService
return connectedClients.Where(x => x.User == user).ToList();
}
public void SendAction(User user, string action)
public async Task SendAction(User user, string action)
{
var clients = NotificationRepository.GetClients().Where(x => x.User == user).ToList();
var clients = NotificationRepository.GetClients().Include(x => x.User).Where(x => x.User == user).ToList();
foreach (var client in clients)
{
@ -52,12 +53,12 @@ public class NotificationServerService
NotificationClient = client
};
var connected = connectedClients.Where(x => x.NotificationClient == client).ToList();
var connected = connectedClients.Where(x => x.NotificationClient.Id == client.Id).ToList();
if (connected.Count > 0)
{
var clientService = connected[0];
clientService.SendAction(action);
await clientService.SendAction(action);
}
else
{

View file

@ -141,6 +141,7 @@ namespace Moonlight
app.UseStaticFiles();
app.UseRouting();
app.UseWebSockets();
app.MapControllers();