Skip to content

Commit

Permalink
Merge pull request #27 from MrDave1999/feat/forbidden-result
Browse files Browse the repository at this point in the history
* feat: Add a new result called Forbidden

* feat: Add a object result called ForbiddenResult
  • Loading branch information
MrDave1999 authored Oct 24, 2023
2 parents 5a446f7 + 3cb32df commit c5a26dc
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ The following table is used as a reference to know which type of result correspo
| Result.Conflict | 409 - Conflict |
| Result.Failure | 422 - Unprocessable Entity |
| Result.CriticalError | 500 - Internal Server Error |
| Result.Forbidden | 403 - Forbidden |

### Integration with Fluent Validation

Expand Down
9 changes: 9 additions & 0 deletions src/AspNetCore/ForbiddenResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace SimpleResults;

internal class ForbiddenResult : ObjectResult
{
public ForbiddenResult(object value) : base(value)
{
StatusCode = StatusCodes.Status403Forbidden;
}
}
1 change: 1 addition & 0 deletions src/AspNetCore/ResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public static ActionResult<Result> ToActionResult(this Result result)
ResultStatus.Conflict => new ConflictObjectResult(result),
ResultStatus.Failure => new UnprocessableContentResult(result),
ResultStatus.CriticalError => new InternalServerErrorResult(result),
ResultStatus.Forbidden => new ForbiddenResult(result),
_ => throw new NotSupportedException($"Result {result.Status} conversion is not supported.")
};
}
9 changes: 9 additions & 0 deletions src/Core/Resources/ResponseMessages.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Core/Resources/ResponseMessages.es.resx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@
<data name="Failure" xml:space="preserve">
<value>Se ha producido un error durante la ejecución de un servicio</value>
</data>
<data name="Forbidden" xml:space="preserve">
<value>No tienes permisos para realizar esta acción</value>
</data>
<data name="Invalid" xml:space="preserve">
<value>Ocurrió un error de validación de datos</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions src/Core/Resources/ResponseMessages.resx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@
<data name="Failure" xml:space="preserve">
<value>An error occurred during the execution of a service</value>
</data>
<data name="Forbidden" xml:space="preserve">
<value>You do not have permissions to perform this action</value>
</data>
<data name="Invalid" xml:space="preserve">
<value>A data validation error occurred</value>
</data>
Expand Down
26 changes: 26 additions & 0 deletions src/Core/Result.Errors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,30 @@ public static Result CriticalError(IEnumerable<string> errors)
Status = ResultStatus.CriticalError,
Errors = errors
};

/// <inheritdoc cref="Forbidden(string)" />
public static Result Forbidden()
=> Forbidden(ResponseMessages.Forbidden);

/// <param name="message">An error message.</param>
/// <inheritdoc cref="Forbidden(string, IEnumerable{string})" />
public static Result Forbidden(string message)
=> Forbidden(message, Enumerable.Empty<string>());

/// <inheritdoc cref="Forbidden(string, IEnumerable{string})" />
public static Result Forbidden(IEnumerable<string> errors)
=> Forbidden(string.Empty, errors);

/// <summary>
/// Represents a situation where the user does not have permission to perform some action.
/// </summary>
/// <param name="message">A general description of the error.</param>
/// <param name="errors">A collection of errors.</param>
public static Result Forbidden(string message, IEnumerable<string> errors) => new()
{
IsSuccess = false,
Message = message,
Status = ResultStatus.Forbidden,
Errors = errors
};
}
3 changes: 2 additions & 1 deletion src/Core/ResultStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public enum ResultStatus
Unauthorized,
Conflict,
Failure,
CriticalError
CriticalError,
Forbidden
}
22 changes: 22 additions & 0 deletions tests/ResultExtensionsTests.Errors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,26 @@ public void ToActionResult_WhenOperationResultIsCriticalError_ShouldReturnsInter
actualValue.Data.Should().BeNull();
actualValue.Status.Should().Be(ResultStatus.CriticalError);
}

[Test]
public void ToActionResult_WhenOperationResultIsForbidden_ShouldReturnsForbiddenResult()
{
// Arrange
int expectedHttpCode = 403;
Result<Person> result = Result.Forbidden();

// Act
ActionResult<Result<Person>> actionResult = result.ToActionResult();
var contentResult = actionResult.Result as ForbiddenResult;
var actualValue = (Result<Person>)contentResult.Value;

// Asserts
contentResult.StatusCode.Should().Be(expectedHttpCode);
actualValue.IsSuccess.Should().BeFalse();
actualValue.IsFailed.Should().BeTrue();
actualValue.Message.Should().Be(ResponseMessages.Forbidden);
actualValue.Errors.Should().BeEmpty();
actualValue.Data.Should().BeNull();
actualValue.Status.Should().Be(ResultStatus.Forbidden);
}
}
18 changes: 18 additions & 0 deletions tests/ResultTests.Errors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,23 @@ public void CriticalError_WhenResultIsCriticalError_ShouldReturnsResultObject()
actual.Message.Should().Be(expectedMessage);
actual.Errors.Should().BeEquivalentTo(expectedErrors);
actual.Status.Should().Be(ResultStatus.CriticalError);
}

[Test]
public void Forbidden_WhenResultIsForbidden_ShouldReturnsResultObject()
{
// Arrange
var expectedMessage = "Forbidden";
var expectedErrors = new[] { "error" };

// Act
Result actual = Result.Forbidden(expectedMessage, expectedErrors);

// Asserts
actual.IsSuccess.Should().BeFalse();
actual.IsFailed.Should().BeTrue();
actual.Message.Should().Be(expectedMessage);
actual.Errors.Should().BeEquivalentTo(expectedErrors);
actual.Status.Should().Be(ResultStatus.Forbidden);
}
}

0 comments on commit c5a26dc

Please sign in to comment.