diff --git a/Endpoint/Controllers/V1/AuthController.cs b/Endpoint/Controllers/V1/AuthController.cs index b5ef2b8..4453f65 100644 --- a/Endpoint/Controllers/V1/AuthController.cs +++ b/Endpoint/Controllers/V1/AuthController.cs @@ -22,7 +22,7 @@ using OAuthProvider = Mirea.Api.Security.Common.Domain.OAuthProvider; namespace Mirea.Api.Endpoint.Controllers.V1; [ApiVersion("1.0")] -public class AuthController(IOptionsSnapshot user, AuthService auth, PasswordHashService passwordService) : BaseController +public class AuthController(IOptionsSnapshot user, IOptionsSnapshot generalConfig, AuthService auth, PasswordHashService passwordService, OAuthService oAuthService) : BaseController { private CookieOptionsParameters GetCookieParams() => new() @@ -31,6 +31,95 @@ public class AuthController(IOptionsSnapshot user, AuthService auth, Pass Path = UrlHelper.GetSubPathWithoutFirstApiName + "api" }; + private static string GenerateHtmlResponse(string title, string message, OAuthProvider? provider, bool isError = false) + { + string messageColor = isError ? "red" : "white"; + string script = ""; + + return $"{title}

{title}

{message}

Это информационная страница. Вы можете закрыть её.

{script}"; + } + + [HttpGet("OAuth2")] + [BadRequestResponse] + [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] + [Produces("text/html")] + [MaintenanceModeIgnore] + public async Task OAuth2([FromQuery] string code, [FromQuery] string state) + { + var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); + string title; + string message; + OAuthProvider provider; + OAuthUser oAuthUser; + + try + { + (provider, oAuthUser) = await oAuthService.LoginOAuth(HttpContext, GetCookieParams(), + HttpContext.GetApiUrl(Url.Action("OAuth2")!), code, state); + } + catch (Exception e) + { + title = "Произошла ошибка при общении с провайдером OAuth!"; + message = e.Message; + return Content(GenerateHtmlResponse(title, message, null, true), "text/html"); + } + + var userEntity = user.Value; + + if (userId != null) + { + userEntity.OAuthProviders ??= new Dictionary(); + + if (!userEntity.OAuthProviders.TryAdd(provider, oAuthUser)) + { + title = "Ошибка связи аккаунта!"; + message = "Этот OAuth провайдер уже связан с вашей учетной записью. Пожалуйста, используйте другого провайдера или удалите связь с аккаунтом."; + return Content(GenerateHtmlResponse(title, message, provider, true), "text/html"); + } + + userEntity.SaveSetting(); + + title = "Учетная запись успешно связана."; + message = "Вы успешно связали свою учетную запись с провайдером OAuth. Вы можете продолжить использовать приложение."; + return Content(GenerateHtmlResponse(title, message, provider), "text/html"); + } + + if (userEntity.OAuthProviders != null && + userEntity.OAuthProviders.TryGetValue(provider, out var userOAuth) && + userOAuth.Id == oAuthUser.Id) + { + await auth.LoginOAuthAsync(GetCookieParams(), HttpContext, new User + { + Id = 1.ToString(), + Username = userEntity.Username, + Email = userEntity.Email, + PasswordHash = userEntity.PasswordHash, + Salt = userEntity.Salt, + TwoFactorAuthenticator = userEntity.TwoFactorAuthenticator, + SecondFactorToken = userEntity.Secret, + OAuthProviders = userEntity.OAuthProviders + }, provider); + + title = "Успешный вход в аккаунт."; + message = "Вы успешно вошли в свою учетную запись. Добро пожаловать!"; + return Content(GenerateHtmlResponse(title, message, provider), "text/html"); + } + + title = "Вы успешно зарегистрированы."; + message = "Процесс завершен. Вы можете закрыть эту страницу."; + userEntity.Email = string.IsNullOrEmpty(oAuthUser.Email) ? string.Empty : oAuthUser.Email; + userEntity.Username = string.IsNullOrEmpty(oAuthUser.Username) ? string.Empty : oAuthUser.Username; + userEntity.OAuthProviders ??= []; + userEntity.OAuthProviders.Add(provider, oAuthUser); + userEntity.SaveSetting(); + return Content(GenerateHtmlResponse(title, message, provider), "text/html"); + } + /// /// Initiates the OAuth2 authorization process for the selected provider. ///