Feature: Google OAuth2

This commit is contained in:
Kamigen
2024-04-22 16:43:20 -04:00
parent e3d570722e
commit 5f92998663
4 changed files with 71 additions and 20 deletions

View File

@@ -1,8 +1,6 @@
using System.Dynamic; using System.Dynamic;
using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Interfaces;
using Hutopy.Domain.Entities;
using Hutopy.Domain.Interfaces; using Hutopy.Domain.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Application.Users.Commands; namespace Hutopy.Application.Users.Commands;
public record CreateUserCommand : IRequest<Guid> public record CreateUserCommand : IRequest<Guid>

View File

@@ -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.Interfaces;
using Hutopy.Domain.Models; using Hutopy.Domain.Models;
using Hutopy.Infrastructure.Identity; using Hutopy.Infrastructure.Identity;
@@ -8,6 +10,8 @@ namespace Hutopy.Infrastructure.Services;
public class UserService(UserManager<ApplicationUser> userManager) : IUserService public class UserService(UserManager<ApplicationUser> userManager) : IUserService
{ {
private readonly Random _random = new(DateTime.Now.Millisecond);
public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password)
{ {
var applicationUser = new ApplicationUser var applicationUser = new ApplicationUser
@@ -22,26 +26,13 @@ public class UserService(UserManager<ApplicationUser> userManager) : IUserServic
if (!response.Succeeded) 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) public async Task CreateUserAsync(Userinfo userInfo)
{ {
var applicationUser = new ApplicationUser await CreateUserAsync(userInfo.Email, userInfo.GivenName, userInfo.GivenName, userInfo.FamilyName, GeneratePassword(24));
{
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");
}
} }
public async Task<UserModel?> FindUserByIdAsync(string id) public async Task<UserModel?> FindUserByIdAsync(string id)
@@ -50,7 +41,7 @@ public class UserService(UserManager<ApplicationUser> userManager) : IUserServic
if (response == null) return null; if (response == null) return null;
var userModel = new UserModel() var userModel = new UserModel
{ {
Id = response.Id, Id = response.Id,
UserName = response.UserName, UserName = response.UserName,
@@ -68,7 +59,7 @@ public class UserService(UserManager<ApplicationUser> userManager) : IUserServic
if (response == null) return null; if (response == null) return null;
var userModel = new UserModel() var userModel = new UserModel
{ {
Id = response.Id, Id = response.Id,
UserName = response.UserName, UserName = response.UserName,
@@ -79,5 +70,23 @@ public class UserService(UserManager<ApplicationUser> userManager) : IUserServic
return userModel; 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();
}
} }

View File

@@ -1,4 +1,5 @@
using Hutopy.Application; using Hutopy.Application;
using Hutopy.Application.Common.Interfaces;
using Hutopy.Domain.Interfaces; using Hutopy.Domain.Interfaces;
using Hutopy.Infrastructure; using Hutopy.Infrastructure;
using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Data;
@@ -48,6 +49,7 @@ builder.Services.AddInfrastructureServices(builder.Configuration);
builder.Services.AddWebServices(); builder.Services.AddWebServices();
builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IGoogleService, GoogleService>();
var app = builder.Build(); var app = builder.Build();

View File

@@ -6,6 +6,39 @@
"version": "1.0.0" "version": "1.0.0"
}, },
"paths": { "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": { "/api/JoinUs": {
"get": { "get": {
"tags": [ "tags": [
@@ -559,6 +592,15 @@
}, },
"components": { "components": {
"schemas": { "schemas": {
"CreateGoogleUserCommand": {
"type": "object",
"additionalProperties": false,
"properties": {
"accessToken": {
"type": "string"
}
}
},
"PaginatedListOfFutureCreatorListDto": { "PaginatedListOfFutureCreatorListDto": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,