Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
neozhu committed Dec 20, 2024
1 parent f51a414 commit 2e38bab
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 30 deletions.
30 changes: 15 additions & 15 deletions src/CleanAspire.Api/IdentityApiAdditionalEndpointsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi
var routeGroup = endpoints.MapGroup("/account").WithTags("Authentication", "Account Management");
routeGroup.MapPost("/logout", async (SignInManager<TUser> signInManager) =>
{
await signInManager.SignOutAsync();
await signInManager.SignOutAsync().ConfigureAwait(false);
logger.LogInformation("User has been logged out successfully.");
return Results.Ok();
})
Expand All @@ -52,9 +52,9 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi
.WithDescription("Logs out the currently authenticated user by signing them out of the system. This endpoint requires the user to be authorized before calling, and returns an HTTP 200 OK response upon successful logout.");

routeGroup.MapGet("/profile", async Task<Results<Ok<ProfileResponse>, ValidationProblem, NotFound>>
(ClaimsPrincipal claimsPrincipal, HttpContext context, IServiceProvider sp) =>
(ClaimsPrincipal claimsPrincipal, HttpContext context) =>
{
var userManager = sp.GetRequiredService<UserManager<TUser>>();
var userManager = context.RequestServices.GetRequiredService<UserManager<TUser>>();
if (await userManager.GetUserAsync(claimsPrincipal) is not { } user)
{
return TypedResults.NotFound();
Expand Down Expand Up @@ -113,9 +113,9 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi
.WithDescription("Allows users to update their profile, including username, email, nickname, avatar, time zone, and language code.");

routeGroup.MapPost("/updateEmail", async Task<Results<Ok, ValidationProblem, NotFound>>
(ClaimsPrincipal claimsPrincipal, [FromBody] UpdateEmailRequest request, HttpContext context, [FromServices] IServiceProvider sp) =>
(ClaimsPrincipal claimsPrincipal, [FromBody] UpdateEmailRequest request, HttpContext context) =>
{
var userManager = sp.GetRequiredService<UserManager<TUser>>();
var userManager = context.RequestServices.GetRequiredService<UserManager<TUser>>();
if (await userManager.GetUserAsync(claimsPrincipal) is not { } user)
{
return TypedResults.NotFound();
Expand Down Expand Up @@ -143,9 +143,9 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi


routeGroup.MapPost("/signup", async Task<Results<Created, ValidationProblem>>
([FromBody] SignupRequest request, HttpContext context, [FromServices] IServiceProvider sp) =>
([FromBody] SignupRequest request, HttpContext context) =>
{
var userManager = sp.GetRequiredService<UserManager<TUser>>();
var userManager = context.RequestServices.GetRequiredService<UserManager<TUser>>();
var user = new TUser();
if (!userManager.SupportsUserEmail)
{
Expand Down Expand Up @@ -174,9 +174,9 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi
.WithDescription("Allows a new user to sign up by providing required details such as email, password, and tenant-specific information. This endpoint creates a new user account and sends a confirmation email for verification.");

routeGroup.MapDelete("/deleteOwnerAccount", async Task<Results<Ok, ValidationProblem, NotFound>>
(ClaimsPrincipal claimsPrincipal, SignInManager<TUser> signInManager, [FromBody] DeleteUserRequest request, [FromServices] IServiceProvider sp) =>
(ClaimsPrincipal claimsPrincipal, SignInManager<TUser> signInManager, HttpContext context,[FromBody] DeleteUserRequest request) =>
{
var userManager = sp.GetRequiredService<UserManager<TUser>>();
var userManager = context.RequestServices.GetRequiredService<UserManager<TUser>>();
if (await userManager.GetUserAsync(claimsPrincipal) is not { } user)
{
return TypedResults.NotFound();
Expand Down Expand Up @@ -204,9 +204,9 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi
.WithDescription("Allows users to delete their own account permanently.");

routeGroup.MapGet("/confirmEmail", async Task<Results<ContentHttpResult, UnauthorizedHttpResult>>
([FromQuery] string userId, [FromQuery] string code, [FromQuery] string? changedEmail, [FromServices] IServiceProvider sp) =>
([FromQuery] string userId, [FromQuery] string code, [FromQuery] string? changedEmail, HttpContext context) =>
{
var userManager = sp.GetRequiredService<UserManager<TUser>>();
var userManager = context.RequestServices.GetRequiredService<UserManager<TUser>>();
if (await userManager.FindByIdAsync(userId) is not { } user)
{
return TypedResults.Unauthorized();
Expand Down Expand Up @@ -422,8 +422,8 @@ public static IEndpointRouteBuilder MapIdentityApiAdditionalEndpoints<TUser>(thi
}).Produces(StatusCodes.Status200OK)
.ProducesValidationProblem(StatusCodes.Status422UnprocessableEntity)
.ProducesProblem(StatusCodes.Status400BadRequest)
.WithSummary("")
.WithDescription("");
.WithSummary("External Login with Google OAuth")
.WithDescription("Handles external login using Google OAuth 2.0. Exchanges an authorization code for tokens, validates the user's identity, and signs the user in.");

async Task SendConfirmationEmailAsync(TUser user, UserManager<TUser> userManager, HttpContext context, string email, bool isChange = false)
{
Expand All @@ -449,15 +449,15 @@ async Task SendConfirmationEmailAsync(TUser user, UserManager<TUser> userManager
await emailSender.SendConfirmationLinkAsync(user, email, HtmlEncoder.Default.Encode(confirmEmailUrl));
}
routeGroup.MapPost("/forgotPassword", async Task<Results<Ok, ValidationProblem>>
(HttpContext context, [FromBody] ForgotPasswordRequest resetRequest, [FromServices] IServiceProvider sp) =>
(HttpContext context, [FromBody] ForgotPasswordRequest resetRequest) =>
{
var configuration = context.RequestServices.GetRequiredService<IConfiguration>();
var clientBaseUrl = configuration["ClientBaseUrl"];
if (string.IsNullOrEmpty(clientBaseUrl))
{
throw new InvalidOperationException("Client base URL is not configured.");
}
var userManager = sp.GetRequiredService<UserManager<TUser>>();
var userManager = context.RequestServices.GetRequiredService<UserManager<TUser>>();
var user = await userManager.FindByEmailAsync(resetRequest.Email);

if (user is not null && await userManager.IsEmailConfirmedAsync(user))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public SignInRequestBuilder(Dictionary<string, object> pathParameters, IRequestA
public SignInRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/account/google/signIn?code={code}&state={state}", rawUrl)
{
}
/// <summary>
/// Handles external login using Google OAuth 2.0. Exchanges an authorization code for tokens, validates the user&apos;s identity, and signs the user in.
/// </summary>
/// <returns>A <see cref="Stream"/></returns>
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
Expand All @@ -55,6 +58,9 @@ public async Task<Stream> PostAsync(Action<RequestConfiguration<global::CleanAsp
};
return await RequestAdapter.SendPrimitiveAsync<Stream>(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Handles external login using Google OAuth 2.0. Exchanges an authorization code for tokens, validates the user&apos;s identity, and signs the user in.
/// </summary>
/// <returns>A <see cref="RequestInformation"/></returns>
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
Expand All @@ -80,10 +86,11 @@ public RequestInformation ToPostRequestInformation(Action<RequestConfiguration<g
{
return new global::CleanAspire.Api.Client.Account.Google.SignIn.SignInRequestBuilder(rawUrl, RequestAdapter);
}
/// <summary>
/// Handles external login using Google OAuth 2.0. Exchanges an authorization code for tokens, validates the user&apos;s identity, and signs the user in.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
#pragma warning disable CS1591
public partial class SignInRequestBuilderPostQueryParameters
#pragma warning restore CS1591
{
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
Expand Down
38 changes: 25 additions & 13 deletions src/CleanAspire.ClientApp/Pages/Account/GoogleLoginCallback.razor
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
public string? State { get; set; }
public string? Error { get; set; }

protected override async Task OnInitializedAsync()
protected override void OnInitialized()
{
if (string.IsNullOrEmpty(AuthorizationCode))
{
Expand All @@ -55,21 +55,33 @@
return;
}

try
{
await SignInManagement.LoginWithGoogle(AuthorizationCode, State);
}
catch (ProblemDetails ex)
{
// Log and display API-specific problem details
Error = $"An error occurred during login: {ex.Detail ?? "Please contact support if the issue persists."}";
}
catch (Exception ex)

}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// Catch-all for other exceptions
Error = $"Unexpected error: {ex.Message}. Please refresh the page or contact support.";
if (!string.IsNullOrEmpty(AuthorizationCode) && !string.IsNullOrEmpty(State))
{
try
{
await SignInManagement.LoginWithGoogle(AuthorizationCode, State);
StateHasChanged();
}
catch (ProblemDetails ex)
{
// Log and display API-specific problem details
Error = $"An error occurred during login: {ex.Detail ?? "Please contact support if the issue persists."}";
}
catch (Exception ex)
{
// Catch-all for other exceptions
Error = $"Unexpected error: {ex.Message}. Please refresh the page or contact support.";
}
}
}
}

}


0 comments on commit 2e38bab

Please sign in to comment.