Example #1
0
        private async Task <RangeValue> HandleConflictsAsync(IAsyncDatabaseCommands databaseCommands,
                                                             ConflictException e, long minNextMax, long calculatedCapacity)
        {
            // resolving the conflict by selecting the highest number
            long highestMax = -1;

            if (e.ConflictedVersionIds.Length == 0)
            {
                throw new InvalidOperationException("Got conflict exception, but no conflicted versions", e);
            }
            foreach (var conflictedVersionId in e.ConflictedVersionIds)
            {
                var doc = await databaseCommands.GetAsync(conflictedVersionId).ConfigureAwait(false);

                highestMax = Math.Max(highestMax, GetMaxFromDocument(doc, minNextMax, calculatedCapacity));
            }

            await PutDocumentAsync(databaseCommands, new JsonDocument
            {
                Etag       = e.Etag,
                Metadata   = new RavenJObject(),
                DataAsJson = RavenJObject.FromObject(new { Max = highestMax }),
                Key        = HiLoDocumentKey
            }).ConfigureAwait(false);

            return(await GetNextRangeAsync(databaseCommands).ConfigureAwait(false));
        }
        public async Task ExecuteInternal_ArtifactIsDeleted_ThrowsConflictException()
        {
            // Arrange
            ConflictException conflictException = null;

            _artifactVersionsRepository.Setup(t => t.IsItemDeleted(ArtifactId))
            .ReturnsAsync(true);

            _artifactVersionsRepository.Setup(t => t.GetVersionControlArtifactInfoAsync(It.IsAny <int>(), It.IsAny <int?>(), It.IsAny <int>()))
            .ReturnsAsync(new VersionControlArtifactInfo()
            {
                Id = ArtifactId
            });

            // Act
            try
            {
                await _stateChangeExecutor.Execute();
            }
            catch (ConflictException ex)
            {
                conflictException = ex;
            }

            // Assert
            Assert.IsNotNull(conflictException);
            Assert.AreEqual(ErrorCodes.Conflict, conflictException.ErrorCode);
        }
        public void CreateAthlete_CallsRepositoryAndThrowsException()
        {
            var input = new AthleteRequest
            {
                Username = "******",
                Email    = "*****@*****.**",
                FullName = "User Two"
            };
            var expected = new ConflictException(
                new List <string>()
            {
                ErrorConstants.UsernameAlreadyExists
            });

            var convertedDto = new AthleteDto
            {
                Username = "******",
                Email    = "*****@*****.**",
                FullName = "User Two"
            };

            mockAthleteRepository.Setup(repo => repo.AddAthlete(convertedDto))
            .Throws(expected);

            // act
            var actual = Assert.Throws <ConflictException>(
                () => athleteService.CreateAthlete(input)
                );

            // assert
            Assert.Equal(expected.Messages, actual.Messages);
            mockAthleteRepository.Verify(repo => repo.AddAthlete(convertedDto), Times.Once);
            mockAthleteRepository.VerifyNoOtherCalls();
        }
Example #4
0
        /// <summary>
        /// Invoke.
        /// </summary>
        /// <param name="context">Http context.</param>
        public async Task Invoke(HttpContext context)
        {
            context = context ?? throw new ArgumentNullException(nameof(context));

            try
            {
                await _next(context);
            }
            catch (Exception error)
            {
                Log.Error(error, error.Message);

                var response = context.Response;
                response.ContentType = "application/json";
                response.StatusCode  = error switch
                {
                    AppException _ => StatusCodes.Status400BadRequest,
                    NotFoundException _ => StatusCodes.Status404NotFound,
                    ConflictException _ => StatusCodes.Status409Conflict,
                                 _ => StatusCodes.Status500InternalServerError,
                };

                var result = JsonSerializer.Serialize(new { message = error?.Message });
                await response.WriteAsync(result);
            }
        }
        public async Task ExecuteInternal_LockedByAnotherUser_ThrowsConflictException()
        {
            // Arrange
            ConflictException conflictException = null;

            _artifactVersionsRepository.Setup(t => t.IsItemDeleted(ArtifactId))
            .ReturnsAsync(false);

            var vcArtifactInfo = new VersionControlArtifactInfo
            {
                Id           = ArtifactId,
                VersionCount = CurrentVersionId,
                LockedByUser = new UserGroup
                {
                    Id = UserId + 10
                }
            };

            _artifactVersionsRepository.Setup(t => t.GetVersionControlArtifactInfoAsync(ArtifactId, null, UserId))
            .ReturnsAsync(vcArtifactInfo);

            // Act
            try
            {
                await _stateChangeExecutor.Execute();
            }
            catch (ConflictException ex)
            {
                conflictException = ex;
            }

            // Assert
            Assert.IsNotNull(conflictException);
            Assert.AreEqual(ErrorCodes.Conflict, conflictException.ErrorCode);
        }
Example #6
0
    /// <summary>
    /// Returns all <see cref="ConflictData"/>s for a set of new <see cref="AccessPoint"/> candidates.
    /// </summary>
    /// <param name="accessPoints">The set of <see cref="AccessPoint"/>s candidates to build the list for.</param>
    /// <param name="appEntry">The <see cref="AppEntry"/> the <paramref name="accessPoints"/> are intended for.</param>
    /// <returns>A dictionary of <see cref="AccessPoint.GetConflictIDs"/> mapping to the according <see cref="ConflictData"/>.</returns>
    /// <exception cref="ConflictException">There are inner conflicts within <paramref name="accessPoints"/>.</exception>
    /// <seealso cref="AccessPoint.GetConflictIDs"/>
    public static IDictionary <string, ConflictData> GetConflictData(this IEnumerable <AccessPoint> accessPoints, AppEntry appEntry)
    {
        #region Sanity checks
        if (accessPoints == null)
        {
            throw new ArgumentNullException(nameof(accessPoints));
        }
        if (appEntry == null)
        {
            throw new ArgumentNullException(nameof(appEntry));
        }
        #endregion

        var newConflictIDs = new Dictionary <string, ConflictData>();
        foreach (var accessPoint in accessPoints)
        {
            foreach (string conflictID in accessPoint.GetConflictIDs(appEntry))
            {
                var conflictData = new ConflictData(accessPoint, appEntry);
                try
                {
                    newConflictIDs.Add(conflictID, conflictData);
                }
                #region Error handling
                catch (ArgumentException)
                {
                    throw ConflictException.InnerConflict(conflictData, newConflictIDs[conflictID]);
                }
                #endregion
            }
        }
        return(newConflictIDs);
    }
Example #7
0
    /// <summary>
    /// Checks new <see cref="AccessPoint"/> candidates for conflicts with existing ones.
    /// </summary>
    /// <param name="appList">The <see cref="AppList"/> containing the existing <see cref="AccessPoint"/>s.</param>
    /// <param name="accessPoints">The set of <see cref="AccessPoint"/>s candidates to check.</param>
    /// <param name="appEntry">The <see cref="AppEntry"/> the <paramref name="accessPoints"/> are intended for.</param>
    /// <exception cref="KeyNotFoundException">An <see cref="AccessPoint"/> reference to a <see cref="Capability"/> is invalid.</exception>
    /// <exception cref="ConflictException">One or more of the <paramref name="accessPoints"/> would cause a conflict with the existing <see cref="AccessPoint"/>s in <see cref="AppList"/>.</exception>
    public static void CheckForConflicts(this AppList appList, [InstantHandle] IEnumerable <AccessPoint> accessPoints, AppEntry appEntry)
    {
        #region Sanity checks
        if (appList == null)
        {
            throw new ArgumentNullException(nameof(appList));
        }
        if (accessPoints == null)
        {
            throw new ArgumentNullException(nameof(accessPoints));
        }
        if (appEntry == null)
        {
            throw new ArgumentNullException(nameof(appEntry));
        }
        #endregion

        var newConflictData      = accessPoints.GetConflictData(appEntry);
        var existingConflictData = appList.Entries.GetConflictData();

        foreach ((string conflictId, var newEntry) in newConflictData)
        {
            if (existingConflictData.TryGetValue(conflictId, out var existingEntry))
            {
                // Ignore conflicts that are actually just re-applications of existing access points
                if (existingEntry != newEntry)
                {
                    throw ConflictException.NewConflict(existingEntry, newEntry);
                }
            }
        }
    }
        public void AddAthlete_ThrowsConflictAthleteAndEmail()
        {
            var input = new AthleteDto
            {
                Username = "******",
                Email    = "*****@*****.**",
                FullName = "User Three"
            };
            var expected = new ConflictException(
                new List <string>()
            {
                ErrorConstants.UsernameAlreadyExists,
                ErrorConstants.EmailAlreadyExists
            });

            var existingEntity = new AthleteEntity
            {
                Username = "******",
                Email    = "*****@*****.**",
                FullName = "User Three Other"
            };

            testContext.Add(existingEntity);
            testContext.SaveChanges();

            // act
            var actual = Assert.Throws <ConflictException>(
                () => athleteRepository.AddAthlete(input));

            // assert
            Assert.Equal(expected.Message, actual.Message);
        }
Example #9
0
 public static ErrorResponse ToErrorResponse(this ConflictException e)
 {
     return(new ErrorResponse()
     {
         Code = e.Code,
         Message = e.Message
     });
 }
Example #10
0
        private async Task <RangeValue> GetNextMaxAsyncInner(IAsyncDatabaseCommands databaseCommands)
        {
            var minNextMax = Range.Max;

            using (databaseCommands.ForceReadFromMaster())
                while (true)
                {
                    try
                    {
                        ConflictException ce = null;
                        JsonDocument      document;
                        try
                        {
                            document = await GetDocumentAsync(databaseCommands).ConfigureAwait(false);
                        }
                        catch (ConflictException e)
                        {
                            ce       = e;
                            document = null;
                        }
                        if (ce != null)
                        {
                            return(await HandleConflictsAsync(databaseCommands, ce, minNextMax).ConfigureAwait(false));
                        }

                        long min, max;
                        if (document == null)
                        {
                            min      = minNextMax + 1;
                            max      = minNextMax + capacity;
                            document = new JsonDocument
                            {
                                Etag = Etag.Empty,
                                // sending empty etag means - ensure the that the document does NOT exists
                                Metadata   = new RavenJObject(),
                                DataAsJson = RavenJObject.FromObject(new { Max = max }),
                                Key        = HiLoDocumentKey
                            };
                        }
                        else
                        {
                            var oldMax = GetMaxFromDocument(document, minNextMax);
                            min = oldMax + 1;
                            max = oldMax + capacity;

                            document.DataAsJson["Max"] = max;
                        }

                        await PutDocumentAsync(databaseCommands, document).ConfigureAwait(false);

                        return(new RangeValue(min, max));
                    }
                    catch (ConcurrencyException)
                    {
                        //expected & ignored, will retry this
                    }
                }
        }
        public void Constructor_Success_IfMessageValid()
        {
            var ex = new ConflictException("Unexpected conflict error");

            Assert.NotNull(ex);
            Assert.Null(ex.ErrorCode);
            Assert.Null(ex.InnerException);
            Assert.Equal("Unexpected conflict error", ex.Message);
        }
        public void Constructor_Success_IfMessageErrorCodeAndInnerExceptionValid()
        {
            var ex = new ConflictException("Unexpected conflict error", "5000", new Exception("Error Test"));

            Assert.NotNull(ex);
            Assert.NotNull(ex.InnerException);
            Assert.Equal("5000", ex.ErrorCode);
            Assert.Equal("5000 - Unexpected conflict error: Error Test", ex.Message);
        }
Example #13
0
 static HttpStatusCode GetStatusCode(Exception exception)
 {
     return(exception switch
     {
         ConflictException _ => HttpStatusCode.Conflict,
         NotFoundException _ => HttpStatusCode.NotFound,
         UnauthorizedAccessException _ => HttpStatusCode.Unauthorized,
         AlertManagerUpdateException _ => HttpStatusCode.BadRequest,
         _ => HttpStatusCode.InternalServerError
     });
Example #14
0
        private HttpResponseMessage HandleConflictEx(ConflictException ex)
        {
            var resp = new HttpResponseMessage(HttpStatusCode.Conflict)
            {
                Content      = new StringContent(ex.Message),
                ReasonPhrase = "conflict"
            };

            return(resp);
        }
Example #15
0
        public async Task <TResponse> Handle(
            TRequest request,
            CancellationToken cancellationToken,
            RequestHandlerDelegate <TResponse> next)
        {
            _logger.LogInformation("Request: {@Request}." + UserIdMessage(), request);

            _timer.Start();

            var       response          = default(TResponse);
            Exception responseException = null;

            try
            {
                response = await next();
            }
            catch (AppException exception)
            {
                _logger.LogError("Request {Status}: {Message}." + UserIdMessage(), exception.Status, exception.Message);
                responseException = exception;
            }
            catch (DomainException exception)
            {
                _logger.LogError("Domain Exception: {Message}." + UserIdMessage(), exception.Message);
                responseException = exception;
            }
            catch (DbUpdateConcurrencyException)
            {
                _logger.LogError("Request Concurrency Exception: {@Request}." + UserIdMessage(), request);
                responseException =
                    new ConflictException("Data have been modified since entities were loaded.");
            }
            catch (Exception exception)
            {
                _logger.LogCritical(exception, "Unexpected Server Exception." + UserIdMessage());
                responseException = new InternalServerErrorException();
            }

            _timer.Stop();

            if (_timer.ElapsedMilliseconds > 2000)
            {
                _logger.LogWarning(
                    "Request Performance Issue: {@Request} ({ElapsedMilliseconds} milliseconds)." + UserIdMessage(),
                    request,
                    _timer.ElapsedMilliseconds);
            }

            if (responseException != null)
            {
                throw responseException;
            }

            return(response);
        }
Example #16
0
 private HttpError HandleException(HttpContext context, Exception ex)
 {
     return(ex switch
     {
         NotFoundException e => new HttpError(context, HttpStatusCode.NotFound, new Error(e.Error.Code, e.Error.Message)),
         UnauthorizedException e => new HttpError(context, HttpStatusCode.Unauthorized, new Error(e.Error.Code, e.Error.Message)),
         PermissionException e => new HttpError(context, HttpStatusCode.Forbidden, new Error(e.Error.Code, e.Error.Message)),
         ValidationException e => new HttpError(context, HttpStatusCode.BadRequest, new Error(e.Error.Code, e.Error.Message)).SetErrors(e.Errors),
         ConflictException e => new HttpError(context, HttpStatusCode.Conflict, new Error(e.Error.Code, e.Error.Message)),
         _ => new HttpError(context, HttpStatusCode.InternalServerError, new Error("internal", "Internal error server."))
     });
Example #17
0
        public static FulcrumException ToFulcrumException(FulcrumError error)
        {
            if (error == null)
            {
                return(null);
            }
            FulcrumException exception;

            switch (error.TypeId)
            {
            case BusinessRuleException.ExceptionTypeId:
                exception = new BusinessRuleException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case ConflictException.ExceptionTypeId:
                exception = new ConflictException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case ServerContractException.ExceptionTypeId:
                exception = new ServerContractException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case NotFoundException.ExceptionTypeId:
                exception = new NotFoundException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case UnauthorizedException.ExceptionTypeId:
                exception = new UnauthorizedException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case AssertionFailedException.ExceptionTypeId:
                exception = new AssertionFailedException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case NotImplementedException.ExceptionTypeId:
                exception = new NotImplementedException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            case TryAgainException.ExceptionTypeId:
                exception = new TryAgainException(error.TechnicalMessage, ToFulcrumException(error.InnerError));
                break;

            default:
                exception = null;
                break;
            }
            if (exception == null)
            {
                var message = $"The TypeId ({error.TypeId}) was not recognized: {error.ToJsonString(Formatting.Indented)}";
                return(new AssertionFailedException(message, ToFulcrumException(error.InnerError)));
            }
            exception.CopyFrom(error);
            return(exception);
        }
        private Ticket GetTicketWithExceptions(string ticketId, ExpectedResultEnum expectedFacadeResult)
        {
            FulcrumException fulcrumException = null;

            switch (expectedFacadeResult)
            {
            case ExpectedResultEnum.Ok:
                return(new Ticket
                {
                    Id = ticketId
                });

            case ExpectedResultEnum.BusinessRuleException:
                fulcrumException = new BusinessRuleException("Business rule exception");
                break;

            case ExpectedResultEnum.ConflictException:
                fulcrumException = new ConflictException("Conflict exception");
                break;

            case ExpectedResultEnum.ServerContractException:
                fulcrumException = new ServerContractException("Contract exception");
                break;

            case ExpectedResultEnum.NotFoundException:
                fulcrumException = new NotFoundException("Not found exception");
                break;

            case ExpectedResultEnum.UnauthorizedException:
                fulcrumException = new UnauthorizedException("Unauthorized exception");
                break;

            case ExpectedResultEnum.AssertionFailedException:
                fulcrumException = new AssertionFailedException("Assertion failed exception");
                break;

            case ExpectedResultEnum.NotImplementedException:
                fulcrumException = new NotImplementedException("Not implemented exception");
                break;

            case ExpectedResultEnum.TryAgainException:
                fulcrumException = new TryAgainException("Try again exception");
                break;

            default:
                fulcrumException = new AssertionFailedException($"Unexpected switch value: {expectedFacadeResult}");
                break;
            }
            // This is to be able to test that the properties are copied all the way back to the test case.
            fulcrumException.Code = fulcrumException.InstanceId;
            throw fulcrumException;
        }
        public async Task ExecuteInternal_NoTransitionAvailableForStates_ThrowsConflictException()
        {
            // Arrange
            ConflictException conflictException = null;

            _artifactVersionsRepository.Setup(t => t.IsItemDeleted(ArtifactId))
            .ReturnsAsync(false);

            var vcArtifactInfo = new VersionControlArtifactInfo
            {
                Id           = ArtifactId,
                VersionCount = CurrentVersionId,
                LockedByUser = new UserGroup
                {
                    Id = UserId
                }
            };

            _artifactVersionsRepository.Setup(t => t.GetVersionControlArtifactInfoAsync(ArtifactId, null, UserId))
            .ReturnsAsync(vcArtifactInfo);

            var fromState = new WorkflowState
            {
                Id         = FromStateId,
                WorkflowId = WorkflowId,
                Name       = "Ready"
            };

            _workflowRepository.Setup(t => t.GetStateForArtifactAsync(UserId, ArtifactId, int.MaxValue, true))
            .ReturnsAsync(fromState);

            _workflowRepository.Setup(
                t => t.GetTransitionForAssociatedStatesAsync(UserId, ArtifactId, WorkflowId, FromStateId, ToStateId, TransitionId))
            .ReturnsAsync((WorkflowTransition)null);
            _workflowRepository.Setup(
                t => t.GetWorkflowEventTriggersForTransition(UserId, ArtifactId, WorkflowId, FromStateId, ToStateId, TransitionId))
            .ThrowsAsync(new ConflictException("", ErrorCodes.Conflict));

            // Act
            try
            {
                await _stateChangeExecutor.Execute();
            }
            catch (ConflictException ex)
            {
                conflictException = ex;
            }

            // Assert
            Assert.IsNotNull(conflictException);
            Assert.AreEqual(ErrorCodes.Conflict, conflictException.ErrorCode);
        }
Example #20
0
 public (HttpStatusCode, Problem) HandleException(Exception exception)
 {
     return(exception switch
     {
         WhoAreYouException ex => Handle(ex),
         AccessException ex => Handle(ex),
         NotFoundException ex => Handle(ex),
         ServiceAvailabilityException ex => Handle(ex),
         ValidationException ex => Handle(ex),
         SerializationException ex => Handle(ex),
         ConflictException ex => Handle(ex),
         _ => Handle(exception),
     });
Example #21
0
        protected IActionResult ExceptionResult(Exception ex)
        {
            // Do not retry if the quota is exceeded
            var noRetry = ex is QuotaExceededException;

            var err = new ErrorResponse(ex.Message, noRetry);

            return(ex switch
            {
                UnauthorizedException _ => Unauthorized(err),
                ConflictException _ => Conflict(err),
                NotFoundException _ => NotFound(err),
                _ => BadRequest(err)
            });
Example #22
0
        public void GetContextTest()
        {
            var result = new ConflictException();

            Assert.AreEqual(result.GetType().Name, "ConflictException");

            var result2 = new ConflictException("mensaje");

            Assert.AreEqual(result2.GetType().Name, "ConflictException");

            var result3 = new ConflictException("mensaje", new Exception());

            Assert.AreEqual(result3.GetType().Name, "ConflictException");
        }
Example #23
0
        public async Task Invoke_HandlesConflictExceptions()
        {
            // Arrange
            var exception = new ConflictException("conflict exception message");
            var sut       = new ErrorHandlingMiddleware(ctx => throw exception, _loggerFactory);

            // Act
            await sut.Invoke(_httpContext);

            // Assert
            _httpResponse.Received(1).ContentType = "application/json";
            _httpResponse.Received(1).StatusCode  = (int)HttpStatusCode.Conflict;

            _bodyStream.Length.ShouldBeGreaterThan(0);
            AssertStreamContains(_bodyStream, exception.Message);
        }
        protected override async Task CheckNewItemIsUnique(BranchOffice value)
        {
            // does the Tenant already have a BranchOffice of the same name?
            if (await Repository.Query().AnyAsync(e => e.Id == value.Id))
            {
                throw ConflictException.IdConflict(nameof(BranchOffice), value.Id);
            }

            // does the Tenant already have a BranchOffice of the same name?
            if (await Repository.Query().AnyAsync(
                    e => e.Name == value.Name &&
                    e.TenantId == value.TenantId
                    ))
            {
                throw BadRequestException.NamedEntityExists(nameof(BranchOffice), value.Name);
            }
        }
Example #25
0
        protected override async Task CheckNewItemIsUnique(Position value)
        {
            // is there already a Position with the same id?
            if (await Repository.Query().AnyAsync(e => e.Id == value.Id))
            {
                throw ConflictException.IdConflict(nameof(Position), value.Id);
            }

            // does the Tenant already have a Position of the same name?
            if (await Repository.Query().AnyAsync(e =>
                                                  e.Name == value.Name &&
                                                  e.TenantId == value.TenantId
                                                  ))
            {
                throw BadRequestException.NamedEntityExists(nameof(Department), value.Name);
            }
        }
Example #26
0
        public Task GetErrorResponseAsync()
        {
            var context   = HttpContext.Features.Get <IExceptionHandlerFeature>();
            var exception = context.Error;

            _logger.LogError($"internal error: \r\n{exception}");

            Response.StatusCode = exception switch
            {
                NotSupportedException _ => StatusCodes.Status501NotImplemented,
                ConflictException _ => StatusCodes.Status400BadRequest,
                NotFoundException _ => StatusCodes.Status404NotFound,
                                      _ => Response.StatusCode
            };

            return(Task.CompletedTask);
        }
    }
        public static void ConfigureExceptionHandler(this IApplicationBuilder app)
        {
            app.UseExceptionHandler(appError =>
            {
                appError.Run(async context =>
                {
                    context.Response.ContentType = "application/json";

                    var contextFeature = context.Features.Get <IExceptionHandlerFeature>();
                    if (contextFeature != null)
                    {
                        if (contextFeature.Error is BadRequestException)
                        {
                            var exception = (BadRequestException)contextFeature.Error;
                            context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                            var response = new
                            {
                                context.Response.StatusCode,
                                exception.Message
                            };
                            await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
                            return;
                        }
                        if (contextFeature.Error is NotFoundException)
                        {
                            var exception = (NotFoundException)contextFeature.Error;
                            context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                            var response = new
                            {
                                context.Response.StatusCode,
                                exception.Message
                            };
                            await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
                            return;
                        }

                        ConflictException serverError = new ConflictException("INTERNAL ERROR");
                        context.Response.StatusCode   = (int)HttpStatusCode.Conflict;
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(serverError));
                    }
                });
            });
        }
Example #28
0
        public void OnException(ExceptionContext context)
        {
            if (context == null)
            {
                return;
            }

            var exception = context.Exception;

            _logger.LogError(exception.Message);

            var statusCode = exception switch
            {
                ArgumentNullException _ => StatusCodes.Status400BadRequest,
                ArgumentOutOfRangeException _ => StatusCodes.Status400BadRequest,
                ArgumentException _ => StatusCodes.Status400BadRequest,
                BadRequestException _ => StatusCodes.Status400BadRequest,
                NotFoundException _ => StatusCodes.Status404NotFound,
                ConflictException _ => StatusCodes.Status409Conflict,
                _ => StatusCodes.Status500InternalServerError
            };

            var response = context.HttpContext.Response;

            response.StatusCode  = statusCode;
            response.ContentType = "application/json";

            var errorDetails = new ErrorDetails
            {
                Message    = exception.Message,
                StatusCode = statusCode
            };

            var json = JsonSerializer.Serialize <ErrorDetails>(errorDetails, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented        = true
            });

            response.WriteAsync(json);
        }
    }
        private static Task HandleExceptionAsync(HttpContext context, System.Exception exception)
        {
            var serializedError = string.Empty;

            var code = exception switch
            {
                NotFoundException _ => HttpStatusCode.NotFound,
                InvalidCredentialsException _ => HttpStatusCode.Unauthorized,
                ConflictException _ => HttpStatusCode.Conflict,
                _ => throw exception,
            };

            if (string.IsNullOrEmpty(serializedError))
            {
                serializedError = JsonConvert.SerializeObject(new { error = exception.Message });
            }

            context.Response.ContentType = "application/json";
            context.Response.StatusCode  = (int)code;
            return(context.Response.WriteAsync(serializedError));
        }
        protected override async Task CheckNewItemIsUnique(Employee value)
        {
            // is there already an Employee entity with the same id?
            if (await Repository.Query().AnyAsync(e => e.Id == value.Id))
            {
                throw ConflictException.IdConflict(nameof(Employee), value.Id);
            }

            // does the Department already have an Employee of the same name?
            if (await Repository.Query().AnyAsync(e =>
                                                  e.FirstName == value.FirstName &&
                                                  e.LastName == value.LastName &&
                                                  e.Patronymic == value.Patronymic &&
                                                  e.BranchOfficeId == value.BranchOfficeId &&
                                                  e.DepartmentId == value.DepartmentId &&
                                                  e.ExternalId == value.ExternalId &&
                                                  e.TenantId == value.TenantId))
            {
                throw BadRequestException.NamedEntityExists(nameof(Employee), value.FullName);
            }
        }