/
bazhinilya
/
net-simple-jwt
Обзор
Документация
Войти
/
bazhinilya
/
net-simple-jwt
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
Controllers/AuthController.cs
225 строк
7 KB
bazhinilya
Initial commit
16 июн 2026, 23:19
16 июн 2026, 23:19
afe56b6
Код
Авторство
О чём код?
using net_simple_jwt.Data; using net_simple_jwt.Dto; using net_simple_jwt.Entities; using net_simple_jwt.Events; using net_simple_jwt.Services; namespace net_simple_jwt.Controllers; [ApiController] [Route("api/auth")] public class AuthController( IPasswordHasher _passwordHasher, ITokenService _tokenService, AuthEvents _events, IUserRepository _userRepository ) : ControllerBase { [AllowAnonymous] [HttpPost("register")] public async Task<IActionResult> Register([FromBody] RegisterRequest request) { // 1. Событие ПЕРЕД регистрацией var registrationContext = new UserRegistrationContext { Email = request.Email, Password = request.Password, AdditionalData = request.AdditionalData ?? [] }; if (_events.OnBeforeRegister != null) { var shouldCancel = await _events.OnBeforeRegister(registrationContext); if (shouldCancel || registrationContext.Cancel) { return BadRequest(new { message = registrationContext.CancelReason ?? "Registration cancelled" }); } } // 2. Проверка существования var existingUser = await _userRepository.GetByEmailAsync(request.Email); if (existingUser != null) return BadRequest(new { message = "Email already exists" }); // 3. Создание пользователя var user = new User { Id = Guid.NewGuid(), Email = request.Email, PasswordHash = _passwordHasher.HashPassword(request.Password), CreatedAt = DateTime.UtcNow }; await _userRepository.CreateAsync(user); // 4. Событие ПОСЛЕ регистрации if (_events.OnAfterRegister != null) { var registeredContext = new UserRegisteredContext { User = user, AdditionalData = registrationContext.AdditionalData }; await _events.OnAfterRegister(registeredContext); } // 5. Генерация токенов var accessToken = _tokenService.GenerateAccessToken(user); var refreshToken = _tokenService.GenerateRefreshToken(); await _userRepository.UpdateRefreshTokenAsync( user.Id, refreshToken, DateTime.UtcNow.AddDays(7) ); return Ok(new { accessToken, refreshToken, user = new { id = user.Id, email = user.Email } }); } [AllowAnonymous] [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginRequest request) { // 1. Событие ПЕРЕД логином var loginContext = new UserLoginContext { Email = request.Email }; if (_events.OnBeforeLogin != null) { var shouldCancel = await _events.OnBeforeLogin(loginContext); if (shouldCancel || loginContext.Cancel) { return Unauthorized(); } } // 2. Поиск пользователя var user = await _userRepository.GetByEmailAsync(request.Email); if (user == null) return Unauthorized(); // 3. Проверка блокировки if (user.LockoutEnd > DateTime.UtcNow) return Unauthorized(); // 4. Проверка пароля if (!_passwordHasher.VerifyPassword(request.Password, user.PasswordHash)) { await _userRepository.IncrementFailedAttemptsAsync(user.Id); if (user.FailedLoginAttempts >= 5) await _userRepository.LockoutAsync(user.Id, DateTime.UtcNow.AddMinutes(15)); return Unauthorized(); } // 5. Сброс попыток await _userRepository.ResetFailedAttemptsAsync(user.Id); // 6. Генерация токенов var accessToken = _tokenService.GenerateAccessToken(user); var refreshToken = _tokenService.GenerateRefreshToken(); await _userRepository.UpdateRefreshTokenAsync( user.Id, refreshToken, DateTime.UtcNow.AddDays(7) ); // 7. Событие ПОСЛЕ логина var response = new Dictionary<string, object> { ["accessToken"] = accessToken, ["refreshToken"] = refreshToken, ["userId"] = user.Id, ["email"] = user.Email }; if (_events.OnAfterLogin != null) { var loggedInContext = new UserLoggedInContext { User = user, AccessToken = accessToken, RefreshToken = refreshToken, ResponseData = response }; await _events.OnAfterLogin(loggedInContext); return Ok(loggedInContext.ResponseData); } return Ok(response); } [AllowAnonymous] [HttpPost("refresh")] public async Task<IActionResult> Refresh([FromBody] RefreshRequest request) { var user = await _userRepository.GetByRefreshTokenAsync(request.RefreshToken); if (user == null || user.RefreshTokenExpiryTime <= DateTime.UtcNow) return Unauthorized(); // Событие ПЕРЕД обновлением if (_events.OnBeforeRefresh != null) { var refreshContext = new UserRefreshContext { User = user, RefreshToken = request.RefreshToken }; await _events.OnBeforeRefresh(refreshContext); } var newAccessToken = _tokenService.GenerateAccessToken(user); var newRefreshToken = _tokenService.GenerateRefreshToken(); await _userRepository.UpdateRefreshTokenAsync( user.Id, newRefreshToken, DateTime.UtcNow.AddDays(7) ); // Событие ПОСЛЕ обновления var response = new Dictionary<string, object> { ["accessToken"] = newAccessToken, ["refreshToken"] = newRefreshToken }; if (_events.OnAfterRefresh != null) { var refreshedContext = new UserRefreshedContext { User = user, NewAccessToken = newAccessToken, NewRefreshToken = newRefreshToken, ResponseData = response }; await _events.OnAfterRefresh(refreshedContext); return Ok(refreshedContext.ResponseData); } return Ok(response); } [Authorize] [HttpPost("logout")] public async Task<IActionResult> Logout([FromBody] LogoutRequest? request = null) { if (request?.RefreshToken != null) { await _userRepository.RemoveRefreshTokenAsync(request.RefreshToken); } return Ok(); } }