forked from AcaMate/AcaMate_API
136 lines
4.8 KiB
C#
136 lines
4.8 KiB
C#
using AcaMate.Common.Data;
|
|
using AcaMate.Common.Token;
|
|
using AcaMate.Common.Models;
|
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using System.Linq.Expressions;
|
|
using System.Security.Claims;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
namespace AcaMate.V1.Services;
|
|
|
|
public interface IRepositoryService
|
|
{
|
|
Task<bool> SaveData<T, K>(T entity, Expression<Func<T, K>> key) where T : class;
|
|
Task<ValidateToken> ValidateToken(string token, string refresh);
|
|
}
|
|
|
|
public class RepositoryService: IRepositoryService
|
|
{
|
|
private readonly AppDbContext _dbContext;
|
|
private readonly ILogger<RepositoryService> _logger;
|
|
private readonly JwtTokenService _jwtTokenService;
|
|
|
|
public RepositoryService(AppDbContext dbContext, ILogger<RepositoryService> logger, JwtTokenService jwtTokenService)
|
|
{
|
|
_dbContext = dbContext;
|
|
_logger = logger;
|
|
_jwtTokenService = jwtTokenService;
|
|
}
|
|
|
|
public async Task<bool> SaveData<T, K> (T entity, Expression<Func<T, K>> key) where T : class
|
|
{
|
|
try
|
|
{
|
|
var value = key.Compile()(entity);
|
|
|
|
// x 라 함은 Expression 으로 생성되는 트리에서 T 타입으의 매개변수를 지칭함
|
|
var parameter = Expression.Parameter(typeof(T), "x");
|
|
|
|
var invokedExpr = Expression.Invoke(key, parameter);
|
|
var constantExpr = Expression.Constant(value, key.Body.Type);
|
|
var equalsExpr = Expression.Equal(invokedExpr, constantExpr);
|
|
|
|
var predicate = Expression.Lambda<Func<T, bool>>(equalsExpr, parameter);
|
|
|
|
var dbSet = _dbContext.Set<T>();
|
|
|
|
var entityData = await dbSet.FirstOrDefaultAsync(predicate);
|
|
|
|
if (entityData != null)
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 해당 PK 존재 [{value}]: 계속");
|
|
var entry = _dbContext.Entry(entityData);
|
|
entry.CurrentValues.SetValues(entity);
|
|
if (entry.Properties.Any(p => p.IsModified))
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 변경사항 존재: 계속");
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 변경사항 없음: 종료");
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 처음등록");
|
|
dbSet.Add(entity);
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
_logger.LogInformation($"[{typeof(T)}] DB 저장 완료: 종료");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 알 수 없는 오류: 종료 {ex}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//토큰 태울때는 인코딩 된 걸로 태워야지 원본꺼 태우면 데이터에 손상옵니다.
|
|
public async Task<ValidateToken> ValidateToken(string token, string refresh)
|
|
{
|
|
var principalToken = _jwtTokenService.ValidateToken(token);
|
|
if (principalToken != null)
|
|
{
|
|
var uid = principalToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty;
|
|
_logger.LogInformation($"토큰 변환 - {uid}");
|
|
return new ValidateToken
|
|
{
|
|
token = token,
|
|
refresh = refresh,
|
|
uid = uid
|
|
};
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation("엑세스 토큰 만료");
|
|
var refreshToken = await _dbContext.RefreshTokens
|
|
.FirstOrDefaultAsync(t => t.refresh_token == refresh);
|
|
if (refreshToken == null)
|
|
{
|
|
throw new SecurityTokenException("리프레시 토큰도 잘못되었음");
|
|
}
|
|
var uid = refreshToken.uid;
|
|
|
|
if (refreshToken.expire_date > DateTime.Now)
|
|
{
|
|
_logger.LogInformation($"리프레시 : {uid}");
|
|
var access = _jwtTokenService.GenerateJwtToken(uid);
|
|
return new ValidateToken
|
|
{
|
|
token = access,
|
|
refresh = refreshToken.refresh_token,
|
|
uid = uid
|
|
};
|
|
}
|
|
else
|
|
{
|
|
refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
|
_logger.LogInformation("리프레시 토큰 만료");
|
|
await SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
|
return new ValidateToken
|
|
{
|
|
token = token,
|
|
refresh = refreshToken.refresh_token,
|
|
uid = uid
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
} |