Skip to content

Commit

Permalink
Merge pull request #31 from szymonpoltorak/roles
Browse files Browse the repository at this point in the history
Roles
  • Loading branch information
szymonpoltorak authored Jul 15, 2023
2 parents 7239210 + 3997be5 commit 51b8bad
Show file tree
Hide file tree
Showing 27 changed files with 558 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package razepl.dev.socialappbackend.admin;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import razepl.dev.socialappbackend.admin.interfaces.IAdminController;
import razepl.dev.socialappbackend.admin.interfaces.IAdminService;
import razepl.dev.socialappbackend.auth.apicalls.AuthResponse;
import razepl.dev.socialappbackend.auth.apicalls.RegisterRequest;
import razepl.dev.socialappbackend.auth.interfaces.AuthInterface;
import razepl.dev.socialappbackend.home.data.UserData;

import java.util.List;

import static razepl.dev.socialappbackend.admin.Constants.ADMIN_MAPPING;
import static razepl.dev.socialappbackend.admin.Constants.ENDPOINT_MATCHER;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = ADMIN_MAPPING)
public class AdminController implements IAdminController {
private final IAdminService adminService;
private final AuthInterface authInterface;

@Override
@GetMapping(value = ENDPOINT_MATCHER)
public final List<UserData> getUsersList() {
return adminService.getUsersList();
}

@Override
@DeleteMapping(value = ENDPOINT_MATCHER)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public final void deleteUser(@RequestParam String email) {
adminService.deleteUser(email);
}

@Override
@PatchMapping(value = ENDPOINT_MATCHER)
public final void updateUsersName(@RequestParam String email, @RequestParam String newName) {
adminService.updateUsersName(email, newName);
}

@Override
@PostMapping(value = ENDPOINT_MATCHER)
@ResponseStatus(value = HttpStatus.CREATED)
public final AuthResponse createUser(@RequestBody RegisterRequest registerRequest) {
return authInterface.registerUser(registerRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package razepl.dev.socialappbackend.admin;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import razepl.dev.socialappbackend.admin.interfaces.IAdminService;
import razepl.dev.socialappbackend.entities.user.interfaces.UserRepository;
import razepl.dev.socialappbackend.home.data.UserData;
import razepl.dev.socialappbackend.home.interfaces.DataServiceInterface;

import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class AdminService implements IAdminService {
private final UserRepository userRepository;
private final DataServiceInterface dataService;

@Override
public final List<UserData> getUsersList() {
log.info("Getting users list");

return userRepository
.findAll()
.stream()
.map(dataService::buildUserData)
.toList();
}

@Override
public final void deleteUser(String email) {
log.info("Deleting user with email: {}", email);

userRepository.deleteByEmail(email);
}

@Override
public final void updateUsersName(String email, String newName) {
log.info("Updating user with email: {}", email);
log.info("New name: {}", newName);

userRepository
.findByEmail(email)
.ifPresent(user -> {
user.setName(newName);

userRepository.save(user);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package razepl.dev.socialappbackend.admin;

final class Constants {
static final String ENDPOINT_MATCHER = "/users";
static final String ADMIN_MAPPING = "/api/admin";

private Constants() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package razepl.dev.socialappbackend.admin.interfaces;

import razepl.dev.socialappbackend.auth.apicalls.AuthResponse;
import razepl.dev.socialappbackend.auth.apicalls.RegisterRequest;
import razepl.dev.socialappbackend.home.data.UserData;

import java.util.List;

/**
* Represents the controller interface for admin-related operations.
*/
public interface IAdminController {
/**
* Retrieves a list of user data for all users.
*
* @return The list of user data.
*/
List<UserData> getUsersList();

/**
* Deletes a user with the specified email.
*
* @param email - The email of the user to delete.
*/
void deleteUser(String email);

/**
* Updates the name of a user with the specified email.
*
* @param email - The email of the user to update.
* @param newName - The new name for the user.
*/
void updateUsersName(String email, String newName);

/**
* Creates a new user based on the provided registration request.
*
* @param registerRequest - The registration request containing user details.
* @return The authentication response for the created user.
*/
AuthResponse createUser(RegisterRequest registerRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package razepl.dev.socialappbackend.admin.interfaces;

import razepl.dev.socialappbackend.home.data.UserData;

import java.util.List;

/**
* Represents the service interface for admin-related operations.
*/
public interface IAdminService {
/**
* Retrieves a list of user data for all users.
*
* @return The list of user data.
*/
List<UserData> getUsersList();

/**
* Deletes a user with the specified email.
*
* @param email - The email of the user to delete.
*/
void deleteUser(String email);

/**
* Updates the name of a user with the specified email.
*
* @param email - The email of the user to update.
* @param newName - The new name for the user.
*/
void updateUsersName(String email, String newName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import razepl.dev.socialappbackend.auth.interfaces.AuthServiceInterface;
import razepl.dev.socialappbackend.config.jwt.interfaces.JwtServiceInterface;
import razepl.dev.socialappbackend.config.jwt.interfaces.TokenManager;
import razepl.dev.socialappbackend.entities.user.Role;
import razepl.dev.socialappbackend.config.enums.Role;
import razepl.dev.socialappbackend.entities.user.User;
import razepl.dev.socialappbackend.entities.user.interfaces.UserRepository;
import razepl.dev.socialappbackend.exceptions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package razepl.dev.socialappbackend.config;

import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
Expand All @@ -14,10 +15,13 @@
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import razepl.dev.socialappbackend.config.enums.Role;
import razepl.dev.socialappbackend.config.interfaces.AppConfigInterface;
import razepl.dev.socialappbackend.entities.user.User;
import razepl.dev.socialappbackend.entities.user.interfaces.UserRepository;
import razepl.dev.socialappbackend.exceptions.AuthManagerInstanceException;

import java.time.LocalDate;
import java.util.List;

import static razepl.dev.socialappbackend.config.constants.CorsConfig.*;
Expand Down Expand Up @@ -81,4 +85,32 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration c
throw new AuthManagerInstanceException("Could not create authManager bean!");
}
}

@Bean
@Override
public CommandLineRunner commandLineRunner() {
return args -> {
User admin = User
.builder()
.name("Admin")
.surname("admin")
.role(Role.ADMIN)
.email("[email protected]")
.password(passwordEncoder().encode("Ab!#$123zncA"))
.dateOfBirth(LocalDate.parse("2000-01-01"))
.build();
userRepository.save(admin);

User moderator = User
.builder()
.name("moderator")
.surname("moderator")
.role(Role.MODERATOR)
.email("[email protected]")
.password(passwordEncoder().encode("Ab!#$789asdhjaksA"))
.dateOfBirth(LocalDate.parse("2000-01-01"))
.build();
userRepository.save(moderator);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand All @@ -23,8 +24,10 @@
import razepl.dev.socialappbackend.config.jwt.interfaces.JwtFilter;
import razepl.dev.socialappbackend.exceptions.SecurityChainException;

import static razepl.dev.socialappbackend.config.constants.Headers.LOGOUT_URL;
import static razepl.dev.socialappbackend.config.constants.Headers.WHITE_LIST;
import static razepl.dev.socialappbackend.config.constants.Headers.*;
import static razepl.dev.socialappbackend.config.enums.Permissions.*;
import static razepl.dev.socialappbackend.config.enums.Role.ADMIN;
import static razepl.dev.socialappbackend.config.enums.Role.MODERATOR;

/**
* Class made to configure security filter chain in app.
Expand Down Expand Up @@ -56,6 +59,35 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) {
.authorizeHttpRequests(request -> request
.requestMatchers(WHITE_LIST)
.permitAll()

.requestMatchers(ADMIN_MATCHERS).hasRole(ADMIN.name())

.requestMatchers(HttpMethod.GET, ADMIN_MATCHERS)
.hasAuthority(ADMIN_READ.name())

.requestMatchers(HttpMethod.POST, ADMIN_MATCHERS)
.hasAuthority(ADMIN_WRITE.name())

.requestMatchers(HttpMethod.PATCH, ADMIN_MATCHERS)
.hasAuthority(ADMIN_UPDATE.name())

.requestMatchers(HttpMethod.DELETE, ADMIN_MATCHERS)
.hasAuthority(ADMIN_DELETE.name())

.requestMatchers(MODERATOR_MATCHERS).hasAnyRole(ADMIN.name(), MODERATOR.name())

.requestMatchers(HttpMethod.GET, MODERATOR_MATCHERS)
.hasAnyAuthority(ADMIN_READ.name(), MODERATOR_READ.name())

.requestMatchers(HttpMethod.POST, MODERATOR_MATCHERS)
.hasAnyAuthority(ADMIN_WRITE.name(), MODERATOR_WRITE.name())

.requestMatchers(HttpMethod.PATCH, MODERATOR_MATCHERS)
.hasAnyAuthority(ADMIN_UPDATE.name(), MODERATOR_UPDATE.name())

.requestMatchers(HttpMethod.DELETE, MODERATOR_MATCHERS)
.hasAnyAuthority(ADMIN_DELETE.name(), MODERATOR_DELETE.name())

.anyRequest()
.authenticated()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ public final class Headers {
*/
private static final String SWAGGER_UI_MATCHERS = "/swagger-ui/**";

/**
* Admin endpoints matcher.
*/
public static final String ADMIN_MATCHERS = "/api/admin/**";

/**
* Moderator endpoints matcher.
*/
public static final String MODERATOR_MATCHERS = "/api/moderator/**";

/**
* List of URLs that should be excluded from authentication requirements.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package razepl.dev.socialappbackend.config.enums;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum Permissions {
ADMIN_READ("admin:read"),
ADMIN_WRITE("admin:write"),
ADMIN_DELETE("admin:delete"),
ADMIN_UPDATE("admin:update"),
MODERATOR_READ("moderator:read"),
MODERATOR_WRITE("moderator:write"),
MODERATOR_DELETE("moderator:delete"),
MODERATOR_UPDATE("moderator:update");

private final String permission;
}
Loading

0 comments on commit 51b8bad

Please sign in to comment.