From 5f92998663b6cb325758160c2647d345ec8b837b Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:43:20 -0400 Subject: [PATCH] Feature: Google OAuth2 --- src/Application/Users/Commands/CreateUser.cs | 2 - src/Infrastructure/Services/UserService.cs | 45 ++++++++++++-------- src/Web/Program.cs | 2 + src/Web/wwwroot/api/specification.json | 42 ++++++++++++++++++ 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 8992f01..e15cc1b 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -1,8 +1,6 @@ using System.Dynamic; using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; using Hutopy.Domain.Interfaces; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Application.Users.Commands; public record CreateUserCommand : IRequest diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 169c5f3..767a1c4 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,4 +1,6 @@ -using Google.Apis.Oauth2.v2.Data; +using System.Security.Cryptography; +using System.Text; +using Google.Apis.Oauth2.v2.Data; using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; @@ -8,6 +10,8 @@ namespace Hutopy.Infrastructure.Services; public class UserService(UserManager userManager) : IUserService { + private readonly Random _random = new(DateTime.Now.Millisecond); + public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser @@ -22,26 +26,13 @@ public class UserService(UserManager userManager) : IUserServic if (!response.Succeeded) { - throw new Exception("Failed to create user"); + throw new Exception("Failed to create user", new AggregateException(response.Errors.Select(e => new Exception(e.Description)))); } } public async Task CreateUserAsync(Userinfo userInfo) { - var applicationUser = new ApplicationUser - { - UserName = userInfo.Name, - Email = userInfo.Email, - FirstName = userInfo.GivenName, - LastName = userInfo.FamilyName - }; - - var response = await userManager.CreateAsync(applicationUser, Guid.NewGuid().ToString("N")[..32]); - - if (!response.Succeeded) - { - throw new Exception("Failed to create user"); - } + await CreateUserAsync(userInfo.Email, userInfo.GivenName, userInfo.GivenName, userInfo.FamilyName, GeneratePassword(24)); } public async Task FindUserByIdAsync(string id) @@ -50,7 +41,7 @@ public class UserService(UserManager userManager) : IUserServic if (response == null) return null; - var userModel = new UserModel() + var userModel = new UserModel { Id = response.Id, UserName = response.UserName, @@ -68,7 +59,7 @@ public class UserService(UserManager userManager) : IUserServic if (response == null) return null; - var userModel = new UserModel() + var userModel = new UserModel { Id = response.Id, UserName = response.UserName, @@ -79,5 +70,23 @@ public class UserService(UserManager userManager) : IUserServic return userModel; } + + private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private const string SpecialCharacters = "!@#$%^&*()_+"; + + private String GeneratePassword(int length) + { + // Using a string builder has additional overhead, maybe we can find something else + var password = new StringBuilder(); + + for (var i = 0; i < length; i++) + { + password.Append(Characters[_random.Next(Characters.Length)]); + } + + password.Append(SpecialCharacters[_random.Next(SpecialCharacters.Length)]); + + return password.ToString(); + } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index b2b34db..76fb1d8 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,4 +1,5 @@ using Hutopy.Application; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; @@ -48,6 +49,7 @@ builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); builder.Services.AddScoped(); +builder.Services.AddScoped(); var app = builder.Build(); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 944608b..fc53d77 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,6 +6,39 @@ "version": "1.0.0" }, "paths": { + "/api/Google": { + "post": { + "tags": [ + "Google" + ], + "operationId": "CreateGoogleUser", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGoogleUserCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "guid" + } + } + } + } + } + } + }, "/api/JoinUs": { "get": { "tags": [ @@ -559,6 +592,15 @@ }, "components": { "schemas": { + "CreateGoogleUserCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "accessToken": { + "type": "string" + } + } + }, "PaginatedListOfFutureCreatorListDto": { "type": "object", "additionalProperties": false,