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
32 changes: 22 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.5.Final</version>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.16.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
Expand All @@ -54,6 +54,10 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
Expand Down Expand Up @@ -159,7 +163,15 @@
</excludes>
</configuration>
</plugin>
</plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.github.WeeiaEduTeam.InfinityFinanceAPI;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
class CorsConfiguration {

@Value("${management.endpoints.web.cors.mapping-pattern}")
private String mappingPattern;

@Value("${management.endpoints.web.cors.allowed-methods}")
private String allowedMethods;

@Value("${management.endpoints.web.cors.allowed-headers}")
private String allowedHeaders;

@Value("${management.endpoints.web.cors.allowed-origins}")
private String allowedOrigins;

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.github.WeeiaEduTeam.InfinityFinanceAPI;

import com.github.WeeiaEduTeam.InfinityFinanceAPI.role.RoleType;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.stream.Collectors;

@Configuration
@SpringBootApplication
public class InfinityFinanceApiApplication {
class InfinityFinanceApiApplication {

public static void main(String[] args) {
SpringApplication.run(InfinityFinanceApiApplication.class, args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,25 @@ public class AppUser implements UserDetails {
@Column(name = "user_id")
private Long id;

//@Column(unique = true)
@Column(unique = true)
private String username;

//@Column(unique = true)
@Column(unique = true)
private String email;

private String password;

private String firstName;
private String secondName;


@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinTable(name="user_roles",

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private List<Role> roles = new ArrayList<>();

@JsonIgnore
@OneToMany(mappedBy = "appuser")
private List<Transaction> transactions = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.github.WeeiaEduTeam.InfinityFinanceAPI.appuser;

import com.github.WeeiaEduTeam.InfinityFinanceAPI.appuser.dto.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping(path = "/api/v1")
class AppUserAdminController {

private final AppUserAdminService appUserAdminService;

@GetMapping("/admin/users")
public ResponseEntity<List<AppUserDTO>> getAllUsers(
@RequestParam(defaultValue = "0") Integer page,
@RequestParam(defaultValue = "ASC") Sort.Direction direction,
@RequestParam(defaultValue = "id") String by) {

var users = appUserAdminService.getAllUsers(page, direction, by);

return ResponseEntity.ok(users);
}

@GetMapping("/admin/users/{userId:[0-9]+}")
public ResponseEntity<AppUserDTO> getSingleUser(@PathVariable long userId) {

var user = appUserAdminService.getSingleUser(userId);

return ResponseEntity.ok(user);
}

@PostMapping("/admin/users")
ResponseEntity<AppUserDTO> createAccount(@RequestBody CreateAppUserAdminDTO createAppUserAdminDTO) {

var user = appUserAdminService.createAccount(createAppUserAdminDTO);

return ResponseEntity.created(URI.create("/users/" + user.getId())).body(user);
}

@DeleteMapping("/admin/users/{userId:[0-9]+}")
ResponseEntity<Void> deleteAllUsersAndAllRelated(@PathVariable long userId) {
appUserAdminService.findAndDeleteUserWithRolesAndTransactions(userId);

return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

@PutMapping("/admin/users/{userId:[0-9]+}")
ResponseEntity<AppUserDTO> replaceUserAllDetails(
@PathVariable long userId,
@RequestBody ReplaceAppUserAllDetailsDTO replaceAppUserAllDetailsDTO) {

var replacedUser = appUserAdminService.replaceUserAllDetails(userId, replaceAppUserAllDetailsDTO);

return ResponseEntity.ok(replacedUser);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package com.github.WeeiaEduTeam.InfinityFinanceAPI.appuser;

import com.github.WeeiaEduTeam.InfinityFinanceAPI.appuser.dto.*;
import com.github.WeeiaEduTeam.InfinityFinanceAPI.appuser.rolestrategy.AppUserRoleStrategyFacade;
import com.github.WeeiaEduTeam.InfinityFinanceAPI.exception.ResourceNotFoundException;
import com.github.WeeiaEduTeam.InfinityFinanceAPI.util.CustomPageable;
import com.github.WeeiaEduTeam.InfinityFinanceAPI.transaction.TransactionAdminService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.function.Function;

@Service
@Slf4j
public class AppUserAdminService implements UserDetailsService {

@Autowired
private AppUserRepository appUserRepository;
@Autowired
private AppUserUtil appUserUtil;
@Autowired
private AppUserRoleStrategyFacade appUserRoleStrategyFacade;
@Autowired
private CustomPageable customPageable;

private TransactionAdminService transactionAdminService;

public void setTransactionAdminService(TransactionAdminService transactionAdminService) {
this.transactionAdminService = transactionAdminService;
}

public AppUser getUserById(long userId) {

return appUserRepository.findById(userId).orElseThrow(() -> ResourceNotFoundException.createWith("Could not find any user with id " + userId));
}

public AppUser getUserByUserName(String username) {
return appUserRepository.findByUsername(username);
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return getUserByUserName(username);
}

public Long getLoggedInUserId() {
return appUserRepository.getLoggedInUserId().orElseThrow(() -> new UsernameNotFoundException("User not found in the database"));
}

public List<AppUserDTO> getAllUsers(Integer pageNumber, Sort.Direction sortDirection, String sortBy) {
Pageable page = validateAndCreatePageable(pageNumber, sortDirection, sortBy);

var foundUsers = getUsers(page);

return foundUsers.stream().map(mapToAppUserDTO()).toList();
}

private @NotNull Page<AppUser> getUsers(Pageable page) {
return appUserRepository.findAll(page);
}

@NotNull
private Function<AppUser, AppUserDTO> mapToAppUserDTO() {
return appUserUtil::mapToAppUserDTO;
}

private Pageable validateAndCreatePageable(int pageNumber, Sort.Direction sortDirection, String sortBy) {
return customPageable.validateAndCreatePageable(pageNumber, sortDirection, sortBy, AppUser.class);
}

public AppUserDTO getSingleUser(long userId) {
var foundUser = getUserById(userId);

return mapToAppUserDTO(foundUser);
}

private AppUserDTO mapToAppUserDTO(AppUser foundUser) {
return appUserUtil.mapToAppUserDTO(foundUser);
}

public <T> AppUserDTO createAccount(T objectDTO) {
AppUser user = createAppUserFromCreateAppUserDTOAndHashPassword(objectDTO);

setRolesForUser(user, objectDTO);

user = saveUser(user);

return mapToAppUserDTO(user);
}

private <T> void setRolesForUser(AppUser user, T objectDTO) {
appUserRoleStrategyFacade.addRolesForUser(user, objectDTO);
}


private <T> AppUser createAppUserFromCreateAppUserDTOAndHashPassword(T createAppUserDTO) {
return appUserUtil.mapToAppUserFactory(createAppUserDTO);
}
@Transactional
public void findAndDeleteUserWithRolesAndTransactions(long userId) {
deleteTransactionsRelatedWithUser(userId);
deleteUserWithRoles(userId);
}

private void deleteTransactionsRelatedWithUser(long userId) {
transactionAdminService.deleteTransactionsRelatedWithUser(userId);
}

private void deleteUserWithRoles(long userId) {
var user = getUserById(userId);
deleteUser(user);
deleteRoleFromUser(user);
}

private void deleteRoleFromUser(AppUser user) {
appUserRoleStrategyFacade.removeRoles(user);
}

private void deleteUser(AppUser user) {
appUserRepository.delete(user);
}

AppUser saveUser(AppUser user) {
return appUserRepository.save(user);
}

@Transactional
public AppUserDTO replaceUserAllDetails(long userId, ReplaceAppUserAllDetailsDTO replaceAppUserAllDetailsDTO) {
var foundUser = getUserById(userId);

var overwrittenUser = overwriteAppUserAllDetails(foundUser, replaceAppUserAllDetailsDTO);

return mapAppUserToAppUserDTO(overwrittenUser);
}

private AppUserDTO mapAppUserToAppUserDTO(AppUser user) {
return appUserUtil.mapToAppUserDTO(user);
}

private AppUser overwriteAppUserAllDetails(AppUser foundUser, ReplaceAppUserAllDetailsDTO replaceAppUserAllDetailsDTO) {
return appUserUtil.overwriteAppUserAllDetails(foundUser, replaceAppUserAllDetailsDTO);
}
}
Loading