AcaMate_API/Program/V1/Controllers/UserController.cs

302 lines
11 KiB
C#

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore.Query;
using MySqlConnector;
using System.Linq;
using AcaMate.Common.Data;
using AcaMate.Common.Token;
using AcaMate.Common.Models;
using AcaMate.V1.Models;
using AcaMate.V1.Services;
namespace AcaMate.V1.Controllers;
[ApiController]
[Route("/api/v1/in/user")]
[ApiExplorerSettings(GroupName = "사용자")]
public class UserController : ControllerBase
{
private readonly AppDbContext _dbContext;
private readonly ILogger<UserController> _logger;
private readonly JwtTokenService _jwtTokenService;
private readonly IRepositoryService _repositoryService;
public UserController(AppDbContext dbContext, ILogger<UserController> logger, JwtTokenService jwtTokenService, IRepositoryService repositoryService)
{
_dbContext = dbContext;
_logger = logger;
_jwtTokenService = jwtTokenService;
_repositoryService = repositoryService;
}
[HttpGet]
[CustomOperation("회원 정보 조회", "회원 정보 조회", "사용자")]
public async Task<IActionResult> GetUserData(string token, string refresh)
{
if(string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh))
return BadRequest(APIResponse.InvalidInputError());
try
{
var validateToken = await _repositoryService.ValidateToken(token, refresh);
var user = await _dbContext.User
.Where(u => u.uid == validateToken.uid)
.Select(u => new User
{
uid = u.uid,
name = u.name,
auto_login_yn = u.auto_login_yn,
birth = u.birth,
device_id = u.device_id,
login_date = u.login_date,
type = u.type
})
.FirstOrDefaultAsync();
// _logger.LogInformation($"CHECK!! {user.}");
return Ok(APIResponse.Send("000", "정상", user));
}
catch (TokenException tokenEx)
{
_logger.LogInformation($"[로그인] : {tokenEx}");
return Ok(APIResponse.Send("001", "로그인 진행: 토큰에 문제가 있음",Empty));
}
catch (RefreshRevokeException refreshEx)
{
_logger.LogInformation($"[로그인] : {refreshEx}");
return Ok(APIResponse.Send("001", "로그인 진행: 리프레시 토큰 폐기",Empty));
}
catch (Exception ex)
{
return StatusCode(500, APIResponse.UnknownError());
}
}
[HttpGet("login")]
[CustomOperation("SNS 로그인", "로그인 후 회원이 있는지 확인", "사용자")]
public async Task<IActionResult> Login(string acctype, string sns_id)
{
// API 동작 파라미터 입력 값 확인
if (string.IsNullOrEmpty(acctype) && string.IsNullOrEmpty(sns_id))
return BadRequest(APIResponse.InvalidInputError());
try
{
var login = await _dbContext.Login
.FirstOrDefaultAsync(l => l.sns_type == acctype && l.sns_id == sns_id);
if (login != null)
{
// 로그인 정보가 존재 하는 상황
var uid = login.uid;
var user = await _dbContext.User
.FirstOrDefaultAsync(u => u.uid == uid);
if (user != null)
{
// 정상적으로 User 테이블에도 있는것이 확인 됨
user.login_date = DateTime.Now;
await _dbContext.SaveChangesAsync();
// 토큰 생성은 로그인이 이제 되고 나서 한다.
var accessToken = _jwtTokenService.GenerateJwtToken(uid);//, "Normal");
var refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
_logger.LogInformation($"{uid}: {accessToken}, {refreshToken}");
await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
return Ok(APIResponse.Send("000","정상", new
{
token = accessToken,
refresh = refreshToken.refresh_token
}));
}
}
// case 1: Login 테이블에 값이 없다 == 로그인이 처음
// case 2: User 테이블에 값이 없다 == 이건 문제가 있는 상황 -> 해결은 회원가입 재 진행 시도
// Login에는 있는데 User 테이블에 없다? 말이 안되긴 하는데...
return Ok(APIResponse.Send("001", "회원가입 진행: 로그인 정보가 없음",Empty));
}
catch (Exception ex)
{
_logger.LogInformation($"[로그인][에러] : {ex}");
return StatusCode(500, APIResponse.UnknownError());
}
}
[HttpGet("academy")]
[CustomOperation("학원 리스트 확인", "사용자가 등록된 학원 리스트 확인", "사용자")]
public async Task<IActionResult> ReadAcademyInfo(string token, string refresh)
{
_logger.LogInformation($"토큰 : {token}, {refresh}");
if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh))
{
return BadRequest(APIResponse.InvalidInputError());
}
try
{
var validateToken = await _repositoryService.ValidateToken(token, refresh);
var uid = validateToken.uid;
var userAcademy = await _dbContext.UserAcademy
.Where(ua => ua.uid == uid)
.Select(ua => ua.bid)
.ToListAsync();
var academies = await _dbContext.Academy
.Where(a => userAcademy.Contains(a.bid))
.Select(a => new AcademyName
{
bid = a.bid,
name = a.business_name
})
.ToListAsync();
return Ok(APIResponse.Send("000","정상.",academies));
}
catch (TokenException tokenEx)
{
_logger.LogInformation($"[로그인] : {tokenEx}");
return Ok(APIResponse.Send("001", "[로그인] : 토큰에 문제가 있음",Empty));
}
catch (RefreshRevokeException refreshEx)
{
_logger.LogInformation($"[로그인] : {refreshEx}");
return Ok(APIResponse.Send("001", "[로그인] : 폐기된 리프레시 토큰",Empty));
}
catch (Exception ex)
{
_logger.LogInformation($"[로그인][에러] : {ex}");
return StatusCode(500, APIResponse.UnknownError());
}
}
[HttpPost("register")]
[CustomOperation("회원 가입", "사용자 회원 가입", "사용자")]
public async Task<IActionResult> UserRegister([FromBody] UserAll request)
{
if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError());
var atIndex = request.email.IndexOf('@');
var localPartEmail = request.email.Substring(0, atIndex);
var uid = $"AM{localPartEmail}{DateTime.Now:yyyyMMdd}";
var user = new User
{
uid = uid,
name = request.name,
birth = request.birth,
type = request.type,
device_id = request.device_id,
auto_login_yn = request.auto_login_yn,
login_date = request.login_date,
push_token = request.push_token
};
var login = new Login
{
uid = uid,
sns_id = request.sns_id,
sns_type = request.sns_type
};
var permission = new Permission
{
uid = uid,
location_yn = request.location_yn,
camera_yn = request.camera_yn,
photo_yn = request.photo_yn,
push_yn = request.push_yn,
market_app_yn = request.market_app_yn,
market_sms_yn = request.market_sms_yn,
market_email_yn = request.market_email_yn
};
var contact = new Contact
{
uid = uid,
email = request.email,
phone = request.phone,
address = request.address
};
if (await _repositoryService.SaveData<User, string>(user, u => u.uid))
{
await _repositoryService.SaveData<Login, string>(login, l => l.sns_id);
await _repositoryService.SaveData<Permission, string>(permission, p => p.uid);
await _repositoryService.SaveData<Contact, string>(contact, c => c.uid);
}
// TO-DO: jwt 토큰 만들어서 여기서 보내는 작업을 해야 함
var token = _jwtTokenService.GenerateJwtToken(uid);
var refreshToken = _jwtTokenService.GenerateRefreshToken(uid);
await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
return Ok(APIResponse.Send("000","정상",new
{
accessToken = token,
refreshToken = refreshToken.refresh_token
}));
}
[HttpGet("logout")]
[CustomOperation("로그아웃", "사용자 로그아웃", "사용자")]
public async Task<IActionResult> Logout(string token, string refresh) //([FromBody] UserAll request)
{
if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError());
try
{
var validateToken = await _repositoryService.ValidateToken(token, refresh);
var refreshToken = await _dbContext.RefreshTokens.FirstOrDefaultAsync(r => r.uid == validateToken.uid);
if (refreshToken != null)
{
refreshToken.revoke_Date = DateTime.Now;
await _repositoryService.SaveData<RefreshToken, string>(refreshToken, rt => rt.uid);
return Ok(APIResponse.Send("000", "로그아웃 정상", Empty));
}
else
{
return Ok(APIResponse.Send("000", "로그아웃 정상", Empty));
}
}
catch (TokenException tokenEx)
{
return Ok(APIResponse.Send("101", "입력 받은 토큰의 문제", Empty));
}
catch (RefreshRevokeException refreshEx)
{
return Ok(APIResponse.Send("102", "폐기된 리프레시 토큰", Empty));
}
catch (Exception ex)
{
return StatusCode(500, APIResponse.UnknownError());
}
}
// [HttpGet("set")]
}