forked from AcaMate/AcaMate_API
232 lines
11 KiB
C#
232 lines
11 KiB
C#
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using Back.Program.Common.Auth;
|
|
using Back.Program.Common.Data;
|
|
using Back.Program.Common.Model;
|
|
using Back.Program.Models.Entities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Back.Program.Services.V1
|
|
{
|
|
public interface IRepositoryService
|
|
{
|
|
// Task<ValidateToken> ValidateToken(string token, string refresh);
|
|
Task<bool> SaveData<T>(T entity, Expression<Func<T, object>> key = null) where T : class;
|
|
Task<bool> DeleteData<T>(T entity, Expression<Func<T, object>> key = null) where T : class;
|
|
String ReadSummary(Type type, String name);
|
|
}
|
|
|
|
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<ValidateToken> ValidateToken(string token, string refresh)
|
|
// {
|
|
// var principalToken = await _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 TokenException("입력 받은 토큰 자체의 문제");
|
|
// //
|
|
// // var uid = refreshToken.uid;
|
|
// //
|
|
// // if (refreshToken.revoke_Date < DateTime.Now)
|
|
// // throw new RefreshRevokeException("리프레시 토큰 해지");
|
|
// //
|
|
// // 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
|
|
// // };
|
|
// // }
|
|
// }
|
|
// }
|
|
|
|
public async Task<bool> SaveData<T>(T entity, Expression<Func<T, object>> key = null) where T : class
|
|
{
|
|
try
|
|
{
|
|
if (key != null)
|
|
{
|
|
// key를 가지고 EF 로 돌리는게 아니라 내가 조건을 넣어서 하는 경우에 사용함
|
|
var value = key.Compile()(entity);
|
|
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 entityData = await _dbContext.Set<T>().FirstOrDefaultAsync(predicate);
|
|
|
|
if (entityData != null)
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 해당 PK 존재 = [{value}]: 계속");
|
|
_dbContext.Entry(entityData).CurrentValues.SetValues(entity);
|
|
if (!(_dbContext.Entry(entityData).Properties.Any(p => p.IsModified)))
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 변경 사항 없음");
|
|
return true;
|
|
}
|
|
|
|
_logger.LogInformation($"[{typeof(T)}] 변경 사항이 존재");
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 처음등록");
|
|
_dbContext.Set<T>().Add(entity);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// EF 로 직접 키를 잡아서 사용 (관계키나 이런거 할때도 노상관됨)
|
|
|
|
// 모델이 존재하지 않거나 기본 키 정의가 되지 않은 오류가 발생할 건데 그건 운영 단계에서는 오류 나면 안되는거니
|
|
var keyProperties = _dbContext.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties;
|
|
|
|
// 각 키 속성에 대해, entity에서 실제 키 값을 추출
|
|
var keyValues = keyProperties.Select(p => typeof(T).GetProperty(p.Name).GetValue(entity)).ToArray();
|
|
|
|
// 기본 키 값을 이용해서 기존 엔티티를 찾음 (복합 키도 자동으로 처리됨)
|
|
var existingEntity = await _dbContext.Set<T>().FindAsync(keyValues);
|
|
|
|
if (existingEntity != null)
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 기존 데이터 발견: 기본 키 값({string.Join(", ", keyValues)})");
|
|
// 기존 엔티티를 업데이트: 새 entity의 값으로 교체
|
|
_dbContext.Entry(existingEntity).CurrentValues.SetValues(entity);
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 신규 데이터 등록: 기본 키 값({string.Join(", ", keyValues)})");
|
|
// 데이터가 없으면 새 엔티티 추가
|
|
_dbContext.Set<T>().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<bool> DeleteData<T>(T entity, Expression<Func<T, object>> key = null) where T : class
|
|
{
|
|
try
|
|
{
|
|
if (key != null)
|
|
{
|
|
// key를 통해 조건식을 만들어 삭제할 엔티티를 찾는 경우
|
|
var value = key.Compile()(entity);
|
|
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 entityData = await _dbContext.Set<T>().FirstOrDefaultAsync(predicate);
|
|
if (entityData == null)
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 삭제 대상 데이터가 존재하지 않습니다. (값 = {value})");
|
|
return false;
|
|
}
|
|
_logger.LogInformation($"[{typeof(T)}] 조건에 맞는 데이터 발견 (값 = {value}): 삭제 진행");
|
|
_dbContext.Set<T>().Remove(entityData);
|
|
}
|
|
else
|
|
{
|
|
// key가 없는 경우 EF Core 메타데이터를 사용하여 기본 키를 통한 삭제
|
|
var entityType = _dbContext.Model.FindEntityType(typeof(T));
|
|
if (entityType == null)
|
|
{
|
|
throw new InvalidOperationException($"Entity type '{typeof(T).Name}'이 모델에 존재하지 않습니다.");
|
|
}
|
|
|
|
var primaryKey = entityType.FindPrimaryKey();
|
|
if (primaryKey == null)
|
|
{
|
|
throw new InvalidOperationException($"Entity type '{typeof(T).Name}'에 기본 키가 정의되어 있지 않습니다.");
|
|
}
|
|
|
|
var keyProperties = primaryKey.Properties;
|
|
var keyValues = keyProperties.Select(p => typeof(T).GetProperty(p.Name).GetValue(entity)).ToArray();
|
|
|
|
var existingEntity = await _dbContext.Set<T>().FindAsync(keyValues);
|
|
if (existingEntity == null)
|
|
{
|
|
_logger.LogInformation($"[{typeof(T)}] 기본 키 값({string.Join(", ", keyValues)})에 해당하는 삭제 대상 데이터가 존재하지 않습니다.");
|
|
return false;
|
|
}
|
|
_logger.LogInformation($"[{typeof(T)}] 기본 키 값({string.Join(", ", keyValues)})에 해당하는 데이터 발견: 삭제 진행");
|
|
_dbContext.Set<T>().Remove(existingEntity);
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
_logger.LogInformation($"[{typeof(T)}] DB에서 삭제 완료");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError($"[{typeof(T)}] 삭제 중 오류 발생: {ex}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
public string ReadSummary(Type type, string name)
|
|
{
|
|
var method = type.GetMethod(name) ?? throw new OutNULLException("swagger summary Load ERROR: NULL");
|
|
var att = method.GetCustomAttribute<CustomOperationAttribute>() ?? throw new OutNULLException("swagger summary Load ERROR: NULL");
|
|
return att.Summary;
|
|
}
|
|
}
|
|
}
|