JOBot/JOBot.Backend/Services/HeadHunterService.cs

189 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text;
using System.Text.Json;
using JOBot.Backend.DAL.Context;
using JOBot.Backend.DAL.Models;
using JOBot.Backend.DTOs.HeadHunterApi;
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<HeadHunterService> logger,
IOptions<HeadHunterConfig> config,
IWebHostEnvironment env,
AppDbContext dbContext)
{
public enum Status
{
UserAuthRejectedError,
HeadHunterAuthRejectedError,
UserNotFoundError,
HeadHunterResponseDeserializationFailedError,
Success
}
private readonly HeadHunterConfig _config = config.Value;
/// <summary>
/// Generate HeadHunter oauth authorization link
/// </summary>
/// <param name="userId">Telegram UserId</param>
/// <returns>Link for auth</returns>
public string GenerateAuthLink(long userId)
{
return string.Format(_config.Links.AuthLink, [_config.ClientId, GetRedirectUrl(userId)]);
}
/// <summary>
/// Auth user on HeadHunter API
/// </summary>
/// <param name="userId"></param>
/// <param name="authorizationCode"></param>
/// <param name="error"></param>
/// <returns></returns>
public async Task<Status> 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<string, string>
{
{ "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<HeadHunterTokenResponseDto>(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;
user.ExpiresIn = responseDto.ExpiresIn;
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;
}
public async Task<Status> UpdateUserAccessToken(User user)
{
if (user.RefreshToken == null)
return Status.UserAuthRejectedError;
using var client = new HttpClient(); //TODO: Написать wrapper для работы с HH API
var form = new Dictionary<string, string>
{
{ "refresh_token", user.RefreshToken },
{ "grant_type", "refresh_token" }
};
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)
});
var responseDto =
JsonSerializer.Deserialize<HeadHunterTokenResponseDto>(await res.Content.ReadAsStringAsync());
if (responseDto == null)
{
logger.LogWarning(
$"User {user.Username ?? user.UserId.ToString()} access token accept completed with error " +
$"{nameof(Status.HeadHunterResponseDeserializationFailedError)}");
return Status.HeadHunterResponseDeserializationFailedError;
}
user.RefreshToken = responseDto.RefreshToken;
user.AccessToken = responseDto.AccessToken;
await dbContext.SaveChangesAsync();
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();
}
}