Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build/generate-client.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
curl -X POST https://generator3.swagger.io/api/generate \
-H 'content-type: application/json' \
-d '{
"specURL" : "https://collector.exceptionless.io/docs/v2/swagger.json",
"specURL" : "https://collector.exceptionless.io/docs/v2/openapi.json",
"lang" : "typescript-fetch",
"type" : "CLIENT",
"options" : {
Expand All @@ -11,4 +11,4 @@ curl -X POST https://generator3.swagger.io/api/generate \
}
},
"codegenVersion" : "V3"
}' --output exceptionless-ts.zip
}' --output exceptionless-ts.zip
5 changes: 2 additions & 3 deletions src/Exceptionless.Core/Configuration/AppOptions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System.Diagnostics;
using System.Text.Json.Serialization;
using Exceptionless.Core.Configuration;
using Exceptionless.Core.Extensions;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Exceptionless.Core;

Expand All @@ -26,7 +25,7 @@ public class AppOptions
/// </summary>
public string? ExceptionlessServerUrl { get; internal set; }

[JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof(JsonStringEnumConverter))]
public AppMode AppMode { get; internal set; }
public string AppScope { get; internal set; } = null!;

Expand Down
7 changes: 3 additions & 4 deletions src/Exceptionless.Core/Configuration/EmailOptions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using Exceptionless.Core.Extensions;
using System.Text.Json.Serialization;
using Exceptionless.Core.Extensions;
using Exceptionless.Core.Utility;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Exceptionless.Core.Configuration;

Expand All @@ -26,7 +25,7 @@ public class EmailOptions

public int SmtpPort { get; internal set; }

[JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof(JsonStringEnumConverter))]
public SmtpEncryption SmtpEncryption { get; internal set; }

public string? SmtpUser { get; internal set; }
Expand Down
29 changes: 21 additions & 8 deletions src/Exceptionless.Core/Models/Stack.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using Foundatio.Repositories.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Exceptionless.Core.Models;
Expand Down Expand Up @@ -123,13 +123,26 @@ public static class KnownTypes
}
}

[JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof(JsonStringEnumConverter))]
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
public enum StackStatus
{
[EnumMember(Value = "open")] Open,
[EnumMember(Value = "fixed")] Fixed,
[EnumMember(Value = "regressed")] Regressed,
[EnumMember(Value = "snoozed")] Snoozed,
[EnumMember(Value = "ignored")] Ignored,
[EnumMember(Value = "discarded")] Discarded
[JsonStringEnumMemberName("open")]
[EnumMember(Value = "open")]
Open,
[JsonStringEnumMemberName("fixed")]
[EnumMember(Value = "fixed")]
Fixed,
[JsonStringEnumMemberName("regressed")]
[EnumMember(Value = "regressed")]
Regressed,
[JsonStringEnumMemberName("snoozed")]
[EnumMember(Value = "snoozed")]
Snoozed,
[JsonStringEnumMemberName("ignored")]
[EnumMember(Value = "ignored")]
Ignored,
[JsonStringEnumMemberName("discarded")]
[EnumMember(Value = "discarded")]
Discarded
}
2 changes: 1 addition & 1 deletion src/Exceptionless.Web/ClientApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"format": "npm run format:prettier && npm run format:eslint",
"format:eslint": "eslint . --fix --concurrency=auto",
"format:prettier": "prettier --write .",
"generate-models": "swagger-typescript-api generate -p http://localhost:5200/docs/v2/swagger.json -o ./src/lib/generated -n api.ts --no-client --templates api-templates",
"generate-models": "swagger-typescript-api generate -p http://localhost:5200/docs/v2/openapi.json -o ./src/lib/generated -n api.ts --no-client --templates api-templates",
"generate-templates": "swagger-typescript-api generate-templates -o api-templates",
"test:e2e": "playwright test",
"test:unit": "vitest run",
Expand Down
1 change: 1 addition & 0 deletions src/Exceptionless.Web/Controllers/EventController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Exceptionless.Web.Extensions;
using Exceptionless.Web.Models;
using Exceptionless.Web.Utility;
using Exceptionless.Web.Utility.OpenApi;
using FluentValidation;
using Foundatio.Caching;
using Foundatio.Queues;
Expand Down
24 changes: 12 additions & 12 deletions src/Exceptionless.Web/Controllers/StackController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
using McSherry.SemanticVersioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System.Text.Json;

namespace Exceptionless.Web.Controllers;

Expand Down Expand Up @@ -132,14 +132,14 @@ public async Task<ActionResult> MarkFixedAsync(string ids, string? version = nul
[HttpPost("mark-fixed")]
[Consumes("application/json")]
[ApiExplorerSettings(IgnoreApi = true)]
public async Task<ActionResult> MarkFixedAsync(JObject data)
public async Task<ActionResult> MarkFixedAsync(JsonDocument data)
{
string? id = null;
if (data.TryGetValue("ErrorStack", out var value))
id = value.Value<string>();
if (data.RootElement.TryGetProperty("ErrorStack", out var errorStackProp))
id = errorStackProp.GetString();

if (data.TryGetValue("Stack", out value))
id = value.Value<string>();
if (data.RootElement.TryGetProperty("Stack", out var stackProp))
id = stackProp.GetString();

if (String.IsNullOrEmpty(id))
return NotFound();
Expand Down Expand Up @@ -217,22 +217,22 @@ public async Task<IActionResult> AddLinkAsync(string id, ValueFromBody<string?>
[HttpPost("add-link")]
[Consumes("application/json")]
[ApiExplorerSettings(IgnoreApi = true)]
public async Task<IActionResult> AddLinkAsync(JObject data)
public async Task<IActionResult> AddLinkAsync(JsonDocument data)
{
string? id = null;
if (data.TryGetValue("ErrorStack", out var value))
id = value.Value<string>();
if (data.RootElement.TryGetProperty("ErrorStack", out var errorStackProp))
id = errorStackProp.GetString();

if (data.TryGetValue("Stack", out value))
id = value.Value<string>();
if (data.RootElement.TryGetProperty("Stack", out var stackProp))
id = stackProp.GetString();

if (String.IsNullOrEmpty(id))
return NotFound();

if (id.StartsWith("http"))
id = id.Substring(id.LastIndexOf('/') + 1);

string? url = data.GetValue("Link")?.Value<string>();
string? url = data.RootElement.TryGetProperty("Link", out var linkProp) ? linkProp.GetString() : null;
return await AddLinkAsync(id, new ValueFromBody<string?>(url));
}

Expand Down
12 changes: 6 additions & 6 deletions src/Exceptionless.Web/Controllers/WebHookController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using Foundatio.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System.Text.Json;

namespace Exceptionless.App.Controllers.API;

Expand Down Expand Up @@ -105,10 +105,10 @@ public Task<ActionResult<WorkInProgressResult>> DeleteAsync(string ids)
[HttpPost("~/api/v1/projecthook/subscribe")]
[Consumes("application/json")]
[ApiExplorerSettings(IgnoreApi = true)]
public async Task<ActionResult<WebHook>> SubscribeAsync(JObject data, int apiVersion = 1)
public async Task<ActionResult<WebHook>> SubscribeAsync(JsonDocument data, int apiVersion = 1)
{
string? eventType = data.GetValue("event")?.Value<string>();
string? url = data.GetValue("target_url")?.Value<string>();
string? eventType = data.RootElement.TryGetProperty("event", out var eventProp) ? eventProp.GetString() : null;
string? url = data.RootElement.TryGetProperty("target_url", out var urlProp) ? urlProp.GetString() : null;
if (String.IsNullOrEmpty(eventType) || String.IsNullOrEmpty(url))
return BadRequest();

Expand Down Expand Up @@ -143,9 +143,9 @@ public async Task<ActionResult<WebHook>> SubscribeAsync(JObject data, int apiVer
[HttpPost("~/api/v1/projecthook/unsubscribe")]
[Consumes("application/json")]
[ApiExplorerSettings(IgnoreApi = true)]
public async Task<IActionResult> UnsubscribeAsync(JObject data)
public async Task<IActionResult> UnsubscribeAsync(JsonDocument data)
{
string? targetUrl = data.GetValue("target_url")?.Value<string>();
string? targetUrl = data.RootElement.TryGetProperty("target_url", out var urlProp) ? urlProp.GetString() : null;

// don't let this anon method delete non-zapier hooks
if (targetUrl is null || !targetUrl.StartsWith("https://hooks.zapier.com"))
Expand Down
4 changes: 2 additions & 2 deletions src/Exceptionless.Web/Exceptionless.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
<PackageReference Include="Exceptionless.AspNetCore" Version="6.1.0" />
<PackageReference Include="Joonasw.AspNetCore.SecurityHeaders" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
<PackageReference Include="MiniValidation" Version="0.9.2" />
<PackageReference Include="NEST.JsonNetSerializer" Version="7.17.5" />
<PackageReference Include="OAuth2" Version="0.10.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
<PackageReference Include="Scalar.AspNetCore" Version="2.11.1" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
Expand All @@ -34,7 +35,6 @@
<PackageReference Include="OpenTelemetry.Instrumentation.ElasticsearchClient" Version="1.13.0-beta.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.14.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.13.0-beta.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Exceptionless.Insulation\Exceptionless.Insulation.csproj" />
Expand Down
14 changes: 9 additions & 5 deletions src/Exceptionless.Web/Hubs/WebSocketConnectionManager.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using Exceptionless.Core;
using Newtonsoft.Json;
using Exceptionless.Web.Utility;

namespace Exceptionless.Web.Hubs;

Expand All @@ -11,12 +12,15 @@ public class WebSocketConnectionManager : IDisposable
private static readonly ArraySegment<byte> _keepAliveMessage = new(Encoding.ASCII.GetBytes("{}"), 0, 2);
private readonly ConcurrentDictionary<string, WebSocket> _connections = new();
private readonly Timer? _timer;
private readonly JsonSerializerSettings _serializerSettings;
private readonly JsonSerializerOptions _serializerOptions;
private readonly ILogger _logger;

public WebSocketConnectionManager(AppOptions options, JsonSerializerSettings serializerSettings, ILoggerFactory loggerFactory)
public WebSocketConnectionManager(AppOptions options, ILoggerFactory loggerFactory)
{
_serializerSettings = serializerSettings;
_serializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = LowerCaseUnderscoreNamingPolicy.Instance
};
_logger = loggerFactory.CreateLogger<WebSocketConnectionManager>();
if (!options.EnableWebSockets)
return;
Expand Down Expand Up @@ -119,7 +123,7 @@ private Task SendMessageAsync(WebSocket socket, object message)
if (!CanSendWebSocketMessage(socket))
return Task.CompletedTask;

string serializedMessage = JsonConvert.SerializeObject(message, _serializerSettings);
string serializedMessage = JsonSerializer.Serialize(message, _serializerOptions);
Task.Factory.StartNew(async () =>
{
if (!CanSendWebSocketMessage(socket))
Expand Down
8 changes: 5 additions & 3 deletions src/Exceptionless.Web/Models/Auth/ExternalAuthInfo.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Text.Json.Serialization;

namespace Exceptionless.Web.Models;

// NOTE: This will bypass our LowerCaseUnderscorePropertyNamesContractResolver and provide the correct casing.
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public record ExternalAuthInfo
{
[Required]
[JsonPropertyName("clientId")]
public required string ClientId { get; init; }

[Required]
[JsonPropertyName("code")]
public required string Code { get; init; }

[Required]
[JsonPropertyName("redirectUri")]
public required string RedirectUri { get; init; }

[JsonPropertyName("inviteToken")]
public string? InviteToken { get; init; }
}
Loading
Loading