← Назад к вопросам

Что делал в личном кабинете

1.0 Junior🔥 11 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Личный кабинет: архитектура и реализация

В рамках разработки личного кабинета я работал над несколькими ключевыми компонентами системы, которые являются критичными для удобства пользователя и безопасности его данных.

Основные функции

Личный кабинет предоставляет пользователю централизованное место для управления профилем и всеми аспектами его взаимодействия с платформой:

  • Просмотр и редактирование профиля — изменение личных данных, аватара, контактной информации
  • Управление учётными записями — смена пароля, двухфакторная аутентификация, управление сеансами
  • История действий — просмотр истории входов, действий в системе, истории платежей
  • Уведомления и настройки — управление email-уведомлениями, SMS-оповещениями, настройками конфиденциальности

Архитектура реализации

Реализация основана на многослойной архитектуре (clean architecture):

@RestController
@RequestMapping("/api/v1/user/profile")
public class UserProfileController {
    
    private final UserProfileService userProfileService;
    private final JwtTokenProvider tokenProvider;
    
    @GetMapping
    public ResponseEntity<UserProfileDTO> getProfile(
            @AuthenticationPrincipal UserDetails userDetails) {
        return ResponseEntity.ok(
            userProfileService.getUserProfile(userDetails.getUsername())
        );
    }
    
    @PutMapping
    public ResponseEntity<UserProfileDTO> updateProfile(
            @RequestBody UpdateProfileRequest request,
            @AuthenticationPrincipal UserDetails userDetails) {
        return ResponseEntity.ok(
            userProfileService.updateUserProfile(userDetails.getUsername(), request)
        );
    }
}

Уровень сервиса

Основная бизнес-логика расположена в service слое:

@Service
@Transactional
public class UserProfileService {
    
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final EmailService emailService;
    
    public UserProfileDTO getUserProfile(String username) {
        User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UserNotFoundException("User not found"));
        return UserProfileMapper.toDTO(user);
    }
    
    public UserProfileDTO updateUserProfile(String username, UpdateProfileRequest request) {
        User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UserNotFoundException("User not found"));
        
        user.setFirstName(request.getFirstName());
        user.setLastName(request.getLastName());
        user.setEmail(request.getEmail());
        
        User savedUser = userRepository.save(user);
        emailService.sendProfileUpdateNotification(user.getEmail());
        
        return UserProfileMapper.toDTO(savedUser);
    }
    
    public void changePassword(String username, ChangePasswordRequest request) {
        User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UserNotFoundException("User not found"));
        
        if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
            throw new InvalidPasswordException("Old password is incorrect");
        }
        
        user.setPassword(passwordEncoder.encode(request.getNewPassword()));
        userRepository.save(user);
        emailService.sendPasswordChangeNotification(user.getEmail());
    }
}

Безопасность и аутентификация

При работе с личным кабинетом я уделяю особое внимание безопасности данных:

  • JWT токены — используются для stateless аутентификации
  • Refresh tokens — хранятся в базе с таймаутом, для предотвращения перехвата
  • HTTPS — все коммуникации защищены шифрованием
  • CSRF защита — для POST/PUT/DELETE операций
  • Валидация входных данных — на уровне контроллера и сервиса
@Service
public class AuthenticationService {
    
    private final JwtTokenProvider tokenProvider;
    private final RefreshTokenRepository refreshTokenRepository;
    
    public AuthResponse authenticate(LoginRequest request) {
        UserDetails userDetails = loadUserDetails(request.getUsername());
        validateCredentials(request.getPassword(), userDetails.getPassword());
        
        String accessToken = tokenProvider.generateToken(userDetails);
        String refreshToken = generateRefreshToken(userDetails.getUsername());
        
        return new AuthResponse(accessToken, refreshToken);
    }
    
    public AuthResponse refreshAccessToken(String refreshToken) {
        if (!tokenProvider.validateToken(refreshToken)) {
            throw new InvalidTokenException("Refresh token expired");
        }
        
        String username = tokenProvider.getUsernameFromToken(refreshToken);
        UserDetails userDetails = loadUserDetails(username);
        String newAccessToken = tokenProvider.generateToken(userDetails);
        
        return new AuthResponse(newAccessToken, refreshToken);
    }
}

Управление сеансами

Реализована система управления активными сеансами пользователя:

@Service
public class SessionManagementService {
    
    private final SessionRepository sessionRepository;
    
    public void createSession(String username, String deviceInfo, String ipAddress) {
        Session session = new Session();
        session.setUsername(username);
        session.setDeviceInfo(deviceInfo);
        session.setIpAddress(ipAddress);
        session.setLoginTime(LocalDateTime.now());
        session.setExpiryTime(LocalDateTime.now().plusHours(24));
        
        sessionRepository.save(session);
    }
    
    public List<SessionDTO> getActiveSessions(String username) {
        return sessionRepository.findByUsernameAndExpiryTimeAfter(
            username, LocalDateTime.now()
        ).stream()
         .map(SessionMapper::toDTO)
         .collect(Collectors.toList());
    }
    
    public void terminateSession(String sessionId, String username) {
        Session session = sessionRepository.findById(sessionId)
            .orElseThrow(() -> new SessionNotFoundException("Session not found"));
        
        if (!session.getUsername().equals(username)) {
            throw new UnauthorizedException("Cannot terminate other user's session");
        }
        
        sessionRepository.delete(session);
    }
}

База данных

Используется PostgreSQL с ORM Hibernate/JPA для управления данными:

@Entity
@Table(name = "users")
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;
    
    @Column(nullable = false, unique = true)
    private String username;
    
    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false)
    private String email;
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "last_name")
    private String lastName;
    
    @Column(name = "created_at")
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Session> sessions;
}

Тестирование

Для каждого компонента написаны unit и интеграционные тесты:

@SpringBootTest
public class UserProfileServiceTest {
    
    @MockBean
    private UserRepository userRepository;
    
    @Autowired
    private UserProfileService userProfileService;
    
    @Test
    void testGetUserProfile_Success() {
        User user = new User();
        user.setUsername("testuser");
        user.setEmail("test@example.com");
        
        when(userRepository.findByUsername("testuser"))
            .thenReturn(Optional.of(user));
        
        UserProfileDTO profile = userProfileService.getUserProfile("testuser");
        
        assertNotNull(profile);
        assertEquals("testuser", profile.getUsername());
    }
}

Результат

Реализованный личный кабинет обеспечивает удобный и безопасный способ управления профилем, соответствует лучшим практикам разработки и гарантирует защиту персональных данных пользователя.

Что делал в личном кабинете | PrepBro