using System.Text; using System.Text.Json; using JOBot.Backend.DAL.Context; using JOBot.Backend.DTOs.HeadHunterHook; using JOBot.Backend.Infrastructure.Config; using JOBot.Infrastructure.Config; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using RabbitMQ.Client; namespace JOBot.Backend.Services; public class HeadHunterService( IChannel channel, ILogger logger, IOptions config, IWebHostEnvironment env, AppDbContext dbContext) { public enum Status { UserAuthRejectedError, HeadHunterAuthRejectedError, UserNotFoundError, HeadHunterResponseDeserializationFailedError, Success } private readonly HeadHunterConfig _config = config.Value; /// /// Generate HeadHunter oauth authorization link /// /// Telegram UserId /// Link for auth public string GenerateAuthLink(long userId) { return string.Format(_config.Links.AuthLink, [_config.ClientId, GetRedirectUrl(userId)]); } public async Task AuthUser(int userId, string authorizationCode, string? error) //TODO: Разбить этот метод { logger.LogInformation($"Authorization for user {userId} in process..."); if (!string.IsNullOrEmpty(error)) { logger.LogWarning($"User {userId} auth completed with error {error}"); return Status.UserAuthRejectedError; } HeadHunterTokenResponseDto? responseDto; if (!env.IsDevelopment()) //Production server { using var client = new HttpClient(); var form = new Dictionary { { "client_id", _config.ClientId }, { "client_secret", _config.Secret }, { "code", authorizationCode }, { "grant_type", "authorization_code" }, { "redirect_uri", GetRedirectUrl(userId) } }; client.BaseAddress = new UriBuilder(_config.Links.HeadHunterApiDomain) { Port = -1, Scheme = "https" }.Uri; client.DefaultRequestHeaders.UserAgent.ParseAdd("Jobot BackEnd Service"); using var res = await client.SendAsync( new HttpRequestMessage( HttpMethod.Post, _config.Links.HeadHunterTokenRoute) { Content = new FormUrlEncodedContent(form) }); if (!res.IsSuccessStatusCode) { logger.LogWarning($"Response of HttpRequest {_config.Links.HeadHunterApiDomain}" + $"{_config.Links.HeadHunterTokenRoute} has unsuccessful status code {res.StatusCode}"); logger.LogWarning($"{res.Content.ReadAsStringAsync().Result}"); return Status.HeadHunterAuthRejectedError; } responseDto = JsonSerializer.Deserialize(await res.Content.ReadAsStringAsync()); if (responseDto == null) { logger.LogWarning($"User {userId} auth completed with error " + $"{nameof(Status.HeadHunterResponseDeserializationFailedError)}"); return Status.HeadHunterResponseDeserializationFailedError; } } else { responseDto = new HeadHunterTokenResponseDto("testtoken", 0, "testtoken", "--"); } var user = await dbContext.Users.FirstOrDefaultAsync(x => x.UserId == userId); if (user == null) { logger.LogWarning($"User {userId} search completed with error {nameof(Status.UserNotFoundError)}"); return Status.UserNotFoundError; } user.AccessToken = responseDto.AccessToken; user.RefreshToken = responseDto.RefreshToken; await dbContext.SaveChangesAsync(); logger.LogInformation($"User {userId} auth completed!"); await channel.BasicPublishAsync( string.Empty, RabbitQueues.AuthQueue, Encoding.UTF8.GetBytes(userId.ToString())); logger.LogInformation("RabbitMQ event was created"); return Status.Success; } private string GetRedirectUrl(long userId) { return new UriBuilder(_config.Links.HookDomain) { Port = -1, Scheme = "https", Path = _config.Links.HookRoute, Query = $"?userId={userId}" }.ToString(); } }