fixes and cleanup
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Michele Scandura 2021-09-21 11:09:26 +01:00
parent 17d6cd28d6
commit 7e3e645fc9
48 changed files with 1530 additions and 1538 deletions

View File

@ -1,3 +1,4 @@
using System;
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
namespace Sledgemapper.Api.Commands namespace Sledgemapper.Api.Commands
@ -6,7 +7,7 @@ namespace Sledgemapper.Api.Commands
{ {
public Note Note { get; private set; } public Note Note { get; private set; }
public DeleteNoteCommand(string sessionName, Note note, string userId) : base(sessionName, userId) public DeleteNoteCommand(Guid campaign, Guid mapName, Note note, string userId) : base(campaign, mapName, userId)
{ {
Note = note; Note = note;
} }

View File

@ -1,12 +1,13 @@
using System;
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
namespace Sledgemapper.Api.Commands namespace Sledgemapper.Api.Commands
{ {
public class DeleteOverlayCommand : BaseCommand<bool> public class DeleteOverlayCommand : BaseCommand<bool>
{ {
public Overlay Overlay { get; private set; } public Overlay Overlay { get; private set; }
public DeleteOverlayCommand(string sessionName, Overlay overlay, string userId) : base(sessionName, userId) public DeleteOverlayCommand(Guid campaign, Guid mapName, Overlay overlay, string userId) : base(campaign, mapName, userId)
{ {
Overlay = overlay; Overlay = overlay;
} }

View File

@ -1,3 +1,4 @@
using System;
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
namespace Sledgemapper.Api.Commands namespace Sledgemapper.Api.Commands
@ -6,7 +7,7 @@ namespace Sledgemapper.Api.Commands
{ {
public Wall Wall { get; private set; } public Wall Wall { get; private set; }
public DeleteWallCommand(string sessionName, Wall wall, string userId) : base(sessionName, userId) public DeleteWallCommand(Guid campaign, Guid mapName, Wall wall, string userId) : base(campaign, mapName, userId)
{ {
Wall = wall; Wall = wall;
} }

View File

@ -162,7 +162,7 @@ namespace Sledgemapper.Api.Controllers
Subject = new ClaimsIdentity(new[] Subject = new ClaimsIdentity(new[]
{ {
new Claim("Id", user.Id.ToString()), new Claim("Id", user.Id),
new Claim(JwtRegisteredClaimNames.Sub, user.Email), new Claim(JwtRegisteredClaimNames.Sub, user.Email),
new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(JwtRegisteredClaimNames.Email, user.Email),
// the JTI is used for our refresh token which we will be convering in the next video // the JTI is used for our refresh token which we will be convering in the next video

View File

@ -24,7 +24,7 @@ namespace Sledgemapper.Api.Controllers
[Route("{campaignName}")] [Route("{campaignName}")]
public async Task<ActionResult<bool>> Post(string campaignName) public async Task<ActionResult<bool>> Post(string campaignName)
{ {
var result = await _mediator.Send(new NewCampaignCommand(campaignName, UserId.ToString())); var result = await _mediator.Send(new NewCampaignCommand(campaignName, UserId));
if (!result) if (!result)
{ {
return BadRequest(); return BadRequest();
@ -51,7 +51,7 @@ namespace Sledgemapper.Api.Controllers
[Route("{campaignName}/players/{email}")] [Route("{campaignName}/players/{email}")]
public async Task<bool> Invite(string campaignName, string email) public async Task<bool> Invite(string campaignName, string email)
{ {
var result = await _mediator.Send(new InvitePlayerToCampaignCommand(campaignName, email, UserId.ToString())); var result = await _mediator.Send(new InvitePlayerToCampaignCommand(campaignName, email, UserId));
return result; return result;
} }
@ -59,7 +59,7 @@ namespace Sledgemapper.Api.Controllers
[Route("{campaignName}/players")] [Route("{campaignName}/players")]
public async Task<List<Player>> GetPlayers(string campaignName) public async Task<List<Player>> GetPlayers(string campaignName)
{ {
var result = await _mediator.Send(new GetCampaignPlayersCommand(campaignName, UserId.ToString())); var result = await _mediator.Send(new GetCampaignPlayersCommand(campaignName, UserId));
return result; return result;
} }
@ -68,7 +68,7 @@ namespace Sledgemapper.Api.Controllers
[Route("{campaignName}/maps")] [Route("{campaignName}/maps")]
public async Task<List<Session>> GetMaps(Guid campaignName) public async Task<List<Session>> GetMaps(Guid campaignName)
{ {
var result = await _mediator.Send(new GetCampaignMapsCommand(campaignName, UserId.ToString())); var result = await _mediator.Send(new GetCampaignMapsCommand(campaignName, UserId));
return result; return result;
} }

View File

@ -1,11 +1,11 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Sledgemapper.Api.Commands; using Sledgemapper.Api.Commands;
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Sledgemapper.Api.Controllers namespace Sledgemapper.Api.Controllers
{ {
@ -14,15 +14,30 @@ namespace Sledgemapper.Api.Controllers
public class MapController : ControllerBase public class MapController : ControllerBase
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
public MapController(IMediator mediator)
{
_mediator = mediator;
}
private string UserId => HttpContext.User.Claims.FirstOrDefault(m => m.Type == "Id").Value; private string UserId => HttpContext.User.Claims.FirstOrDefault(m => m.Type == "Id").Value;
public MapController(IMediator mediator) => _mediator = mediator; [HttpDelete("overlay")]
public async Task Delete(Guid campaign, Guid mapName, [FromBody] Overlay overlay)
[HttpPost]
public async Task<Guid> Post(string campaign, string mapName)
{ {
var result = await _mediator.Send(new NewSessionCommand(campaign, mapName, UserId)); await _mediator.Send(new DeleteOverlayCommand(campaign, mapName, overlay, UserId));
return result; }
[HttpDelete("wall")]
public async Task Delete(Guid campaign, Guid mapName, [FromBody] Wall wall)
{
await _mediator.Send(new DeleteWallCommand(campaign, mapName, wall, UserId));
}
[HttpDelete("note")]
public async Task Delete(Guid campaign, Guid mapName, [FromBody] Note note)
{
await _mediator.Send(new DeleteNoteCommand(campaign, mapName, note, UserId));
} }
[HttpGet] [HttpGet]
@ -32,6 +47,13 @@ namespace Sledgemapper.Api.Controllers
return result; return result;
} }
[HttpPost]
public async Task<Guid> Post(string campaign, string mapName)
{
var result = await _mediator.Send(new NewSessionCommand(campaign, mapName, UserId));
return result;
}
[HttpPost("snapshot")] [HttpPost("snapshot")]
public async Task Post(string campaign, string mapName, [FromBody] Session session) public async Task Post(string campaign, string mapName, [FromBody] Session session)
{ {
@ -67,23 +89,5 @@ namespace Sledgemapper.Api.Controllers
{ {
await _mediator.Send(new NewLineCommand(campaign, mapName, line, UserId)); await _mediator.Send(new NewLineCommand(campaign, mapName, line, UserId));
} }
[HttpDelete("overlay")]
public async Task Delete(string campaign, string mapName, [FromBody] Overlay overlay)
{
await _mediator.Send(new DeleteOverlayCommand(mapName, overlay, UserId));
}
[HttpDelete("wall")]
public async Task Delete(string campaign, string mapName, [FromBody] Wall wall)
{
await _mediator.Send(new DeleteWallCommand(mapName, wall, UserId));
}
[HttpDelete("note")]
public async Task Delete(string campaign, string mapName, [FromBody] Note note)
{
await _mediator.Send(new DeleteNoteCommand(mapName, note, UserId));
}
} }
} }

View File

@ -1,7 +1,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models namespace Sledgemapper.Api.Core.Entities
{ {
public class MapLog public class MapLog
@ -10,7 +10,7 @@ namespace Sledgemapper.Api.Models
public int MapLogId { get; set; } public int MapLogId { get; set; }
[Required] [Required]
public string UserId{get;set;} public string UserId { get; set; }
[Required] [Required]
public Guid SessionId { get; set; } public Guid SessionId { get; set; }

View File

@ -3,7 +3,7 @@ using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace Sledgemapper.Api.Models namespace Sledgemapper.Api.Core.Entities
{ {
[Index(nameof(CampaignId), nameof(SessionName), IsUnique = true)] [Index(nameof(CampaignId), nameof(SessionName), IsUnique = true)]
public class Session public class Session
@ -13,7 +13,7 @@ namespace Sledgemapper.Api.Models
public Guid SessionId { get; set; } public Guid SessionId { get; set; }
[Required] [Required]
public Guid CampaignId { get; set; } public Guid CampaignId { get; set; }
[Required] [Required]
public string SessionName { get; set; } public string SessionName { get; set; }

View File

@ -1,7 +1,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models namespace Sledgemapper.Api.Core.Entities
{ {
public class SessionUser public class SessionUser
{ {

View File

@ -1,7 +1,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models namespace Sledgemapper.Api.Core.Entities
{ {
public class Snapshot public class Snapshot

View File

@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
namespace Sledgemapper.Entities namespace Sledgemapper.Api.Core.Entities
{ {
public class User:IdentityUser public class User : IdentityUser
{ {
// public int Id { get; set; } // public int Id { get; set; }
public string FirstName { get; set; } public string FirstName { get; set; }
@ -13,6 +13,6 @@ namespace Sledgemapper.Entities
public string Initials { get; set; } public string Initials { get; set; }
// public byte[] PasswordHash { get; set; } // public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; } public byte[] PasswordSalt { get; set; }
public ICollection<Api.Core.Entities.Campaign> Campaigns {get;set;} public ICollection<Campaign> Campaigns { get; set; }
} }
} }

View File

@ -1,7 +1,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models namespace Sledgemapper.Api.Core.Entities
{ {
public class UserConnection public class UserConnection
{ {
@ -11,6 +11,6 @@ namespace Sledgemapper.Api.Models
public Guid UserId { get; set; } public Guid UserId { get; set; }
[Required] [Required]
public string ConnectionId{get;set;} public string ConnectionId { get; set; }
} }
} }

View File

@ -7,31 +7,29 @@ using System.Threading.Tasks;
using System; using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Sledgemapper.Api.Models; using Sledgemapper.Api.Models;
using System.Collections.Generic;
using Sledgemapper.Api.Core.Entities; using Sledgemapper.Api.Core.Entities;
namespace Sledgemapper.Api.Handlers namespace Sledgemapper.Api.Handlers
{ {
public abstract class BaseCommandHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : BaseCommand<TResponse> public abstract class BaseCommandHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : BaseCommand<TResponse>
{ {
protected SledgemapperDbContext Dbcontext { get; } protected SledgemapperDbContext DbContext { get; }
protected IMediator Mediator { get; } protected IMediator Mediator { get; }
public abstract Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken); public abstract Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken);
public BaseCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) protected BaseCommandHandler(IMediator mediator, SledgemapperDbContext dbContext)
{ {
Dbcontext = dbcontext; DbContext = dbContext;
Mediator = mediator; Mediator = mediator;
} }
protected async Task CheckAuthorization(TRequest command) protected async Task CheckAuthorization(TRequest command)
{ {
var user = await Dbcontext.Users.FindAsync(command.UserId); var user = await DbContext.Users.FindAsync(command.UserId);
Dbcontext.Attach(user); DbContext.Attach(user);
var campaign = await GetCampaignForUser(command); var campaign = await GetCampaignForUser(command);
@ -46,9 +44,9 @@ namespace Sledgemapper.Api.Handlers
protected async Task<Campaign> GetCampaignForUser(TRequest command) protected async Task<Campaign> GetCampaignForUser(TRequest command)
{ {
var user = await Dbcontext.Users.FindAsync(command.UserId); var user = await DbContext.Users.FindAsync(command.UserId);
Dbcontext.Attach(user); DbContext.Attach(user);
var campaign = await Dbcontext var campaign = await DbContext
.Campaigns .Campaigns
.Where(campaign => campaign.CampaignId == command.Campaign) .Where(campaign => campaign.CampaignId == command.Campaign)
.Include(c => c.InvitedUsers) .Include(c => c.InvitedUsers)
@ -60,8 +58,8 @@ namespace Sledgemapper.Api.Handlers
protected async Task<Session> SaveLog(TRequest command, string operation, string type, string data, CancellationToken cancellationToken) protected async Task<Session> SaveLog(TRequest command, string operation, string type, string data, CancellationToken cancellationToken)
{ {
var session = Dbcontext.Sessions.First(m => m.SessionId == command.SessionId); var session = DbContext.Sessions.First(m => m.SessionId == command.SessionId);
Dbcontext.MapLogs.Add(new Models.MapLog DbContext.MapLogs.Add(new MapLog
{ {
Operation = operation, Operation = operation,
SessionId = session.SessionId, SessionId = session.SessionId,
@ -70,7 +68,7 @@ namespace Sledgemapper.Api.Handlers
Object = data, Object = data,
UserId = command.UserId, UserId = command.UserId,
}); });
await Dbcontext.SaveChangesAsync(cancellationToken); await DbContext.SaveChangesAsync(cancellationToken);
return session; return session;
} }

View File

@ -6,31 +6,32 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using Sledgemapper.Api.Models; using Sledgemapper.Api.Models;
using Sledgemapper.Api.Commands;
namespace Sledgemapper.Api.Commands namespace Sledgemapper.Api.Handlers
{ {
public class GetMapSnapshotCommandHandler : IRequestHandler<GetMapSnapshotCommand, Shared.Entities.Session> public class GetMapSnapshotCommandHandler : IRequestHandler<GetMapSnapshotCommand, Session>
{ {
private readonly SledgemapperDbContext _dbcontext; private readonly SledgemapperDbContext _dbcontext;
public GetMapSnapshotCommandHandler(SledgemapperDbContext dbcontext) { _dbcontext = dbcontext; } public GetMapSnapshotCommandHandler(SledgemapperDbContext dbcontext) { _dbcontext = dbcontext; }
public async Task<Shared.Entities.Session> Handle(GetMapSnapshotCommand notification, CancellationToken cancellationToken) public async Task<Session> Handle(GetMapSnapshotCommand notification, CancellationToken cancellationToken)
{ {
Snapshot snapshot; Snapshot snapshot;
double timestamp; double timestamp;
Shared.Entities.Session mapSession; Session mapSession;
var session = _dbcontext.Sessions.First(m => m.SessionId == notification.MapId); var session = _dbcontext.Sessions.First(m => m.SessionId == notification.MapId);
snapshot = _dbcontext.Snapshots.OrderByDescending(s => s.Timestamp).FirstOrDefault(m => m.SessionId == session.SessionId); snapshot = _dbcontext.Snapshots.OrderByDescending(s => s.Timestamp).FirstOrDefault(m => m.SessionId == session.SessionId);
if (snapshot is null) if (snapshot is null)
{ {
timestamp = 0; timestamp = 0;
mapSession = new Shared.Entities.Session(); mapSession = new Session();
} }
else else
{ {
mapSession = JsonSerializer.Deserialize<Shared.Entities.Session>(snapshot.Object); mapSession = JsonSerializer.Deserialize<Session>(snapshot.Object);
timestamp = snapshot.Timestamp; timestamp = snapshot.Timestamp;
} }
@ -57,7 +58,7 @@ namespace Sledgemapper.Api.Commands
var note = JsonSerializer.Deserialize<Note>(mapUpdate.Object); var note = JsonSerializer.Deserialize<Note>(mapUpdate.Object);
mapSession.NewNote(note); mapSession.NewNote(note);
break; break;
case "L": case "L":
var line = JsonSerializer.Deserialize<Line>(mapUpdate.Object); var line = JsonSerializer.Deserialize<Line>(mapUpdate.Object);
mapSession.NewLine(line); mapSession.NewLine(line);
break; break;
@ -65,9 +66,9 @@ namespace Sledgemapper.Api.Commands
var room = JsonSerializer.Deserialize<Room>(mapUpdate.Object); var room = JsonSerializer.Deserialize<Room>(mapUpdate.Object);
mapSession.NewRoom(room); mapSession.NewRoom(room);
break; break;
} }

View File

@ -10,7 +10,7 @@ namespace Sledgemapper.Api.Handlers
{ {
public class NewLineCommandHandler : BaseCommandHandler<NewLineCommand, bool> public class NewLineCommandHandler : BaseCommandHandler<NewLineCommand, bool>
{ {
public NewLineCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) : base(mediator, dbcontext) public NewLineCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) : base(mediator, dbContext)
{ {
} }

View File

@ -5,8 +5,9 @@ using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using Sledgemapper.Api.Commands;
namespace Sledgemapper.Api.Commands namespace Sledgemapper.Api.Handlers
{ {
public class NewSnapshotCommandHandler : IRequestHandler<NewSnapshotCommand, bool> public class NewSnapshotCommandHandler : IRequestHandler<NewSnapshotCommand, bool>
{ {
@ -17,18 +18,19 @@ namespace Sledgemapper.Api.Commands
public async Task<bool> Handle(NewSnapshotCommand notification, CancellationToken cancellationToken) public async Task<bool> Handle(NewSnapshotCommand notification, CancellationToken cancellationToken)
{ {
var session = _dbcontext.Sessions.First(m => m.SessionName == notification.SessionName); var session = _dbcontext.Sessions.First(m => m.SessionName == notification.SessionName);
var newSnapshot = new Models.Snapshot{ var newSnapshot = new Models.Snapshot
SessionId=session.SessionId, {
Timestamp=notification.Timestamp, SessionId = session.SessionId,
Object = JsonSerializer.Serialize(notification.Session) Timestamp = notification.Timestamp,
Object = JsonSerializer.Serialize(notification.Session)
}; };
await _dbcontext.Snapshots.AddAsync(newSnapshot); await _dbcontext.Snapshots.AddAsync(newSnapshot);
await _dbcontext.SaveChangesAsync(); await _dbcontext.SaveChangesAsync();
return true; return true;
} }

View File

@ -4,13 +4,13 @@ using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Sledgemapper.Api.Notifications; using Sledgemapper.Api.Notifications;
using Sledgemapper.Api.Handlers; using Sledgemapper.Api.Commands;
namespace Sledgemapper.Api.Commands namespace Sledgemapper.Api.Handlers
{ {
public class NewTileCommandHandler : BaseCommandHandler<NewTileCommand, bool> public class NewTileCommandHandler : BaseCommandHandler<NewTileCommand, bool>
{ {
public NewTileCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) : base(mediator, dbcontext) public NewTileCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) : base(mediator, dbContext)
{ {
} }

View File

@ -10,7 +10,7 @@ namespace Sledgemapper.Api.Handlers
{ {
public class NewWallCommandHandler : BaseCommandHandler<NewWallCommand, bool> public class NewWallCommandHandler : BaseCommandHandler<NewWallCommand, bool>
{ {
public NewWallCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) : base(mediator, dbcontext) public NewWallCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) : base(mediator, dbContext)
{ {
} }

View File

@ -1,28 +0,0 @@
// using MediatR;
// using Sledgemapper.Api.Infrastructure.Data;
// using System.Threading;
// using System.Threading.Tasks;
// using Sledgemapper.Api.Notifications;
// using System.Linq;
// namespace Sledgemapper.Api.Commands
// {
// public class PingCommandHandler : IRequestHandler<PingCommand, bool>
// {
// private readonly SledgemapperDbContext _dbcontext;
// private readonly IMediator _mediator;
// public PingCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) { _dbcontext = dbcontext; _mediator = mediator; }
// public async Task<bool> Handle(PingCommand notification, CancellationToken cancellationToken)
// {
// var session = _dbcontext.Sessions.First(m => m.SessionName == notification.SessionName);
// await _mediator.Publish(new PingNotification(session, notification.Location, notification.UserId));
// return true;
// }
// }
// }

View File

@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers
public async Task Handle(DeleteNoteNotification notification, CancellationToken cancellationToken) public async Task Handle(DeleteNoteNotification notification, CancellationToken cancellationToken)
{ {
await _hub.Clients.Groups(notification.Session.SessionName).DeleteNote(notification.Note); await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteNote(notification.Note);
} }
} }
} }

View File

@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers
public async Task Handle(DeleteOverlayNotification notification, CancellationToken cancellationToken) public async Task Handle(DeleteOverlayNotification notification, CancellationToken cancellationToken)
{ {
await _hub.Clients.Groups(notification.Session.SessionName).DeleteOverlay(notification.Overlay); await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteOverlay(notification.Overlay);
} }
} }
} }

View File

@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers
public async Task Handle(DeleteTileNotification notification, CancellationToken cancellationToken) public async Task Handle(DeleteTileNotification notification, CancellationToken cancellationToken)
{ {
await _hub.Clients.Groups(notification.Session.SessionName).DeleteTile(notification.Tile); await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteTile(notification.Tile);
} }
} }
} }

View File

@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers
public async Task Handle(DeleteWallNotification notification, CancellationToken cancellationToken) public async Task Handle(DeleteWallNotification notification, CancellationToken cancellationToken)
{ {
await _hub.Clients.Groups(notification.Session.SessionName).DeleteWall(notification.Wall); await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteWall(notification.Wall);
} }
} }
} }

View File

@ -1,23 +0,0 @@
// using MediatR;
// using Microsoft.AspNetCore.SignalR;
// using Sledgemapper.Api.Notifications;
// using Sledgemapper.Clients;
// using System.Threading;
// using System.Threading.Tasks;
// using Sledgemapper.Api.Hubs;
// namespace Sledgemapper.Api.Handlers
// {
// public class SendPingMessage : INotificationHandler<PingNotification>
// {
// private readonly IHubContext<SledgemapperHub, ISledgemapperClient> _hub;
// public SendPingMessage(IHubContext<SledgemapperHub, ISledgemapperClient> hub) => _hub = hub;
// public async Task Handle(PingNotification notification, CancellationToken cancellationToken)
// {
// await _hub.Clients.Groups(notification.Session.SessionName).Ping(notification.Location, notification.UserId);
// }
// }
// }

View File

@ -3,7 +3,6 @@ using Sledgemapper.Api.Commands;
using Sledgemapper.Api.Infrastructure.Data; using Sledgemapper.Api.Infrastructure.Data;
using Sledgemapper.Api.Models; using Sledgemapper.Api.Models;
using System; using System;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -29,8 +28,8 @@ namespace Sledgemapper.Api.Handlers
CampaignId = campaign.CampaignId CampaignId = campaign.CampaignId
}; };
Dbcontext.Sessions.Add(session); DbContext.Sessions.Add(session);
await Dbcontext.SaveChangesAsync(); await DbContext.SaveChangesAsync(cancellationToken);
return session.SessionId; return session.SessionId;
} }
} }

View File

@ -1,17 +1,17 @@
using System; using System;
using System.Globalization; using System.Globalization;
namespace Sledgemapper.Helpers namespace Sledgemapper.Api.Helpers
{ {
// Custom exception class for throwing application specific exceptions (e.g. for validation) // Custom exception class for throwing application specific exceptions (e.g. for validation)
// that can be caught and handled within the application // that can be caught and handled within the application
public class AppException : Exception public class AppException : Exception
{ {
public AppException() : base() {} public AppException() : base() { }
public AppException(string message) : base(message) { } public AppException(string message) : base(message) { }
public AppException(string message, params object[] args) public AppException(string message, params object[] args)
: base(string.Format(CultureInfo.CurrentCulture, message, args)) : base(string.Format(CultureInfo.CurrentCulture, message, args))
{ {
} }

View File

@ -2,7 +2,7 @@ using AutoMapper;
using Sledgemapper.Entities; using Sledgemapper.Entities;
using Sledgemapper.Models.Users; using Sledgemapper.Models.Users;
namespace Sledgemapper.Helpers namespace Sledgemapper.Api.Helpers
{ {
public class AutoMapperProfile : Profile public class AutoMapperProfile : Profile
{ {

View File

@ -17,12 +17,10 @@ namespace Sledgemapper.Api.Hubs
{ {
private static readonly ConcurrentDictionary<Guid, string> UserColors = new(); private static readonly ConcurrentDictionary<Guid, string> UserColors = new();
private readonly SledgemapperDbContext _dbContext; private readonly SledgemapperDbContext _dbContext;
// private readonly DataContext _datacontext;
public SledgemapperHub(SledgemapperDbContext dbContext/*, DataContext datacontext*/) public SledgemapperHub(SledgemapperDbContext dbContext/*, DataContext datacontext*/)
{ {
_dbContext = dbContext; _dbContext = dbContext;
// _datacontext = datacontext;
} }
// other colors // other colors
@ -87,12 +85,12 @@ namespace Sledgemapper.Api.Hubs
public async Task Ping(string sessionName, Tile location) public async Task Ping(string sessionName, Tile location)
{ {
var userId = new Guid( Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value); var userId = new Guid(Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value);
var user = _dbContext.Users.First(u => u.Id == userId.ToString()); var user = _dbContext.Users.First(u => u.Id == userId.ToString());
var player = new Player { UserId = userId, Initials = user.Initials, Position = new Tile { X = 0, Y = 0 }, Color = UserColors[userId] }; var player = new Player { UserId = userId, Initials = user.Initials, Position = new Tile { X = 0, Y = 0 }, Color = UserColors[userId] };
await Clients.Group(sessionName).Ping(new Ping{X=location.X, Y=location.Y, Player=player}); await Clients.Group(sessionName).Ping(new Ping { X = location.X, Y = location.Y, Player = player });
} }
public async Task<bool> JoinSession(Guid mapId) public async Task<bool> JoinSession(Guid mapId)
@ -114,7 +112,7 @@ namespace Sledgemapper.Api.Hubs
await Clients.Group(session.SessionId.ToString()).NewPlayer(player); await Clients.Group(session.SessionId.ToString()).NewPlayer(player);
await Clients.Group(session.SessionId.ToString()).RefreshPlayers(); await Clients.Group(session.SessionId.ToString()).RefreshPlayers();
return true; return true;
} }
@ -136,7 +134,7 @@ namespace Sledgemapper.Api.Hubs
public async Task UpdatePosition(string sessionName, Guid sessionId, Tile tile) public async Task UpdatePosition(string sessionName, Guid sessionId, Tile tile)
{ {
var userId = new Guid(Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value); var userId = new Guid(Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value);
var SessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList(); var sessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList();
var user = _dbContext.Users.First(u => u.Id == userId.ToString()); var user = _dbContext.Users.First(u => u.Id == userId.ToString());
var player = new Player { UserId = userId, Initials = user.Initials, Position = tile, Color = UserColors[userId] }; var player = new Player { UserId = userId, Initials = user.Initials, Position = tile, Color = UserColors[userId] };
await Clients.Group(sessionId.ToString()).PlayerUpdate(player); await Clients.Group(sessionId.ToString()).PlayerUpdate(player);
@ -148,7 +146,7 @@ namespace Sledgemapper.Api.Hubs
var userConnection = new UserConnection { ConnectionId = Context.ConnectionId, UserId = userId }; var userConnection = new UserConnection { ConnectionId = Context.ConnectionId, UserId = userId };
_dbContext.UserConnections.Add(userConnection); _dbContext.UserConnections.Add(userConnection);
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync();
var availableColor = Colors.Where(m => !UserColors.Values.Contains(m)).First(); var availableColor = Colors.First(m => !UserColors.Values.Contains(m));
UserColors.AddOrUpdate(userId, availableColor, (key, oldValue) => availableColor); UserColors.AddOrUpdate(userId, availableColor, (key, oldValue) => availableColor);
await base.OnConnectedAsync(); await base.OnConnectedAsync();
} }
@ -156,26 +154,26 @@ namespace Sledgemapper.Api.Hubs
public override async Task OnDisconnectedAsync(Exception exception) public override async Task OnDisconnectedAsync(Exception exception)
{ {
var userConnection = _dbContext.UserConnections.FirstOrDefault(m => m.ConnectionId == Context.ConnectionId); var userConnection = _dbContext.UserConnections.FirstOrDefault(m => m.ConnectionId == Context.ConnectionId);
var userId = userConnection.UserId;
if (userConnection != null) if (userConnection != null)
{ {
var userId = userConnection.UserId;
_dbContext.UserConnections.Remove(userConnection); _dbContext.UserConnections.Remove(userConnection);
}
var userSessions = _dbContext.SessionUsers.Where(m => m.UserId == userId).ToList(); var userSessions = _dbContext.SessionUsers.Where(m => m.UserId == userId).ToList();
{
foreach (var userSession in userSessions)
{ {
var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionId == userSession.SessionId); foreach (var userSession in userSessions)
{
var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionId == userSession.SessionId);
await Clients.Group(session.SessionName).RemovePlayer(new Player { UserId = userId }); //send remove player await Clients.Group(session.SessionName).RemovePlayer(new Player { UserId = userId }); //send remove player
_dbContext.SessionUsers.Remove(userSession); _dbContext.SessionUsers.Remove(userSession);
}
} }
await _dbContext.SaveChangesAsync();
await base.OnDisconnectedAsync(exception);
} }
await _dbContext.SaveChangesAsync();
await base.OnDisconnectedAsync(exception);
} }
} }
} }

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Sledgemapper.Models.Users namespace Sledgemapper.Api.Models
{ {
public class AuthResult public class AuthResult
{ {

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Models.Users namespace Sledgemapper.Api.Models
{ {
public class AuthenticateModel public class AuthenticateModel
{ {

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Models.Users namespace Sledgemapper.Api.Models
{ {
public class RegisterModel public class RegisterModel
{ {

View File

@ -1,4 +1,6 @@
namespace Sledgemapper.Models.Users using Sledgemapper.Models.Users;
namespace Sledgemapper.Api.Models
{ {
public class RegistrationResponse : AuthResult public class RegistrationResponse : AuthResult
{ {

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Models.Users namespace Sledgemapper.Api.Models
{ {
public class UserLoginRequest public class UserLoginRequest
{ {

View File

@ -1,8 +1,7 @@
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Sledgemapper.Clients namespace Sledgemapper.Shared.Clients
{ {
public interface ISledgemapperClient public interface ISledgemapperClient
{ {

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Sledgemapper.Api.Hubs namespace Sledgemapper.Shared
{ {
public static class ExtensionMethods public static class ExtensionMethods
{ {
@ -20,6 +20,6 @@ namespace Sledgemapper.Api.Hubs
} }
} }
} }
} }

View File

@ -8,8 +8,10 @@ using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Threading; using System.Threading;
using System.Diagnostics; using System.Diagnostics;
using System.Collections;
using System.Collections.Concurrent;
namespace System.Collections.Concurrent namespace Sledgemapper.Shared
{ {
/// <summary> /// <summary>
/// Provides a thread-safe dictionary for use with data binding. /// Provides a thread-safe dictionary for use with data binding.

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sledgemapper/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,7 +1,3 @@
using Microsoft.AspNetCore.SignalR.Client;
using Polly;
using Refit;
using Sledgemapper.Shared.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -10,20 +6,21 @@ using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
using Polly;
using Refit;
using Sledgemapper.Shared.Entities;
namespace Sledgemapper namespace Sledgemapper
{ {
public class CommunicationManager public class CommunicationManager
{ {
public IMapApi Api { get; private set; } private readonly ChannelsQueue _queue = new();
public HubConnection Connection { get; private set; }
public readonly Session SessionData; public readonly Session SessionData;
private readonly ChannelsQueue Queue = new();
private AuthenticateResponse _authenticateResponse; private AuthenticateResponse _authenticateResponse;
public CommunicationManager(Session sessionData) public CommunicationManager(Session sessionData)
{ {
#if DEBUG #if DEBUG
var baseAddress = "http://localhost:5000"; var baseAddress = "http://localhost:5000";
#else #else
@ -32,115 +29,93 @@ namespace Sledgemapper
SessionData = sessionData; SessionData = sessionData;
Connection = new HubConnectionBuilder() Connection = new HubConnectionBuilder()
.WithAutomaticReconnect() .WithAutomaticReconnect()
.WithUrl($"{baseAddress}/SledgemapperHub",
.WithUrl($"{baseAddress}/SledgemapperHub", options => options => { options.AccessTokenProvider = () => Task.FromResult(_authenticateResponse.Token); })
{ .Build();
options.AccessTokenProvider = () => Task.FromResult(_authenticateResponse.Token);
})
.Build();
Api = RestService.For<IMapApi>( Api = RestService.For<IMapApi>(
new HttpClient(new AuthenticatedHttpClientHandler(GetToken)) new HttpClient(new AuthenticatedHttpClientHandler(GetToken))
{ {
BaseAddress = new Uri(baseAddress) BaseAddress = new Uri(baseAddress)
} }
); );
Connection.On<Session>("UpdateMap", (map) => Connection.On<Session>("UpdateMap", map =>
{ {
SessionData.Map = map.Map; SessionData.Map = map.Map;
SessionData.Walls = map.Walls; SessionData.Walls = map.Walls;
SessionData.Overlays = map.Overlays; SessionData.Overlays = map.Overlays;
}); });
Connection.On<Player>("PlayerUpdate", (player) => Connection.On<Player>("PlayerUpdate", player =>
{ {
var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId);
if (p != null) if (p != null)
{
p.Position = player.Position; p.Position = player.Position;
}
else else
{
SessionData.Players.Add(player); SessionData.Players.Add(player);
}
}); });
Connection.On<Tile>("DeleteTile", (tile) => Connection.On<Tile>("DeleteTile", tile => { SessionData.Map.Remove(tile.ToString(), out var _); });
Connection.On<Wall>("DeleteWall", tile => { SessionData.Walls.Remove(tile.ToString(), out var _); });
Connection.On<Note>("DeleteNote", tile => { SessionData.Notes.Remove(tile.ToString(), out var _); });
Connection.On<Overlay>("DeleteOverlay",
tile => { SessionData.Overlays.Remove(tile.ToString(), out var _); });
Connection.On<Tile>("NewTile", tile =>
{ {
SessionData.Map.Remove(tile.ToString(), out var _); SessionData.Map.Remove(tile.ToString(), out var _);
SessionData.Map.TryAdd(tile.ToString(), tile);
}); });
Connection.On<Wall>("DeleteWall", (tile) => Connection.On<Room>("NewRoom", room =>
{ {
SessionData.Walls.Remove(tile.ToString(), out var _); SessionData.Rooms.Remove(room.ToString(), out var _);
}); SessionData.Rooms.TryAdd(room.ToString(), room);
});
Connection.On<Note>("DeleteNote", (tile) => Connection.On<Line>("NewLine", line =>
{ {
SessionData.Notes.Remove(tile.ToString(), out var _); SessionData.Lines.Remove(line.ToString(), out var _);
}); SessionData.Lines.TryAdd(line.ToString(), line);
});
Connection.On<Overlay>("DeleteOverlay", (tile) =>
{
SessionData.Overlays.Remove(tile.ToString(), out var _);
});
Connection.On<Tile>("NewTile", (tile) =>
{
SessionData.Map.Remove(tile.ToString(), out var _);
SessionData.Map.TryAdd(tile.ToString(), tile);
});
Connection.On<Room>("NewRoom", (room) =>
{
SessionData.Rooms.Remove(room.ToString(), out var _);
SessionData.Rooms.TryAdd(room.ToString(), room);
});
Connection.On<Line>("NewLine", (line) =>
{
SessionData.Lines.Remove(line.ToString(), out var _);
SessionData.Lines.TryAdd(line.ToString(), line);
});
Connection.On("RefreshPlayers", () => Connection.On("RefreshPlayers", () =>
{ {
if (!string.IsNullOrWhiteSpace(State.Instance.MapName)) if (!string.IsNullOrWhiteSpace(State.Instance.MapName))
{ Connection?.SendAsync("UpdatePosition", State.Instance.MapName, State.Instance.MapId,
Connection?.SendAsync("UpdatePosition", State.Instance.MapName, State.Instance.MapId, SessionData.Players.First(p => p.UserId == new Guid(_authenticateResponse.Id))); SessionData.Players.First(p => p.UserId == new Guid(_authenticateResponse.Id)));
} });
});
Connection.On<Player>("RemovePlayer", (player) => Connection.On<Player>("RemovePlayer", player =>
{ {
var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId);
if (p != null) if (p != null) SessionData.Players.Remove(p);
{ });
SessionData.Players.Remove(p);
}
});
Connection.On<Wall>("NewWall", (tile) => Connection.On<Wall>("NewWall", tile =>
{ {
SessionData.Walls.Remove(tile.ToString(), out var _); SessionData.Walls.Remove(tile.ToString(), out var _);
SessionData.Walls.TryAdd(tile.ToString(), tile); SessionData.Walls.TryAdd(tile.ToString(), tile);
}); });
Connection.On<Overlay>("NewOverlay", (tile) => Connection.On<Overlay>("NewOverlay", tile =>
{ {
SessionData.Overlays.Remove(tile.ToString(), out var _); SessionData.Overlays.Remove(tile.ToString(), out var _);
SessionData.Overlays.TryAdd(tile.ToString(), tile); SessionData.Overlays.TryAdd(tile.ToString(), tile);
}); });
Connection.On<Note>("NewNote", (note) => Connection.On<Note>("NewNote", note =>
{ {
//SessionData.Notes.Remove(note.ToString(), out var _); //SessionData.Notes.Remove(note.ToString(), out var _);
SessionData.Notes.AddOrUpdate(note.ToString(), note, (key, oldnote) => note); SessionData.Notes.AddOrUpdate(note.ToString(), note, (key, oldnote) => note);
}); });
Connection.On<Player>("NewPlayer", (player) => Connection.On<Player>("NewPlayer", player =>
{ {
var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId);
if (p is null) if (p is null)
@ -154,41 +129,11 @@ namespace Sledgemapper
} }
}); });
Connection.On<Ping>("Ping", (ping) => Connection.On<Ping>("Ping", ping => { SessionData.Pings.TryAdd(Guid.NewGuid(), ping); });
{
SessionData.Pings.TryAdd(Guid.NewGuid(), ping);
});
} }
public IMapApi Api { get; }
public HubConnection Connection { get; }
private Task<string> GetToken()
{
return Task.FromResult(_authenticateResponse.Token);
}
public async Task<IMapApi.AuthResult> Register(RegisterModel registerModel)
{
var result = await Api.Register(registerModel).ConfigureAwait(false);
return result;
}
public async Task<AuthenticateResponse> Login(AuthenticateModel authenticateModel)
{
_authenticateResponse = await Api.Authenticate(authenticateModel).ConfigureAwait(false);
return _authenticateResponse;
}
private async Task Execute(Func<Task> call)
{
await Policy
.Handle<ApiException>(ex => ex.StatusCode == HttpStatusCode.RequestTimeout)
.RetryForeverAsync()
//.RetryAsync(Polly.RetrySyntax., async (exception, retryCount) => await Task.Delay(500))
.ExecuteAsync(async () => await call().ConfigureAwait(false))
.ConfigureAwait(false);
}
public void Enqueue(BaseMapEntity entity, TileAction action) public void Enqueue(BaseMapEntity entity, TileAction action)
{ {
@ -198,64 +143,112 @@ namespace Sledgemapper
switch (entity) switch (entity)
{ {
case Tile tile: case Tile tile:
Queue.Enqueue(async () => await Execute(async () => await Api.NewTile(tile, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.NewTile(tile, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Overlay overlay: case Overlay overlay:
Queue.Enqueue(async () => await Execute(async () => await Api.NewOverlay(overlay,State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.NewOverlay(overlay, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Wall wall: case Wall wall:
Queue.Enqueue(async () => await Execute(async () => await Api.NewWall(wall, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.NewWall(wall, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Note note: case Note note:
Queue.Enqueue(async () => await Execute(async () => await Api.NewNote(note, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.NewNote(note, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Room room: case Room room:
Queue.Enqueue(async () => await Execute(async () => await Api.NewRoom(room, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.NewRoom(room, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Line line: case Line line:
Queue.Enqueue(async () => await Execute(async () => await Api.NewLine(line, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.NewLine(line, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
} }
break; break;
case TileAction.Delete: case TileAction.Delete:
switch (entity) switch (entity)
{ {
case Tile tile: case Tile tile:
Queue.Enqueue(async () => await Execute(async () => await Api.DeleteTile(tile, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.DeleteTile(tile, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Overlay overlay: case Overlay overlay:
Queue.Enqueue(async () => await Execute(async () => await Api.DeleteOverlay(overlay, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.DeleteOverlay(overlay, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Wall wall: case Wall wall:
Queue.Enqueue(async () => await Execute(async () => await Api.DeleteWall(wall, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.DeleteWall(wall, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
case Note note: case Note note:
Queue.Enqueue(async () => await Execute(async () => await Api.DeleteNote(note, State.Instance.MapId).ConfigureAwait(false))); _queue.Enqueue(async () => await Execute(async () =>
await Api.DeleteNote(note, State.Instance.CampaignId, State.Instance.MapId)
.ConfigureAwait(false)));
break; break;
} }
break; break;
} }
}
private async Task Execute(Func<Task> call)
{
await Policy
.Handle<ApiException>(ex => ex.StatusCode == HttpStatusCode.RequestTimeout)
.RetryForeverAsync()
//.RetryAsync(Polly.RetrySyntax., async (exception, retryCount) => await Task.Delay(500))
.ExecuteAsync(async () => await call().ConfigureAwait(false))
.ConfigureAwait(false);
}
private Task<string> GetToken()
{
return Task.FromResult(_authenticateResponse.Token);
}
public async Task<AuthenticateResponse> Login(AuthenticateModel authenticateModel)
{
_authenticateResponse = await Api.Authenticate(authenticateModel).ConfigureAwait(false);
return _authenticateResponse;
} }
internal async Task Ping(Tile location) internal async Task Ping(Tile location)
{ {
if (Connection!=null && Connection.State == HubConnectionState.Connected) if (Connection is { State: HubConnectionState.Connected })
{ {
await Connection.InvokeAsync("Ping",SessionData.SessionName, location); await Connection.InvokeAsync("Ping", SessionData.SessionName, location);
} }
} }
public async Task<IMapApi.AuthResult> Register(RegisterModel registerModel)
{
var result = await Api.Register(registerModel).ConfigureAwait(false);
return result;
}
} }
class AuthenticatedHttpClientHandler : HttpClientHandler internal class AuthenticatedHttpClientHandler : HttpClientHandler
{ {
private readonly Func<Task<string>> getToken; private readonly Func<Task<string>> _getToken;
public AuthenticatedHttpClientHandler(Func<Task<string>> getToken) public AuthenticatedHttpClientHandler(Func<Task<string>> getToken)
{ {
if (getToken == null) throw new ArgumentNullException(nameof(getToken)); _getToken = getToken ?? throw new ArgumentNullException(nameof(getToken));
this.getToken = getToken;
//if (myConfigurationService.VerifySslCertificate == false) //if (myConfigurationService.VerifySslCertificate == false)
//{ //{
@ -264,19 +257,18 @@ namespace Sledgemapper
//} //}
} }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{ {
// See if the request has an authorize header // See if the request has an authorize header
var auth = request.Headers.Authorization; var auth = request.Headers.Authorization;
if (auth != null) if (auth != null)
{ {
var token = await getToken().ConfigureAwait(false); var token = await _getToken().ConfigureAwait(false);
request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token); request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token);
} }
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
} }
} }
} }

View File

@ -70,17 +70,17 @@ namespace Sledgemapper
[Delete("/session/{sessionName}/wall")] [Delete("/map/{campaignId}/{mapId}/wall")]
Task DeleteWall([Body] Wall wall, Guid sessionName); Task DeleteWall([Body] Wall wall, Guid campaignId, Guid mapId);
[Delete("/session/{sessionName}/tile")] [Delete("/map/{campaignId}/{mapId}/tile")]
Task DeleteTile([Body] Tile tile, Guid sessionName); Task DeleteTile([Body] Tile tile, Guid campaignId, Guid mapId);
[Delete("/session/{sessionName}/overlay")] [Delete("/map/{campaignId}/{mapId}/overlay")]
Task DeleteOverlay([Body] Overlay overlay, Guid sessionName); Task DeleteOverlay([Body] Overlay overlay, Guid campaignId, Guid mapId);
[Delete("/session/{sessionName}/note")] [Delete("/map/{campaignId}/{mapId}/note")]
Task DeleteNote([Body] Note overlay, Guid sessionName); Task DeleteNote([Body] Note overlay, Guid campaignId, Guid mapId);
public class AuthResult public class AuthResult

View File

@ -14,7 +14,7 @@ namespace Sledgemapper
public int TileDeleteDivider { get; set; } public int TileDeleteDivider { get; set; }
public int PingDuration {get;set;} public int PingDuration {get;set;}
private static readonly Settings instance = new Settings(); private static readonly Settings instance = new ();
// Explicit static constructor to tell C# compiler // Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit // not to mark type as beforefieldinit

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ namespace Sledgemapper
{ {
public sealed class State public sealed class State
{ {
private static readonly State instance = new State(); private static readonly State instance = new ();
public Tile SelectedTile { get; set; } public Tile SelectedTile { get; set; }
public Tile HoveredTile { get; set; } public Tile HoveredTile { get; set; }

View File

@ -1,4 +1,3 @@
using Myra.Graphics2D.UI;
using Sentry; using Sentry;
using System; using System;
using TinyMessenger; using TinyMessenger;

View File

@ -5,7 +5,6 @@ using Myra.Graphics2D.UI;
using Myra.Graphics2D.UI.File; using Myra.Graphics2D.UI.File;
using Myra.Graphics2D.UI.Properties; using Myra.Graphics2D.UI.Properties;
using Newtonsoft.Json; using Newtonsoft.Json;
using Sentry;
using Sledgemapper.Messages; using Sledgemapper.Messages;
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
using System; using System;

View File

@ -2,7 +2,6 @@
using Myra.Graphics2D.Brushes; using Myra.Graphics2D.Brushes;
using Myra.Graphics2D.UI; using Myra.Graphics2D.UI;
using Sledgemapper.Messages; using Sledgemapper.Messages;
using Sledgemapper.Shared.Entities;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using TinyMessenger; using TinyMessenger;

View File

@ -1,7 +1,4 @@
/* Generated by MyraPad at 02/09/2021 16:26:04 */ /* Generated by MyraPad at 02/09/2021 16:26:04 */
using Myra.Graphics2D.UI;
using Sentry;
using System;
namespace Sledgemapper.UI namespace Sledgemapper.UI
{ {

View File

@ -1,7 +1,6 @@
/* Generated by MyraPad at 01/12/2020 11:46:54 */ /* Generated by MyraPad at 01/12/2020 11:46:54 */
using System.Linq; using System.Linq;
using Myra.Graphics2D.TextureAtlases; using Myra.Graphics2D.TextureAtlases;
using Myra.Graphics2D.UI;
using Sledgemapper.Messages; using Sledgemapper.Messages;
using Sledgemapper.Shared.Entities; using Sledgemapper.Shared.Entities;
using TinyMessenger; using TinyMessenger;
@ -22,7 +21,7 @@ namespace Sledgemapper.UI
{ {
var note = CommunicationManager.SessionData.Notes.Values.ElementAt(i); var note = CommunicationManager.SessionData.Notes.Values.ElementAt(i);
var item = new NoteListItem(); var item = new NoteListItem();
item.LblNoteText.Text = $"{note.ToString()} - {note.Text}"; item.LblNoteText.Text = $"{note} - {note.Text}";
item.BtnNoteCenter.Image = new TextureRegion(CachedContent.Instance.Location); item.BtnNoteCenter.Image = new TextureRegion(CachedContent.Instance.Location);
item.BtnNoteView.Image = new TextureRegion(CachedContent.Instance.Eye); item.BtnNoteView.Image = new TextureRegion(CachedContent.Instance.Eye);
item.BtnNoteCenter.Click += (s, e) => item.BtnNoteCenter.Click += (s, e) =>

View File

@ -1,5 +1,5 @@
/* Generated by MyraPad at 28/08/2021 19:49:08 */ /* Generated by MyraPad at 28/08/2021 19:49:08 */
using Myra.Graphics2D.UI;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Sledgemapper.UI namespace Sledgemapper.UI