I don't know what I'm doing anymore

This commit is contained in:
Michele 2020-11-16 00:03:42 +00:00
parent ea9cc32534
commit 8fdee0cb67
17 changed files with 342 additions and 116 deletions

View file

@ -0,0 +1,19 @@
using MediatR;
using System;
namespace Sledgemapper.Api.Commands
{
public abstract class BaseCommand<T> : IRequest<T>
{
public double Timestamp { get; private set; }
public string SessionName { get; private set; }
public int UserId { get; set; }
public BaseCommand(string sessionName, int userId)
{
Timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
SessionName = sessionName;
UserId=userId;
}
}
}

View file

@ -2,14 +2,10 @@ using MediatR;
namespace Sledgemapper.Api.Commands
{
public class NewSessionCommand : IRequest<bool>
public class NewSessionCommand : BaseCommand<bool>
{
public string SessionName { get; set; }
public int UserId { get; }
public NewSessionCommand(string sessionName, int userId)
public NewSessionCommand(string sessionName, int userId):base(sessionName, userId)
{
SessionName = sessionName;
UserId = userId;
}
}
}

View file

@ -0,0 +1,47 @@
using System.Transactions;
using System.Net.Mail;
using MediatR;
using Sledgemapper.Api.Data;
using Sledgemapper.Shared.Entities;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Sledgemapper.Api.Handlers;
namespace Sledgemapper.Api.Commands
{
public class SaveNewTileCommand:BaseCommand<bool>
{
public Tile Tile {get;set;}
public SaveNewTileCommand(string sessionName, Tile tile, int userId):base(sessionName, userId){
Tile=tile;
}
}
public class SaveNewTileCommandHandler : IRequestHandler<SaveNewTileCommand, bool>
{
private readonly MyDbContext _dbcontext;
private readonly IMediator _mediator;
public SaveNewTileCommandHandler(IMediator mediator, MyDbContext dbcontext){ _dbcontext = dbcontext; _mediator= mediator;}
public async Task<bool> Handle(SaveNewTileCommand notification, CancellationToken cancellationToken)
{
var jsonString = JsonSerializer.Serialize<Tile>(notification.Tile);
_dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog
{
Operation = "N",
SessionName = notification.SessionName,
Type = "T",
Timestamp = notification.Timestamp,
Object = jsonString
});
await _dbcontext.SaveChangesAsync();
await _mediator.Publish(new NewTileNotification(notification.SessionName, notification.Tile));
return true;
}
}
}

View file

@ -1,3 +1,4 @@
using System.Net;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -17,48 +18,50 @@ namespace Sledgemapper.Api.Controllers
public SessionController(IMediator mediator) { _mediator = mediator; }
[HttpPost]
public async Task Post(string sessionName)
public async Task<bool> Post(string sessionName)
{
var userId = int.Parse(HttpContext.User.Identity.Name);
var result = await _mediator.Send(new NewSessionCommand(sessionName, userId));
}
return result;
}
[HttpPost("tile")]
public async Task Post(string sessionName, [FromBody]Tile tile)
public async Task Post(string sessionName, [FromBody] Tile tile)
{
await _mediator.Publish(new NewTileNotification(sessionName, tile));
var userId = int.Parse(HttpContext.User.Identity.Name);
await _mediator.Send(new SaveNewTileCommand(sessionName, tile, userId));
}
[HttpPost("overlay")]
public async Task Post(string sessionName, [FromBody]Overlay overlay)
public async Task Post(string sessionName, [FromBody] Overlay overlay)
{
await _mediator.Publish(new NewOverlayNotification(sessionName, overlay));
}
[HttpPost("wall")]
public async Task Post(string sessionName, [FromBody]Wall wall)
[HttpPost("wall")]
public async Task Post(string sessionName, [FromBody] Wall wall)
{
await _mediator.Publish(new NewWallNotification(sessionName, wall));
}
[HttpDelete("tile")]
public async Task Delete(string sessionName, [FromBody]Tile tile)
[HttpDelete("tile")]
public async Task Delete(string sessionName, [FromBody] Tile tile)
{
await _mediator.Publish(new DeleteTileNotification(sessionName, tile));
}
[HttpDelete("overlay")]
public async Task Delete(string sessionName, [FromBody]Overlay overlay)
public async Task Delete(string sessionName, [FromBody] Overlay overlay)
{
await _mediator.Publish(new DeleteOverlayNotification(sessionName, overlay));
}
[HttpDelete("wall")]
public async Task Delete(string sessionName, [FromBody]Wall wall)
[HttpDelete("wall")]
public async Task Delete(string sessionName, [FromBody] Wall wall)
{
await _mediator.Publish(new DeleteWallNotification(sessionName, wall));
}
}
}

View file

@ -13,30 +13,30 @@ namespace Sledgemapper.Api.Data
}
}
public class MyDbContext : DbContext
{
public DbSet<MapLog> MapLogs { get; set; }
public DbSet<Session> Sessions { get; set; }
public DbSet<UserConnection> UserConnections { get; set; }
public DbSet<SessionUser> SessionUsers { get; set; }
public MyDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// optionsBuilder.
// options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
// optionsBuilder.UseSqlite("Filename=SledgemapperDatabase.db", options =>
// {
// options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
// });
optionsBuilder.UseSqlite("Filename=MyDatabase.db").UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
// protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
// {
// // optionsBuilder.
// // options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
// // optionsBuilder.UseSqlite("Filename=SledgemapperDatabase.db", options =>
// // {
// // options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
// // });
// optionsBuilder.UseSqlite("Filename=MyDatabase.db").UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
base.OnConfiguring(optionsBuilder);
}
// base.OnConfiguring(optionsBuilder);
// }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@ -45,8 +45,28 @@ namespace Sledgemapper.Api.Data
modelBuilder.Entity<MapLog>(entity =>
{
entity.HasKey(e => e.MapLogId);
//entity.HasIndex(e => {e.SessionName, e.Timestamp});
});
});
modelBuilder.Entity<Session>().ToTable("Session", "dbo");
modelBuilder.Entity<Session>(entity =>
{
entity.HasKey(e => e.SessionId);
entity.HasIndex(e => e.SessionName).IsUnique();
});
modelBuilder.Entity<UserConnection>().ToTable("UserConnection", "dbo");
modelBuilder.Entity<UserConnection>(entity =>
{
entity.HasKey(e => e.UserConnectionId);
});
modelBuilder.Entity<SessionUser>().ToTable("SessionUser", "dbo");
modelBuilder.Entity<SessionUser>(entity =>
{
entity.HasKey(e => e.SessionUserId);
});
base.OnModelCreating(modelBuilder);
}
}

View file

@ -20,11 +20,11 @@ namespace Sledgemapper.Api.Handlers
public async Task<bool> Handle(NewSessionCommand notification, CancellationToken cancellationToken)
{
// _dbcontext.MapLogs.Add(new Session
// {
// SessionName = notification.SessionName,
// OwnerUserId = notification.UserId
// });
_dbcontext.Sessions.Add(new Session
{
SessionName = notification.SessionName,
OwnerUserId = notification.UserId
});
await _dbcontext.SaveChangesAsync();
return true;
}

View file

@ -12,6 +12,8 @@ using Sledgemapper.Api.Data;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Authorization;
using Sledgemapper.Api.Models;
using Sledgemapper.Helpers;
namespace SignalRChat.Hubs
{
@ -20,11 +22,15 @@ namespace SignalRChat.Hubs
[Authorize]
public class SledgemapperHub : Hub<ISledgemapperClient>
{
public SledgemapperHub()
{
private readonly MyDbContext _dbContext;
private readonly DataContext _datacontext;
public SledgemapperHub(MyDbContext dbContext, DataContext datacontext)
{
_dbContext = dbContext;
_datacontext = datacontext;
}
private static Dictionary<string, Session> _sessions = new Dictionary<string, Session>();
// private static Dictionary<string, Session> _sessions = new Dictionary<string, Session>();
public List<string> Colors = new List<string>{"CC0000",
"CC3300",
"FFCC00",
@ -114,60 +120,116 @@ namespace SignalRChat.Hubs
await Clients.Group(sessionName).DeleteOverlay(tile);
}
public async Task<Session> NewSession(string sessionName, string initials)
// public async Task<Session> NewSession(string sessionName, string initials)
// {
// var userId = int.Parse(Context.User.Identity.Name);
// // var user = this.Context.GetHttpContext().;
// var session = new Session();
// session.Colors = new List<string>(Colors);
// session.Colors.Shuffle();
// var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[0], Initials = initials };
// session.Players.Add(player);
// _sessions.Add(sessionName, session);
// await Groups.AddToGroupAsync(Context.ConnectionId, sessionName);
// return session;
// }
public async Task<Sledgemapper.Shared.Entities.Session> JoinSession(string sessionName, string initials)
{
var session = _dbContext.Sessions.FirstOrDefault(s => s.SessionName == sessionName);
var userId = int.Parse(Context.User.Identity.Name);
// var user = this.Context.GetHttpContext().;
var session = new Session();
session.Colors = new List<string>(Colors);
session.Colors.Shuffle();
var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[0], Initials = initials };
session.Players.Add(player);
_sessions.Add(sessionName, session);
await Groups.AddToGroupAsync(Context.ConnectionId, sessionName);
return session;
}
public async Task<Session> JoinSession(string sessionName, string initials)
{
if (_sessions.ContainsKey(sessionName))
if (session != null)
{
var session = _sessions[sessionName];
var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[session.Players.Count], Initials = initials };
session.Players.Add(player);
await Clients.Group(sessionName).NewPlayer(player);
// var newSession = new Session();
var userSession = new SessionUser { SessionId = session.SessionId, UserId = userId };
_dbContext.SessionUsers.Add(userSession);
await _dbContext.SaveChangesAsync();
var usersSession = _dbContext.SessionUsers.Where(m => m.SessionId == session.SessionId).Select(m => m.UserId).ToList();
var players = _datacontext.
Users.
Where(m => usersSession.Contains(m.Id)).
Select(p => new Player
{
Initials = p.Initials,
UserId = userId,
Position = new Tile { X = 0, Y = 0 }
}).ToList();
await _dbContext.SaveChangesAsync();
await Groups.AddToGroupAsync(Context.ConnectionId, sessionName);
return session;
var newSession = new Sledgemapper.Shared.Entities.Session
{
Players = players,
SessionName = sessionName
};
return newSession;
}
else
{
return null;
}
// if (_sessions.ContainsKey(sessionName))
// {
// var session = _sessions[sessionName];
// var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[session.Players.Count], Initials = initials };
// session.Players.Add(player);
// await Clients.Group(sessionName).NewPlayer(player);
// return session;
// }
// else
// {
// return null;
// }
}
public async Task UpdatePosition(string sessionName, Tile tile)
{
var player = _sessions[sessionName].Players.First(m => m.ConnectionId == Context.ConnectionId);
player.Position = tile;
await Clients.Group(sessionName).PlayerUpdate(player);
// var userId = int.Parse(Context.User.Identity.Name);
// var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionName == sessionName);
// var player = _sessions[sessionName].Players.First(m => m.ConnectionId == Context.ConnectionId);
// player.Position = tile;
// await Clients.Group(sessionName).PlayerUpdate(player);
}
public async Task<Session> Refresh(string sessionName)
// public async Task<Session> Refresh(string sessionName)
// {
// return _sessions[sessionName];
// }
// public async Task Sync(string sessionName, Session map)
// {
// _sessions[sessionName].Map = map.Map;
// _sessions[sessionName].Overlays = map.Overlays;
// _sessions[sessionName].Walls = map.Walls;
// await Clients.Group(sessionName).UpdateMap(_sessions[sessionName]);
// }
public override async Task OnConnectedAsync()
{
return _sessions[sessionName];
var userId = int.Parse(Context.User.Identity.Name);
//var result = _connectedPlayers.AddOrUpdate(Context.ConnectionId, userId,(key, oldValue) => userId);
var userConnection = new UserConnection { ConnectionId = Context.ConnectionId, UserId = userId };
_dbContext.UserConnections.Add(userConnection);
await _dbContext.SaveChangesAsync();
await base.OnConnectedAsync();
}
public async Task Sync(string sessionName, Session map)
public override Task OnDisconnectedAsync(Exception exception)
{
_sessions[sessionName].Map = map.Map;
_sessions[sessionName].Overlays = map.Overlays;
_sessions[sessionName].Walls = map.Walls;
await Clients.Group(sessionName).UpdateMap(_sessions[sessionName]);
_connectedPlayers.TryRemove(Context.ConnectionId, out var userId);
return base.OnDisconnectedAsync(exception);
}
ConcurrentDictionary<string, int> _connectedPlayers = new ConcurrentDictionary<string, int>();
}
}

Binary file not shown.

View file

@ -1,3 +1,4 @@
using System.Data;
using System;
using System.ComponentModel.DataAnnotations;

View file

@ -0,0 +1,18 @@
using System.Data;
using System;
using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models
{
public class SessionUser
{
[Key]
public int SessionUserId { get; set; }
[Required]
public int SessionId { get; set; }
[Required]
public int UserId { get; set; }
}
}

View file

@ -0,0 +1,17 @@
using System.Data;
using System;
using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models
{
public class UserConnection
{
[Key]
public int UserConnectionId { get; set; }
[Required]
public int UserId { get; set; }
[Required]
public string ConnectionId{get;set;}
}
}

View file

@ -15,7 +15,9 @@ namespace SignalRChat
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
var host= CreateHostBuilder(args).Build();
CreateDbIfNotExists(host);
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
@ -32,22 +34,22 @@ namespace SignalRChat
// webBuilder.UseStartup<Startup>();
// });
// private static void CreateDbIfNotExists(IHost host)
// {
// using (var scope = host.Services.CreateScope())
// {
// var services = scope.ServiceProvider;
// try
// {
// var context = services.GetRequiredService<MyDbContext>();
// DbInitializer.Initialize(context);
// }
// catch (Exception ex)
// {
// var logger = services.GetRequiredService<ILogger<Program>>();
// logger.LogError(ex, "An error occurred creating the DB.");
// }
// }
// }
private static void CreateDbIfNotExists(IHost host)
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<MyDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}
}
}
}

Binary file not shown.

View file

@ -2,7 +2,7 @@ namespace Sledgemapper.Shared.Entities
{
public class Player
{
public string ConnectionId { get; set; }
public int UserId { get; set; }
public string Color { get; set; }
public string Initials { get; set; }

View file

@ -7,6 +7,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
namespace Sledgemapper
@ -26,7 +28,7 @@ namespace Sledgemapper
.WithAutomaticReconnect()
.WithUrl("http://localhost:5000/SledgemapperHub", options =>
{
{
options.AccessTokenProvider = () => Task.FromResult(_authenticateResponse.Token);
})
@ -35,16 +37,8 @@ namespace Sledgemapper
var httpClientHandler = new HttpClientHandler();
//if (myConfigurationService.VerifySslCertificate == false)
//{
httpClientHandler.ServerCertificateCustomValidationCallback =
(message, certificate, chain, sslPolicyErrors) => true;
//}
Api = RestService.For<IMapApi>(
new HttpClient(httpClientHandler)
new HttpClient(new AuthenticatedHttpClientHandler(GetToken))
{
BaseAddress = new Uri("http://localhost:5000")
}
@ -59,7 +53,7 @@ namespace Sledgemapper
Connection.On<Player>("PlayerUpdate", (player) =>
{
var p = SessionData.Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId);
var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId);
if (p != null)
{
p.Position = player.Position;
@ -101,7 +95,7 @@ namespace Sledgemapper
Connection.On<Player>("NewPlayer", (player) =>
{
var p = SessionData.Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId);
var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId);
if (p is null)
{
SessionData.Players.Add(player);
@ -114,6 +108,11 @@ namespace Sledgemapper
});
}
private Task<string> GetToken()
{
return Task.FromResult(_authenticateResponse.Token);
}
public async Task<bool> Register(RegisterModel registerModel)
{
var result = await Api.Register(registerModel);
@ -173,4 +172,34 @@ namespace Sledgemapper
}
}
class AuthenticatedHttpClientHandler : HttpClientHandler
{
private readonly Func<Task<string>> getToken;
public AuthenticatedHttpClientHandler(Func<Task<string>> getToken)
{
if (getToken == null) throw new ArgumentNullException(nameof(getToken));
this.getToken = getToken;
//if (myConfigurationService.VerifySslCertificate == false)
//{
ServerCertificateCustomValidationCallback =
(message, certificate, chain, sslPolicyErrors) => true;
//}
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// See if the request has an authorize header
var auth = request.Headers.Authorization;
if (auth != null)
{
var token = await getToken().ConfigureAwait(false);
request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token);
}
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
}

View file

@ -9,8 +9,12 @@ using System.Threading.Tasks;
namespace Sledgemapper
{
[Headers("Authorization: Bearer")]
public interface IMapApi
{
[Post("/session/{sessionName}")]
Task<bool> NewSession(string sessionName);
[Post("/session/{sessionName}/tile")]
Task NewTile([Body] Tile tile, string sessionName);
@ -28,10 +32,13 @@ namespace Sledgemapper
[Delete("/session/{sessionName}/overlay")]
Task DeleteOverlay([Body] Overlay overlay, string sessionName);
[Headers("Authorization")]
[Post("/users/register")]
Task<HttpResponseMessage> Register([Body] RegisterModel registerModel);
[Headers("Authorization")]
[Post("/users/authenticate")]
Task<AuthenticateResponse> Authenticate([Body] AuthenticateModel registerModel);
}

View file

@ -473,16 +473,21 @@ namespace Sledgemapper
var successful = false;
try
{
var session = await _communicationManager.Connection?.InvokeAsync<Session>("NewSession", localContent.TxtSession.Text, _authResponse.Initials);
if (session != null)
var result = await _communicationManager.Api.NewSession(localContent.TxtSession.Text);
// var session = await _communicationManager.Connection?.InvokeAsync<Session>("NewSession", localContent.TxtSession.Text, _authResponse.Initials);
if (result)
{
_sessionData = session;
//_sessionData;
_sessionData.SessionName = localContent.TxtSession.Text;
_sessionData.MapEntityAdded -= OnMapEntityAdded;
_sessionData.MapEntityAdded += OnMapEntityAdded;
_sessionData.Players = session.Players;
// _sessionData.Players = session.Players;
}
successful = session != null;
successful = result;
var result2 = await _communicationManager.Connection?.InvokeAsync<Session>("JoinSession", localContent.TxtSession.Text, _authResponse.Initials);
}
catch (Exception ex)
{