Skip to content

Commit

Permalink
Added action result to unauthorized exception
Browse files Browse the repository at this point in the history
  • Loading branch information
joaofx committed Mar 28, 2023
1 parent 401abe6 commit a0be419
Show file tree
Hide file tree
Showing 21 changed files with 202 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ public async Task<Result> Handle(Command request, CancellationToken ct)

var result = await _userLogin.LoginAsync(request.Email, request.Password, request.RememberMe);

if (result.Succeeded)
if (result.Result.Succeeded)
{
return new Result
{
RedirectTo = request.ReturnUrl,
SignInResult = result
SignInResult = result.Result
};
}

Expand Down
1 change: 0 additions & 1 deletion samples/MiruNext/src/MiruNext/Features/Orders/List.cshtml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

@model MiruNext.Features.Orders.OrderList.Result

<h3>Orders</h3>
Expand Down
8 changes: 7 additions & 1 deletion samples/MiruNext/src/MiruNext/Features/Orders/OrderList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ public override async Task HandleAsync(Query request, CancellationToken ct)
Orders = new[]
{
new Order { Id = 1, CreatedAt = 1.OfPreviousMonth() },
new Order { Id = 2, CreatedAt = 5.OfPreviousMonth() }
new Order { Id = 2, CreatedAt = 5.OfPreviousMonth() },
new Order { Id = 3, CreatedAt = 5.OfPreviousMonth() },
new Order { Id = 4, CreatedAt = 5.OfPreviousMonth() },
new Order { Id = 5, CreatedAt = 5.OfPreviousMonth() },
new Order { Id = 6, CreatedAt = 5.OfPreviousMonth() },
new Order { Id = 8, CreatedAt = 5.OfPreviousMonth() },
new Order { Id = 9, CreatedAt = 5.OfPreviousMonth() },
},
Page = request.Page,
Status = request.Status
Expand Down
137 changes: 68 additions & 69 deletions samples/Playground/src/Playground/Features/Accounts/AccountLogin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,96 +10,95 @@
using Playground.Domain;
using SignInResult = Microsoft.AspNetCore.Identity.SignInResult;

namespace Playground.Features.Accounts
namespace Playground.Features.Accounts;

public class AccountLogin
{
public class AccountLogin
public class Query : IRequest<Command>
{
public class Query : IRequest<Command>
{
public string ReturnUrl { get; set; }
}
public string ReturnUrl { get; set; }
}

public class Command : IRequest<Result>
{
public string Email { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
public class Command : IRequest<Result>
{
public string Email { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }

public string ReturnUrl { get; set; }
}
public string ReturnUrl { get; set; }
}

public class Result : IRedirect
public class Result : IRedirect
{
public SignInResult SignInResult { get; set; }
public object RedirectTo { get; set; }
}

public class Handler :
IRequestHandler<Query, Command>,
IRequestHandler<Command, Result>
{
private readonly IUserLogin<User> _userLogin;
private readonly IUserSession<User> _userSession;

public Handler(IUserLogin<User> userLogin, IUserSession<User> userSession)
{
public SignInResult SignInResult { get; set; }
public object RedirectTo { get; set; }
_userLogin = userLogin;
_userSession = userSession;
}

public class Handler :
IRequestHandler<Query, Command>,
IRequestHandler<Command, Result>

public async Task<Command> Handle(Query request, CancellationToken ct)
{
private readonly IUserLogin<User> _userLogin;
private readonly IUserSession<User> _userSession;
// TODO: get from UserfyOptions
request.ReturnUrl ??= "/";

public Handler(IUserLogin<User> userLogin, IUserSession<User> userSession)
// Clear the existing external cookie to ensure a clean login process
await _userSession.LogoutAsync();

return new Command
{
_userLogin = userLogin;
_userSession = userSession;
}
ReturnUrl = request.ReturnUrl,
RememberMe = true
};
}

public async Task<Command> Handle(Query request, CancellationToken ct)
{
// TODO: get from UserfyOptions
request.ReturnUrl ??= "/";
public async Task<Result> Handle(Command request, CancellationToken ct)
{
// TODO: get from UserfyOptions
request.ReturnUrl ??= "/";

// Clear the existing external cookie to ensure a clean login process
await _userSession.LogoutAsync();

return new Command
{
ReturnUrl = request.ReturnUrl,
RememberMe = true
};
}
var result = await _userLogin.LoginAsync(request.Email, request.Password, request.RememberMe);

public async Task<Result> Handle(Command request, CancellationToken ct)
if (result.Result.Succeeded)
{
// TODO: get from UserfyOptions
request.ReturnUrl ??= "/";

var result = await _userLogin.LoginAsync(request.Email, request.Password, request.RememberMe);

if (result.Succeeded)
return new Result
{
return new Result
{
RedirectTo = request.ReturnUrl,
SignInResult = result
};
}

// TODO: get message from UserfyOptions
throw new DomainException("User and password not found");
RedirectTo = request.ReturnUrl,
SignInResult = result.Result
};
}

// TODO: get message from UserfyOptions
throw new DomainException("User and password not found");
}
}

public class Validator : AbstractValidator<Command>
public class Validator : AbstractValidator<Command>
{
public Validator()
{
public Validator()
{
RuleFor(x => x.Email).NotEmpty().EmailAddress();
RuleFor(x => x.Email).NotEmpty().EmailAddress();

RuleFor(x => x.Password).NotEmpty();
}
RuleFor(x => x.Password).NotEmpty();
}
}

public class AccountsController : MiruController
{
[HttpGet("/Accounts/Login")]
public async Task<Command> Login(Query request) => await SendAsync(request);
public class AccountsController : MiruController
{
[HttpGet("/Accounts/Login")]
public async Task<Command> Login(Query request) => await SendAsync(request);

[HttpPost("/Accounts/Login")]
public async Task<Result> Login(Command request) => await SendAsync(request);
}
[HttpPost("/Accounts/Login")]
public async Task<Result> Login(Command request) => await SendAsync(request);
}
}
}
4 changes: 2 additions & 2 deletions src/Miru.Core/Templates/AccountLogin.stub
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ public class AccountLogin

var result = await _userLogin.LoginAsync(request.Email, request.Password, request.RememberMe);

if (result.Succeeded)
if (result.Result.Succeeded)
{
return new Result
{
RedirectTo = request.ReturnUrl,
SignInResult = result
SignInResult = result.Result
};
}

Expand Down
15 changes: 7 additions & 8 deletions src/Miru.Testing/DomainEventsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
using Miru.Domain;
using Shouldly;

namespace Miru.Testing
namespace Miru.Testing;

[ShouldlyMethods]
public static class DomainEventsShouldExtensions
{
[ShouldlyMethods]
public static class DomainEventsShouldExtensions
{
public static void ShouldPublishEvent<TEvent>(this EntityEventable entity)
where TEvent : class, IDomainEvent =>
public static void ShouldPublishEvent<TEvent>(this EntityEventable entity)
where TEvent : class, IDomainEvent =>
entity.DomainEvents
.OfType<TEvent>()
.SingleOrDefault()
.ShouldNotBeNull();
}
.ShouldNotBeNull($"Could not find event of type {typeof(TEvent).FullName}");
}
16 changes: 16 additions & 0 deletions src/Miru/Html/Tags/IfHasTagHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace Miru.Html.Tags;

[HtmlTargetElement("*", Attributes = "miru-if-has")]
public class IfHasTagHelper : TagHelper
{
[HtmlAttributeName("miru-if-has")]
public object Instance { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (Instance == null)
output.SuppressOutput();
}
}
3 changes: 1 addition & 2 deletions src/Miru/Mvc/UrlHelperExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ public static UrlBuilder<TRequest> Build<TRequest>(this IUrlHelper urlHelper) wh
var urlOptions = urlHelper.ActionContext.HttpContext.RequestServices.GetRequiredService<UrlOptions>();

var urlMaps = urlHelper.ActionContext.HttpContext.RequestServices.GetService<IUrlMaps>();
var urlPrefix = urlHelper.ActionContext.HttpContext.RequestServices.GetService<UrlPrefix>();

return new UrlBuilder<TRequest>(request, urlOptions, urlMaps, urlPrefix);
return new UrlBuilder<TRequest>(request, urlOptions, urlMaps);
}

public static string Full<TRequest>(this IUrlHelper urlHelper) where TRequest : class, new()
Expand Down
9 changes: 7 additions & 2 deletions src/Miru/Security/UnauthorizedException.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
using System;
using Microsoft.AspNetCore.Mvc;

namespace Miru.Security;

public class UnauthorizedException : Exception
{
public UnauthorizedException(string message = null) : base(message)
public ActionResult ActionResult { get; }

public UnauthorizedException(
string message = null,
ActionResult actionResult = null) : base(message)
{
ActionResult = actionResult;
}
}
1 change: 1 addition & 0 deletions src/Miru/Storages/LocalDiskStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public async Task PutAsync(MiruPath remote, Stream stream)
{
var fullRemoteDir = Path / remote;

// TODO: Parameter replaceIfExists
Files.DeleteIfExists(fullRemoteDir);

fullRemoteDir.Dir().EnsureDirExist();
Expand Down
8 changes: 1 addition & 7 deletions src/Miru/Urls/UrlBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,17 @@ public class UrlBuilder<TInput> where TInput : class
private readonly List<string> _withoutProperties = new();
private readonly List<KeyValuePair<string, object>> _withoutPropertyAndValues = new();
private readonly IUrlMaps _urlMaps;
private readonly UrlPrefix _urlPrefix;
private readonly UrlOptions _urlOptions;
private bool _acceptCommand;

public UrlBuilder(
TInput request,
UrlOptions urlOptions,
IUrlMaps urlMaps,
UrlPrefix urlPrefix)
IUrlMaps urlMaps)
{
Request = request;
_urlOptions = urlOptions;
_urlMaps = urlMaps;
_urlPrefix = urlPrefix;
}

public static implicit operator string(UrlBuilder<TInput> input)
Expand Down Expand Up @@ -101,9 +98,6 @@ public override string ToString()
return path.Substring(0, questionMarkPos);
}
}

if (_urlPrefix.Prefix.IsNotEmpty())
return $"/{_urlPrefix.Prefix}{path}";

return path;
}
Expand Down
17 changes: 7 additions & 10 deletions src/Miru/Urls/UrlLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,34 @@ namespace Miru.Urls;
public class UrlLookup
{
private readonly IUrlMaps _urlMaps;
private readonly UrlPrefix _urlPrefix;
private readonly UrlOptions _urlOptions;

public UrlLookup(
IOptions<UrlOptions> urlOptions,
IUrlMaps urlMaps,
UrlPrefix urlPrefix)
IUrlMaps urlMaps)
{
_urlOptions = urlOptions.Value;
_urlMaps = urlMaps;
_urlPrefix = urlPrefix;
}

public string For<TRequest>() where TRequest : class, new()
{
return new UrlBuilder<TRequest>(new TRequest(), _urlOptions, _urlMaps, _urlPrefix);
return new UrlBuilder<TRequest>(new TRequest(), _urlOptions, _urlMaps);
}

public string For<TRequest>(TRequest request) where TRequest : class
{
return new UrlBuilder<TRequest>(request, _urlOptions, _urlMaps, _urlPrefix);
return new UrlBuilder<TRequest>(request, _urlOptions, _urlMaps);
}

public UrlBuilder<TRequest> Build<TRequest>() where TRequest : class, new()
{
return new UrlBuilder<TRequest>(new TRequest(), _urlOptions, _urlMaps, _urlPrefix);
return new UrlBuilder<TRequest>(new TRequest(), _urlOptions, _urlMaps);
}

public UrlBuilder<TRequest> Build<TRequest>(TRequest request) where TRequest : class
{
return new UrlBuilder<TRequest>(request, _urlOptions, _urlMaps, _urlPrefix);
return new UrlBuilder<TRequest>(request, _urlOptions, _urlMaps);
}

public string FullFor<TRequest>() where TRequest : class, new()
Expand All @@ -43,7 +40,7 @@ public string FullFor<TRequest>() where TRequest : class, new()
if (baseUrl.EndsWith('/'))
baseUrl = baseUrl.Substring(0, baseUrl.Length - 1);

return $"{baseUrl}{new UrlBuilder<TRequest>(new TRequest(), _urlOptions, _urlMaps, _urlPrefix)}";
return $"{baseUrl}{new UrlBuilder<TRequest>(new TRequest(), _urlOptions, _urlMaps)}";
}

public string FullFor<TRequest>(TRequest request) where TRequest : class
Expand All @@ -53,6 +50,6 @@ public string FullFor<TRequest>() where TRequest : class, new()
if (baseUrl.NotEmpty() && baseUrl.EndsWith('/'))
baseUrl = baseUrl.Substring(0, baseUrl.Length - 1);

return $"{baseUrl}{new UrlBuilder<TRequest>(request, _urlOptions, _urlMaps, _urlPrefix)}";
return $"{baseUrl}{new UrlBuilder<TRequest>(request, _urlOptions, _urlMaps)}";
}
}

0 comments on commit a0be419

Please sign in to comment.