Merge net10-port: .NET 10 port

This commit is contained in:
2026-10-09 12:47:35 -07:00
71 changed files with 444 additions and 235 deletions

2
.vscode/launch.json vendored
View File

@@ -11,7 +11,7 @@
"preLaunchTask": "build debug", "preLaunchTask": "build debug",
// If you have changed target frameworks, make sure to update the program path. // If you have changed target frameworks, make sure to update the program path.
//#### THIS MEANS YOU JOHNNY! If the debugger fails this is the issue //#### THIS MEANS YOU JOHNNY! If the debugger fails this is the issue
"program": "${workspaceFolder}/server/bin/Debug/net6.0/sockeye.dll", "program": "${workspaceFolder}/server/bin/Debug/net10.0/sockeye.dll",
"args": [], "args": [],
"cwd": "${workspaceFolder}/server", "cwd": "${workspaceFolder}/server",
"stopAtEntry": false, "stopAtEntry": false,

View File

@@ -1,9 +1,10 @@
namespace Sockeye namespace Sockeye
{ {
using Asp.Versioning.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using System; using System;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using Sockeye.Util; using Sockeye.Util;

View File

@@ -2,6 +2,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using TwoFactorAuthNet; using TwoFactorAuthNet;
using QRCoder; using QRCoder;

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -2,6 +2,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -2,6 +2,7 @@ using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -2,6 +2,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -12,7 +12,9 @@ namespace Sockeye.Api.Controllers
[Route("fetch")]//Legacy v7 license fetch route [Route("fetch")]//Legacy v7 license fetch route
[Produces("text/plain")] [Produces("text/plain")]
#pragma warning disable AV0014 // Missing API behavior
public class FetchController : ControllerBase public class FetchController : ControllerBase
#pragma warning restore AV0014 // Missing API behavior
{ {
private readonly AyContext ct; private readonly AyContext ct;

View File

@@ -2,6 +2,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks;
@@ -36,7 +37,8 @@ namespace Sockeye.Api.Controllers
public async Task<IActionResult> Get() public async Task<IActionResult> Get()
{ {
var report = await _healthCheckService.CheckHealthAsync(); var report = await _healthCheckService.CheckHealthAsync();
Response.Headers.Add("Cache-Control", "no-store, no-cache"); //Response.Headers.Append("Cache-Control", "no-store, no-cache");
Response.Headers["Cache-Control"] = "no-store, no-cache";
return report.Status == HealthStatus.Healthy ? Ok(report.Status.ToString()) : StatusCode(503, report.Status.ToString()); return report.Status == HealthStatus.Healthy ? Ok(report.Status.ToString()) : StatusCode(503, report.Status.ToString());
} }
}//eoc }//eoc

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,78 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Sockeye.Models;
using Sockeye.Api.ControllerHelpers;
using Newtonsoft.Json.Linq;
using System;
using Sockeye.Biz;
namespace Sockeye.Api.Controllers
{
[Produces("application/json")]
[Route("api/order")]
public class OrderController : ControllerBase //RECEIVE ORDERS FROM VENDOR (MyCommerce)
{
private readonly AyContext ct;
private readonly ILogger<OrderController> log;
private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public OrderController(AyContext dbcontext, ILogger<OrderController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
//Receive an order notification from ShareIt
//https://account.mycommerce.com/home/wiki/7479805
[HttpPost("shareit")]
public async Task<IActionResult> Post([FromHeader] string Authorization, [FromBody] JObject j)
{
if (!serverState.IsOpen)
{
var msg = ("Server state was not open when Vendor Order notification received; returning 503 (temp. unavailable) to them, they should retry when server open again.");
log.LogError(msg);
await NotifyEventHelper.AddOpsProblemEvent(msg);
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
(string username, string password) = Sockeye.Util.AutoOrderProcessingUtil.GetUsernameAndPasswordFromAuthorizeHeader(Authorization);
if (username == "Y24PYYDQSA1L12905N5MKU" && password == "MA8GMQK2PC3FDNT1RTR68R")
{
//save it to the database
var vn = new VendorNotification();
vn.Created = DateTime.UtcNow;
vn.VendorId = 1;//MyCommerce/shareit is vendor 1, for now that's all that's needed
vn.VendorData = j.ToString();
await ct.VendorNotification.AddAsync(vn);
await ct.SaveChangesAsync();
}
}
catch (Exception ex)
{
log.LogError(ex, "OrderController/shareit - Exception processing vendor notification, returned 503 to vendor");
await NotifyEventHelper.AddOpsProblemEvent("OrderController/shareit - Exception processing vendor notification, see log");
return StatusCode(503);//ask it to retry again later
}
return Ok("ok");//shareit notifier looks for an OK response to know if it should resend or not https://account.mycommerce.com/home/wiki/7479805
}
//------------
}//eoc
}//eons

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -3,6 +3,7 @@ using System.Threading.Tasks;
using System; using System;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -14,7 +14,9 @@ namespace Sockeye.Api.Controllers
// [AllowAnonymous] // [AllowAnonymous]
[Route("rvf")]//v8 fetch license route [Route("rvf")]//v8 fetch license route
[Produces("application/json")] [Produces("application/json")]
#pragma warning disable AV0014 // Missing API behavior
public class RvfController : ControllerBase public class RvfController : ControllerBase
#pragma warning restore AV0014 // Missing API behavior
{ {
private readonly AyContext ct; private readonly AyContext ct;

View File

@@ -13,7 +13,9 @@ namespace Sockeye.Api.Controllers
{ {
[Route("rvr")]//v8 TRIAL REQUEST HANDLER ROUTE [Route("rvr")]//v8 TRIAL REQUEST HANDLER ROUTE
[Produces("application/json")] [Produces("application/json")]
#pragma warning disable AV0014 // Missing API behavior
public class RvrController : ControllerBase public class RvrController : ControllerBase
#pragma warning restore AV0014 // Missing API behavior
{ {
private readonly AyContext ct; private readonly AyContext ct;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System; using System;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -2,6 +2,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@@ -14,7 +15,7 @@ using Newtonsoft.Json.Linq;
using Sockeye.Models; using Sockeye.Models;
using Sockeye.Api.ControllerHelpers; using Sockeye.Api.ControllerHelpers;
using Sockeye.Biz; using Sockeye.Biz;
//using StackExchange.Profiling;
namespace Sockeye.Api.Controllers namespace Sockeye.Api.Controllers
{ {

View File

@@ -2,6 +2,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Sockeye.Api.ControllerHelpers; using Sockeye.Api.ControllerHelpers;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -2,6 +2,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -2,6 +2,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Asp.Versioning;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -843,6 +843,11 @@ namespace Sockeye.DataList
sValue = sValue.Replace(nfi.CurrencyGroupSeparator, ""); sValue = sValue.Replace(nfi.CurrencyGroupSeparator, "");
sValue = sValue.Replace(nfi.CurrencyDecimalSeparator, "."); sValue = sValue.Replace(nfi.CurrencyDecimalSeparator, ".");
} }
//case 4676
// Decimal, Currency (after the existing separator normalisation)
if (!decimal.TryParse(sValue, NumberStyles.Number, CultureInfo.InvariantCulture, out var d))
throw new ArgumentException($"Invalid numeric filter value [{sValue}]");
sValue = d.ToString(CultureInfo.InvariantCulture);
} }
break; break;
case UiFieldDataType.Integer: case UiFieldDataType.Integer:
@@ -852,6 +857,12 @@ namespace Sockeye.DataList
sValue = sValue.Replace(nfi.NumberGroupSeparator, ""); sValue = sValue.Replace(nfi.NumberGroupSeparator, "");
sValue = sValue.Replace(nfi.NumberDecimalSeparator, "."); sValue = sValue.Replace(nfi.NumberDecimalSeparator, ".");
} }
//case 4676
// Integer, InternalId, Enum, MemorySize, Roles
if (!long.TryParse(sValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out var l))
throw new ArgumentException($"Invalid numeric filter value [{sValue}]");
sValue = l.ToString(CultureInfo.InvariantCulture);
} }
break; break;
case UiFieldDataType.InternalId: case UiFieldDataType.InternalId:
@@ -1152,7 +1163,7 @@ namespace Sockeye.DataList
/// ///
public static string TagFilterToSqlCriteriaHelper(string SqlColumnNameToFilter, List<string> sValue, bool bAny) public static string TagFilterToSqlCriteriaHelper(string SqlColumnNameToFilter, List<string> sValue, bool bAny)
{ {
if(sValue.Count==0) return string.Empty; if (sValue.Count == 0) return string.Empty;
//if it's an OR (any) query then need to build individual terms, if it's not then it's just an all or AND query and can pass through as is //if it's an OR (any) query then need to build individual terms, if it's not then it's just an all or AND query and can pass through as is
if (sValue.Count > 0 && bAny == true) if (sValue.Count > 0 && bAny == true)
{ {

View File

@@ -124,11 +124,9 @@ namespace Sockeye
logConfig.AddTarget("blackhole", nullTarget); logConfig.AddTarget("blackhole", nullTarget);
// Step 3. Set target properties // Step 3. Set target properties
fileTarget.FileName = Path.Combine(ServerBootConfig.SOCKEYE_LOG_PATH, "log-sockeye.txt"); fileTarget.FileName = Path.Combine(ServerBootConfig.SOCKEYE_LOG_PATH, "log-sockeye.txt");
fileTarget.Layout = "${longdate}|${uppercase:${level}}|${logger}|${message:exceptionSeparator==>:withException=true}"; fileTarget.Layout = "${longdate}|${uppercase:${level}}|${logger}|${message:exceptionSeparator==>:withException=true}";
fileTarget.ArchiveFileName = Path.Combine(ServerBootConfig.SOCKEYE_LOG_PATH, "log-sockeye-{#}.txt"); fileTarget.ArchiveFileName = Path.Combine(ServerBootConfig.SOCKEYE_LOG_PATH, "log-sockeye-{#}.txt");
fileTarget.ArchiveNumbering = ArchiveNumberingMode.Rolling;//so expect to see 1 to 10 or 0 to ten as may be
fileTarget.ArchiveAboveSize = 1000000;//1mb maximum file size fileTarget.ArchiveAboveSize = 1000000;//1mb maximum file size
fileTarget.MaxArchiveFiles = 9;//max 10 files totalling 10mb, the current log-sockeye.txt and log-sockeye-[0-9].txt fileTarget.MaxArchiveFiles = 9;//max 10 files totalling 10mb, the current log-sockeye.txt and log-sockeye-[0-9].txt
@@ -197,7 +195,9 @@ namespace Sockeye
} }
// NLog: setup the logger first to catch all errors // NLog: setup the logger first to catch all errors
var logger = NLogBuilder.ConfigureNLog(logConfig).GetLogger("BOOT"); // var logger = NLogBuilder.ConfigureNLog(logConfig).GetLogger("BOOT");
NLog.LogManager.Configuration = logConfig;
var logger = NLog.LogManager.GetLogger("BOOT");
#endregion #endregion

View File

@@ -4,7 +4,6 @@ using System.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@@ -12,7 +11,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
@@ -21,7 +20,8 @@ using Sockeye.Util;
using Sockeye.Generator; using Sockeye.Generator;
using Sockeye.Biz; using Sockeye.Biz;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
using StackExchange.Profiling; using Asp.Versioning.ApiExplorer;
using Asp.Versioning;
namespace Sockeye namespace Sockeye
@@ -56,24 +56,6 @@ namespace Sockeye
_newLog.LogDebug("Health"); _newLog.LogDebug("Health");
services.AddHealthChecks().AddDbContextCheck<AyContext>(); ; services.AddHealthChecks().AddDbContextCheck<AyContext>(); ;
_newLog.LogDebug("Profiler");
//https://dotnetthoughts.net/using-miniprofiler-in-aspnetcore-webapi/
services.AddMemoryCache();
services.AddMiniProfiler(options =>
{
options.RouteBasePath = "/profiler";
//in testing only ignorepaths was reliable and worked and docs say it prevents any profiling at all
options.IgnorePath("/auth").IgnorePath("/user").IgnorePath("/docs").IgnorePath("/cust").IgnorePath("/notify/hello").IgnorePath("/notify/new-count");
options.ResultsAuthorize = request =>
{
if (request.HttpContext.Items["AY_PROFILER_ALLOWED"] != null)
return true;
return false;
};
}).AddEntityFramework();
//Server state service for shutting people out of api //Server state service for shutting people out of api
_newLog.LogDebug("ServerState service"); _newLog.LogDebug("ServerState service");
services.AddSingleton(new Sockeye.Api.ControllerHelpers.ApiServerState()); services.AddSingleton(new Sockeye.Api.ControllerHelpers.ApiServerState());
@@ -195,28 +177,46 @@ namespace Sockeye
// #region Swagger
// services
// .AddApiVersioning(options =>
// {
// options.AssumeDefaultVersionWhenUnspecified = true;
// options.DefaultApiVersion = new ApiVersion(8,0);// Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0");
// options.ReportApiVersions = true;
// });
// services.AddVersionedApiExplorer(options =>
// {
// // add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// // note: the specified format code will format the version as "'v'major[.minor][-status]"
// options.GroupNameFormat = "'v'VVV";
// // note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// // can also be used to control the format of the API version in route templates
// //THIS IS WHAT ADDS THE API version PARAMETER AUTOMATICALLY so you don't need to type an 8 in every swagger-ui route test
// options.SubstituteApiVersionInUrl = true;
// });
#region Swagger #region Swagger
services services
.AddApiVersioning(options => .AddApiVersioning(options =>
{ {
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); options.DefaultApiVersion = new ApiVersion(8, 0);
options.ReportApiVersions = true; options.ReportApiVersions = true;
}); })
services.AddVersionedApiExplorer(options => .AddMvc()
{ .AddApiExplorer(options =>
{
// format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service // THIS IS WHAT ADDS THE API version PARAMETER AUTOMATICALLY so you don't need to type an 8 in every swagger-ui route test
// note: the specified format code will format the version as "'v'major[.minor][-status]" options.SubstituteApiVersionInUrl = true;
options.GroupNameFormat = "'v'VVV"; });
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
//THIS IS WHAT ADDS THE API version PARAMETER AUTOMATICALLY so you don't need to type an 8 in every swagger-ui route test
options.SubstituteApiVersionInUrl = true;
});
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddSwaggerGen( services.AddSwaggerGen(
c => c =>
@@ -234,16 +234,23 @@ namespace Sockeye
Scheme = "bearer" //The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer". Scheme = "bearer" //The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer".
}); });
c.AddSecurityRequirement(new OpenApiSecurityRequirement{ // c.AddSecurityRequirement(new OpenApiSecurityRequirement{
{ // {
new OpenApiSecurityScheme{ // new OpenApiSecurityScheme{
Reference = new OpenApiReference{ // Reference = new OpenApiReference{
Id = "Bearer", //The name of the previously defined security scheme. // Id = "Bearer", //The name of the previously defined security scheme.
Type = ReferenceType.SecurityScheme // Type = ReferenceType.SecurityScheme
} // }
},new List<string>() // },new List<string>()
} // }
}); // });
c.AddSecurityRequirement(document => new OpenApiSecurityRequirement
{
// "Bearer" must match the name given to AddSecurityDefinition above
[new OpenApiSecuritySchemeReference("Bearer", document)] = []
});
} }
); );
services.AddSwaggerGenNewtonsoftSupport(); services.AddSwaggerGenNewtonsoftSupport();
@@ -390,56 +397,7 @@ namespace Sockeye
{ {
if (!context.User.Identity.IsAuthenticated) if (!context.User.Identity.IsAuthenticated)
{ {
#region Profiler workaround
//Is this a profiler route? If so we're going to use the dl token to authorize
if (context.Request.Path.Value.StartsWith("/profiler/results"))
{
//someone is requesting the profiler
//check for a dl token "t" and rehydrate user if found
//Note that the profiler UI triggers it's own requests to to get the token
//we need to check the referer which was the first page of profile
string token = string.Empty;
//is the token in the request?
if (context.Request.Query.ContainsKey("t"))
{
token = context.Request.Query["t"].ToString();
}
else if (context.Request.Headers["Referer"].Count > 0)
{//Maybe it's in the referer
//try to split it on the ?
string[] stuff = context.Request.Headers["Referer"].ToString().Split('?');
if (stuff.Count() > 1)
{
var q = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(stuff[1]);
if (q.ContainsKey("t"))
{
token = q["t"].ToString();
}
}
}
if (!string.IsNullOrWhiteSpace(token))
{
using (AyContext ct = ServiceProviderProvider.DBContext)
{
var u = ct.User.AsNoTracking().SingleOrDefault(z => z.DlKey == token.ToString() && z.Active == true);
if (u != null)
{
//this is necessary because they might have an expired JWT but this would just keep on working without a date check
//the default is the same timespan as the jwt so it's all good
var utcNow = new DateTimeOffset(DateTime.Now.ToUniversalTime(), TimeSpan.Zero);
if (u.DlKeyExpire > utcNow.DateTime)
{
if (Sockeye.Api.ControllerHelpers.Authorized.HasReadFullRole(u.Roles, SockType.ServerMetrics))
context.Request.HttpContext.Items["AY_PROFILER_ALLOWED"] = true;
}
}
}
}
}
#endregion profiler workaround
context.Request.HttpContext.Items["AY_ROLES"] = 0; context.Request.HttpContext.Items["AY_ROLES"] = 0;
await next.Invoke(); await next.Invoke();
} }
@@ -510,7 +468,7 @@ namespace Sockeye
if (!bLocalReportRenderRequest) if (!bLocalReportRenderRequest)
{ {
context.Response.StatusCode = 401; context.Response.StatusCode = 401;
context.Response.Headers.Add("X-Sockeye-Authorization-Error", "E2004 - Authorization token replaced by more recent login"); context.Response.Headers.Append("X-Sockeye-Authorization-Error", "E2004 - Authorization token replaced by more recent login");
await context.Response.WriteAsync("E2004 - Authorization token replaced by more recent login"); await context.Response.WriteAsync("E2004 - Authorization token replaced by more recent login");
} }
} }
@@ -525,11 +483,7 @@ namespace Sockeye
#endregion #endregion
_newLog.LogDebug("Profiler");
app.UseMiniProfiler();
_newLog.LogDebug("Endpoints pipeline"); _newLog.LogDebug("Endpoints pipeline");
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>
{ {

View File

@@ -7,6 +7,7 @@ using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.OpenSsl;
using Sockeye.Models; using Sockeye.Models;
using Sockeye.Util; using Sockeye.Util;
using System.Globalization;
@@ -311,12 +312,10 @@ namespace Sockeye.Biz
//stamp a unique value in the key so it can be revoked later //stamp a unique value in the key so it can be revoked later
//used to use the digest value of the key for this with xml key //used to use the digest value of the key for this with xml key
//whole unix timestamp seconds but kept as a double to work beyond 2038 //whole unix timestamp seconds but kept as a double to work beyond 2038
//case 4670
w.WritePropertyName("Id"); w.WritePropertyName("Id");
var vv = Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds); w.WriteValue(Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString(CultureInfo.InvariantCulture));
string sId = vv.ToString();
if (sId.Contains(","))
sId = sId.Split('.')[0];
w.WriteValue(sId);
w.WritePropertyName("Created"); w.WritePropertyName("Created");
w.WriteValue(System.DateTime.Now); w.WriteValue(System.DateTime.Now);
@@ -348,7 +347,8 @@ namespace Sockeye.Biz
w.WriteValue(l.MaintenanceExpire.AddYears(2)); w.WriteValue(l.MaintenanceExpire.AddYears(2));
w.WritePropertyName("TotalScheduleableUsers"); w.WritePropertyName("TotalScheduleableUsers");
w.WriteValue(l.Users.ToString());//Needs to be a string to match rockfish format //cae 4670
w.WriteValue(l.Users.ToString(CultureInfo.InvariantCulture));//Needs to be a string to match rockfish format
w.WritePropertyName("Expires"); w.WritePropertyName("Expires");
w.WriteValue(l.MaintenanceExpire); w.WriteValue(l.MaintenanceExpire);
@@ -649,7 +649,71 @@ HOW TO INSTALL YOUR LICENSE KEY
#endregion templates #endregion templates
#region key signing test harness function
internal static string Sign(string keyText)
{
// StringBuilder sbKey = new StringBuilder();
// StringWriter sw = new StringWriter(sbKey);
//GET JSON as a string with whitespace stripped outside of delimited strings
//http://stackoverflow.com/questions/8913138/minify-indented-json-string-in-net
string keyNoWS = System.Text.RegularExpressions.Regex.Replace(keyText, "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1");
//**** Note this is our real 2016 private key
var privatePEM = @"-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAz7wrvLDcKVMZ31HFGBnLWL08IodYIV5VJkKy1Z0n2snprhSi
u3izxTyz+SLpftvKHJpky027ii7l/pL9Bo3JcjU5rKrxXavnE7TuYPjXn16dNLd0
K/ERSU+pXLmUaVN0nUWuGuUMoGJMEXoulS6pJiG11yu3BM9fL2Nbj0C6a+UwzEHF
mns3J/daZOb4gAzMUdJfh9OJ0+wRGzR8ZxyC99Na2gDmqYglUkSMjwLTL/HbgwF4
OwmoQYJBcET0Wa6Gfb17SaF8XRBV5ZtpCsbStkthGeoXZkFriB9c1eFQLKpBYQo2
DW3H1MPG2nAlQZLbkJj5cSh7/t1bRF08m6P+EQIDAQABAoIBAQCGvTpxLRXgB/Kk
EtmQBEsMx9EVZEwZeKIqKuDsBP8wvf4/10ql5mhT6kehtK9WhSDW5J2z8DtQKZMs
SBKuCZE77qH2CPp9E17SPWzQoRbaW/gDlWpYhgf8URs89XH5zxO4XtXKw/4omRlV
zLYiNR2pifv0EHqpOAg5KGzewdEo4VgXgtRWpHZLMpH2Q0/5ZIKMhstI6vFHP1p7
jmU4YI6uxiu7rVrZDmIUsAGoTdMabNqK/N8hKaoBiIto0Jn1ck26g+emLg8m160y
Xciu5yFUU+PP1SJMUs+k1UnAWf4p46X9jRLQCBRue9o0Ntiq/75aljRoDvgdwDsR
mg4ZANqxAoGBAPBoM5KoMZ4sv8ZFv8V+V8hgL5xiLgGoiwQl91mRsHRM/NQU5A/w
tH8nmwUrJOrksV7kX9228smKmoliTptyGGyi1NPmSkA7cN9YYnENoOEBHCVNK9vh
P+bkbMYUDNMW4fgOj09oXtQtMl5E2B3OTGoNwZ2w13YQJ8RIniLPsX7nAoGBAN01
eQNcUzQk9YrFGTznOs8udDLBfigDxaNnawvPueulJdBy6ZXDDrKmkQQA7xxl8YPr
dNtBq2lOgnb6+smC15TaAfV/fb8BLmkSwdn4Fy0FApIXIEOnLq+wjkte98nuezl8
9KXDzaqNI9hPuk2i36tJuLLMH8hzldveWbWjSlRHAoGBAKRPE7CQtBjfjNL+qOta
RrT0yJWhpMANabYUHNJi+K8ET2jEPnuGkFa3wwPtUPYaCABLJhprB9Unnid3wTIM
8RSO1ddd9jGgbqy3w9Bw+BvQnmQAMpG9iedNB+r5mSpM4XSgvuIO+4EYwuwbMXpt
nVx+um4Eh75xnDxTRYGVYkLRAoGAaZVpUlpR+HSfooHbPv+bSWKB4ewLPCw4vHrT
VErtEfW8q9b9eRcmP81TMFcFykc6VN4g47pfh58KlKHM7DwAjDLWdohIy89TiKGE
V3acEUfv5y0UoFX+6ara8Ey+9upWdKUY3Lotw3ckoc3EPeQ84DQK7YSSswnAgLaL
mS/8fWcCgYBjRefVbEep161d2DGruk4X7eNI9TFJ278h6ydW5kK9aTJuxkrtKIp4
CYf6emoB4mLXFPvAmnsalkhN2iB29hUZCXXSUjpKZrpijL54Wdu2S6ynm7aT97NF
oArP0E2Vbow3JMxq/oeXmHbrLMLQfYyXwFmciLFigOtkd45bfHdrbA==
-----END RSA PRIVATE KEY-----";
PemReader pr = new PemReader(new StringReader(privatePEM));
AsymmetricCipherKeyPair keys = (AsymmetricCipherKeyPair)pr.ReadObject();
var encoder = new UTF8Encoding(false, true);
var inputData = encoder.GetBytes(keyNoWS);
var signer = SignerUtilities.GetSigner("SHA256WITHRSA");
signer.Init(true, keys.Private);
signer.BlockUpdate(inputData, 0, inputData.Length);
var sign = signer.GenerateSignature();
var signature = Convert.ToBase64String(sign);
System.Text.StringBuilder sbOut = new StringBuilder();
sbOut.AppendLine("[KEY");
sbOut.AppendLine(keyText);
sbOut.AppendLine("KEY]");
sbOut.AppendLine("[SIGNATURE");
sbOut.AppendLine(signature);
sbOut.AppendLine("SIGNATURE]");
return sbOut.ToString();
}
#endregion
//eoc //eoc

View File

@@ -206,6 +206,73 @@ oArP0E2Vbow3JMxq/oeXmHbrLMLQfYyXwFmciLFigOtkd45bfHdrbA==
} }
#region key signing test harness function
internal static string Sign(string keyText)
{
// StringBuilder sbKey = new StringBuilder();
// StringWriter sw = new StringWriter(sbKey);
//GET JSON as a string with whitespace stripped outside of delimited strings
//http://stackoverflow.com/questions/8913138/minify-indented-json-string-in-net
string keyNoWS = System.Text.RegularExpressions.Regex.Replace(keyText, "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1");
//**** Note this is our real 2016 private key
var privatePEM = @"-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAz7wrvLDcKVMZ31HFGBnLWL08IodYIV5VJkKy1Z0n2snprhSi
u3izxTyz+SLpftvKHJpky027ii7l/pL9Bo3JcjU5rKrxXavnE7TuYPjXn16dNLd0
K/ERSU+pXLmUaVN0nUWuGuUMoGJMEXoulS6pJiG11yu3BM9fL2Nbj0C6a+UwzEHF
mns3J/daZOb4gAzMUdJfh9OJ0+wRGzR8ZxyC99Na2gDmqYglUkSMjwLTL/HbgwF4
OwmoQYJBcET0Wa6Gfb17SaF8XRBV5ZtpCsbStkthGeoXZkFriB9c1eFQLKpBYQo2
DW3H1MPG2nAlQZLbkJj5cSh7/t1bRF08m6P+EQIDAQABAoIBAQCGvTpxLRXgB/Kk
EtmQBEsMx9EVZEwZeKIqKuDsBP8wvf4/10ql5mhT6kehtK9WhSDW5J2z8DtQKZMs
SBKuCZE77qH2CPp9E17SPWzQoRbaW/gDlWpYhgf8URs89XH5zxO4XtXKw/4omRlV
zLYiNR2pifv0EHqpOAg5KGzewdEo4VgXgtRWpHZLMpH2Q0/5ZIKMhstI6vFHP1p7
jmU4YI6uxiu7rVrZDmIUsAGoTdMabNqK/N8hKaoBiIto0Jn1ck26g+emLg8m160y
Xciu5yFUU+PP1SJMUs+k1UnAWf4p46X9jRLQCBRue9o0Ntiq/75aljRoDvgdwDsR
mg4ZANqxAoGBAPBoM5KoMZ4sv8ZFv8V+V8hgL5xiLgGoiwQl91mRsHRM/NQU5A/w
tH8nmwUrJOrksV7kX9228smKmoliTptyGGyi1NPmSkA7cN9YYnENoOEBHCVNK9vh
P+bkbMYUDNMW4fgOj09oXtQtMl5E2B3OTGoNwZ2w13YQJ8RIniLPsX7nAoGBAN01
eQNcUzQk9YrFGTznOs8udDLBfigDxaNnawvPueulJdBy6ZXDDrKmkQQA7xxl8YPr
dNtBq2lOgnb6+smC15TaAfV/fb8BLmkSwdn4Fy0FApIXIEOnLq+wjkte98nuezl8
9KXDzaqNI9hPuk2i36tJuLLMH8hzldveWbWjSlRHAoGBAKRPE7CQtBjfjNL+qOta
RrT0yJWhpMANabYUHNJi+K8ET2jEPnuGkFa3wwPtUPYaCABLJhprB9Unnid3wTIM
8RSO1ddd9jGgbqy3w9Bw+BvQnmQAMpG9iedNB+r5mSpM4XSgvuIO+4EYwuwbMXpt
nVx+um4Eh75xnDxTRYGVYkLRAoGAaZVpUlpR+HSfooHbPv+bSWKB4ewLPCw4vHrT
VErtEfW8q9b9eRcmP81TMFcFykc6VN4g47pfh58KlKHM7DwAjDLWdohIy89TiKGE
V3acEUfv5y0UoFX+6ara8Ey+9upWdKUY3Lotw3ckoc3EPeQ84DQK7YSSswnAgLaL
mS/8fWcCgYBjRefVbEep161d2DGruk4X7eNI9TFJ278h6ydW5kK9aTJuxkrtKIp4
CYf6emoB4mLXFPvAmnsalkhN2iB29hUZCXXSUjpKZrpijL54Wdu2S6ynm7aT97NF
oArP0E2Vbow3JMxq/oeXmHbrLMLQfYyXwFmciLFigOtkd45bfHdrbA==
-----END RSA PRIVATE KEY-----";
PemReader pr = new PemReader(new StringReader(privatePEM));
AsymmetricCipherKeyPair keys = (AsymmetricCipherKeyPair)pr.ReadObject();
var encoder = new UTF8Encoding(false, true);
var inputData = encoder.GetBytes(keyNoWS);
var signer = SignerUtilities.GetSigner("SHA256WITHRSA");
signer.Init(true, keys.Private);
signer.BlockUpdate(inputData, 0, inputData.Length);
var sign = signer.GenerateSignature();
var signature = Convert.ToBase64String(sign);
System.Text.StringBuilder sbOut = new StringBuilder();
sbOut.AppendLine("[KEY");
sbOut.AppendLine(keyText);
sbOut.AppendLine("KEY]");
sbOut.AppendLine("[SIGNATURE");
sbOut.AppendLine(signature);
sbOut.AppendLine("SIGNATURE]");
return sbOut.ToString();
}
#endregion
#region old stuff #region old stuff
#region license classes #region license classes

View File

@@ -519,7 +519,8 @@ namespace Sockeye.Biz
else else
{ {
log.LogDebug($"Windows: Calling browserFetcher download async now:"); log.LogDebug($"Windows: Calling browserFetcher download async now:");
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision); //await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision);
await new BrowserFetcher().DownloadAsync();
} }
@@ -532,17 +533,20 @@ namespace Sockeye.Biz
//Keep for debugging headfully //Keep for debugging headfully
// var DefaultArgs = "--no-sandbox"; // var DefaultArgs = "--no-sandbox";
var DefaultArgs = "--headless --no-sandbox"; //var DefaultArgs = "--headless --no-sandbox";
var DefaultArgs = new[] { "--no-sandbox" };
if (!string.IsNullOrWhiteSpace(ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS)) if (!string.IsNullOrWhiteSpace(ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS))
{ {
log.LogDebug($"SOCKEYE_REPORT_RENDER_BROWSER_PARAMS will be used: {ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS}"); log.LogDebug($"SOCKEYE_REPORT_RENDER_BROWSER_PARAMS will be used: {ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS}");
lo.Args = new string[] { $"{ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS}" };// SOCKEYE_REPORT_RENDER_BROWSER_PARAMS //lo.Args = new string[] { $"{ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS}" };// SOCKEYE_REPORT_RENDER_BROWSER_PARAMS
lo.Args = ServerBootConfig.SOCKEYE_REPORT_RENDER_BROWSER_PARAMS.Split(' ', StringSplitOptions.RemoveEmptyEntries);
} }
else else
{ {
log.LogDebug($"SOCKEYE_REPORT_RENDER_BROWSER_PARAMS not set, using defaults '{DefaultArgs}'"); log.LogDebug($"SOCKEYE_REPORT_RENDER_BROWSER_PARAMS not set, using defaults '{DefaultArgs}'");
lo.Args = new string[] { DefaultArgs }; //lo.Args = new string[] { DefaultArgs };
lo.Args = DefaultArgs;
} }
System.Text.StringBuilder PageLog = new System.Text.StringBuilder(); System.Text.StringBuilder PageLog = new System.Text.StringBuilder();
@@ -568,8 +572,9 @@ namespace Sockeye.Biz
case ConsoleType.Error: case ConsoleType.Error:
try try
{ {
var errorArgs = await Task.WhenAll(args.Message.Args.Select(arg => arg.ExecutionContext.EvaluateFunctionAsync("(arg) => arg instanceof Error ? arg.message : arg", arg))); var errorArgs = await Task.WhenAll(args.Message.Args.Select(arg => arg.EvaluateFunctionAsync("(arg) => arg instanceof Error ? arg.message : arg")));
PageLog.AppendLine($"ERROR: {args.Message.Text} args: [{string.Join<object>(", ", errorArgs)}]"); // PageLog.AppendLine($"ERROR: {args.Message.Text} args: [{string.Join<object>(", ", errorArgs)}]");
PageLog.AppendLine($"ERROR: {args.Message.Text} args: [{string.Join(", ", errorArgs)}]");
} }
catch { } catch { }
break; break;

View File

@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<GenerateFullPaths>true</GenerateFullPaths> <GenerateFullPaths>true</GenerateFullPaths>
<Version>8.0.16</Version> <Version>8.1.0</Version>
<FileVersion>8.0.16.0</FileVersion> <FileVersion>8.1.0.0</FileVersion>
<ApplicationIcon>sockeye.ico</ApplicationIcon> <ApplicationIcon>sockeye.ico</ApplicationIcon>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile> <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
<noWarn>1591</noWarn> <noWarn>1591</noWarn>
@@ -18,35 +18,30 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Bogus" Version="34.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="BouncyCastle.NetCore" Version="1.9.0" /> <PackageReference Include="Bogus" Version="35.6.5" />
<PackageReference Include="Enums.NET" Version="4.0.0" /> <PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0" />
<PackageReference Include="jose-jwt" Version="4.0.0" /> <PackageReference Include="Enums.NET" Version="5.0.0" />
<PackageReference Include="MailKit" Version="3.2.0" /> <PackageReference Include="jose-jwt" Version="5.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.5" /> <PackageReference Include="MailKit" Version="4.18.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.4" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.12" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.12" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" /> <PackageReference Include="Asp.Versioning.Mvc" Version="10.2.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.5" /> <PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="10.2.1" />
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="6.0.5"> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.12" />
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.12">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.5" /> <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.12" />
<PackageReference Include="Microsoft.OpenApi" Version="1.3.1" /> <PackageReference Include="NLog" Version="6.2.1" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" /> <PackageReference Include="NLog.Web.AspNetCore" Version="6.2.1" />
<PackageReference Include="MiniProfiler.EntityFrameworkCore" Version="4.2.22" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.3" />
<PackageReference Include="NLog" Version="5.0.0" /> <PackageReference Include="PuppeteerSharp" Version="25.12.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.0.0" /> <PackageReference Include="QRCoder" Version="1.8.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
<PackageReference Include="PuppeteerSharp" Version="7.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.2.3" />
<PackageReference Include="QRCoder" Version="1.4.3" /> <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="10.2.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.4.0" />
<PackageReference Include="TwoFactorAuth.Net" Version="1.4.0" /> <PackageReference Include="TwoFactorAuth.Net" Version="1.4.0" />
</ItemGroup> </ItemGroup>
@@ -69,6 +64,8 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="sockeye.tests" />
</ItemGroup>
</Project> </Project>

View File

@@ -863,7 +863,7 @@ namespace Sockeye.Util
using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{ {
file.Read(bytes, 0, bytes.Length); file.ReadExactly(bytes, 0, bytes.Length);
} }
var headerPos = BitConverter.ToInt32(bytes, peHeaderOffset); var headerPos = BitConverter.ToInt32(bytes, peHeaderOffset);

View File

@@ -0,0 +1,102 @@
namespace sockeye.tests;
/*
Extract key fixture data, note that pgroup / format is 1 for v7 product family keys and not 1 for any v8 family keys
mkdir C:\data\sockeye-fixtures
$env:PGCLIENTENCODING = "UTF8"
.\psql -U postgres -d sockeye -At -o C:\data\sockeye-fixtures\resign.json -c "
SELECT json_agg(t ORDER BY t.id) FROM (
SELECT id,
pgroup AS format,
key
FROM alicense
WHERE key IS NOT NULL
) t;"
*/
// public class UnitTest1
// {
// [Fact]
// public void Test1()
// {
// }
// }
using System.Text.Json;
public record ResignRow(long Id, int Format, string Key);
public static class ResignFixture
{
static readonly Lazy<Dictionary<long, ResignRow>> _rows = new(Load);
public static IReadOnlyDictionary<long, ResignRow> Rows => _rows.Value;
static Dictionary<long, ResignRow> Load()
{
var path = "C:\\data\\sockeye-fixtures\\resign.json";//Environment.GetEnvironmentVariable("SOCKEYE_RESIGN_FIXTURE");
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
throw new InvalidOperationException(
"Set SOCKEYE_RESIGN_FIXTURE to the exported alicense JSON file.");
var rows = JsonSerializer.Deserialize<List<ResignRow>>(
File.ReadAllText(path),
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
return rows.ToDictionary(r => r.Id);
}
}
public class ResignTests
{
public static IEnumerable<object[]> RowIds() =>
ResignFixture.Rows.Keys.Select(id => new object[] { id });
[Theory]
[MemberData(nameof(RowIds))]
public void Stored_licence_resigns_identically(long id)
{
var row = ResignFixture.Rows[id];
var keyText = Between(row.Key, "[KEY", "KEY]");
var expected = StripWs(Between(row.Key, "[SIGNATURE", "SIGNATURE]"));
var actual = row.Format == 1
? Sockeye.Biz.KeyFactory.Sign(keyText) // your extracted internal methods
: Sockeye.Biz.RavenKeyFactory.Sign(keyText);
//test sign returns whole key with signature need to re-extract signature only
actual = StripWs(Between(actual, "[SIGNATURE", "SIGNATURE]"));
Assert.Equal(expected, actual);
}
[Fact]
public void Fixture_covers_both_formats()
{
Assert.Contains(ResignFixture.Rows.Values, r => r.Format == 1);
Assert.Contains(ResignFixture.Rows.Values, r => r.Format == 2);
Assert.Contains(ResignFixture.Rows.Values, r => r.Format == 3);
}
[Fact]
public void Tampered_payload_does_not_match()
{
var row = ResignFixture.Rows.Values.First(r => r.Format == 1);
var keyText = Between(row.Key, "[KEY", "KEY]") + "x";
var expected = StripWs(Between(row.Key, "[SIGNATURE", "SIGNATURE]"));
Assert.NotEqual(expected, StripWs(Between(Sockeye.Biz.KeyFactory.Sign(keyText), "[SIGNATURE", "SIGNATURE]")));
}
static string Between(string s, string start, string end)
{
int a = s.IndexOf(start, StringComparison.Ordinal);
int b = s.IndexOf(end, StringComparison.Ordinal);
if (a < 0 || b < 0 || b < a)
throw new FormatException($"Markers {start}/{end} not found");
return s.Substring(a + start.Length, b - a - start.Length);
}
static string StripWs(string s) => string.Concat(s.Where(c => !char.IsWhiteSpace(c)));
}

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\server\sockeye.csproj" />
</ItemGroup>
</Project>