Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/ru/t1/java/demo/config/KafkaConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
import org.springframework.kafka.support.serializer.JsonDeserializer;
import org.springframework.kafka.support.serializer.JsonSerializer;
import org.springframework.util.backoff.FixedBackOff;
import ru.t1.java.demo.dto.TransactionForAccept;
import ru.t1.java.demo.kafka.KafkaProducer;
import ru.t1.java.demo.kafka.MessageDeserializer;
import ru.t1.java.demo.model.dto.TransactionForAccept;

import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -83,7 +83,7 @@ ConcurrentKafkaListenerContainerFactory<String, T> kafkaListenerContainerFactory

@Bean
ConcurrentKafkaListenerContainerFactory<String, TransactionForAccept> kafkaListenerContainerTransactionForAcceptFactory() {
return (ConcurrentKafkaListenerContainerFactory<String, TransactionForAccept>) kafkaListenerContainerFactory("ru.t1.java.demo.dto.TransactionForAccept");
return (ConcurrentKafkaListenerContainerFactory<String, TransactionForAccept>) kafkaListenerContainerFactory("ru.t1.java.demo.model.dto.TransactionForAccept");
}

private void factoryBuilder(ConsumerFactory<String, T> consumerFactory, ConcurrentKafkaListenerContainerFactory<String, T> factory) {
Expand Down
102 changes: 102 additions & 0 deletions src/main/java/ru/t1/java/demo/config/WebSecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package ru.t1.java.demo.config;


import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import ru.t1.java.demo.service.impl.UserDetailsServiceImpl;
import ru.t1.java.demo.util.AuthEntryPointJwt;
import ru.t1.java.demo.util.AuthTokenFilter;
import ru.t1.java.demo.util.JwtUtils;

@Configuration
@EnableMethodSecurity
@RequiredArgsConstructor
public class WebSecurityConfig { // extends WebSecurityConfigurerAdapter { // Spring Boot 2
private final UserDetailsServiceImpl userDetailsService;
private final JwtUtils jwtUtils;
private final AuthEntryPointJwt unauthorizedHandler;

// Spring Boot 2

// @Override
// public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
// authenticationManagerBuilder.userDetailsService(userDetailsService)
// .passwordEncoder(passwordEncoder());
// }

// @Override
// protected void configure(HttpSecurity http) throws Exception {
// http.cors().and().csrf().disable()
// .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// .authorizeRequests().antMatchers("/api/auth/**").permitAll()
// .antMatchers("/api/test/**").permitAll()
// .anyRequest().authenticated();
//
// http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
// }

// @Bean
// @Override
// public AuthenticationManager authenticationManagerBean() throws Exception {
// return super.authenticationManagerBean();
// }

@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter(jwtUtils, userDetailsService);
}

@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();

authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());

return authProvider;
}


@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.requestMatchers("/api/auth/**").anonymous()
.requestMatchers("/parse/**").anonymous()
.requestMatchers("/parse").anonymous()
.requestMatchers("/actuator/prometheus").anonymous()
.requestMatchers("/actuator/*").anonymous()
.anyRequest().anonymous()
);

http.authenticationProvider(authenticationProvider());

http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

return http.build();
}
}
120 changes: 120 additions & 0 deletions src/main/java/ru/t1/java/demo/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package ru.t1.java.demo.controller;


import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import ru.t1.java.demo.model.Role;
import ru.t1.java.demo.model.RoleEnum;
import ru.t1.java.demo.model.User;
import ru.t1.java.demo.model.dto.JwtResponse;
import ru.t1.java.demo.model.dto.LoginRequest;
import ru.t1.java.demo.model.dto.MessageResponse;
import ru.t1.java.demo.model.dto.SignupRequest;
import ru.t1.java.demo.repository.RoleRepository;
import ru.t1.java.demo.repository.UserRepository;
import ru.t1.java.demo.service.impl.UserDetailsImpl;
import ru.t1.java.demo.util.JwtUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthenticationManager authenticationManager;

private final UserRepository userRepository;

private final RoleRepository roleRepository;

private final PasswordEncoder encoder;

private final JwtUtils jwtUtils;

@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {

Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);

UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());

return ResponseEntity.ok(new JwtResponse(jwt,
userDetails.getId(),
userDetails.getUsername(),
userDetails.getEmail(),
roles));
}

@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
if (userRepository.existsByLogin(signUpRequest.getUsername())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Username is already taken!"));
}

if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Email is already in use!"));
}

// Create new user's account
User user = new User(signUpRequest.getUsername(),
signUpRequest.getEmail(),
encoder.encode(signUpRequest.getPassword()));

Set<String> strRoles = signUpRequest.getRole();
Set<Role> roles = new HashSet<>();

if (strRoles == null) {
Role userRole = roleRepository.findByName(RoleEnum.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
} else {
strRoles.forEach(role -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(RoleEnum.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(adminRole);

break;
case "mod":
Role modRole = roleRepository.findByName(RoleEnum.ROLE_MODERATOR)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(modRole);

break;
default:
Role userRole = roleRepository.findByName(RoleEnum.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
}
});
}

user.setRoles(roles);
userRepository.save(user);

return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
}
}
68 changes: 68 additions & 0 deletions src/main/java/ru/t1/java/demo/controller/ClientController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package ru.t1.java.demo.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import ru.t1.java.demo.model.Client;
import ru.t1.java.demo.model.dto.CheckRequest;
import ru.t1.java.demo.model.dto.CheckResponse;
import ru.t1.java.demo.model.dto.ClientDto;
import ru.t1.java.demo.service.ClientService;
import ru.t1.java.demo.util.ClientMapper;

@RestController
@RequiredArgsConstructor
@Slf4j
public class ClientController {

private final ClientService clientService;
private final ClientMapper clientMapper;

@GetMapping(value = "/parse")
public void parseSource() {
throw new IllegalStateException();

// clientRepository.save(Client.builder()
// .firstName("John42")
// .build());
// clientRepository.findClientByFirstName("John42");
// metricService.incrementByName(Metrics.CLIENT_CONTROLLER_REQUEST_COUNT.getValue());
}

@PostMapping(value = "/checkClient")
public ResponseEntity<CheckResponse> parseSource(@RequestBody CheckRequest checkRequest) {
return ResponseEntity.ok()
.body(CheckResponse.builder()
.blocked(Math.random() < 0.5)
.build());
}

@GetMapping("/client")
public ResponseEntity<ClientDto> getClient() {
return ResponseEntity.ok()
.body(ClientDto.builder()
.firstName("John")
.build());
}

@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return "Admin Board.";
}

@GetMapping("/register")
public ResponseEntity<Client> register(@RequestBody ClientDto clientDto) {
log.info("Registering client: {}", clientDto);
Client client = clientService.registerClient(
clientMapper.toEntityWithId(clientDto)
);
log.info("Client registered: {}", client.getId());
return ResponseEntity.ok().body(client);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import ru.t1.java.demo.dto.TransactionForAccept;
import ru.t1.java.demo.dto.TransactionResult;
import ru.t1.java.demo.mapper.TransactionResultMapper;
import ru.t1.java.demo.model.Transaction;
import ru.t1.java.demo.model.dto.TransactionForAccept;
import ru.t1.java.demo.model.dto.TransactionResult;
import ru.t1.java.demo.service.TransactionService;

import java.math.BigDecimal;
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/ru/t1/java/demo/mapper/ClientMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.t1.java.demo.mapper;

import org.mapstruct.*;
import ru.t1.java.demo.model.Client;
import ru.t1.java.demo.model.dto.ClientDto;

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE,
componentModel = MappingConstants.ComponentModel.SPRING)
public interface ClientMapper {
Client toEntity(ClientDto clientDto);

ClientDto toDto(Client client);

@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
Client partialUpdate(ClientDto clientDto, @MappingTarget Client client);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
import ru.t1.java.demo.dto.TransactionForAccept;
import ru.t1.java.demo.dto.TransactionResult;
import ru.t1.java.demo.model.Transaction;
import ru.t1.java.demo.model.dto.TransactionForAccept;
import ru.t1.java.demo.model.dto.TransactionResult;

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE,
componentModel = MappingConstants.ComponentModel.SPRING)
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/ru/t1/java/demo/model/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public class Client extends EntityObject {
@Column(name = "middle_name")
private String middleName;

@Column(name = "blocked_for")
private Boolean blockedFor;

@Column(name = "blocked_whom")
private String blockedWhom;

@OneToMany(cascade = CascadeType.ALL,
mappedBy = "client")
private List<Account> accounts = new ArrayList<>();
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/ru/t1/java/demo/model/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.t1.java.demo.model;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Table(name = "role")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Role {

@Id
@SequenceGenerator(name = "ID_GEN", sequenceName = "role_seq", allocationSize = 1)
@GeneratedValue(generator = "ID_GEN", strategy = GenerationType.SEQUENCE)
private Long id;

@Enumerated(EnumType.STRING)
@Column(length = 20)
private RoleEnum name;

}
Loading