| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Application.Abstractions.YouTube;
- using Domain.Entities.Members;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.Logging;
- using SharedKernel.Results;
- namespace Application.Features.Api.MyPage.Sns.Connect;
- internal sealed class Handler(
- IAppDbContext db,
- IGoogleOAuthService oauthService,
- ILogger<Handler> logger
- ) : ICommandHandler<Command, Result<Response>>
- {
- private const string Provider = "Google";
- public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
- {
- if (string.IsNullOrWhiteSpace(request.Code))
- {
- return Result.Failure<Response>(Error.Problem("Sns.CodeRequired", "Authorization code 가 필요합니다."));
- }
- if (string.IsNullOrWhiteSpace(request.RedirectUri))
- {
- return Result.Failure<Response>(Error.Problem("Sns.RedirectUriRequired", "Redirect URI 가 필요합니다."));
- }
- var config = await db.Config.AsNoTracking().OrderByDescending(x => x.ID).FirstOrDefaultAsync(ct);
- if (config is null
- || string.IsNullOrEmpty(config.External.GoogleClientId)
- || string.IsNullOrEmpty(config.External.GoogleClientSecretEnc)
- ) {
- return Result.Failure<Response>(Error.Problem("Sns.OAuthConfigMissing", "Google OAuth 설정이 없습니다."));
- }
- var tokens = await oauthService.ExchangeCodeAsync(
- request.Code,
- request.RedirectUri,
- config.External.GoogleClientId,
- config.External.GoogleClientSecretEnc,
- ct
- );
- if (tokens is null)
- {
- return Result.Failure<Response>(Error.Problem("Sns.OAuthExchangeFailed", "Google 인증 코드 교환에 실패했습니다."));
- }
- var existing = await db.MemberOAuthToken.FirstOrDefaultAsync(t => t.MemberID == request.MemberID && t.Provider == Provider, ct);
- var scopesStr = string.Join(" ", tokens.Scopes);
- if (existing is null)
- {
- var token = MemberOAuthToken.Create(
- request.MemberID,
- Provider,
- tokens.AccessToken,
- tokens.RefreshToken,
- tokens.ExpiresAt,
- scopesStr
- );
- db.MemberOAuthToken.Add(token);
- }
- else
- {
- existing.UpdateTokens(tokens.AccessToken, tokens.RefreshToken, tokens.ExpiresAt, scopesStr);
- }
- await db.SaveChangesAsync(ct);
- logger.LogInformation("[Sns.Connect] Google 연동 완료: memberID={MemberID}", request.MemberID);
- return Result.Success(new Response(Provider, DateTime.UtcNow, tokens.ExpiresAt));
- }
- }
|