forked from AcaMate/AcaMate_API
[♻️] DB 저장 및 삭제 로직 변경 후 적용
This commit is contained in:
parent
f2df6cb1e6
commit
968bd33b9d
|
@ -114,7 +114,8 @@ public class UserController : ControllerBase
|
||||||
var refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
var refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
||||||
_logger.LogInformation($"{uid}: {accessToken}, {refreshToken}");
|
_logger.LogInformation($"{uid}: {accessToken}, {refreshToken}");
|
||||||
|
|
||||||
await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
// await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
||||||
|
await _repositoryService.SaveData<RefreshToken>(refreshToken);
|
||||||
|
|
||||||
return Ok(APIResponse.Send("000","정상", new
|
return Ok(APIResponse.Send("000","정상", new
|
||||||
{
|
{
|
||||||
|
@ -236,17 +237,18 @@ public class UserController : ControllerBase
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (await _repositoryService.SaveData<User, string>(user, u => u.uid))
|
if (await _repositoryService.SaveData<User>(user))
|
||||||
{
|
{
|
||||||
await _repositoryService.SaveData<Login, string>(login, l => l.sns_id);
|
await _repositoryService.SaveData<Login>(login);
|
||||||
await _repositoryService.SaveData<Permission, string>(permission, p => p.uid);
|
await _repositoryService.SaveData<Permission>(permission);
|
||||||
await _repositoryService.SaveData<Contact, string>(contact, c => c.uid);
|
await _repositoryService.SaveData<Contact>(contact);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TO-DO: jwt 토큰 만들어서 여기서 보내는 작업을 해야 함
|
// TO-DO: jwt 토큰 만들어서 여기서 보내는 작업을 해야 함
|
||||||
var token = _jwtTokenService.GenerateJwtToken(uid);
|
var token = _jwtTokenService.GenerateJwtToken(uid);
|
||||||
var refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
var refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
||||||
await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
|
||||||
|
await _repositoryService.SaveData<RefreshToken>(refreshToken);
|
||||||
|
|
||||||
return Ok(APIResponse.Send("000","정상",new
|
return Ok(APIResponse.Send("000","정상",new
|
||||||
{
|
{
|
||||||
|
@ -268,7 +270,7 @@ public class UserController : ControllerBase
|
||||||
if (refreshToken != null)
|
if (refreshToken != null)
|
||||||
{
|
{
|
||||||
refreshToken.revoke_Date = DateTime.Now;
|
refreshToken.revoke_Date = DateTime.Now;
|
||||||
await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
await _repositoryService.SaveData<RefreshToken>(refreshToken);
|
||||||
return Ok(APIResponse.Send("000", "로그아웃 정상", Empty));
|
return Ok(APIResponse.Send("000", "로그아웃 정상", Empty));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -42,6 +42,7 @@ public class FileContentNotFoundException : Exception
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 외부 서비스에 연결시 연결 실패시
|
/// 외부 서비스에 연결시 연결 실패시
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -63,3 +64,13 @@ public class PushInvalidException : Exception
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 값이 있어야 하는데 NULL인 경우
|
||||||
|
/// </summary>
|
||||||
|
public class OutNULLException : Exception
|
||||||
|
{
|
||||||
|
public OutNULLException(string message) : base(message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,19 +5,23 @@ using AcaMate.Common.Models;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using AcaMate.V1.Models;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Microsoft.VisualBasic;
|
using Microsoft.VisualBasic;
|
||||||
|
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using AcaMate.V1.Models;
|
||||||
|
|
||||||
namespace AcaMate.V1.Services;
|
namespace AcaMate.V1.Services;
|
||||||
|
|
||||||
public interface IRepositoryService
|
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);
|
Task<ValidateToken> ValidateToken(string token, string refresh);
|
||||||
Task<bool> SaveDataFK<T>(T entity) where T : class;
|
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
|
public class RepositoryService: IRepositoryService
|
||||||
|
@ -32,58 +36,6 @@ public class RepositoryService: IRepositoryService
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_jwtTokenService = jwtTokenService;
|
_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//토큰 태울때는 인코딩 된 걸로 태워야지 원본꺼 태우면 데이터에 손상옵니다.
|
//토큰 태울때는 인코딩 된 걸로 태워야지 원본꺼 태우면 데이터에 손상옵니다.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 실제로 엑세스 토큰과 리프레시 토큰으로 접근 하기 위한 메서드
|
/// 실제로 엑세스 토큰과 리프레시 토큰으로 접근 하기 위한 메서드
|
||||||
|
@ -131,7 +83,7 @@ public class RepositoryService: IRepositoryService
|
||||||
{
|
{
|
||||||
refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
|
||||||
_logger.LogInformation("리프레시 토큰 만료");
|
_logger.LogInformation("리프레시 토큰 만료");
|
||||||
await SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
// await SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
|
||||||
return new ValidateToken
|
return new ValidateToken
|
||||||
{
|
{
|
||||||
token = token,
|
token = token,
|
||||||
|
@ -142,53 +94,146 @@ public class RepositoryService: IRepositoryService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public async Task SaveData<T, T1>(T pushCabinet)
|
public async Task<bool> SaveData<T>(T entity, Expression<Func<T, object>> key = null) where T : class
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> SaveDataFK<T>(T entity) where T : class
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// EF Core 메타데이터를 통해 엔티티 T의 기본 키 속성 정보를 가져옴
|
if (key != null)
|
||||||
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)})");
|
// key를 가지고 EF 로 돌리는게 아니라 내가 조건을 넣어서 하는 경우에 사용함
|
||||||
// 기존 엔티티를 업데이트: 새 entity의 값으로 교체
|
var value = key.Compile()(entity);
|
||||||
_dbContext.Entry(existingEntity).CurrentValues.SetValues(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
|
else
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"[{typeof(T)}] 신규 데이터 등록: 기본 키 값({string.Join(", ", keyValues)})");
|
// EF 로 직접 키를 잡아서 사용 (관계키나 이런거 할때도 노상관됨)
|
||||||
// 데이터가 없으면 새 엔티티 추가
|
|
||||||
_dbContext.Set<T>().Add(entity);
|
// 모델이 존재하지 않거나 기본 키 정의가 되지 않은 오류가 발생할 건데 그건 운영 단계에서는 오류 나면 안되는거니
|
||||||
|
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();
|
await _dbContext.SaveChangesAsync();
|
||||||
_logger.LogInformation($"[{typeof(T)}] DB 저장 완료");
|
_logger.LogInformation($"[{typeof(T)}] DB 저장 완료: 종료");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError($"[{typeof(T)}] 저장 중 오류 발생: {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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user