feat: add admin role and allow admins to create new users
This commit is contained in:
parent
00fe49b109
commit
930e6e5284
@ -68,6 +68,7 @@ public class SecurityConfig {
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/", "/login", "/swagger-ui/**", "/v3/api-docs/**").permitAll()
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.authenticationProvider(authenticationProvider())
|
||||
|
||||
@ -3,6 +3,7 @@ package online.wesal.wesal.controller;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import online.wesal.wesal.dto.CreateUserRequest;
|
||||
import online.wesal.wesal.dto.LoginRequest;
|
||||
import online.wesal.wesal.dto.LoginResponse;
|
||||
import online.wesal.wesal.dto.UsernameSelectionRequest;
|
||||
@ -65,4 +66,15 @@ public class AuthController {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/admin/createUser")
|
||||
@Operation(summary = "Create new user (Admin only)", description = "Creates a new user - requires admin privileges")
|
||||
public ResponseEntity<?> createUser(@Valid @RequestBody CreateUserRequest request) {
|
||||
try {
|
||||
User user = userService.createUser(request.getEmail(), request.getPassword(), request.getDisplayName());
|
||||
return ResponseEntity.ok(user);
|
||||
} catch (RuntimeException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package online.wesal.wesal.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class CreateUserRequest {
|
||||
|
||||
@Email
|
||||
@NotBlank
|
||||
private String email;
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 8)
|
||||
private String password;
|
||||
|
||||
@NotBlank
|
||||
private String displayName;
|
||||
|
||||
public CreateUserRequest() {}
|
||||
|
||||
public CreateUserRequest(String email, String password, String displayName) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
}
|
||||
@ -37,6 +37,9 @@ public class User {
|
||||
@Column(nullable = false)
|
||||
private boolean activated = false;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String role = "USER";
|
||||
|
||||
public User() {}
|
||||
|
||||
public User(String email, String password, String displayName) {
|
||||
@ -108,4 +111,12 @@ public class User {
|
||||
public void setActivated(boolean activated) {
|
||||
this.activated = activated;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
}
|
||||
@ -3,12 +3,15 @@ package online.wesal.wesal.service;
|
||||
import online.wesal.wesal.entity.User;
|
||||
import online.wesal.wesal.repository.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
@Service
|
||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
@ -21,10 +24,13 @@ public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
User user = userRepository.findByEmail(email)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + email));
|
||||
|
||||
Collection<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + user.getRole()));
|
||||
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
user.getEmail(),
|
||||
user.getPassword(),
|
||||
new ArrayList<>()
|
||||
authorities
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import online.wesal.wesal.repository.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@ -13,6 +14,9 @@ public class UserService {
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public User getCurrentUser() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String email = authentication.getName();
|
||||
@ -33,4 +37,22 @@ public class UserService {
|
||||
user.setUsername(username);
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
public boolean isCurrentUserAdmin() {
|
||||
User user = getCurrentUser();
|
||||
return "ADMIN".equals(user.getRole());
|
||||
}
|
||||
|
||||
public User createUser(String email, String password, String displayName) {
|
||||
if (!isCurrentUserAdmin()) {
|
||||
throw new RuntimeException("Access denied: Admin privileges required");
|
||||
}
|
||||
|
||||
if (userRepository.existsByEmail(email)) {
|
||||
throw new RuntimeException("User with this email already exists");
|
||||
}
|
||||
|
||||
User user = new User(email, passwordEncoder.encode(password), displayName);
|
||||
return userRepository.save(user);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user