Fix AutoDetect
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Text.Json.Serialization;
|
|||||||
using MareSynchronosAuthService.Services;
|
using MareSynchronosAuthService.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MareSynchronosAuthService.Controllers;
|
namespace MareSynchronosAuthService.Controllers;
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ public class DiscoveryController : Controller
|
|||||||
public sealed class RequestDto
|
public sealed class RequestDto
|
||||||
{
|
{
|
||||||
[JsonPropertyName("token")] public string Token { get; set; } = string.Empty;
|
[JsonPropertyName("token")] public string Token { get; set; } = string.Empty;
|
||||||
|
[JsonPropertyName("displayName")] public string? DisplayName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("request")]
|
[HttpPost("request")]
|
||||||
@@ -71,7 +73,9 @@ public class DiscoveryController : Controller
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var fromUid = User?.Claims?.FirstOrDefault(c => c.Type == MareSynchronosShared.Utils.MareClaimTypes.Uid)?.Value ?? string.Empty;
|
var fromUid = User?.Claims?.FirstOrDefault(c => c.Type == MareSynchronosShared.Utils.MareClaimTypes.Uid)?.Value ?? string.Empty;
|
||||||
var fromAlias = User?.Claims?.FirstOrDefault(c => c.Type == MareSynchronosShared.Utils.MareClaimTypes.Alias)?.Value ?? string.Empty;
|
var fromAlias = string.IsNullOrEmpty(req.DisplayName)
|
||||||
|
? (User?.Claims?.FirstOrDefault(c => c.Type == MareSynchronosShared.Utils.MareClaimTypes.Alias)?.Value ?? string.Empty)
|
||||||
|
: req.DisplayName;
|
||||||
|
|
||||||
using var http = new HttpClient();
|
using var http = new HttpClient();
|
||||||
// Use same host as public (goes through nginx)
|
// Use same host as public (goes through nginx)
|
||||||
@@ -83,7 +87,12 @@ public class DiscoveryController : Controller
|
|||||||
http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", serverToken);
|
http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", serverToken);
|
||||||
var payload = System.Text.Json.JsonSerializer.Serialize(new { targetUid, fromUid, fromAlias });
|
var payload = System.Text.Json.JsonSerializer.Serialize(new { targetUid, fromUid, fromAlias });
|
||||||
var resp = await http.PostAsync(url, new StringContent(payload, System.Text.Encoding.UTF8, "application/json"));
|
var resp = await http.PostAsync(url, new StringContent(payload, System.Text.Encoding.UTF8, "application/json"));
|
||||||
// ignore response content, just return Accepted to caller
|
if (!resp.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var txt = await resp.Content.ReadAsStringAsync();
|
||||||
|
HttpContext.RequestServices.GetRequiredService<ILogger<DiscoveryController>>()
|
||||||
|
.LogWarning("notifyRequest failed: {code} {reason} {body}", (int)resp.StatusCode, resp.ReasonPhrase, txt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="MaxMind.GeoIP2" Version="5.3.0" />
|
<PackageReference Include="MaxMind.GeoIP2" Version="5.3.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||||
|
<PackageReference Include="StackExchange.Redis" Version="2.9.11" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="10.2.0" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.Extensions.System.Text.Json" Version="10.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Services.Discovery;
|
||||||
|
|
||||||
|
public interface IDiscoveryPresenceStore : IDisposable
|
||||||
|
{
|
||||||
|
void Publish(string uid, IEnumerable<string> hashes, string? displayName = null);
|
||||||
|
(bool Found, string Token, string? DisplayName) TryMatchAndIssueToken(string requesterUid, string hash);
|
||||||
|
bool ValidateToken(string token, out string targetUid);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Services.Discovery;
|
||||||
|
|
||||||
|
public sealed class InMemoryPresenceStore : IDiscoveryPresenceStore
|
||||||
|
{
|
||||||
|
private readonly ConcurrentDictionary<string, (string Uid, DateTimeOffset ExpiresAt, string? DisplayName)> _presence = new(StringComparer.Ordinal);
|
||||||
|
private readonly ConcurrentDictionary<string, (string TargetUid, DateTimeOffset ExpiresAt)> _tokens = new(StringComparer.Ordinal);
|
||||||
|
private readonly TimeSpan _presenceTtl;
|
||||||
|
private readonly TimeSpan _tokenTtl;
|
||||||
|
private readonly Timer _cleanupTimer;
|
||||||
|
|
||||||
|
public InMemoryPresenceStore(TimeSpan presenceTtl, TimeSpan tokenTtl)
|
||||||
|
{
|
||||||
|
_presenceTtl = presenceTtl;
|
||||||
|
_tokenTtl = tokenTtl;
|
||||||
|
_cleanupTimer = new Timer(_ => Cleanup(), null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_cleanupTimer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cleanup()
|
||||||
|
{
|
||||||
|
var now = DateTimeOffset.UtcNow;
|
||||||
|
foreach (var kv in _presence.ToArray())
|
||||||
|
{
|
||||||
|
if (kv.Value.ExpiresAt <= now) _presence.TryRemove(kv.Key, out _);
|
||||||
|
}
|
||||||
|
foreach (var kv in _tokens.ToArray())
|
||||||
|
{
|
||||||
|
if (kv.Value.ExpiresAt <= now) _tokens.TryRemove(kv.Key, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Publish(string uid, IEnumerable<string> hashes, string? displayName = null)
|
||||||
|
{
|
||||||
|
var exp = DateTimeOffset.UtcNow.Add(_presenceTtl);
|
||||||
|
foreach (var h in hashes.Distinct(StringComparer.Ordinal))
|
||||||
|
{
|
||||||
|
_presence[h] = (uid, exp, displayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public (bool Found, string Token, string? DisplayName) TryMatchAndIssueToken(string requesterUid, string hash)
|
||||||
|
{
|
||||||
|
if (_presence.TryGetValue(hash, out var entry))
|
||||||
|
{
|
||||||
|
if (string.Equals(entry.Uid, requesterUid, StringComparison.Ordinal)) return (false, string.Empty, null);
|
||||||
|
var token = Guid.NewGuid().ToString("N");
|
||||||
|
_tokens[token] = (entry.Uid, DateTimeOffset.UtcNow.Add(_tokenTtl));
|
||||||
|
return (true, token, entry.DisplayName);
|
||||||
|
}
|
||||||
|
return (false, string.Empty, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidateToken(string token, out string targetUid)
|
||||||
|
{
|
||||||
|
targetUid = string.Empty;
|
||||||
|
if (_tokens.TryGetValue(token, out var info))
|
||||||
|
{
|
||||||
|
if (info.ExpiresAt > DateTimeOffset.UtcNow)
|
||||||
|
{
|
||||||
|
targetUid = info.TargetUid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_tokens.TryRemove(token, out _);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Services.Discovery;
|
||||||
|
|
||||||
|
public sealed class RedisPresenceStore : IDiscoveryPresenceStore
|
||||||
|
{
|
||||||
|
private readonly ILogger<RedisPresenceStore> _logger;
|
||||||
|
private readonly IDatabase _db;
|
||||||
|
private readonly TimeSpan _presenceTtl;
|
||||||
|
private readonly TimeSpan _tokenTtl;
|
||||||
|
private readonly JsonSerializerOptions _jsonOpts = new() { DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull };
|
||||||
|
|
||||||
|
public RedisPresenceStore(ILogger<RedisPresenceStore> logger, IConnectionMultiplexer mux, TimeSpan presenceTtl, TimeSpan tokenTtl)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_db = mux.GetDatabase();
|
||||||
|
_presenceTtl = presenceTtl;
|
||||||
|
_tokenTtl = tokenTtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
private static string KeyForHash(string hash) => $"nd:hash:{hash}";
|
||||||
|
private static string KeyForToken(string token) => $"nd:token:{token}";
|
||||||
|
|
||||||
|
public void Publish(string uid, IEnumerable<string> hashes, string? displayName = null)
|
||||||
|
{
|
||||||
|
var entries = hashes.Distinct(StringComparer.Ordinal).ToArray();
|
||||||
|
if (entries.Length == 0) return;
|
||||||
|
var batch = _db.CreateBatch();
|
||||||
|
foreach (var h in entries)
|
||||||
|
{
|
||||||
|
var key = KeyForHash(h);
|
||||||
|
var payload = JsonSerializer.Serialize(new Presence(uid, displayName), _jsonOpts);
|
||||||
|
batch.StringSetAsync(key, payload, _presenceTtl);
|
||||||
|
}
|
||||||
|
batch.Execute();
|
||||||
|
_logger.LogDebug("RedisPresenceStore: published {count} hashes", entries.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (bool Found, string Token, string? DisplayName) TryMatchAndIssueToken(string requesterUid, string hash)
|
||||||
|
{
|
||||||
|
var key = KeyForHash(hash);
|
||||||
|
var val = _db.StringGet(key);
|
||||||
|
if (!val.HasValue) return (false, string.Empty, null);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var p = JsonSerializer.Deserialize<Presence>(val!);
|
||||||
|
if (p == null || string.IsNullOrEmpty(p.Uid)) return (false, string.Empty, null);
|
||||||
|
if (string.Equals(p.Uid, requesterUid, StringComparison.Ordinal)) return (false, string.Empty, null);
|
||||||
|
var token = Guid.NewGuid().ToString("N");
|
||||||
|
_db.StringSet(KeyForToken(token), p.Uid, _tokenTtl);
|
||||||
|
return (true, token, p.DisplayName);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return (false, string.Empty, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidateToken(string token, out string targetUid)
|
||||||
|
{
|
||||||
|
targetUid = string.Empty;
|
||||||
|
var key = KeyForToken(token);
|
||||||
|
var val = _db.StringGet(key);
|
||||||
|
if (!val.HasValue) return false;
|
||||||
|
targetUid = val!;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record Presence(string Uid, string? DisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,88 +1,50 @@
|
|||||||
using System.Collections.Concurrent;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MareSynchronosAuthService.Services.Discovery;
|
||||||
|
|
||||||
namespace MareSynchronosAuthService.Services;
|
namespace MareSynchronosAuthService.Services;
|
||||||
|
|
||||||
public class DiscoveryPresenceService : IHostedService
|
public class DiscoveryPresenceService : IHostedService, IDisposable
|
||||||
{
|
{
|
||||||
private readonly ILogger<DiscoveryPresenceService> _logger;
|
private readonly ILogger<DiscoveryPresenceService> _logger;
|
||||||
|
private readonly IDiscoveryPresenceStore _store;
|
||||||
// hash -> (uid, expiresAt, displayName?)
|
|
||||||
private readonly ConcurrentDictionary<string, (string Uid, DateTimeOffset ExpiresAt, string? DisplayName)> _presence = new(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
// token -> (targetUid, expiresAt)
|
|
||||||
private readonly ConcurrentDictionary<string, (string TargetUid, DateTimeOffset ExpiresAt)> _tokens = new(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
private Timer? _cleanupTimer;
|
|
||||||
private readonly TimeSpan _presenceTtl = TimeSpan.FromMinutes(5);
|
private readonly TimeSpan _presenceTtl = TimeSpan.FromMinutes(5);
|
||||||
private readonly TimeSpan _tokenTtl = TimeSpan.FromMinutes(2);
|
private readonly TimeSpan _tokenTtl = TimeSpan.FromMinutes(2);
|
||||||
|
|
||||||
public DiscoveryPresenceService(ILogger<DiscoveryPresenceService> logger)
|
public DiscoveryPresenceService(ILogger<DiscoveryPresenceService> logger, IDiscoveryPresenceStore store)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_cleanupTimer = new Timer(_ => Cleanup(), null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_cleanupTimer?.Dispose();
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Cleanup()
|
|
||||||
{
|
|
||||||
var now = DateTimeOffset.UtcNow;
|
|
||||||
foreach (var kv in _presence.ToArray())
|
|
||||||
{
|
|
||||||
if (kv.Value.ExpiresAt <= now) _presence.TryRemove(kv.Key, out _);
|
|
||||||
}
|
|
||||||
foreach (var kv in _tokens.ToArray())
|
|
||||||
{
|
|
||||||
if (kv.Value.ExpiresAt <= now) _tokens.TryRemove(kv.Key, out _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Publish(string uid, IEnumerable<string> hashes, string? displayName = null)
|
public void Publish(string uid, IEnumerable<string> hashes, string? displayName = null)
|
||||||
{
|
{
|
||||||
var exp = DateTimeOffset.UtcNow.Add(_presenceTtl);
|
_store.Publish(uid, hashes, displayName);
|
||||||
foreach (var h in hashes.Distinct(StringComparer.Ordinal))
|
|
||||||
{
|
|
||||||
_presence[h] = (uid, exp, displayName);
|
|
||||||
}
|
|
||||||
_logger.LogDebug("Discovery presence published for {uid} with {n} hashes", uid, hashes.Count());
|
_logger.LogDebug("Discovery presence published for {uid} with {n} hashes", uid, hashes.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public (bool Found, string Token, string? DisplayName) TryMatchAndIssueToken(string requesterUid, string hash)
|
public (bool Found, string Token, string? DisplayName) TryMatchAndIssueToken(string requesterUid, string hash)
|
||||||
{
|
{
|
||||||
if (_presence.TryGetValue(hash, out var entry))
|
return _store.TryMatchAndIssueToken(requesterUid, hash);
|
||||||
{
|
|
||||||
if (string.Equals(entry.Uid, requesterUid, StringComparison.Ordinal)) return (false, string.Empty, null);
|
|
||||||
var token = Guid.NewGuid().ToString("N");
|
|
||||||
_tokens[token] = (entry.Uid, DateTimeOffset.UtcNow.Add(_tokenTtl));
|
|
||||||
return (true, token, entry.DisplayName);
|
|
||||||
}
|
|
||||||
return (false, string.Empty, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ValidateToken(string token, out string targetUid)
|
public bool ValidateToken(string token, out string targetUid)
|
||||||
{
|
{
|
||||||
targetUid = string.Empty;
|
return _store.ValidateToken(token, out targetUid);
|
||||||
if (_tokens.TryGetValue(token, out var info))
|
}
|
||||||
{
|
|
||||||
if (info.ExpiresAt > DateTimeOffset.UtcNow)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
targetUid = info.TargetUid;
|
(_store as IDisposable)?.Dispose();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
_tokens.TryRemove(token, out _);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,25 @@ public class Startup
|
|||||||
// Nearby discovery services (well-known + presence)
|
// Nearby discovery services (well-known + presence)
|
||||||
services.AddSingleton<DiscoveryWellKnownProvider>();
|
services.AddSingleton<DiscoveryWellKnownProvider>();
|
||||||
services.AddHostedService(p => p.GetRequiredService<DiscoveryWellKnownProvider>());
|
services.AddHostedService(p => p.GetRequiredService<DiscoveryWellKnownProvider>());
|
||||||
|
|
||||||
|
// Presence store selection
|
||||||
|
var discoveryStore = _configuration.GetValue<string>("NearbyDiscovery:Store") ?? "memory";
|
||||||
|
TimeSpan presenceTtl = TimeSpan.FromMinutes(_configuration.GetValue<int>("NearbyDiscovery:PresenceTtlMinutes", 5));
|
||||||
|
TimeSpan tokenTtl = TimeSpan.FromSeconds(_configuration.GetValue<int>("NearbyDiscovery:TokenTtlSeconds", 120));
|
||||||
|
if (string.Equals(discoveryStore, "redis", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
services.AddSingleton<MareSynchronosAuthService.Services.Discovery.IDiscoveryPresenceStore>(sp =>
|
||||||
|
{
|
||||||
|
var logger = sp.GetRequiredService<ILogger<MareSynchronosAuthService.Services.Discovery.RedisPresenceStore>>();
|
||||||
|
var mux = sp.GetRequiredService<IConnectionMultiplexer>();
|
||||||
|
return new MareSynchronosAuthService.Services.Discovery.RedisPresenceStore(logger, mux, presenceTtl, tokenTtl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddSingleton<MareSynchronosAuthService.Services.Discovery.IDiscoveryPresenceStore>(sp => new MareSynchronosAuthService.Services.Discovery.InMemoryPresenceStore(presenceTtl, tokenTtl));
|
||||||
|
}
|
||||||
|
|
||||||
services.AddSingleton<DiscoveryPresenceService>();
|
services.AddSingleton<DiscoveryPresenceService>();
|
||||||
services.AddHostedService(p => p.GetRequiredService<DiscoveryPresenceService>());
|
services.AddHostedService(p => p.GetRequiredService<DiscoveryPresenceService>());
|
||||||
|
|
||||||
@@ -210,6 +229,8 @@ public class Startup
|
|||||||
};
|
};
|
||||||
|
|
||||||
services.AddStackExchangeRedisExtensions<SystemTextJsonSerializer>(redisConfiguration);
|
services.AddStackExchangeRedisExtensions<SystemTextJsonSerializer>(redisConfiguration);
|
||||||
|
// Also expose raw multiplexer for custom Redis usage (discovery presence)
|
||||||
|
services.AddSingleton<IConnectionMultiplexer>(_ => ConnectionMultiplexer.Connect(options));
|
||||||
}
|
}
|
||||||
private void ConfigureConfigServices(IServiceCollection services)
|
private void ConfigureConfigServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=umbra_dev"
|
||||||
|
},
|
||||||
|
"MareSynchronos": {
|
||||||
|
"Jwt": "dev-secret-umbra-abcdefghijklmnopqrstuvwxyz123456",
|
||||||
|
"RedisConnectionString": "localhost:6379,connectTimeout=5000,syncTimeout=5000",
|
||||||
|
"MetricsPort": 4985
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ public class DiscoveryNotifyController : Controller
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(dto.TargetUid)) return BadRequest();
|
if (string.IsNullOrEmpty(dto.TargetUid)) return BadRequest();
|
||||||
var name = string.IsNullOrEmpty(dto.FromAlias) ? dto.FromUid : dto.FromAlias;
|
var name = string.IsNullOrEmpty(dto.FromAlias) ? dto.FromUid : dto.FromAlias;
|
||||||
var msg = $"{name} wants to pair with you (Nearby)";
|
var msg = $"Nearby Request: {name} [{dto.FromUid}]";
|
||||||
_logger.LogInformation("Discovery notify request to {target} from {from}", dto.TargetUid, name);
|
_logger.LogInformation("Discovery notify request to {target} from {from}", dto.TargetUid, name);
|
||||||
await _hub.Clients.User(dto.TargetUid).Client_ReceiveServerMessage(MareSynchronos.API.Data.Enum.MessageSeverity.Information, msg);
|
await _hub.Clients.User(dto.TargetUid).Client_ReceiveServerMessage(MareSynchronos.API.Data.Enum.MessageSeverity.Information, msg);
|
||||||
return Accepted();
|
return Accepted();
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class Startup
|
|||||||
a.FeatureProviders.Remove(a.FeatureProviders.OfType<ControllerFeatureProvider>().First());
|
a.FeatureProviders.Remove(a.FeatureProviders.OfType<ControllerFeatureProvider>().First());
|
||||||
if (mareConfig.GetValue<Uri>(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null)
|
if (mareConfig.GetValue<Uri>(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null)
|
||||||
{
|
{
|
||||||
a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(MareServerConfigurationController), typeof(MareBaseConfigurationController), typeof(ClientMessageController), typeof(MainController)));
|
a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(MareServerConfigurationController), typeof(MareBaseConfigurationController), typeof(ClientMessageController), typeof(MainController), typeof(DiscoveryNotifyController)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user