using System.Text.Json; using JOBot.Backend.DAL.Context; using JOBot.Backend.DTOs.HeadHunterHook; using JOBot.Backend.Infrastructure.Config; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; namespace JOBot.Backend.Services; public class HeadHunterService(ILogger logger, IOptions config, AppDbContext dbContext) { private readonly HeadHunterConfig _config = config.Value; /// /// Generate HeadHunter oauth authorization link /// /// Telegram UserId /// Link for auth public string GenerateAuthLink(long userId) { var redirectUri = new UriBuilder(_config.Links.HookDomain) { Port = -1, Scheme = "https", Path = _config.Links.HookRoute, Query = $"?userId={userId}" }.ToString(); return string.Format(_config.Links.AuthLink, [_config.ClientId, redirectUri]); } public async Task AuthUser(int userId, string authorizationCode, string? error) { logger.LogInformation($"Authorization for user {userId} in process..."); if (!string.IsNullOrEmpty(error)) { logger.LogWarning($"User {userId} auth completed with error {error}"); return Status.UserAuthRejectedError; } 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", "" } }; 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; } var responseDto = JsonSerializer.Deserialize(await res.Content.ReadAsStringAsync()); if (responseDto == null) { logger.LogWarning($"User {userId} auth completed with error " + $"{nameof(Status.HeadHunterResponseDeserializationFailedError)}"); return Status.HeadHunterResponseDeserializationFailedError; } 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!"); return Status.Success; } public enum Status { UserAuthRejectedError, HeadHunterAuthRejectedError, UserNotFoundError, HeadHunterResponseDeserializationFailedError, Success } }