mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-07 16:19:07 +00:00
fix(backend): sanitize exception disclosure in changed API endpoints
Replace raw exception-message disclosure (ex.Message) returned to API callers with a stable sanitized public message plus correlated structured internal logging, across the endpoints changed in this PR. - Add SanitizedErrors helper: logs the original exception at Error with a generated correlation id and returns a stable public message referencing it so support can trace without exposing internals. - Inject ILogger<T> into the 14 changed controllers and route every ex.Message/dbex.Message disclosure through the helper, preserving status codes, response shapes, and business data (e.g. OpenWorkOrders). - Leave FluentValidation (vex.Errors) and existing fixed-message catches untouched; out-of-scope controllers (Account/Contact/Employee/Asset/ PMSchedule) are unchanged. - Add focused tests proving internal exception text is not returned and that Error logging carrying the original exception is invoked.
This commit is contained in:
parent
6f6c7e04cd
commit
32de36f78c
26 changed files with 386 additions and 99 deletions
|
|
@ -4,6 +4,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -20,7 +21,7 @@ public class AuthenticationControllerTests
|
||||||
|
|
||||||
private static AuthenticationController NewController(Mock<IAuthenticationService> service, string? userId = null)
|
private static AuthenticationController NewController(Mock<IAuthenticationService> service, string? userId = null)
|
||||||
{
|
{
|
||||||
var controller = new AuthenticationController(service.Object);
|
var controller = new AuthenticationController(service.Object, Mock.Of<ILogger<AuthenticationController>>());
|
||||||
if (userId != null)
|
if (userId != null)
|
||||||
{
|
{
|
||||||
controller.ControllerContext = new ControllerContext
|
controller.ControllerContext = new ControllerContext
|
||||||
|
|
@ -82,6 +83,35 @@ public class AuthenticationControllerTests
|
||||||
result.Should().BeOfType<UnauthorizedResult>();
|
result.Should().BeOfType<UnauthorizedResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Login_WhenServiceThrows_ReturnsSanitized500AndLogsInternally()
|
||||||
|
{
|
||||||
|
var service = new Mock<IAuthenticationService>();
|
||||||
|
service.Setup(s => s.LoginAsync(It.IsAny<string?>(), It.IsAny<string?>(), It.IsAny<CancellationToken>()))
|
||||||
|
.ThrowsAsync(new InvalidOperationException("SECRET-internal-stack-detail"));
|
||||||
|
|
||||||
|
var logger = new Mock<ILogger<AuthenticationController>>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
var controller = new AuthenticationController(service.Object, logger.Object);
|
||||||
|
|
||||||
|
var result = await controller.Login(new LoginModel { Username = "x", Password = "y" }, CancellationToken.None);
|
||||||
|
|
||||||
|
var status = result.Should().BeOfType<ObjectResult>().Subject;
|
||||||
|
status.StatusCode.Should().Be(500);
|
||||||
|
var message = (string)status.Value!;
|
||||||
|
message.Should().NotContain("SECRET");
|
||||||
|
message.Should().NotContain("internal-stack-detail");
|
||||||
|
message.Should().Contain("reference");
|
||||||
|
logger.Verify(
|
||||||
|
x => x.Log(
|
||||||
|
LogLevel.Error,
|
||||||
|
It.IsAny<EventId>(),
|
||||||
|
It.IsAny<It.IsAnyType>(),
|
||||||
|
It.Is<Exception>(ex => ex.Message.Contains("SECRET")),
|
||||||
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ChangePassword_Success_ReturnsSuccessMessageWithTrailingSpace()
|
public async Task ChangePassword_Success_ReturnsSuccessMessageWithTrailingSpace()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Api.SeaHavenIndustries.DTOs;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -26,7 +27,7 @@ public class CalendarControllerTests
|
||||||
};
|
};
|
||||||
|
|
||||||
private static CalendarController NewController(Mock<ICalendarService> service) =>
|
private static CalendarController NewController(Mock<ICalendarService> service) =>
|
||||||
new(service.Object);
|
new(service.Object, Mock.Of<ILogger<CalendarController>>());
|
||||||
|
|
||||||
private static object Prop(object source, string name) =>
|
private static object Prop(object source, string name) =>
|
||||||
source.GetType().GetProperty(name)!.GetValue(source)!;
|
source.GetType().GetProperty(name)!.GetValue(source)!;
|
||||||
|
|
@ -45,17 +46,32 @@ public class CalendarControllerTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task AddEvent_WhenServiceThrows_ReturnsBadRequestWithMessage()
|
public async Task AddEvent_WhenServiceThrows_ReturnsSanitizedMessageAndLogsInternally()
|
||||||
{
|
{
|
||||||
var service = new Mock<ICalendarService>();
|
var service = new Mock<ICalendarService>();
|
||||||
service.Setup(s => s.CreateEventAsync(It.IsAny<EditEventInput>(), It.IsAny<CancellationToken>()))
|
service.Setup(s => s.CreateEventAsync(It.IsAny<EditEventInput>(), It.IsAny<CancellationToken>()))
|
||||||
.ThrowsAsync(new InvalidOperationException("boom"));
|
.ThrowsAsync(new InvalidOperationException("SECRET-internal-db-connection-leak"));
|
||||||
|
|
||||||
var result = await NewController(service).AddEvent(ValidDto(), CancellationToken.None);
|
var logger = new Mock<ILogger<CalendarController>>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
var controller = new CalendarController(service.Object, logger.Object);
|
||||||
|
|
||||||
|
var result = await controller.AddEvent(ValidDto(), CancellationToken.None);
|
||||||
|
|
||||||
var bad = result.Should().BeOfType<BadRequestObjectResult>().Subject;
|
var bad = result.Should().BeOfType<BadRequestObjectResult>().Subject;
|
||||||
var response = bad.Value.Should().BeOfType<Response>().Subject;
|
var response = bad.Value.Should().BeOfType<Response>().Subject;
|
||||||
response.Message.Should().Be("boom");
|
response.Status.Should().Be("Error");
|
||||||
|
response.Message.Should().NotContain("SECRET");
|
||||||
|
response.Message.Should().NotContain("internal-db-connection-leak");
|
||||||
|
response.Message.Should().Contain("reference");
|
||||||
|
logger.Verify(
|
||||||
|
x => x.Log(
|
||||||
|
LogLevel.Error,
|
||||||
|
It.IsAny<EventId>(),
|
||||||
|
It.IsAny<It.IsAnyType>(),
|
||||||
|
It.Is<Exception>(ex => ex.Message.Contains("SECRET")),
|
||||||
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
|
||||||
|
Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -16,7 +17,7 @@ public class FollowUpControllerTests
|
||||||
{
|
{
|
||||||
private static FollowUpController NewController(Mock<IFollowUpService> service)
|
private static FollowUpController NewController(Mock<IFollowUpService> service)
|
||||||
{
|
{
|
||||||
var controller = new FollowUpController(service.Object)
|
var controller = new FollowUpController(service.Object, Mock.Of<ILogger<FollowUpController>>())
|
||||||
{
|
{
|
||||||
ControllerContext = new ControllerContext
|
ControllerContext = new ControllerContext
|
||||||
{
|
{
|
||||||
|
|
@ -33,7 +34,7 @@ public class FollowUpControllerTests
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FollowUpController NewControllerNoUser(Mock<IFollowUpService> service) =>
|
private static FollowUpController NewControllerNoUser(Mock<IFollowUpService> service) =>
|
||||||
new(service.Object)
|
new(service.Object, Mock.Of<ILogger<FollowUpController>>())
|
||||||
{
|
{
|
||||||
ControllerContext = new ControllerContext
|
ControllerContext = new ControllerContext
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -14,7 +15,7 @@ namespace Api.SeaHavenIndustries.Tests;
|
||||||
public class LocationControllerTests
|
public class LocationControllerTests
|
||||||
{
|
{
|
||||||
private static LocationController NewController(Mock<ILocationService> service) =>
|
private static LocationController NewController(Mock<ILocationService> service) =>
|
||||||
new(service.Object);
|
new(service.Object, Mock.Of<ILogger<LocationController>>());
|
||||||
|
|
||||||
private static object Prop(object source, string name) =>
|
private static object Prop(object source, string name) =>
|
||||||
source.GetType().GetProperty(name)!.GetValue(source)!;
|
source.GetType().GetProperty(name)!.GetValue(source)!;
|
||||||
|
|
|
||||||
71
Api.SeaHavenIndustries.Tests/SanitizedErrorsTests.cs
Normal file
71
Api.SeaHavenIndustries.Tests/SanitizedErrorsTests.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Api.SeaHavenIndustries.Tests;
|
||||||
|
|
||||||
|
public class SanitizedErrorsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Sanitize_ReturnsStableMessageAndNeverExposesExceptionText()
|
||||||
|
{
|
||||||
|
var logger = new Mock<ILogger>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
|
||||||
|
var message = logger.Object.Sanitize(new InvalidOperationException("SUPER-SECRET-internal-detail"));
|
||||||
|
|
||||||
|
message.Should().NotContain("SUPER-SECRET");
|
||||||
|
message.Should().NotContain("internal-detail");
|
||||||
|
message.Should().StartWith("An unexpected error occurred");
|
||||||
|
message.Should().Contain("reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Sanitize_UsesProvidedPublicMessageInsteadOfExceptionText()
|
||||||
|
{
|
||||||
|
var logger = new Mock<ILogger>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
|
||||||
|
var message = logger.Object.Sanitize(
|
||||||
|
new InvalidOperationException("SUPER-SECRET-internal-detail"),
|
||||||
|
"Vendor not found");
|
||||||
|
|
||||||
|
message.Should().Contain("Vendor not found");
|
||||||
|
message.Should().NotContain("SUPER-SECRET");
|
||||||
|
message.Should().Contain("reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Sanitize_LogsOriginalExceptionAtErrorLevel()
|
||||||
|
{
|
||||||
|
var logger = new Mock<ILogger>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
var exception = new InvalidOperationException("SUPER-SECRET-internal-detail");
|
||||||
|
|
||||||
|
logger.Object.Sanitize(exception);
|
||||||
|
|
||||||
|
logger.Verify(
|
||||||
|
x => x.Log(
|
||||||
|
LogLevel.Error,
|
||||||
|
It.IsAny<EventId>(),
|
||||||
|
It.IsAny<It.IsAnyType>(),
|
||||||
|
It.Is<Exception>(ex => ex == exception),
|
||||||
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Sanitize_ProducesUniqueCorrelationReferencesAcrossCalls()
|
||||||
|
{
|
||||||
|
var logger = new Mock<ILogger>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
var exception = new InvalidOperationException("detail");
|
||||||
|
|
||||||
|
var first = logger.Object.Sanitize(exception);
|
||||||
|
var second = logger.Object.Sanitize(exception);
|
||||||
|
|
||||||
|
first.Should().NotBe(second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ using Api.SeaHavenIndustries.Helper.ViewModel;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -14,7 +15,7 @@ namespace Api.SeaHavenIndustries.Tests;
|
||||||
public class SettingsControllerTests
|
public class SettingsControllerTests
|
||||||
{
|
{
|
||||||
private static SettingsController NewController(Mock<ISettingsService> service) =>
|
private static SettingsController NewController(Mock<ISettingsService> service) =>
|
||||||
new(service.Object);
|
new(service.Object, Mock.Of<ILogger<SettingsController>>());
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetCategoryList_ReturnsPaginationEnvelopeWithServiceItems()
|
public async Task GetCategoryList_ReturnsPaginationEnvelopeWithServiceItems()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -15,7 +16,7 @@ public class UpliftControllerTests
|
||||||
{
|
{
|
||||||
private static UpliftController NewController(Mock<IUpliftService> service, params string[] roles)
|
private static UpliftController NewController(Mock<IUpliftService> service, params string[] roles)
|
||||||
{
|
{
|
||||||
var controller = new UpliftController(service.Object);
|
var controller = new UpliftController(service.Object, Mock.Of<ILogger<UpliftController>>());
|
||||||
var claims = new List<Claim> { new(ClaimTypes.NameIdentifier, "42") };
|
var claims = new List<Claim> { new(ClaimTypes.NameIdentifier, "42") };
|
||||||
claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r)));
|
claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r)));
|
||||||
controller.ControllerContext = new ControllerContext
|
controller.ControllerContext = new ControllerContext
|
||||||
|
|
@ -66,6 +67,41 @@ public class UpliftControllerTests
|
||||||
nf.Value.Should().BeOfType<Response>();
|
nf.Value.Should().BeOfType<Response>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Approve_Forbidden_ReturnsSanitized403AndLogsInternally()
|
||||||
|
{
|
||||||
|
var service = new Mock<IUpliftService>();
|
||||||
|
service.Setup(x => x.ApproveAsync(It.IsAny<ClaimsPrincipal>(), 5, null, It.IsAny<CancellationToken>()))
|
||||||
|
.ThrowsAsync(new UpliftForbiddenException("SECRET-tier-restriction-detail"));
|
||||||
|
|
||||||
|
var logger = new Mock<ILogger<UpliftController>>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
var controller = new UpliftController(service.Object, logger.Object);
|
||||||
|
controller.ControllerContext = new ControllerContext
|
||||||
|
{
|
||||||
|
HttpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "42") }, "Test"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await controller.Approve(5, null);
|
||||||
|
|
||||||
|
var status = result.Should().BeOfType<ObjectResult>().Subject;
|
||||||
|
status.StatusCode.Should().Be(403);
|
||||||
|
var response = status.Value.Should().BeOfType<Response>().Subject;
|
||||||
|
response.Message.Should().NotContain("SECRET");
|
||||||
|
response.Message.Should().Contain("reference");
|
||||||
|
logger.Verify(
|
||||||
|
x => x.Log(
|
||||||
|
LogLevel.Error,
|
||||||
|
It.IsAny<EventId>(),
|
||||||
|
It.IsAny<It.IsAnyType>(),
|
||||||
|
It.Is<Exception>(ex => ex.Message.Contains("SECRET")),
|
||||||
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Approve_ForbiddenTier_Returns403()
|
public async Task Approve_ForbiddenTier_Returns403()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -20,7 +21,7 @@ public class UserControllerTests
|
||||||
|
|
||||||
private static UserController NewController(Mock<IUserService> service, string? userId = null)
|
private static UserController NewController(Mock<IUserService> service, string? userId = null)
|
||||||
{
|
{
|
||||||
var controller = new UserController(service.Object);
|
var controller = new UserController(service.Object, Mock.Of<ILogger<UserController>>());
|
||||||
if (userId != null)
|
if (userId != null)
|
||||||
{
|
{
|
||||||
controller.ControllerContext = new ControllerContext
|
controller.ControllerContext = new ControllerContext
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -16,7 +17,7 @@ public class VendorControllerTests
|
||||||
{
|
{
|
||||||
private static VendorController NewController(Mock<IVendorService> service)
|
private static VendorController NewController(Mock<IVendorService> service)
|
||||||
{
|
{
|
||||||
var controller = new VendorController(service.Object);
|
var controller = new VendorController(service.Object, Mock.Of<ILogger<VendorController>>());
|
||||||
|
|
||||||
controller.ControllerContext = new ControllerContext
|
controller.ControllerContext = new ControllerContext
|
||||||
{
|
{
|
||||||
|
|
@ -218,6 +219,44 @@ public class VendorControllerTests
|
||||||
result.Should().BeOfType<NotFoundResult>();
|
result.Should().BeOfType<NotFoundResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Delete_WhenDeactivationBlocked_ReturnsSanitizedConflictWithOpenWorkOrdersAndLogs()
|
||||||
|
{
|
||||||
|
var openWorkOrders = new List<LinkedWorkOrderDTO> { new() { WorkOrderId = 7 } };
|
||||||
|
var service = new Mock<IVendorService>();
|
||||||
|
service.Setup(x => x.DeleteVendorAsync(It.IsAny<int>(), It.IsAny<string>()))
|
||||||
|
.ThrowsAsync(new VendorDeactivationBlockedException("SECRET-internal-reason", openWorkOrders));
|
||||||
|
|
||||||
|
var logger = new Mock<ILogger<VendorController>>();
|
||||||
|
logger.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||||
|
var controller = new VendorController(service.Object, logger.Object);
|
||||||
|
controller.ControllerContext = new ControllerContext
|
||||||
|
{
|
||||||
|
HttpContext = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "42") }, "Test"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await controller.Delete(5);
|
||||||
|
|
||||||
|
var conflict = result.Should().BeOfType<ConflictObjectResult>().Subject;
|
||||||
|
var value = conflict.Value!;
|
||||||
|
var message = (string)value.GetType().GetProperty("Message")!.GetValue(value)!;
|
||||||
|
message.Should().NotContain("SECRET");
|
||||||
|
message.Should().Contain("reference");
|
||||||
|
var returnedOpenWorkOrders = (List<LinkedWorkOrderDTO>)value.GetType().GetProperty("OpenWorkOrders")!.GetValue(value)!;
|
||||||
|
returnedOpenWorkOrders.Should().HaveCount(1);
|
||||||
|
logger.Verify(
|
||||||
|
x => x.Log(
|
||||||
|
LogLevel.Error,
|
||||||
|
It.IsAny<EventId>(),
|
||||||
|
It.IsAny<It.IsAnyType>(),
|
||||||
|
It.Is<Exception>(ex => ex.Message.Contains("SECRET")),
|
||||||
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Delete_MapsDeactivationBlocked_ToConflict()
|
public async Task Delete_MapsDeactivationBlocked_ToConflict()
|
||||||
{
|
{
|
||||||
|
|
@ -265,7 +304,7 @@ public class VendorControllerTests
|
||||||
public async Task Update_UnauthenticatedUser_ReturnsUnauthorized()
|
public async Task Update_UnauthenticatedUser_ReturnsUnauthorized()
|
||||||
{
|
{
|
||||||
var service = new Mock<IVendorService>();
|
var service = new Mock<IVendorService>();
|
||||||
var controller = new VendorController(service.Object);
|
var controller = new VendorController(service.Object, Mock.Of<ILogger<VendorController>>());
|
||||||
controller.ControllerContext = new ControllerContext
|
controller.ControllerContext = new ControllerContext
|
||||||
{
|
{
|
||||||
HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal() }
|
HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal() }
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using Data.SeaHavenIndustries;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
@ -14,7 +15,7 @@ public class VendorPortalControllerTests
|
||||||
{
|
{
|
||||||
private static VendorPortalController NewController(Mock<IVendorPortalService> service, string? token = "valid-token")
|
private static VendorPortalController NewController(Mock<IVendorPortalService> service, string? token = "valid-token")
|
||||||
{
|
{
|
||||||
var controller = new VendorPortalController(service.Object);
|
var controller = new VendorPortalController(service.Object, Mock.Of<ILogger<VendorPortalController>>());
|
||||||
var context = new DefaultHttpContext();
|
var context = new DefaultHttpContext();
|
||||||
if (token != null)
|
if (token != null)
|
||||||
context.Request.Headers["X-Vendor-Token"] = token;
|
context.Request.Headers["X-Vendor-Token"] = token;
|
||||||
|
|
@ -133,7 +134,8 @@ public class VendorPortalControllerTests
|
||||||
|
|
||||||
var bad = result.Should().BeOfType<BadRequestObjectResult>().Subject;
|
var bad = result.Should().BeOfType<BadRequestObjectResult>().Subject;
|
||||||
var resp = bad.Value.Should().BeOfType<Response>().Subject;
|
var resp = bad.Value.Should().BeOfType<Response>().Subject;
|
||||||
resp.Message.Should().Be("Cannot accept");
|
resp.Message.Should().NotContain("Cannot accept");
|
||||||
|
resp.Message.Should().Contain("reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -169,7 +171,8 @@ public class VendorPortalControllerTests
|
||||||
|
|
||||||
var bad = result.Should().BeOfType<BadRequestObjectResult>().Subject;
|
var bad = result.Should().BeOfType<BadRequestObjectResult>().Subject;
|
||||||
var resp = bad.Value.Should().BeOfType<Response>().Subject;
|
var resp = bad.Value.Should().BeOfType<Response>().Subject;
|
||||||
resp.Message.Should().Contain("Transition");
|
resp.Message.Should().NotContain("Transition");
|
||||||
|
resp.Message.Should().Contain("reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,8 @@
|
||||||
<ProjectReference Include="..\SeaHaven.DataServices\SeaHaven.DataServices.csproj" />
|
<ProjectReference Include="..\SeaHaven.DataServices\SeaHaven.DataServices.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<InternalsVisibleTo Include="Api.SeaHavenIndustries.Tests" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class AuthenticationController : Controller
|
public class AuthenticationController : Controller
|
||||||
{
|
{
|
||||||
private readonly IAuthenticationService _authenticationService;
|
private readonly IAuthenticationService _authenticationService;
|
||||||
|
private readonly ILogger<AuthenticationController> _logger;
|
||||||
|
|
||||||
public AuthenticationController(IAuthenticationService authenticationService)
|
public AuthenticationController(IAuthenticationService authenticationService, ILogger<AuthenticationController> logger)
|
||||||
{
|
{
|
||||||
_authenticationService = authenticationService;
|
_authenticationService = authenticationService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
|
|
@ -46,7 +50,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
||||||
return StatusCode(500, ex.Message);
|
return StatusCode(500, _logger.Sanitize(ex));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +98,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +139,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Error: " + ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +163,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Error: " + ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class CalendarController : Controller
|
public class CalendarController : Controller
|
||||||
{
|
{
|
||||||
private readonly ICalendarService _calendarService;
|
private readonly ICalendarService _calendarService;
|
||||||
|
private readonly ILogger<CalendarController> _logger;
|
||||||
|
|
||||||
public CalendarController(ICalendarService calendarService)
|
public CalendarController(ICalendarService calendarService, ILogger<CalendarController> logger)
|
||||||
{
|
{
|
||||||
_calendarService = calendarService;
|
_calendarService = calendarService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================================
|
// ===================================================================================
|
||||||
|
|
@ -34,7 +38,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +66,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +90,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +113,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +139,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +158,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Api.SeaHavenIndustries.Helper.ViewModel;
|
using Api.SeaHavenIndustries.Helper.ViewModel;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class CommonController : Controller
|
public class CommonController : Controller
|
||||||
{
|
{
|
||||||
private readonly ICommonService _commonService;
|
private readonly ICommonService _commonService;
|
||||||
|
private readonly ILogger<CommonController> _logger;
|
||||||
|
|
||||||
public CommonController(ICommonService commonService)
|
public CommonController(ICommonService commonService, ILogger<CommonController> logger)
|
||||||
{
|
{
|
||||||
_commonService = commonService;
|
_commonService = commonService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -49,7 +53,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new { Status = "Error", Message = ex.Message });
|
return BadRequest(new { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,7 +69,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new { Status = "Error", Message = ex.Message });
|
return BadRequest(new { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -12,10 +14,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class DropdownOptionsController : Controller
|
public class DropdownOptionsController : Controller
|
||||||
{
|
{
|
||||||
private readonly IDropdownOptionsService _dropdownOptionsService;
|
private readonly IDropdownOptionsService _dropdownOptionsService;
|
||||||
|
private readonly ILogger<DropdownOptionsController> _logger;
|
||||||
|
|
||||||
public DropdownOptionsController(IDropdownOptionsService dropdownOptionsService)
|
public DropdownOptionsController(IDropdownOptionsService dropdownOptionsService, ILogger<DropdownOptionsController> logger)
|
||||||
{
|
{
|
||||||
_dropdownOptionsService = dropdownOptionsService;
|
_dropdownOptionsService = dropdownOptionsService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -42,7 +46,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new { message = ex.Message });
|
return BadRequest(new { message = _logger.Sanitize(ex, "The dropdown option could not be saved") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -14,10 +16,12 @@ using SeaHaven.Services.Interfaces;
|
||||||
public class FollowUpController : ControllerBase
|
public class FollowUpController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IFollowUpService _followUpService;
|
private readonly IFollowUpService _followUpService;
|
||||||
|
private readonly ILogger<FollowUpController> _logger;
|
||||||
|
|
||||||
public FollowUpController(IFollowUpService followUpService)
|
public FollowUpController(IFollowUpService followUpService, ILogger<FollowUpController> logger)
|
||||||
{
|
{
|
||||||
_followUpService = followUpService;
|
_followUpService = followUpService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetFollowUpList")]
|
[HttpGet("GetFollowUpList")]
|
||||||
|
|
@ -111,7 +115,7 @@ public class FollowUpController : ControllerBase
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,7 +138,7 @@ public class FollowUpController : ControllerBase
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,7 +177,7 @@ public class FollowUpController : ControllerBase
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -15,10 +17,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class LocationController : Controller
|
public class LocationController : Controller
|
||||||
{
|
{
|
||||||
private readonly ILocationService _locationService;
|
private readonly ILocationService _locationService;
|
||||||
|
private readonly ILogger<LocationController> _logger;
|
||||||
|
|
||||||
public LocationController(ILocationService locationService)
|
public LocationController(ILocationService locationService, ILogger<LocationController> logger)
|
||||||
{
|
{
|
||||||
_locationService = locationService;
|
_locationService = locationService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetLocationList")]
|
[HttpGet("GetLocationList")]
|
||||||
|
|
@ -98,7 +102,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +125,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,7 +146,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class QuotesController : Controller
|
public class QuotesController : Controller
|
||||||
{
|
{
|
||||||
private readonly IQuotesService _quotesService;
|
private readonly IQuotesService _quotesService;
|
||||||
|
private readonly ILogger<QuotesController> _logger;
|
||||||
|
|
||||||
public QuotesController(IQuotesService quotesService)
|
public QuotesController(IQuotesService quotesService, ILogger<QuotesController> logger)
|
||||||
{
|
{
|
||||||
_quotesService = quotesService;
|
_quotesService = quotesService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
@ -31,7 +35,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +53,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +72,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Api.SeaHavenIndustries.Helper.ViewModel;
|
using Api.SeaHavenIndustries.Helper.ViewModel;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class SettingsController : Controller
|
public class SettingsController : Controller
|
||||||
{
|
{
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly ILogger<SettingsController> _logger;
|
||||||
|
|
||||||
public SettingsController(ISettingsService settingsService)
|
public SettingsController(ISettingsService settingsService, ILogger<SettingsController> logger)
|
||||||
{
|
{
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
@ -30,7 +34,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +51,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +68,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +113,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +149,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new { Status = "Error", Message = ex.Message });
|
return BadRequest(new { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,7 +165,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -14,10 +16,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class TaskListTemplateController : Controller
|
public class TaskListTemplateController : Controller
|
||||||
{
|
{
|
||||||
private readonly ITaskListTemplateService _taskListTemplateService;
|
private readonly ITaskListTemplateService _taskListTemplateService;
|
||||||
|
private readonly ILogger<TaskListTemplateController> _logger;
|
||||||
|
|
||||||
public TaskListTemplateController(ITaskListTemplateService taskListTemplateService)
|
public TaskListTemplateController(ITaskListTemplateService taskListTemplateService, ILogger<TaskListTemplateController> logger)
|
||||||
{
|
{
|
||||||
_taskListTemplateService = taskListTemplateService;
|
_taskListTemplateService = taskListTemplateService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -49,7 +53,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +71,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class UpliftController : Controller
|
public class UpliftController : Controller
|
||||||
{
|
{
|
||||||
private readonly IUpliftService _upliftService;
|
private readonly IUpliftService _upliftService;
|
||||||
|
private readonly ILogger<UpliftController> _logger;
|
||||||
|
|
||||||
public UpliftController(IUpliftService upliftService)
|
public UpliftController(IUpliftService upliftService, ILogger<UpliftController> logger)
|
||||||
{
|
{
|
||||||
_upliftService = upliftService;
|
_upliftService = upliftService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -43,15 +47,15 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (KeyNotFoundException ex)
|
catch (KeyNotFoundException ex)
|
||||||
{
|
{
|
||||||
return NotFound(new Response { Status = "Error", Message = ex.Message });
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Uplift request not found") });
|
||||||
}
|
}
|
||||||
catch (UpliftForbiddenException ex)
|
catch (UpliftForbiddenException ex)
|
||||||
{
|
{
|
||||||
return StatusCode(403, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(403, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action on this uplift request") });
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "This uplift request cannot be modified in its current state") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,15 +69,15 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (KeyNotFoundException ex)
|
catch (KeyNotFoundException ex)
|
||||||
{
|
{
|
||||||
return NotFound(new Response { Status = "Error", Message = ex.Message });
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Uplift request not found") });
|
||||||
}
|
}
|
||||||
catch (UpliftForbiddenException ex)
|
catch (UpliftForbiddenException ex)
|
||||||
{
|
{
|
||||||
return StatusCode(403, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(403, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action on this uplift request") });
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "This uplift request cannot be modified in its current state") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
@ -14,10 +16,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class UserController : Controller
|
public class UserController : Controller
|
||||||
{
|
{
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
|
private readonly ILogger<UserController> _logger;
|
||||||
|
|
||||||
public UserController(IUserService userService)
|
public UserController(IUserService userService, ILogger<UserController> logger)
|
||||||
{
|
{
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
[Route("")]
|
[Route("")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -49,7 +53,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +77,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +97,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +113,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
@ -16,10 +18,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class VendorController : Controller
|
public class VendorController : Controller
|
||||||
{
|
{
|
||||||
private readonly IVendorService _vendorService;
|
private readonly IVendorService _vendorService;
|
||||||
|
private readonly ILogger<VendorController> _logger;
|
||||||
|
|
||||||
public VendorController(IVendorService vendorService)
|
public VendorController(IVendorService vendorService, ILogger<VendorController> logger)
|
||||||
{
|
{
|
||||||
_vendorService = vendorService;
|
_vendorService = vendorService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetVendorList")]
|
[HttpGet("GetVendorList")]
|
||||||
|
|
@ -148,7 +152,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,7 +203,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
return Conflict(new
|
return Conflict(new
|
||||||
{
|
{
|
||||||
Status = "Conflict",
|
Status = "Conflict",
|
||||||
Message = dbex.Message,
|
Message = _logger.Sanitize(dbex, "Vendor cannot be deactivated because it has open work orders"),
|
||||||
OpenWorkOrders = dbex.OpenWorkOrders
|
OpenWorkOrders = dbex.OpenWorkOrders
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +213,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +240,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
return Conflict(new
|
return Conflict(new
|
||||||
{
|
{
|
||||||
Status = "Conflict",
|
Status = "Conflict",
|
||||||
Message = dbex.Message,
|
Message = _logger.Sanitize(dbex, "Vendor cannot be deactivated because it has open work orders"),
|
||||||
OpenWorkOrders = dbex.OpenWorkOrders
|
OpenWorkOrders = dbex.OpenWorkOrders
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +250,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,7 +268,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,7 +308,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return StatusCode(500, new Response { Status = "Error", Message = ex.Message });
|
return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
|
@ -13,10 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
private const string TokenHeader = "X-Vendor-Token";
|
private const string TokenHeader = "X-Vendor-Token";
|
||||||
|
|
||||||
private readonly IVendorPortalService _portalService;
|
private readonly IVendorPortalService _portalService;
|
||||||
|
private readonly ILogger<VendorPortalController> _logger;
|
||||||
|
|
||||||
public VendorPortalController(IVendorPortalService portalService)
|
public VendorPortalController(IVendorPortalService portalService, ILogger<VendorPortalController> logger)
|
||||||
{
|
{
|
||||||
_portalService = portalService;
|
_portalService = portalService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("session")]
|
[HttpGet("session")]
|
||||||
|
|
@ -71,7 +75,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +96,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +117,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,7 +138,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +159,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +180,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +201,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,7 +222,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The requested action could not be completed for this dispatch") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
using Api.SeaHavenIndustries.DTOs;
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Api.SeaHavenIndustries.Helper;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
using SeaHaven.Services.Interfaces;
|
using SeaHaven.Services.Interfaces;
|
||||||
using SeaHaven.DataServices.Models;
|
using SeaHaven.DataServices.Models;
|
||||||
|
|
@ -18,13 +20,16 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
private readonly IWorkOrderService _workOrderService;
|
private readonly IWorkOrderService _workOrderService;
|
||||||
private readonly IWorkOrderDispatchService _dispatchService;
|
private readonly IWorkOrderDispatchService _dispatchService;
|
||||||
|
private readonly ILogger<WorkOrderController> _logger;
|
||||||
|
|
||||||
public WorkOrderController(
|
public WorkOrderController(
|
||||||
IWorkOrderService workOrderService,
|
IWorkOrderService workOrderService,
|
||||||
IWorkOrderDispatchService dispatchService)
|
IWorkOrderDispatchService dispatchService,
|
||||||
|
ILogger<WorkOrderController> logger)
|
||||||
{
|
{
|
||||||
_workOrderService = workOrderService;
|
_workOrderService = workOrderService;
|
||||||
_dispatchService = dispatchService;
|
_dispatchService = dispatchService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
@ -60,7 +65,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,7 +112,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,7 +154,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +243,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,7 +262,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,7 +286,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,7 +309,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,7 +370,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,7 +415,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -436,7 +441,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -458,7 +463,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -484,11 +489,11 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The dispatch signoff could not be added") });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
27
Api.SeaHavenIndustries/Helper/SanitizedErrors.cs
Normal file
27
Api.SeaHavenIndustries/Helper/SanitizedErrors.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Api.SeaHavenIndustries.Helper;
|
||||||
|
|
||||||
|
internal static class SanitizedErrors
|
||||||
|
{
|
||||||
|
private const string DefaultPublicMessage = "An unexpected error occurred";
|
||||||
|
|
||||||
|
public static string Sanitize(
|
||||||
|
this ILogger logger,
|
||||||
|
Exception exception,
|
||||||
|
string? publicMessage = null,
|
||||||
|
[CallerMemberName] string operation = "")
|
||||||
|
{
|
||||||
|
var correlationId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
logger.LogError(
|
||||||
|
exception,
|
||||||
|
"Unhandled exception in {Operation}. CorrelationId: {CorrelationId}",
|
||||||
|
operation,
|
||||||
|
correlationId);
|
||||||
|
|
||||||
|
return $"{publicMessage ?? DefaultPublicMessage} (reference {correlationId}).";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue