| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- using System.Diagnostics;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.AspNetCore.Mvc.Filters;
- using Microsoft.AspNetCore.WebUtilities;
- using DeviceDetectorNET;
- using bitforum.Helpers;
- using bitforum.Models;
- namespace bitforum.Controllers.Member.Log
- {
- [Authorize]
- [Route("Member/Log")]
- public class LoginController : Controller
- {
- private readonly ILogger<LoginController> _logger;
- private readonly DefaultDbContext _db;
- private string? _queryString = null;
- public LoginController(ILogger<LoginController> logger, DefaultDbContext db)
- {
- _logger = logger;
- _db = db;
- }
- [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
- public IActionResult Error()
- {
- return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
- }
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- ViewBag.QueryString = _queryString = string.Join("&", QueryHelpers.ParseQuery(HttpContext.Request.QueryString.Value).Select(r => $"{r.Key}={r.Value.FirstOrDefault()}"));
- base.OnActionExecuting(context);
- }
- [HttpGet("Login")]
- public async Task<IActionResult> Index([FromQuery] int page = 1, int perPage = 10, byte? search = null, string? keyword = null, string startAt = null!, string endAt = null!)
- {
- var query = _db.LoginLog.AsQueryable(); // 기본 정렬 유지
- // 검색 조건 적용
- if (!string.IsNullOrEmpty(keyword) && search.HasValue)
- {
- if (search == 1) // ID 검색
- {
- if (int.TryParse(keyword, out int memberID))
- {
- query = query.Where(log => log.MemberID == memberID);
- }
- else
- {
- query = query.Where(log => log.MemberID == 0);
- }
- }
- else if (search == 2)
- {
- query = query.Where(log => _db.LoginLog.Any(c => c.Account.Contains(keyword))); // 이메일 검색
- }
- else if (search == 3)
- {
- query = query.Where(log => _db.Member.Any(m => m.Name != null && m.Name.Contains(keyword))); // 사용자명 검색
- }
- }
- var today = DateTime.UtcNow.Date;
- if (startAt != null && DateTime.TryParse(startAt, out var st))
- {
- query = query.Where(log => log.CreatedAt >= st);
- }
- if (endAt != null && DateTime.TryParse(endAt, out var et))
- {
- query = query.Where(log => log.CreatedAt <= et);
- }
- query = query.OrderByDescending(c => c.CreatedAt);
- // 페이징 처리
- var logs = await query
- .Skip((page - 1) * perPage)
- .Take(perPage)
- .Select(c => new
- {
- Name = _db.Member.Where(m => m.ID == c.MemberID).Select(m => m.Name).FirstOrDefault(), // 사용자명 추가
- c.ID,
- c.MemberID,
- c.Account,
- c.Success,
- c.Reason,
- c.Referer,
- c.Url,
- c.IpAddress,
- c.UserAgent,
- c.CreatedAt
- })
- .ToListAsync();
- var data = new List<object>();
- if (logs.Count > 0)
- {
- foreach (var row in logs)
- {
- var deviceDetector = new DeviceDetector(row.UserAgent);
- deviceDetector.Parse();
- var browser = deviceDetector.GetClient();
- var osInfo = deviceDetector.GetOs();
- var device = deviceDetector.GetModel();
- data.Add(new
- {
- row.ID,
- row.MemberID,
- row.Name,
- row.Account,
- Success = row.Success ? 'Y' : 'N',
- row.Reason,
- row.Referer,
- row.Url,
- row.IpAddress,
- Browser = browser,
- OS = osInfo,
- Device = device,
- ViewURL = $"/Member/Log/Login/{row.ID}?{_queryString}",
- DeleteURL = $"/Member/Log/Login/{row.ID}/Delete?{_queryString}",
- CreatedAt = row.CreatedAt.GetDateAt()
- });
- }
- }
- var parameter = new
- {
- Page = page,
- PerPage = perPage,
- Search = search,
- Keyword = keyword,
- StartAt = startAt,
- EndAt = endAt
- };
- ViewBag.Data = data;
- ViewBag.Total = await query.CountAsync();
- ViewBag.Parameter = parameter;
- ViewBag.Pagination = new Pagination(ViewBag.Total, page, perPage, parameter);
- return View("~/Views/Member/Log/Login/Index.cshtml");
- }
- [HttpGet("Login/{id}")]
- public async Task<IActionResult> View([FromRoute] int id)
- {
- try
- {
- if (id <= 0)
- {
- throw new Exception("유효하지 않은 접근입니다.");
- }
- var loginData = await _db.LoginLog.FindAsync(id);
- if (loginData == null)
- {
- throw new Exception("로그인 정보를 찾을 수 없습니다.");
- }
- var deviceDetector = new DeviceDetector(loginData.UserAgent);
- deviceDetector.Parse();
- var botInfo = deviceDetector.GetBot();
- var clientInfo = deviceDetector.GetClient();
- var osInfo = deviceDetector.GetOs();
- var device = deviceDetector.GetDeviceName();
- var brand = deviceDetector.GetBrandName();
- var model = deviceDetector.GetModel();
- ViewBag.Data = new
- {
- loginData.ID,
- loginData.MemberID,
- Name = _db.Member.Where(m => m.ID == loginData.MemberID).Select(m => m.Name).FirstOrDefault(), // 사용자명 추가
- Success = loginData.Success ? 'Y' : 'N',
- loginData.Account,
- loginData.Reason,
- loginData.Referer,
- loginData.Url,
- loginData.IpAddress,
- loginData.UserAgent,
- loginData.CreatedAt,
- Bot = botInfo,
- Browser = clientInfo,
- OS = osInfo,
- Device = device,
- Brand = brand,
- Model = model,
- };
- }
- catch (Exception e)
- {
- TempData["ErrorMessages"] = e.Message;
- _logger.LogError(e, e.Message);
- }
- return View("~/Views/Member/Log/Login/View.cshtml");
- }
- [HttpGet("Login/{id}/Delete")]
- public async Task<IActionResult> Delete(int id)
- {
- try
- {
- if (id <= 0)
- {
- throw new Exception("유효하지 않은 접근입니다.");
- }
- var data = await _db.LoginLog.FindAsync(id);
- if (data == null)
- {
- throw new Exception("로그인 정보를 찾을 수 없습니다.");
- }
- _db.LoginLog.Remove(data);
- int affectedRows = await _db.SaveChangesAsync();
- if (affectedRows <= 0)
- {
- throw new Exception("로그인 내역 삭제 중 오류가 발생했습니다.");
- }
- string message = "로그인 내역이 삭제되었습니다.";
- TempData["SuccessMessage"] = message;
- _logger.LogInformation(message);
- }
- catch (Exception e)
- {
- TempData["ErrorMessages"] = e.Message;
- _logger.LogError(e, e.Message);
- }
- return Redirect($"/Member/Log/Login?{_queryString}");
- }
- [HttpPost("Login/Delete")]
- public async Task<IActionResult> Delete([FromForm] int[] ids)
- {
- try
- {
- if (ids == null || ids.Length <= 0)
- {
- throw new Exception("유효하지 않은 접근입니다.");
- }
- foreach (var id in ids)
- {
- var data = await _db.LoginLog.FindAsync(id);
- if (data == null)
- {
- throw new Exception($"{id}번 로그인 정보를 찾을 수 없습니다.");
- }
- _db.LoginLog.Remove(data);
- int affectedRows = await _db.SaveChangesAsync();
- if (affectedRows <= 0)
- {
- throw new Exception($"{id}번 로그인 내역 삭제 중 오류가 발생했습니다.");
- }
- }
- string message = $"{ids.Length}건의 로그인 내역이 삭제되었습니다.";
- TempData["SuccessMessage"] = message;
- _logger.LogInformation(message);
- }
- catch (Exception e)
- {
- TempData["ErrorMessages"] = e.Message;
- _logger.LogError(e, e.Message);
- }
- return Redirect($"/Member/Log/Login?{_queryString}");
- }
- }
- }
|