dev #1
@@ -1,8 +1,8 @@
|
||||
POSTGRES_DB=no_copy_
|
||||
POSTGRES_USER=ncp_db
|
||||
POSTGRES_PASSWORD=ncpDbApp
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_DB=admin_db
|
||||
POSTGRES_USER=admin
|
||||
POSTGRES_PASSWORD=adminDbApp
|
||||
POSTGRES_PORT=5454
|
||||
POSTGRES_HOST=db
|
||||
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@ FROM eclipse-temurin:21-jre
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/build/libs/*.jar app.jar
|
||||
|
||||
EXPOSE 8080
|
||||
EXPOSE 8082
|
||||
|
||||
CMD ["java", "-jar", "app.jar"]
|
||||
@@ -20,6 +20,11 @@ configurations {
|
||||
}
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "org.springframework.cloud:spring-cloud-dependencies:2023.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -32,6 +37,8 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.security:spring-security-crypto:6.5.3'
|
||||
implementation("io.jsonwebtoken:jjwt:0.13.0")
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
@@ -39,5 +46,9 @@ dependencies {
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0'
|
||||
//security
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation("io.jsonwebtoken:jjwt:0.13.0")
|
||||
}
|
||||
|
||||
|
||||
+32
-11
@@ -1,22 +1,43 @@
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
admin:
|
||||
build: .
|
||||
container_name: admin-backend
|
||||
ports:
|
||||
- "8082:8080"
|
||||
db:
|
||||
image: postgres:17
|
||||
container_name: admin-db
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: prod
|
||||
POSTGRES_HOST: db
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_DB: no_copy_
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: admin_db
|
||||
POSTGRES_USER: admin
|
||||
POSTGRES_PASSWORD: adminDbApp
|
||||
ports:
|
||||
- "5454:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- app-network
|
||||
restart: unless-stopped
|
||||
|
||||
admin:
|
||||
build: .
|
||||
container_name: admin-backend
|
||||
ports:
|
||||
- "${SERVER_PORT:-8082}:${SERVER_PORT:-8082}"
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: prod
|
||||
POSTGRES_HOST: db
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_DB: admin_db
|
||||
POSTGRES_USER: admin
|
||||
POSTGRES_PASSWORD: adminDbApp
|
||||
SERVER_PORT: ${SERVER_PORT:-8082}
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- app-network
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
external: true
|
||||
+169
-38
@@ -2,68 +2,199 @@ pipeline {
|
||||
agent any
|
||||
|
||||
parameters {
|
||||
string(name: 'BRANCH', defaultValue: 'dev', description: 'Ветка для деплоя')
|
||||
string(name: 'SERVER', defaultValue: '92.242.61.23', description: 'Сервер для деплоя')
|
||||
string(
|
||||
name: 'BRANCH',
|
||||
defaultValue: 'dev',
|
||||
description: 'Ветка для деплоя'
|
||||
)
|
||||
string(
|
||||
name: 'PORT',
|
||||
defaultValue: '8082',
|
||||
description: 'Порт для запуска admin-panel'
|
||||
)
|
||||
string(
|
||||
name: 'SERVER',
|
||||
defaultValue: '92.242.61.23',
|
||||
description: 'Сервер для деплоя'
|
||||
)
|
||||
string(
|
||||
name: 'NETWORK',
|
||||
defaultValue: 'app-network',
|
||||
description: 'Имя сети (будет создана если не существует)'
|
||||
)
|
||||
string(
|
||||
name: 'DB_PORT',
|
||||
defaultValue: '5454',
|
||||
description: 'Порт для базы данных'
|
||||
)
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Git pull') {
|
||||
steps {
|
||||
cleanWs()
|
||||
git branch: params.BRANCH, url: 'https://code.3err0.ru/backdev/admin-panel.git', credentialsId: 'nx-jen'
|
||||
script {
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: [[name: params.BRANCH]],
|
||||
userRemoteConfigs: [[
|
||||
url: 'https://code.3err0.ru/backdev/admin-panel.git',
|
||||
credentialsId: 'nx-jen'
|
||||
]]
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy with docker-compose') {
|
||||
stage('Copy to server') {
|
||||
steps {
|
||||
script {
|
||||
withCredentials([
|
||||
usernamePassword(
|
||||
credentialsId: 'server-root-password',
|
||||
usernameVariable: 'SSH_USER',
|
||||
passwordVariable: 'SSH_PASS'
|
||||
)
|
||||
]) {
|
||||
sh """
|
||||
sshpass -p '${SSH_PASS}' ssh -o StrictHostKeyChecking=no ${SSH_USER}@${params.SERVER} '
|
||||
mkdir -p /opt/deployments/admin-panel-${params.PORT} &&
|
||||
rm -rf /opt/deployments/admin-panel-${params.PORT}/*
|
||||
'
|
||||
|
||||
sshpass -p '${SSH_PASS}' scp -r -o StrictHostKeyChecking=no \
|
||||
. \
|
||||
${SSH_USER}@${params.SERVER}:/opt/deployments/admin-panel-${params.PORT}/
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy admin-panel') {
|
||||
steps {
|
||||
script {
|
||||
def buildTime = sh(script: "TZ='Asia/Novosibirsk' date '+%d-%m-%Y %H:%M:%S'", returnStdout: true).trim()
|
||||
withCredentials([
|
||||
usernamePassword(credentialsId: 'server-root-password', usernameVariable: 'SSH_USER', passwordVariable: 'SSH_PASS'),
|
||||
string(credentialsId: 'DB_USER', variable: 'DB_USER'),
|
||||
string(credentialsId: 'DB_PASSWORD', variable: 'DB_PASSWORD')
|
||||
usernamePassword(
|
||||
credentialsId: 'server-root-password',
|
||||
usernameVariable: 'SSH_USER',
|
||||
passwordVariable: 'SSH_PASS'
|
||||
)
|
||||
]) {
|
||||
sh """
|
||||
sshpass -p '$SSH_PASS' ssh -o StrictHostKeyChecking=no $SSH_USER@$SERVER '
|
||||
cd /opt/deployments/admin-panel || mkdir -p /opt/deployments/admin-panel && cd /opt/deployments/admin-panel
|
||||
sshpass -p '${SSH_PASS}' ssh -o StrictHostKeyChecking=no ${SSH_USER}@${params.SERVER} "
|
||||
cd /opt/deployments/admin-panel-${params.PORT}
|
||||
|
||||
echo "1. Остановка старого контейнера..."
|
||||
docker stop admin-backend 2>/dev/null || echo "Контейнер не найден"
|
||||
docker rm admin-backend 2>/dev/null || echo "Контейнер не найден"
|
||||
echo '1. Проверяем/создаем сеть ${params.NETWORK}...'
|
||||
if ! docker network ls --format '{{.Name}}' | grep -q '^${params.NETWORK}\$'; then
|
||||
docker network create ${params.NETWORK}
|
||||
echo 'Сеть ${params.NETWORK} создана'
|
||||
else
|
||||
echo 'Сеть ${params.NETWORK} уже существует'
|
||||
fi
|
||||
|
||||
echo "2. Копирование файлов..."
|
||||
rsync -av --delete --exclude=.git --exclude=build . $SSH_USER@$SERVER:/opt/deployments/admin-panel/
|
||||
echo '2. Останавливаем старые контейнеры...'
|
||||
docker stop admin-panel-${params.PORT} 2>/dev/null || echo 'Контейнер приложения не найден'
|
||||
docker rm admin-panel-${params.PORT} 2>/dev/null || echo 'Контейнер приложения не найден'
|
||||
|
||||
echo "3. Сборка образа..."
|
||||
docker build --no-cache -t admin-backend:latest .
|
||||
docker stop admin-db-${params.PORT} 2>/dev/null || echo 'Контейнер БД не найден'
|
||||
docker rm admin-db-${params.PORT} 2>/dev/null || echo 'Контейнер БД не найден'
|
||||
|
||||
echo "4. Запуск контейнера..."
|
||||
docker run -d \
|
||||
--name admin-backend \
|
||||
--network app-network \
|
||||
--network-alias admin \
|
||||
-p 8082:8082 \
|
||||
-v uploads_data:/data/uploads:rw \
|
||||
-e POSTGRES_DB=no_copy_ \
|
||||
-e POSTGRES_USER=$DB_USER \
|
||||
-e POSTGRES_PASSWORD=$DB_PASSWORD \
|
||||
-e POSTGRES_PORT=5432 \
|
||||
-e POSTGRES_HOST=db \
|
||||
-e BUILD_TIME='${buildTime}' \
|
||||
--restart unless-stopped \
|
||||
admin-backend:latest
|
||||
echo '3. Запускаем базу данных...'
|
||||
docker run -d \\
|
||||
--name admin-db-${params.PORT} \\
|
||||
--network ${params.NETWORK} \\
|
||||
--network-alias db \\
|
||||
-p ${params.DB_PORT}:5432 \\
|
||||
-v admin_db_data_${params.PORT}:/var/lib/postgresql/data \\
|
||||
-e POSTGRES_DB=admin_db \\
|
||||
-e POSTGRES_USER=admin \\
|
||||
-e POSTGRES_PASSWORD=adminDbApp \\
|
||||
--restart unless-stopped \\
|
||||
postgres:16
|
||||
|
||||
echo "5. Проверка health..."
|
||||
if curl -s -f http://localhost:8082/actuator/health; then
|
||||
echo "Admin backend работает"
|
||||
else
|
||||
echo "Проблема с запуском admin-backend"
|
||||
fi
|
||||
'
|
||||
echo '4. Ждем готовности БД...'
|
||||
sleep 5
|
||||
until docker exec admin-db-${params.PORT} pg_isready -U admin; do
|
||||
echo 'Waiting for database...'
|
||||
sleep 2
|
||||
done
|
||||
echo 'База данных готова'
|
||||
|
||||
echo '5. Собираем образ приложения...'
|
||||
docker build --no-cache -t admin-panel-${params.PORT}:latest .
|
||||
|
||||
echo '6. Запускаем приложение...'
|
||||
docker run -d \\
|
||||
--name admin-panel-${params.PORT} \\
|
||||
--network ${params.NETWORK} \\
|
||||
--network-alias admin \\
|
||||
--network-alias admin-${params.PORT} \\
|
||||
-p ${params.PORT}:${params.PORT} \\
|
||||
-v uploads_data:/data/uploads:rw \\
|
||||
-e POSTGRES_DB=admin_db \\
|
||||
-e POSTGRES_USER=admin \\
|
||||
-e POSTGRES_PASSWORD=adminDbApp \\
|
||||
-e POSTGRES_PORT=5432 \\
|
||||
-e POSTGRES_HOST=db \\
|
||||
-e SERVER_PORT=${params.PORT} \\
|
||||
-e BUILD_TIME='${buildTime}' \\
|
||||
--restart unless-stopped \\
|
||||
admin-panel-${params.PORT}:latest
|
||||
|
||||
echo '7. Проверка...'
|
||||
sleep 10
|
||||
|
||||
if curl -s -f http://localhost:${params.PORT}/actuator/health > /dev/null 2>&1; then
|
||||
echo 'Admin-panel работает на порту ${params.PORT}'
|
||||
echo 'URL: http://${params.SERVER}:${params.PORT}'
|
||||
else
|
||||
echo 'Проверка health не удалась'
|
||||
echo '=== Логи приложения: ==='
|
||||
docker logs admin-panel-${params.PORT} --tail=30
|
||||
echo '=== Логи БД: ==='
|
||||
docker logs admin-db-${params.PORT} --tail=10
|
||||
fi
|
||||
"
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Verify network') {
|
||||
steps {
|
||||
script {
|
||||
withCredentials([
|
||||
usernamePassword(
|
||||
credentialsId: 'server-root-password',
|
||||
usernameVariable: 'SSH_USER',
|
||||
passwordVariable: 'SSH_PASS'
|
||||
)
|
||||
]) {
|
||||
sh """
|
||||
sshpass -p '${SSH_PASS}' ssh -o StrictHostKeyChecking=no ${SSH_USER}@${params.SERVER} "
|
||||
echo '=== Контейнеры в сети ${params.NETWORK} ==='
|
||||
docker network inspect ${params.NETWORK} --format='{{range .Containers}}{{.Name}} ({{.IPv4Address}}){{println}}{{end}}'
|
||||
"
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
echo "Deployment successful"
|
||||
echo "Admin panel URL: http://${params.SERVER}:${params.PORT}"
|
||||
}
|
||||
failure {
|
||||
echo "Deployment failed for branch ${params.BRANCH} on port ${params.PORT}"
|
||||
}
|
||||
always {
|
||||
echo "Deployment process finished"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package ru.soune.nocopy.adminpanel;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableFeignClients
|
||||
public class AdminPanelApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package ru.soune.nocopy.adminpanel.client;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
import ru.soune.nocopy.adminpanel.dto.BaseRequest;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(name = "dashboard", url = "${nocopy-dashboard.url}")
|
||||
public interface DashBoardAppClient {
|
||||
|
||||
@PostMapping("/api/v1/data")
|
||||
Map<String, Object> getUsersWithPagination(@RequestBody BaseRequest request);
|
||||
|
||||
@PostMapping("api/internal/data-info")
|
||||
Map<String, Object> internalDataInfo(@RequestBody BaseRequest request);
|
||||
|
||||
@PostMapping("api/internal/data-control")
|
||||
Map<String, Object> internalDataControl(@RequestBody BaseRequest request);
|
||||
|
||||
@GetMapping("api/internal/data-download/{fileId}")
|
||||
ResponseEntity<byte[]> download(@PathVariable String fileId);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package ru.soune.nocopy.adminpanel.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import ru.soune.nocopy.adminpanel.handler.AdminUserHandler;
|
||||
import ru.soune.nocopy.adminpanel.handler.CreateAdminTemplateHandler;
|
||||
import ru.soune.nocopy.adminpanel.handler.LoginHandler;
|
||||
import ru.soune.nocopy.adminpanel.handler.RequestHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedOrigin("*");
|
||||
config.addAllowedMethod("*");
|
||||
config.addAllowedHeader("*");
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Map<Integer, RequestHandler> handlers(AdminUserHandler adminUserHandler, CreateAdminTemplateHandler createAdminTemplateHandler) {
|
||||
Map<Integer, RequestHandler> map = new HashMap<>();
|
||||
map.put(100, adminUserHandler);
|
||||
map.put(200, createAdminTemplateHandler);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Map<Integer, RequestHandler> loginHandlers(LoginHandler loginHandler) {
|
||||
Map<Integer, RequestHandler> map = new HashMap<>();
|
||||
map.put(101, loginHandler);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package ru.soune.nocopy.adminpanel.config;
|
||||
|
||||
import feign.RequestInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class FeignConfig {
|
||||
|
||||
@Value("${app.internal-api-key}")
|
||||
private String internalApiKey;
|
||||
|
||||
@Bean
|
||||
public RequestInterceptor internalKeyInterceptor() {
|
||||
return requestTemplate -> {
|
||||
requestTemplate.header("X-Internal-Key", internalApiKey);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package ru.soune.nocopy.adminpanel.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import ru.soune.nocopy.adminpanel.util.JwtAuthFilter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityConfig {
|
||||
|
||||
private final JwtAuthFilter jwtAuthFilter;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.sessionManagement(session ->
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/admin/login").permitAll()
|
||||
// .requestMatchers("/api/admin").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package ru.soune.nocopy.adminpanel.controller;
|
||||
|
||||
import feign.FeignException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.soune.nocopy.adminpanel.client.DashBoardAppClient;
|
||||
import ru.soune.nocopy.adminpanel.dto.BaseRequest;
|
||||
import ru.soune.nocopy.adminpanel.dto.BaseResponse;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSection;
|
||||
import ru.soune.nocopy.adminpanel.handler.RequestHandler;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminSectionPermissionService;
|
||||
import ru.soune.nocopy.adminpanel.util.MessageCode;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/admin")
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AdminController {
|
||||
|
||||
private final Map<Integer, RequestHandler> handlers;
|
||||
|
||||
private final Map<Integer, RequestHandler> loginHandlers;
|
||||
|
||||
private final DashBoardAppClient dashBoardAppClient;
|
||||
|
||||
private final AdminSectionPermissionService adminSectionPermissionService;
|
||||
|
||||
private final HttpServletRequest httpServletRequest;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<BaseResponse> handleRequest(@RequestBody BaseRequest request) {
|
||||
log.info("Received request: msg_id={}, version={}", request.getMsgId(), request.getVersion());
|
||||
|
||||
try {
|
||||
RequestHandler handler = handlers.get(request.getMsgId());
|
||||
|
||||
if (handler == null) {
|
||||
log.warn("No handler found for msg_id: {}", request.getMsgId());
|
||||
return ResponseEntity.ok(
|
||||
BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc("No handler for msg_id: " + request.getMsgId())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
BaseResponse response = handler.handle(request);
|
||||
log.info("Request processed successfully: msg_id={}", request.getMsgId());
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error processing request: msg_id={}", request.getMsgId(), e);
|
||||
return ResponseEntity.ok(
|
||||
BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc("Internal server error: " + e.getMessage())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<BaseResponse> handleLoginRequest(@RequestBody BaseRequest request) {
|
||||
log.info("Received request: msg_id={}, version={}", request.getMsgId(), request.getVersion());
|
||||
|
||||
try {
|
||||
RequestHandler handler = loginHandlers.get(request.getMsgId());
|
||||
|
||||
if (handler == null) {
|
||||
log.warn("No handler found for msg_id: {}", request.getMsgId());
|
||||
return ResponseEntity.ok(
|
||||
BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc("No handler for msg_id: " + request.getMsgId())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
BaseResponse response = handler.handle(request);
|
||||
log.info("Request processed successfully: msg_id={}", request.getMsgId());
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error processing request: msg_id={}", request.getMsgId(), e);
|
||||
return ResponseEntity.ok(
|
||||
BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc("Internal server error: " + e.getMessage())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/info")
|
||||
public ResponseEntity<BaseResponse> handleInfo(@RequestBody BaseRequest request) {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return ResponseEntity.ok(BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't reads")
|
||||
.build());
|
||||
}
|
||||
|
||||
request.setAdminId(currentUserId);
|
||||
|
||||
Map<String, Object> response = dashBoardAppClient.internalDataInfo(request);
|
||||
|
||||
return ResponseEntity.ok(
|
||||
BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(response)
|
||||
.build());
|
||||
}
|
||||
|
||||
@PostMapping("/control")
|
||||
public ResponseEntity<BaseResponse> handleControl(@RequestBody BaseRequest request) {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return ResponseEntity.ok(BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't control")
|
||||
.build());
|
||||
}
|
||||
|
||||
request.setAdminId(currentUserId);
|
||||
|
||||
Map<String, Object> response = dashBoardAppClient.internalDataControl(request);
|
||||
|
||||
return ResponseEntity.ok(
|
||||
BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(response)
|
||||
.build());
|
||||
}
|
||||
|
||||
@GetMapping("/download/{fileId}")
|
||||
public ResponseEntity<byte[]> downloadFile(@PathVariable String fileId) {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canRead(currentUserId, AdminSection.CONTENT_MODERATION)) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
try {
|
||||
return dashBoardAppClient.download(fileId);
|
||||
} catch (FeignException.NotFound e) {
|
||||
return ResponseEntity.notFound().build();
|
||||
} catch (FeignException e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class ActionResponse {
|
||||
@JsonProperty("action")
|
||||
private String action;
|
||||
|
||||
@JsonProperty("available_actions")
|
||||
private List<String> availableActions;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class AdminCreateTemplateRequest {
|
||||
|
||||
@JsonProperty("permissions")
|
||||
private Map<String, Integer> permissions;
|
||||
|
||||
@JsonProperty("change_password")
|
||||
private Boolean changePassword;
|
||||
|
||||
@JsonProperty("action")
|
||||
private String action;
|
||||
|
||||
@JsonProperty("id")
|
||||
private Long id;
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class AdminCreateTemplateResponse {
|
||||
@JsonProperty("id")
|
||||
private Long id;
|
||||
|
||||
@JsonProperty("permissions")
|
||||
private Map<String, Integer> permissions;
|
||||
|
||||
@JsonProperty("change_password")
|
||||
private Boolean changePassword;
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class AdminUserRequest {
|
||||
@JsonProperty("action")
|
||||
private String action;
|
||||
|
||||
@JsonProperty("admin_id")
|
||||
private Long adminId;
|
||||
|
||||
@JsonProperty("full_name")
|
||||
private String fullName;
|
||||
|
||||
@JsonProperty("email")
|
||||
private String email;
|
||||
|
||||
@JsonProperty("password")
|
||||
private String password;
|
||||
|
||||
@JsonProperty("new_password")
|
||||
private String newPassword;
|
||||
|
||||
@JsonProperty("old_password")
|
||||
private String oldPassword;
|
||||
|
||||
@JsonProperty("is_super_admin")
|
||||
private Boolean isSuperAdmin;
|
||||
|
||||
@JsonProperty("is_active")
|
||||
private Boolean isActive;
|
||||
|
||||
@JsonProperty("change_password")
|
||||
private Boolean changePassword;
|
||||
|
||||
@JsonProperty("permissions")
|
||||
private Map<String, Integer> permissions;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class AdminUserResponse {
|
||||
@JsonProperty("id")
|
||||
private Long id;
|
||||
|
||||
@JsonProperty("full_name")
|
||||
private String fullName;
|
||||
|
||||
@JsonProperty("email")
|
||||
private String email;
|
||||
|
||||
@JsonProperty("is_active")
|
||||
private Boolean isActive;
|
||||
|
||||
@JsonProperty("is_super_admin")
|
||||
private Boolean isSuperAdmin;
|
||||
|
||||
@JsonProperty("created_at")
|
||||
private String createdAt;
|
||||
|
||||
@JsonProperty("active_password")
|
||||
private Boolean activePassword;
|
||||
|
||||
private Map<String, Integer> permissions;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
|
||||
public class BaseRequest {
|
||||
@JsonProperty("version")
|
||||
Integer version;
|
||||
|
||||
@JsonProperty("msg_id")
|
||||
Integer msgId;
|
||||
|
||||
@JsonProperty("message_body")
|
||||
Object messageBody;
|
||||
|
||||
@JsonProperty(value = "admin_id", required = false)
|
||||
Long adminId;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
|
||||
public class BaseResponse {
|
||||
@JsonProperty("msg_id")
|
||||
private Integer msgId;
|
||||
|
||||
@JsonProperty("message_code")
|
||||
private Integer messageCode;
|
||||
|
||||
@JsonProperty("message_desc")
|
||||
private String messageDesc;
|
||||
|
||||
@JsonProperty("message_body")
|
||||
private Object messageBody;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package ru.soune.nocopy.adminpanel.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class LoginResponse {
|
||||
@JsonProperty("success")
|
||||
private Boolean success;
|
||||
|
||||
@JsonProperty("token")
|
||||
private String token;
|
||||
|
||||
@JsonProperty("admin")
|
||||
private AdminUserResponse admin;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package ru.soune.nocopy.adminpanel.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "admin_create_template")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AdminCreateTemplate {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "permission", columnDefinition = "TEXT")
|
||||
String permission;
|
||||
|
||||
@Column(name = "change_password")
|
||||
Boolean changePassword;
|
||||
|
||||
@Column(name = "name")
|
||||
String name;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ru.soune.nocopy.adminpanel.entity;
|
||||
|
||||
public enum AdminSection {
|
||||
DASH,
|
||||
USERS,
|
||||
STAFF,
|
||||
SUBSCRIPTIONS,
|
||||
TARIFFS,
|
||||
CONTENT_MODERATION,
|
||||
COMPLAINTS,
|
||||
CLAIMS,
|
||||
MAILINGS,
|
||||
API,
|
||||
MONEY,
|
||||
KYC,
|
||||
AGREEMENTS
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package ru.soune.nocopy.adminpanel.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "admin_section_permissions")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class AdminSectionPermission {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "user_id", nullable = false, unique = true)
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "dash", nullable = false)
|
||||
private Integer dash = 0b00;
|
||||
|
||||
@Column(name = "users", nullable = false)
|
||||
private Integer users = 0b00;
|
||||
|
||||
@Column(name = "staff", nullable = false)
|
||||
private Integer staff = 0b00;
|
||||
|
||||
@Column(name = "subscriptions", nullable = false)
|
||||
private Integer subscriptions = 0b00;
|
||||
|
||||
@Column(name = "tariffs", nullable = false)
|
||||
private Integer tariffs = 0b00;
|
||||
|
||||
@Column(name = "content_moderation", nullable = false)
|
||||
private Integer contentModeration = 0b00;
|
||||
|
||||
@Column(name = "complaints", nullable = false)
|
||||
private Integer complaints = 0b00;
|
||||
|
||||
@Column(name = "claims", nullable = false)
|
||||
private Integer claims = 0b00;
|
||||
|
||||
@Column(name = "mailings", nullable = false)
|
||||
private Integer mailings = 0b00;
|
||||
|
||||
@Column(name = "api", nullable = false)
|
||||
private Integer api = 0b00;
|
||||
|
||||
@Column(name = "money", nullable = false)
|
||||
private Integer money = 0b00;
|
||||
|
||||
@Column(name = "kyc", nullable = false)
|
||||
private Integer kyc = 0b00;
|
||||
|
||||
@Column(name = "agreements", nullable = false)
|
||||
private Integer agreements = 0b00;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_at", updatable = false)
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
|
||||
@LastModifiedDate
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package ru.soune.nocopy.adminpanel.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.*;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
import ru.soune.nocopy.adminpanel.permission.AdminPermission;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "admin_users")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString(exclude = {"password", "permissions"})
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class AdminUser {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "full_name")
|
||||
private String fullName;
|
||||
|
||||
@Size(max = 1024)
|
||||
@Column(name = "email", length = 1024, unique = true)
|
||||
private String email;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Size(min = 6)
|
||||
@JsonIgnore
|
||||
private String password;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_at", updatable = false, nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@LastModifiedDate
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private Boolean isActive = true;
|
||||
|
||||
@Column(name = "is_super_admin", nullable = false)
|
||||
private Boolean isSuperAdmin = false;
|
||||
|
||||
@Column(name = "active_password", nullable = false)
|
||||
private Boolean isActivePassword = false;
|
||||
|
||||
@Column(name = "permissions", nullable = false)
|
||||
private Long permissions = AdminPermission.DEFAULT_PERMISSIONS;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ru.soune.nocopy.adminpanel.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum PermissionType {
|
||||
READ(0b01), NONE(0b00), WRITE_AND_READ(0b11);
|
||||
|
||||
private final Integer value;
|
||||
|
||||
PermissionType(Integer value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ru.soune.nocopy.adminpanel.exceptions;
|
||||
|
||||
public class AdminUserNotFoundException extends RuntimeException {
|
||||
public AdminUserNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ru.soune.nocopy.adminpanel.exceptions;
|
||||
|
||||
public class EmailAlreadyExistsException extends RuntimeException {
|
||||
public EmailAlreadyExistsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ru.soune.nocopy.adminpanel.exceptions;
|
||||
|
||||
public class WrongPassword extends RuntimeException {
|
||||
public WrongPassword(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,551 @@
|
||||
package ru.soune.nocopy.adminpanel.handler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.soune.nocopy.adminpanel.dto.*;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSection;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminUser;
|
||||
import ru.soune.nocopy.adminpanel.entity.PermissionType;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.AdminUserNotFoundException;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.EmailAlreadyExistsException;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.WrongPassword;
|
||||
import ru.soune.nocopy.adminpanel.permission.AdminPermission;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminSectionPermissionService;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminUserService;
|
||||
import ru.soune.nocopy.adminpanel.util.JwtUtil;
|
||||
import ru.soune.nocopy.adminpanel.util.MessageCode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AdminUserHandler implements RequestHandler {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final AdminUserService adminUserService;
|
||||
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
private final AdminSectionPermissionService permissionService;
|
||||
|
||||
private final HttpServletRequest httpServletRequest;
|
||||
|
||||
private final AdminSectionPermissionService adminSectionPermissionService;
|
||||
|
||||
@Override
|
||||
public BaseResponse handle(BaseRequest request) throws Exception {
|
||||
AdminUserRequest adminRequest = objectMapper.convertValue(request.getMessageBody(), AdminUserRequest.class);
|
||||
String action = adminRequest.getAction();
|
||||
|
||||
return switch (action) {
|
||||
case "login" -> handleLogin(request, adminRequest);
|
||||
case "create" -> handleCreate(request, adminRequest);
|
||||
case "get_all" -> handleGetAll(request, adminRequest);
|
||||
case "get_by_id" -> handleGetById(request, adminRequest);
|
||||
case "update" -> handleUpdate(request, adminRequest);
|
||||
case "set_super_admin" -> handleSetSuperAdmin(request, adminRequest);
|
||||
case "toggle_active" -> handleToggleActive(request, adminRequest);
|
||||
case "delete" -> handleDelete(request, adminRequest);
|
||||
case "get_permissions_by_id" -> handleGetPermissionsById(request, adminRequest);
|
||||
case "update_permissions" -> handleUpdatePermissions(request, adminRequest);
|
||||
default -> handleInvalidAction(request, action);
|
||||
};
|
||||
}
|
||||
|
||||
private BaseResponse handleLogin(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
String email = adminRequest.getEmail();
|
||||
String password = adminRequest.getPassword();
|
||||
|
||||
boolean authenticated = adminUserService.authenticate(email, password);
|
||||
|
||||
if (!authenticated) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_CREDENTIALS.getCode())
|
||||
.messageDesc(MessageCode.INVALID_CREDENTIALS.getDescription())
|
||||
.build();
|
||||
}
|
||||
|
||||
try {
|
||||
AdminUser admin = adminUserService.findByEmail(email);
|
||||
|
||||
if (!admin.getIsActive()) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_INACTIVE.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_INACTIVE.getDescription())
|
||||
.build();
|
||||
}
|
||||
|
||||
String token = jwtUtil.generateToken(admin.getEmail(), admin.getId());
|
||||
|
||||
LoginResponse loginResponse = LoginResponse.builder()
|
||||
.success(true)
|
||||
.token(token)
|
||||
.admin(convertToResponse(admin))
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(loginResponse)
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleCreate(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.STAFF)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't create profile")
|
||||
.build();
|
||||
}
|
||||
|
||||
boolean superAdmin = adminRequest.getIsSuperAdmin() != null && adminRequest.getIsSuperAdmin();
|
||||
boolean changePassword = adminRequest.getChangePassword() != null ? adminRequest.getChangePassword():
|
||||
!superAdmin;
|
||||
|
||||
AdminUser admin = adminUserService.create(
|
||||
adminRequest.getFullName(),
|
||||
adminRequest.getEmail(),
|
||||
adminRequest.getPassword(),
|
||||
changePassword, superAdmin);
|
||||
|
||||
Map<String, Integer> permissions = adminRequest.getPermissions();
|
||||
Map<AdminSection, Integer> sectionPermissons = new HashMap<>();
|
||||
|
||||
if (superAdmin) {
|
||||
sectionPermissons.put(AdminSection.DASH, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.USERS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.STAFF, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.SUBSCRIPTIONS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.TARIFFS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.CONTENT_MODERATION, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.COMPLAINTS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.CLAIMS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.MAILINGS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.API, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.MONEY, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.KYC, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.AGREEMENTS, PermissionType.WRITE_AND_READ.getValue());
|
||||
} else {
|
||||
for (Map.Entry<String, Integer> entry: permissions.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
AdminSection adminSection = AdminSection.valueOf(name.toUpperCase());
|
||||
|
||||
sectionPermissons.put(adminSection, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
permissionService.setAllPermissions(admin.getId(), sectionPermissons);
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(admin))
|
||||
.build();
|
||||
} catch (EmailAlreadyExistsException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.EMAIL_ALREADY_EXISTS.getCode())
|
||||
.messageDesc(MessageCode.EMAIL_ALREADY_EXISTS.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleGetAll(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't reads")
|
||||
.build();
|
||||
}
|
||||
|
||||
List<AdminUserResponse> admins = adminUserService.findAll().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(admins)
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleGetById(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
AdminUser admin = adminUserService.findById(adminRequest.getAdminId());
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!currentUserId.equals(adminRequest.getAdminId())) {
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't read")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(admin))
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleUpdate(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!currentUserId.equals(adminRequest.getAdminId())) {
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't update profile")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
AdminUser admin = adminUserService.update(
|
||||
adminRequest.getAdminId(),
|
||||
adminRequest.getFullName(),
|
||||
adminRequest.getEmail(),
|
||||
adminRequest.getOldPassword(),
|
||||
adminRequest.getNewPassword());
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(admin))
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
} catch (EmailAlreadyExistsException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.EMAIL_ALREADY_EXISTS.getCode())
|
||||
.messageDesc(MessageCode.EMAIL_ALREADY_EXISTS.getDescription())
|
||||
.build();
|
||||
} catch (WrongPassword e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.WRONG_PASSWORD.getCode())
|
||||
.messageDesc(MessageCode.WRONG_PASSWORD.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleSetSuperAdmin(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't update profile")
|
||||
.build();
|
||||
}
|
||||
|
||||
AdminUser admin = adminUserService.setSuperAdmin(adminRequest.getAdminId(), adminRequest.getIsSuperAdmin());
|
||||
|
||||
Map<AdminSection, Integer> sectionPermissons = new HashMap<>();
|
||||
|
||||
sectionPermissons.put(AdminSection.DASH, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.USERS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.STAFF, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.SUBSCRIPTIONS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.TARIFFS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.CONTENT_MODERATION, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.COMPLAINTS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.CLAIMS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.MAILINGS, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.API, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.MONEY, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.KYC, PermissionType.WRITE_AND_READ.getValue());
|
||||
sectionPermissons.put(AdminSection.AGREEMENTS, PermissionType.WRITE_AND_READ.getValue());
|
||||
|
||||
permissionService.setAllPermissions(admin.getId(), sectionPermissons);
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(admin))
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleToggleActive(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!currentUserId.equals(adminRequest.getAdminId())) {
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't update profile")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
adminUserService.toggleActive(adminRequest.getAdminId(), adminRequest.getIsActive());
|
||||
AdminUser admin = adminUserService.findById(adminRequest.getAdminId());
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(admin))
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleDelete(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't delete profile")
|
||||
.build();
|
||||
}
|
||||
|
||||
adminUserService.delete(adminRequest.getAdminId());
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody("Admin deleted successfully")
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleInvalidAction(BaseRequest request, String action) {
|
||||
ActionResponse response = ActionResponse.builder()
|
||||
.action(action)
|
||||
.availableActions(Arrays.asList(
|
||||
"login", "create", "get_all", "get_by_id",
|
||||
"update", "set_super_admin", "toggle_active", "delete",
|
||||
"get_permissions_by_id", "update_permissions"))
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc(MessageCode.INVALID_ACTION.getDescription())
|
||||
.messageBody(response)
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleGetPermissionsById(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!currentUserId.equals(adminRequest.getAdminId())) {
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't update profile")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
Long userId = adminRequest.getAdminId();
|
||||
AdminUser admin = adminUserService.findById(userId);
|
||||
|
||||
Map<AdminSection, Integer> sectionPermissions = permissionService.getAllPermissions(userId);
|
||||
|
||||
Map<String, Integer> permissionsMap = new HashMap<>();
|
||||
sectionPermissions.forEach((section, value) ->
|
||||
permissionsMap.put(section.name().toLowerCase(), value));
|
||||
|
||||
AdminUserResponse response = AdminUserResponse.builder()
|
||||
.id(admin.getId())
|
||||
.fullName(admin.getFullName())
|
||||
.email(admin.getEmail())
|
||||
.isActive(admin.getIsActive())
|
||||
.isSuperAdmin(AdminPermission.isSuperAdmin(admin.getPermissions()))
|
||||
.createdAt(admin.getCreatedAt().toString())
|
||||
.permissions(permissionsMap)
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(response)
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleUpdatePermissions(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
try {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.USERS)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc("You can't update profile")
|
||||
.build();
|
||||
}
|
||||
|
||||
Long userId = adminRequest.getAdminId();
|
||||
Map<String, Integer> permissionsMap = adminRequest.getPermissions();
|
||||
|
||||
if (permissionsMap == null || permissionsMap.isEmpty()) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_IS_EMPTY.getCode())
|
||||
.messageDesc("Permissions map is required")
|
||||
.build();
|
||||
}
|
||||
|
||||
Map<AdminSection, Integer> permissions = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, Integer> entry : permissionsMap.entrySet()) {
|
||||
try {
|
||||
AdminSection section = AdminSection.valueOf(entry.getKey().toUpperCase());
|
||||
permissions.put(section, entry.getValue());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc("Invalid section: " + entry.getKey() +
|
||||
". Valid sections: " + Arrays.toString(AdminSection.values()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
permissionService.setAllPermissions(userId, permissions);
|
||||
|
||||
AdminUser admin = adminUserService.findById(userId);
|
||||
Map<AdminSection, Integer> updatedPermissions = permissionService.getAllPermissions(userId);
|
||||
|
||||
Map<String, Integer> updatedPermissionsMap = new HashMap<>();
|
||||
updatedPermissions.forEach((section, value) ->
|
||||
updatedPermissionsMap.put(section.name().toLowerCase(), value));
|
||||
|
||||
AdminUserResponse response = AdminUserResponse.builder()
|
||||
.id(admin.getId())
|
||||
.fullName(admin.getFullName())
|
||||
.email(admin.getEmail())
|
||||
.isActive(admin.getIsActive())
|
||||
.isSuperAdmin(AdminPermission.isSuperAdmin(admin.getPermissions()))
|
||||
.createdAt(admin.getCreatedAt().toString())
|
||||
.permissions(updatedPermissionsMap)
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc("Permissions updated successfully")
|
||||
.messageBody(response)
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private AdminUserResponse convertToResponse(AdminUser admin) {
|
||||
Map<AdminSection, Integer> sectionPermissions = permissionService.getAllPermissions(admin.getId());
|
||||
|
||||
Map<String, Integer> permissionsMap = new HashMap<>();
|
||||
sectionPermissions.forEach((section, value) ->
|
||||
permissionsMap.put(section.name().toLowerCase(), value));
|
||||
|
||||
return AdminUserResponse.builder()
|
||||
.id(admin.getId())
|
||||
.fullName(admin.getFullName())
|
||||
.email(admin.getEmail())
|
||||
.isActive(admin.getIsActive())
|
||||
.isSuperAdmin(AdminPermission.isSuperAdmin(admin.getPermissions()))
|
||||
.createdAt(admin.getCreatedAt().toString())
|
||||
.permissions(permissionsMap)
|
||||
.activePassword(admin.getIsActivePassword())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
package ru.soune.nocopy.adminpanel.handler;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.soune.nocopy.adminpanel.dto.*;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminCreateTemplate;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSection;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminCreateTemplateService;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminSectionPermissionService;
|
||||
import ru.soune.nocopy.adminpanel.util.MessageCode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class CreateAdminTemplateHandler implements RequestHandler {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final AdminCreateTemplateService adminCreateTemplateService;
|
||||
|
||||
private final AdminSectionPermissionService adminSectionPermissionService;
|
||||
|
||||
private final HttpServletRequest httpServletRequest;
|
||||
|
||||
@Override
|
||||
public BaseResponse handle(BaseRequest request) {
|
||||
AdminCreateTemplateRequest adminCreateTemplateRequest = objectMapper.convertValue(request.getMessageBody(),
|
||||
AdminCreateTemplateRequest.class);
|
||||
String action = adminCreateTemplateRequest.getAction();
|
||||
|
||||
return switch (action) {
|
||||
case "create" -> handleCreate(request, adminCreateTemplateRequest);
|
||||
case "update" -> handleUpdate(request, adminCreateTemplateRequest);
|
||||
case "delete" -> handleDelete(request, adminCreateTemplateRequest);
|
||||
case "get_all" -> handleGetAll(request);
|
||||
case "get_by_id" -> handleGetById(request, adminCreateTemplateRequest);
|
||||
default -> handleInvalidAction(request, action);
|
||||
};
|
||||
}
|
||||
|
||||
private BaseResponse handleDelete(BaseRequest request, AdminCreateTemplateRequest adminCreateTemplateRequest) {
|
||||
Long adminCreateTemplateRequestId = adminCreateTemplateRequest.getId();
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (adminCreateTemplateRequestId == null || !adminCreateTemplateService.existById(adminCreateTemplateRequestId)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.TEMPLATE_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.TEMPLATE_NOT_FOUND.getDescription())
|
||||
.messageBody(Map.of("id", adminCreateTemplateRequest.getId()))
|
||||
.build();
|
||||
}
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.STAFF)) {
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc(MessageCode.PERMISSION_DENIED.getDescription())
|
||||
.messageBody(Map.of("currentUserId", currentUserId))
|
||||
.build();
|
||||
}
|
||||
|
||||
adminCreateTemplateService.deleteTemplate(adminCreateTemplateRequestId);
|
||||
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(Map.of("id", adminCreateTemplateRequestId))
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleUpdate(BaseRequest request, AdminCreateTemplateRequest adminCreateTemplateRequest) {
|
||||
Map<String, Integer> permissionsMap = adminCreateTemplateRequest.getPermissions();
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (permissionsMap == null || permissionsMap.isEmpty()) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.TEMPLATE_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.TEMPLATE_NOT_FOUND.getDescription())
|
||||
.messageBody(Map.of("id", adminCreateTemplateRequest.getId()))
|
||||
.build();
|
||||
}
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.STAFF)) {
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc(MessageCode.PERMISSION_DENIED.getDescription())
|
||||
.messageBody(Map.of("currentUserId", currentUserId))
|
||||
.build();
|
||||
}
|
||||
|
||||
ObjectNode node = objectMapper.createObjectNode();
|
||||
|
||||
for (Map.Entry<String, Integer> entry: permissionsMap.entrySet()) {
|
||||
node.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
Boolean changePassword = adminCreateTemplateRequest.getChangePassword();
|
||||
|
||||
AdminCreateTemplate adminTemplate =
|
||||
adminCreateTemplateService.updateCreateTemplate(node.toString(), changePassword,
|
||||
adminCreateTemplateRequest.getId(), adminCreateTemplateRequest.getName());
|
||||
|
||||
if (adminTemplate == null) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.TEMPLATE_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.TEMPLATE_NOT_FOUND.getDescription())
|
||||
.messageBody(Map.of("id", adminCreateTemplateRequest.getId()))
|
||||
.build();
|
||||
}
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(adminTemplate))
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleCreate(BaseRequest request, AdminCreateTemplateRequest adminCreateTemplateRequest) {
|
||||
Map<String, Integer> permissionsMap = adminCreateTemplateRequest.getPermissions();
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (permissionsMap == null || permissionsMap.isEmpty()) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_IS_EMPTY.getCode())
|
||||
.messageDesc("Permissions map is required")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
if (!adminSectionPermissionService.canWrite(currentUserId,
|
||||
AdminSection.STAFF)) {
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc(MessageCode.PERMISSION_DENIED.getDescription())
|
||||
.messageBody(Map.of("currentUserId", currentUserId))
|
||||
.build();
|
||||
}
|
||||
|
||||
ObjectNode node = objectMapper.createObjectNode();
|
||||
|
||||
for (Map.Entry<String, Integer> entry: permissionsMap.entrySet()) {
|
||||
node.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
Boolean changePassword = adminCreateTemplateRequest.getChangePassword();
|
||||
|
||||
AdminCreateTemplate adminTemplate =
|
||||
adminCreateTemplateService.createAdminTemplate(node.toString(), changePassword,
|
||||
adminCreateTemplateRequest.getName());
|
||||
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(adminTemplate))
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleGetAll(BaseRequest request) {
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.STAFF)) {
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc(MessageCode.PERMISSION_DENIED.getDescription())
|
||||
.messageBody(Map.of("currentUserId", currentUserId))
|
||||
.build();
|
||||
}
|
||||
|
||||
List<AdminCreateTemplateResponse> templateResponses = adminCreateTemplateService.getAllTemplates()
|
||||
.stream()
|
||||
.map(this::convertToResponse)
|
||||
.toList();
|
||||
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(templateResponses)
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleGetById(BaseRequest request, AdminCreateTemplateRequest adminCreateTemplateRequest) {
|
||||
Long id = adminCreateTemplateRequest.getId();
|
||||
Long currentUserId = (Long) httpServletRequest.getAttribute("userId");
|
||||
|
||||
if (id == null || !adminCreateTemplateService.existById(id)) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.TEMPLATE_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.TEMPLATE_NOT_FOUND.getDescription())
|
||||
.messageBody(Map.of("id", adminCreateTemplateRequest.getId()))
|
||||
.build();
|
||||
}
|
||||
|
||||
if (!adminSectionPermissionService.canRead(currentUserId,
|
||||
AdminSection.STAFF)) {
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.PERMISSION_DENIED.getCode())
|
||||
.messageDesc(MessageCode.PERMISSION_DENIED.getDescription())
|
||||
.messageBody(Map.of("currentUserId", currentUserId))
|
||||
.build();
|
||||
}
|
||||
|
||||
AdminCreateTemplate template = adminCreateTemplateService.getTemplateById(adminCreateTemplateRequest.getId());
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(convertToResponse(template))
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleInvalidAction(BaseRequest request, String action) {
|
||||
ActionResponse response = ActionResponse.builder()
|
||||
.action(action)
|
||||
.availableActions(Arrays.asList("create", "update", "delete", "get_all", "get_by_id"))
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc(MessageCode.INVALID_ACTION.getDescription())
|
||||
.messageBody(response)
|
||||
.build();
|
||||
}
|
||||
|
||||
private AdminCreateTemplateResponse convertToResponse(AdminCreateTemplate adminTemplate) {
|
||||
Map<String, Integer> permissionsMap = null;
|
||||
try {
|
||||
permissionsMap = objectMapper.readValue(
|
||||
adminTemplate.getPermission(),
|
||||
new TypeReference<Map<String, Integer>>() {}
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to parse permissions", e);
|
||||
}
|
||||
|
||||
return AdminCreateTemplateResponse.builder()
|
||||
.id(adminTemplate.getId())
|
||||
.changePassword(adminTemplate.getChangePassword())
|
||||
.permissions(permissionsMap)
|
||||
.name(adminTemplate.getName())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package ru.soune.nocopy.adminpanel.handler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.soune.nocopy.adminpanel.dto.*;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSection;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminUser;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.AdminUserNotFoundException;
|
||||
import ru.soune.nocopy.adminpanel.permission.AdminPermission;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminSectionPermissionService;
|
||||
import ru.soune.nocopy.adminpanel.service.AdminUserService;
|
||||
import ru.soune.nocopy.adminpanel.util.JwtUtil;
|
||||
import ru.soune.nocopy.adminpanel.util.MessageCode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class LoginHandler implements RequestHandler {
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final AdminUserService adminUserService;
|
||||
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
private final AdminSectionPermissionService permissionService;
|
||||
|
||||
@Override
|
||||
public BaseResponse handle(BaseRequest request) {
|
||||
AdminUserRequest adminRequest = objectMapper.convertValue(request.getMessageBody(), AdminUserRequest.class);
|
||||
String action = adminRequest.getAction();
|
||||
|
||||
return switch (action) {
|
||||
case "login" -> handleLogin(request, adminRequest);
|
||||
default -> handleInvalidAction(request, action);
|
||||
};
|
||||
}
|
||||
|
||||
private BaseResponse handleLogin(BaseRequest request, AdminUserRequest adminRequest) {
|
||||
String email = adminRequest.getEmail();
|
||||
String password = adminRequest.getPassword();
|
||||
|
||||
boolean authenticated = adminUserService.authenticate(email, password);
|
||||
|
||||
if (!authenticated) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_CREDENTIALS.getCode())
|
||||
.messageDesc(MessageCode.INVALID_CREDENTIALS.getDescription())
|
||||
.build();
|
||||
}
|
||||
|
||||
try {
|
||||
AdminUser admin = adminUserService.findByEmail(email);
|
||||
|
||||
if (!admin.getIsActive()) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_INACTIVE.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_INACTIVE.getDescription())
|
||||
.build();
|
||||
}
|
||||
|
||||
String token = jwtUtil.generateToken(admin.getEmail(), admin.getId());
|
||||
|
||||
LoginResponse loginResponse = LoginResponse.builder()
|
||||
.success(true)
|
||||
.token(token)
|
||||
.admin(convertToResponse(admin))
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.SUCCESS.getCode())
|
||||
.messageDesc(MessageCode.SUCCESS.getDescription())
|
||||
.messageBody(loginResponse)
|
||||
.build();
|
||||
} catch (AdminUserNotFoundException e) {
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.ADMIN_NOT_FOUND.getCode())
|
||||
.messageDesc(MessageCode.ADMIN_NOT_FOUND.getDescription())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private AdminUserResponse convertToResponse(AdminUser admin) {
|
||||
Map<AdminSection, Integer> sectionPermissions = permissionService.getAllPermissions(admin.getId());
|
||||
|
||||
Map<String, Integer> permissionsMap = new HashMap<>();
|
||||
sectionPermissions.forEach((section, value) ->
|
||||
permissionsMap.put(section.name().toLowerCase(), value));
|
||||
|
||||
return AdminUserResponse.builder()
|
||||
.id(admin.getId())
|
||||
.fullName(admin.getFullName())
|
||||
.email(admin.getEmail())
|
||||
.isActive(admin.getIsActive())
|
||||
.isSuperAdmin(AdminPermission.isSuperAdmin(admin.getPermissions()))
|
||||
.createdAt(admin.getCreatedAt().toString())
|
||||
.permissions(permissionsMap)
|
||||
.activePassword(admin.getIsActivePassword())
|
||||
.build();
|
||||
}
|
||||
|
||||
private BaseResponse handleInvalidAction(BaseRequest request, String action) {
|
||||
ActionResponse response = ActionResponse.builder()
|
||||
.action(action)
|
||||
.availableActions(Arrays.asList(
|
||||
"login"))
|
||||
.build();
|
||||
|
||||
return BaseResponse.builder()
|
||||
.msgId(request.getMsgId())
|
||||
.messageCode(MessageCode.INVALID_ACTION.getCode())
|
||||
.messageDesc(MessageCode.INVALID_ACTION.getDescription())
|
||||
.messageBody(response)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package ru.soune.nocopy.adminpanel.handler;
|
||||
|
||||
import ru.soune.nocopy.adminpanel.dto.BaseRequest;
|
||||
import ru.soune.nocopy.adminpanel.dto.BaseResponse;
|
||||
|
||||
public interface RequestHandler {
|
||||
BaseResponse handle(BaseRequest request) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package ru.soune.nocopy.adminpanel.permission;
|
||||
|
||||
public class AdminPermission {
|
||||
public static final long ADMIN_BIT = 1L;
|
||||
public static final long SUPER_ADMIN_BIT = 1L << 1;
|
||||
|
||||
public static final long DEFAULT_PERMISSIONS = ADMIN_BIT;
|
||||
public static final long SUPER_ADMIN_PERMISSIONS = ADMIN_BIT | SUPER_ADMIN_BIT;
|
||||
|
||||
public static boolean hasPermission(long userPermissions, long permissionBit) {
|
||||
return (userPermissions & permissionBit) != 0;
|
||||
}
|
||||
|
||||
public static boolean isAdmin(long permissions) {
|
||||
return hasPermission(permissions, ADMIN_BIT);
|
||||
}
|
||||
|
||||
public static boolean isSuperAdmin(long permissions) {
|
||||
return hasPermission(permissions, SUPER_ADMIN_BIT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package ru.soune.nocopy.adminpanel.permission;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSection;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminUser;
|
||||
|
||||
import ru.soune.nocopy.adminpanel.service.AdminSectionPermissionService;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PermissionChecker {
|
||||
|
||||
private final AdminSectionPermissionService sectionPermissionService;
|
||||
|
||||
public boolean isSuperAdmin(AdminUser admin) {
|
||||
if (admin == null || !admin.getIsActive()) return false;
|
||||
return AdminPermission.isSuperAdmin(admin.getPermissions());
|
||||
}
|
||||
|
||||
public void checkSuperAdmin(AdminUser admin) {
|
||||
if (!isSuperAdmin(admin)) {
|
||||
throw new SecurityException("Super admin permission required");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canReadSection(AdminUser admin, AdminSection section) {
|
||||
if (admin == null || !admin.getIsActive()) return false;
|
||||
if (isSuperAdmin(admin)) return true;
|
||||
|
||||
return sectionPermissionService.canRead(admin.getId(), section);
|
||||
}
|
||||
|
||||
public boolean canWriteSection(AdminUser admin, AdminSection section) {
|
||||
if (admin == null || !admin.getIsActive()) return false;
|
||||
if (isSuperAdmin(admin)) return true;
|
||||
|
||||
return sectionPermissionService.canWrite(admin.getId(), section);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package ru.soune.nocopy.adminpanel.permission;
|
||||
|
||||
public class SectionPermissions {
|
||||
public static final int NONE = 0b00;
|
||||
public static final int READ = 0b01;
|
||||
public static final int WRITE = 0b11;
|
||||
|
||||
public static boolean canRead(int permission) {
|
||||
return (permission & READ) == READ;
|
||||
}
|
||||
|
||||
public static boolean canWrite(int permission) {
|
||||
return (permission & WRITE) == WRITE;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package ru.soune.nocopy.adminpanel.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminCreateTemplate;
|
||||
|
||||
@Repository
|
||||
public interface AdminCreateTemplateRepository extends JpaRepository<AdminCreateTemplate, Long> {
|
||||
|
||||
boolean existsById(Long id);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package ru.soune.nocopy.adminpanel.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSectionPermission;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface AdminSectionPermissionRepository extends JpaRepository<AdminSectionPermission, Long> {
|
||||
Optional<AdminSectionPermission> findByUserId(Long userId);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ru.soune.nocopy.adminpanel.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminUser;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface AdminUserRepository extends JpaRepository<AdminUser, Long> {
|
||||
Optional<AdminUser> findByEmail(String email);
|
||||
|
||||
boolean existsByEmail(String email);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package ru.soune.nocopy.adminpanel.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminCreateTemplate;
|
||||
import ru.soune.nocopy.adminpanel.repository.AdminCreateTemplateRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AdminCreateTemplateService {
|
||||
|
||||
private final AdminCreateTemplateRepository adminCreateTemplateRepository;
|
||||
|
||||
public AdminCreateTemplate createAdminTemplate(String permissionsMap, Boolean changePassword, String name) {
|
||||
AdminCreateTemplate adminCreateTemplate = AdminCreateTemplate.builder()
|
||||
.permission(permissionsMap)
|
||||
.changePassword(changePassword)
|
||||
.name(name)
|
||||
.build();
|
||||
|
||||
return adminCreateTemplateRepository.save(adminCreateTemplate);
|
||||
}
|
||||
|
||||
public AdminCreateTemplate updateCreateTemplate(String permissionsMap, Boolean changePassword, Long id, String name) {
|
||||
AdminCreateTemplate adminCreateTemplate = adminCreateTemplateRepository.findById(id).orElse(null);
|
||||
|
||||
if (adminCreateTemplate == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!permissionsMap.isEmpty()) {
|
||||
adminCreateTemplate.setPermission(permissionsMap);
|
||||
}
|
||||
|
||||
if (changePassword != null) {
|
||||
adminCreateTemplate.setChangePassword(changePassword);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
adminCreateTemplate.setName(name);
|
||||
}
|
||||
|
||||
return adminCreateTemplateRepository.save(adminCreateTemplate);
|
||||
}
|
||||
|
||||
public void deleteTemplate(Long id) {
|
||||
adminCreateTemplateRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public boolean existById(Long id) {
|
||||
return adminCreateTemplateRepository.existsById(id);
|
||||
}
|
||||
|
||||
public List<AdminCreateTemplate> getAllTemplates() {
|
||||
return adminCreateTemplateRepository.findAll();
|
||||
}
|
||||
|
||||
public AdminCreateTemplate getTemplateById(Long id) {
|
||||
return adminCreateTemplateRepository.findById(id).orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package ru.soune.nocopy.adminpanel.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSectionPermission;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminSection;
|
||||
import ru.soune.nocopy.adminpanel.permission.SectionPermissions;
|
||||
import ru.soune.nocopy.adminpanel.repository.AdminSectionPermissionRepository;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AdminSectionPermissionService {
|
||||
|
||||
private final AdminSectionPermissionRepository repository;
|
||||
|
||||
@Transactional
|
||||
public AdminSectionPermission getOrCreate(Long userId) {
|
||||
return repository.findByUserId(userId)
|
||||
.orElseGet(() -> {
|
||||
AdminSectionPermission permission = new AdminSectionPermission();
|
||||
permission.setUserId(userId);
|
||||
return repository.save(permission);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean canRead(Long userId, AdminSection section) {
|
||||
AdminSectionPermission permission = getOrCreate(userId);
|
||||
int value = getSectionValue(permission, section);
|
||||
return SectionPermissions.canRead(value);
|
||||
}
|
||||
|
||||
public boolean canWrite(Long userId, AdminSection section) {
|
||||
AdminSectionPermission permission = getOrCreate(userId);
|
||||
int value = getSectionValue(permission, section);
|
||||
return SectionPermissions.canWrite(value);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setPermission(Long userId, AdminSection section, int permissionValue) {
|
||||
AdminSectionPermission permission = getOrCreate(userId);
|
||||
setSectionValue(permission, section, permissionValue);
|
||||
repository.save(permission);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setAllPermissions(Long userId, Map<AdminSection, Integer> permissions) {
|
||||
AdminSectionPermission permission = getOrCreate(userId);
|
||||
permissions.forEach((section, value) -> setSectionValue(permission, section, value));
|
||||
|
||||
repository.save(permission);
|
||||
}
|
||||
|
||||
public Map<AdminSection, Integer> getAllPermissions(Long userId) {
|
||||
AdminSectionPermission permission = getOrCreate(userId);
|
||||
Map<AdminSection, Integer> result = new HashMap<>();
|
||||
|
||||
for (AdminSection section : AdminSection.values()) {
|
||||
result.put(section, getSectionValue(permission, section));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getSectionValue(AdminSectionPermission permission, AdminSection section) {
|
||||
return switch (section) {
|
||||
case DASH -> permission.getDash();
|
||||
case USERS -> permission.getUsers();
|
||||
case STAFF -> permission.getStaff();
|
||||
case SUBSCRIPTIONS -> permission.getSubscriptions();
|
||||
case TARIFFS -> permission.getTariffs();
|
||||
case CONTENT_MODERATION -> permission.getContentModeration();
|
||||
case COMPLAINTS -> permission.getComplaints();
|
||||
case CLAIMS -> permission.getClaims();
|
||||
case MAILINGS -> permission.getMailings();
|
||||
case API -> permission.getApi();
|
||||
case MONEY -> permission.getMoney();
|
||||
case KYC -> permission.getKyc();
|
||||
case AGREEMENTS -> permission.getAgreements();
|
||||
};
|
||||
}
|
||||
|
||||
private void setSectionValue(AdminSectionPermission permission, AdminSection section, int value) {
|
||||
if (value == SectionPermissions.WRITE) {
|
||||
value = SectionPermissions.WRITE;
|
||||
}
|
||||
|
||||
switch (section) {
|
||||
case DASH -> permission.setDash(value);
|
||||
case USERS -> permission.setUsers(value);
|
||||
case STAFF -> permission.setStaff(value);
|
||||
case SUBSCRIPTIONS -> permission.setSubscriptions(value);
|
||||
case TARIFFS -> permission.setTariffs(value);
|
||||
case CONTENT_MODERATION -> permission.setContentModeration(value);
|
||||
case COMPLAINTS -> permission.setComplaints(value);
|
||||
case CLAIMS -> permission.setClaims(value);
|
||||
case MAILINGS -> permission.setMailings(value);
|
||||
case API -> permission.setApi(value);
|
||||
case MONEY -> permission.setMoney(value);
|
||||
case KYC -> permission.setKyc(value);
|
||||
case AGREEMENTS -> permission.setAgreements(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package ru.soune.nocopy.adminpanel.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.adminpanel.entity.AdminUser;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.AdminUserNotFoundException;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.EmailAlreadyExistsException;
|
||||
import ru.soune.nocopy.adminpanel.exceptions.WrongPassword;
|
||||
import ru.soune.nocopy.adminpanel.permission.AdminPermission;
|
||||
import ru.soune.nocopy.adminpanel.repository.AdminUserRepository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AdminUserService {
|
||||
|
||||
private final AdminUserRepository adminUserRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
@Transactional
|
||||
public AdminUser create(String fullName, String email, String password, boolean changePassword, boolean superAdmin) {
|
||||
if (adminUserRepository.existsByEmail(email)) {
|
||||
throw new EmailAlreadyExistsException("Email already exists: " + email);
|
||||
}
|
||||
|
||||
AdminUser admin = new AdminUser();
|
||||
admin.setFullName(fullName);
|
||||
admin.setEmail(email);
|
||||
admin.setPassword(passwordEncoder.encode(password));
|
||||
admin.setCreatedAt(LocalDateTime.now());
|
||||
admin.setIsActive(true);
|
||||
admin.setIsActivePassword(!changePassword);
|
||||
admin.setPermissions(superAdmin ? AdminPermission.SUPER_ADMIN_PERMISSIONS : AdminPermission.DEFAULT_PERMISSIONS);
|
||||
|
||||
return adminUserRepository.save(admin);
|
||||
}
|
||||
|
||||
public AdminUser findById(Long id) {
|
||||
return adminUserRepository.findById(id)
|
||||
.orElseThrow(() -> new AdminUserNotFoundException("Admin not found: " + id));
|
||||
}
|
||||
|
||||
public AdminUser findByEmail(String email) {
|
||||
return adminUserRepository.findByEmail(email)
|
||||
.orElseThrow(() -> new AdminUserNotFoundException("Admin not found: " + email));
|
||||
}
|
||||
|
||||
public List<AdminUser> findAll() {
|
||||
return adminUserRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AdminUser update(Long id, String fullName, String email, String oldPassword, String newPassword) {
|
||||
AdminUser admin = findById(id);
|
||||
|
||||
if (fullName != null) admin.setFullName(fullName);
|
||||
|
||||
if (email != null && !email.equals(admin.getEmail())) {
|
||||
if (adminUserRepository.existsByEmail(email)) {
|
||||
throw new EmailAlreadyExistsException("Email already exists: " + email);
|
||||
}
|
||||
admin.setEmail(email);
|
||||
}
|
||||
|
||||
if (newPassword != null && oldPassword != null) {
|
||||
if (passwordEncoder.matches(oldPassword, admin.getPassword())) {
|
||||
admin.setPassword(passwordEncoder.encode(newPassword));
|
||||
admin.setIsActivePassword(true);
|
||||
} else {
|
||||
throw new WrongPassword("Old password not equal current");
|
||||
}
|
||||
}
|
||||
|
||||
return adminUserRepository.save(admin);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AdminUser setSuperAdmin(Long id, boolean superAdmin) {
|
||||
AdminUser admin = findById(id);
|
||||
admin.setPermissions(superAdmin ? AdminPermission.SUPER_ADMIN_PERMISSIONS : AdminPermission.DEFAULT_PERMISSIONS);
|
||||
return adminUserRepository.save(admin);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void toggleActive(Long id, Boolean isActive) {
|
||||
AdminUser admin = findById(id);
|
||||
admin.setIsActive(isActive);
|
||||
adminUserRepository.save(admin);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long id) {
|
||||
adminUserRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public boolean authenticate(String email, String password) {
|
||||
return adminUserRepository.findByEmail(email)
|
||||
.filter(AdminUser::getIsActive)
|
||||
.map(admin -> passwordEncoder.matches(password, admin.getPassword()))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package ru.soune.nocopy.adminpanel.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import ru.soune.nocopy.adminpanel.dto.BaseResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthFilter extends OncePerRequestFilter {
|
||||
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
|
||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String token = authHeader.substring(7);
|
||||
|
||||
if (!jwtUtil.validateToken(token)) {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json");
|
||||
|
||||
BaseResponse errorResponse = BaseResponse.builder()
|
||||
.messageCode(MessageCode.INVALID_CREDENTIALS.getCode())
|
||||
.messageDesc("Invalid or expired token")
|
||||
.build();
|
||||
|
||||
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
|
||||
return;
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(jwtUtil.extractEmail(token), null,
|
||||
List.of(new SimpleGrantedAuthority("ROLE_ADMIN")));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
request.setAttribute("userId", jwtUtil.extractUserId(token));
|
||||
request.setAttribute("email", jwtUtil.extractEmail(token));
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package ru.soune.nocopy.adminpanel.util;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class JwtUtil {
|
||||
|
||||
@Value("${jwt.secret:Z29nb3Bvd2VycmFuZ2VydHVtYmF5YW1iZjMyNDIyMjh3aW5lcndpbmVy}")
|
||||
private String secret;
|
||||
|
||||
@Value("${jwt.expiration:3600000}")
|
||||
private Long expiration;
|
||||
|
||||
private SecretKey getSigningKey() {
|
||||
return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String generateToken(String email, Long userId) {
|
||||
return Jwts.builder()
|
||||
.setSubject(email)
|
||||
.claim("userId", userId)
|
||||
.setIssuedAt(new Date())
|
||||
.setExpiration(new Date(System.currentTimeMillis() + expiration))
|
||||
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Claims extractClaims(String token) {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(getSigningKey())
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
public String extractEmail(String token) {
|
||||
return extractClaims(token).getSubject();
|
||||
}
|
||||
|
||||
public Long extractUserId(String token) {
|
||||
return extractClaims(token).get("userId", Long.class);
|
||||
}
|
||||
|
||||
public boolean isTokenExpired(String token) {
|
||||
return extractClaims(token).getExpiration().before(new Date());
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
return !isTokenExpired(token);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package ru.soune.nocopy.adminpanel.util;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum MessageCode {
|
||||
SUCCESS(0, "Success"),
|
||||
INVALID_ACTION(2, "Invalid action"),
|
||||
ADMIN_NOT_FOUND(4, "Admin not found"),
|
||||
TEMPLATE_NOT_FOUND(4, "Template not found or id is null"),
|
||||
EMAIL_ALREADY_EXISTS(2, "Email already exists"),
|
||||
WRONG_PASSWORD(2, "Wrong password"),
|
||||
INVALID_CREDENTIALS(2, "Invalid credentials"),
|
||||
PERMISSION_DENIED(2, "Permission denied"),
|
||||
ADMIN_INACTIVE(2, "Admin is inactive"),
|
||||
PERMISSION_IS_EMPTY(2, "Permission is empty");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
MessageCode(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,29 @@
|
||||
spring:
|
||||
cloud:
|
||||
compatibility-verifier:
|
||||
enabled: false
|
||||
datasource:
|
||||
url: jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
||||
username: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
url: jdbc:postgresql://${POSTGRES_HOST:db}:${POSTGRES_PORT:5432}/${POSTGRES_DB:admin_db}
|
||||
username: ${POSTGRES_USER:admin}
|
||||
password: ${POSTGRES_PASSWORD:adminDbApp}
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: validate
|
||||
ddl-auto: update
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
format_sql: true
|
||||
|
||||
server:
|
||||
port: 8080
|
||||
port: ${SERVER_PORT:8082}
|
||||
|
||||
app:
|
||||
internal-api-key: "tljzkXiEYF1klSHuG2hPZKjx6EsBX8RQP6UrzMdQanSKbRYuHuOBwrXejZkn7V4FICvIahoDmYD2hjNBPw61NFbGIt4scOzwZpyCiXEa1YKLAeJSPso4S43LIZlKjO4S"
|
||||
|
||||
jwt:
|
||||
secret: Z29nb3Bvd2VycmFuZ2VydHVtYmF5YW1iZjMyNDIyMjh3aW5lcndpbmVy
|
||||
expiration: 3600000
|
||||
|
||||
nocopy-dashboard:
|
||||
url: http://172.17.0.1:3001
|
||||
Reference in New Issue
Block a user