Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package org.example.visacasemanagementsystem;

import org.example.visacasemanagementsystem.user.security.SecurityUser;
import org.example.visacasemanagementsystem.user.security.UserPrincipal;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Objects;

@Controller
public class ApplicationViewController {
@GetMapping("/dashboard")
public String dashboard(@AuthenticationPrincipal SecurityUser principal) {
public String dashboard(@AuthenticationPrincipal UserPrincipal principal) {
if (principal == null) {
return "redirect:/user/login";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public class VisaCaseManagementSystemApplication {
public static void main(String[] args) {
SpringApplication.run(VisaCaseManagementSystemApplication.class, args);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,43 @@
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class DataInitializer{

@Bean
public CommandLineRunner initData(UserRepository userRepository) {
public CommandLineRunner initData(UserRepository userRepository, PasswordEncoder passwordEncoder) {
return args -> {

if (userRepository.findByEmail("user@test.com").isEmpty()) {
User user = new User();
user.setFullName("USER");
user.setUsername("user@test.com");
user.setEmail("user@test.com");
user.setPassword("password");
user.setPassword(passwordEncoder.encode("password"));
user.setUserAuthorization(UserAuthorization.USER);
userRepository.save(user);
System.out.println("Testanvändare skapad med ID: " + user.getId());
}

if (userRepository.findByEmail("admin@test.com").isEmpty()) {
User admin = new User();
admin.setFullName("ADMIN");
admin.setEmail("user@test.com2");
admin.setPassword("password");
admin.setUsername("admin@test.com");
admin.setEmail("admin@test.com");
admin.setPassword(passwordEncoder.encode("password"));
admin.setUserAuthorization(UserAuthorization.ADMIN);
userRepository.save(admin);
System.out.println("Test-admin skapad med ID: " + admin.getId());
}

if (userRepository.findByEmail("admin@test.com").isEmpty()) {
if (userRepository.findByEmail("sysadmin@test.com").isEmpty()) {
User sysadmin = new User();
sysadmin.setFullName("SYSTEM ADMIN");
sysadmin.setEmail("admin@test.com");
sysadmin.setPassword("password");
sysadmin.setUsername("sysadmin@test.com");
sysadmin.setEmail("sysadmin@test.com");
sysadmin.setPassword(passwordEncoder.encode("password"));
sysadmin.setUserAuthorization(UserAuthorization.SYSADMIN);
userRepository.save(sysadmin);
System.out.println("Test-sysadmin skapad med ID: " + sysadmin.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,60 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

private final UserDetailsService userDetailsService;

public SecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
.requestMatchers("/user/signup").permitAll()
.requestMatchers("/user/login").permitAll()
.requestMatchers("/dashboard").authenticated()
.requestMatchers("/**/admin").hasRole("ADMIN")
.requestMatchers("/**/applicant").hasRole("USER")
//TODO: requestMatchers for /**/{userId} endpoints, etc.
.anyRequest().hasRole("SYSADMIN")
)
.headers(headers -> headers.frameOptions(frame -> frame.disable()));
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
.formLogin(l -> l
.defaultSuccessUrl("/dashboard", true)
.loginPage("/user/login"))
.logout(withDefaults()) //TODO: Custom logout page required
.httpBasic(withDefaults());

return http.build();
}

@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authnProvider = new DaoAuthenticationProvider(userDetailsService);
authnProvider.setPasswordEncoder(passwordEncoder());
return authnProvider;
}

@Bean
public static PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
public enum UserAuthorization {
USER,
ADMIN,
SYSADMIN
SYSADMIN;

public String asAuthority() {
return "ROLE_" + name();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.example.visacasemanagementsystem.user.dto.CreateUserDTO;
import org.example.visacasemanagementsystem.user.dto.UpdateUserDTO;
import org.example.visacasemanagementsystem.user.dto.UserDTO;
import org.example.visacasemanagementsystem.user.security.SecurityUser;
import org.example.visacasemanagementsystem.user.security.UserPrincipal;
import org.example.visacasemanagementsystem.user.service.UserService;
import org.example.visacasemanagementsystem.visa.dto.VisaDTO;
import org.example.visacasemanagementsystem.visa.service.VisaService;
Expand All @@ -18,7 +18,6 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -71,7 +70,7 @@ public String userLoginForm(){
// Uneditable profile view from where the user themselves or a sysadmin can access the profile edit view through a
// button only available to them
@GetMapping("/profile/view/{userId}")
public String viewProfile(@AuthenticationPrincipal SecurityUser principal,
public String viewProfile(@AuthenticationPrincipal UserPrincipal principal,
@PathVariable Long userId,
Model model) {
UserDTO user = userService.findById(userId)
Expand All @@ -90,7 +89,7 @@ public String viewProfile(@AuthenticationPrincipal SecurityUser principal,

// Form for editing a users information, only available to the user themselves and sysadmins
@GetMapping("/profile/edit/{userId}")
public String showProfileEditForm(@AuthenticationPrincipal SecurityUser principal,
public String showProfileEditForm(@AuthenticationPrincipal UserPrincipal principal,
@PathVariable Long userId,
Model model) {
userService.validateProfileAccess(principal, userId);
Expand All @@ -104,7 +103,7 @@ public String showProfileEditForm(@AuthenticationPrincipal SecurityUser principa

// Posting information from user edit form
@PostMapping("/profile/edit/{userId}")
public String updateProfile(@AuthenticationPrincipal SecurityUser principal,
public String updateProfile(@AuthenticationPrincipal UserPrincipal principal,
@PathVariable Long userId,
@RequestParam String fullName,
@RequestParam String email,
Expand All @@ -124,7 +123,7 @@ public String updateProfile(@AuthenticationPrincipal SecurityUser principal,

// A list view of users only available to sysadmins
@GetMapping("/user/list")
public String userListView(@AuthenticationPrincipal SecurityUser principal,
public String userListView(@AuthenticationPrincipal UserPrincipal principal,
Model model) {
userService.validateSysAdmin(principal);
List<UserDTO> allUsers = userService.findAll();
Expand All @@ -134,7 +133,7 @@ public String userListView(@AuthenticationPrincipal SecurityUser principal,
}

@GetMapping("/dashboard/applicant")
public String applicantDashboard(@AuthenticationPrincipal SecurityUser principal,
public String applicantDashboard(@AuthenticationPrincipal UserPrincipal principal,
Model model) {
List<VisaDTO> visas = visaService.findVisasByApplicantId(principal.getUserId());
model.addAttribute("name", principal.getFullName());
Expand All @@ -143,7 +142,7 @@ public String applicantDashboard(@AuthenticationPrincipal SecurityUser principal
}

@GetMapping("/dashboard/admin")
public String adminDashboard(@AuthenticationPrincipal SecurityUser principal,
public String adminDashboard(@AuthenticationPrincipal UserPrincipal principal,
Model model) {
userService.validateAdmin(principal);
List<VisaDTO> assignedCases = visaService.findVisasByHandlerId(principal.getUserId());
Expand All @@ -155,7 +154,7 @@ public String adminDashboard(@AuthenticationPrincipal SecurityUser principal,
}

@GetMapping("/dashboard/sysadmin")
public String sysAdminDashboard(@AuthenticationPrincipal SecurityUser principal,
public String sysAdminDashboard(@AuthenticationPrincipal UserPrincipal principal,
Model model) {
userService.validateSysAdmin(principal);
List<UserDTO> allUsers = userService.findAll();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ public class User {
@Column(nullable = false, updatable = false)
private Long id;

@NotBlank @Column(unique = true, nullable = false)
private String username;

@NotBlank @Column(nullable = false)
private String password;

@NotBlank @Column(nullable = false)
private String fullName;

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

//Placeholder password storage solution
@NotBlank private String password;

@NotNull @Enumerated(EnumType.STRING)
private UserAuthorization userAuthorization;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public User toEntity(CreateUserDTO dto){
User user = new User();
user.setFullName(dto.fullName());
user.setEmail(dto.email());
user.setUsername(dto.email());
user.setUserAuthorization(dto.userAuthorization());
return user;
}
Expand All @@ -38,5 +39,6 @@ public void updateEntityFromDTO(UpdateUserDTO dto, User user) {

user.setFullName(dto.fullName());
user.setEmail(dto.email());
user.setUsername(dto.email());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import org.example.visacasemanagementsystem.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findByEmail(String email);

Optional<User> findByUsername(String username);

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ public UserDetailsServiceImpl(UserRepository userRepository) {

@Override
@NullMarked
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("No user found with email: " + email));
return new SecurityUser(user);
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("No user found with username: " + username));

return new UserPrincipal(user);
}
}
Loading