Compare commits
122 Commits
39663e914d
...
gradle-set
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9463ad5935 | ||
|
|
55d6a6328f | ||
| 03dd52de71 | |||
|
|
859273a9c1 | ||
| 653536b0da | |||
|
|
5fca5bde55 | ||
|
|
d36fd17690 | ||
|
|
295f977a21 | ||
|
|
1a00d0cd19 | ||
|
|
2da6a58b20 | ||
|
|
0d2883fe2a | ||
|
|
7f99d11209 | ||
|
|
053ac89e3c | ||
|
|
cfca22bf66 | ||
|
|
7c5cc38cff | ||
|
|
dae0a4b78d | ||
|
|
882ffe7094 | ||
|
|
136771ab60 | ||
| 3865c26397 | |||
|
|
26a217cd50 | ||
| ff52a198dc | |||
|
|
f3d59a0ef3 | ||
|
|
d84485e52b | ||
|
|
f789d89995 | ||
|
|
7e0174bcc2 | ||
|
|
fe1d59a3bb | ||
|
|
69a99c9312 | ||
|
|
a6414ae64d | ||
|
|
9cf47f0e2a | ||
|
|
6c89562dc3 | ||
|
|
e85eabbed5 | ||
|
|
1ec4ba8212 | ||
|
|
a1ff181443 | ||
|
|
ee8f48bc43 | ||
|
|
7ec1aee884 | ||
|
|
a3adfa8ee0 | ||
|
|
d893afa1f3 | ||
|
|
d984128176 | ||
|
|
f8d73c9ed0 | ||
|
|
208b935ffa | ||
|
|
f12dfc7029 | ||
|
|
98a890e915 | ||
|
|
0c1b52d734 | ||
|
|
3f6764dd7d | ||
|
|
67c3d0b3e6 | ||
|
|
36208ef071 | ||
|
|
b546a0cf01 | ||
|
|
3935f6ad21 | ||
|
|
fd5ad7e88e | ||
|
|
8c957fe694 | ||
|
|
cb0ef7ddd5 | ||
|
|
42e466fe8b | ||
|
|
2c5fa4fa13 | ||
|
|
ebce44c889 | ||
|
|
955dc48f51 | ||
|
|
29e75e6298 | ||
|
|
187fd105d3 | ||
|
|
1b92fd269e | ||
|
|
23025e3606 | ||
|
|
38c11e2d9f | ||
|
|
610723c561 | ||
|
|
0e2fb945a4 | ||
|
|
ef32572521 | ||
|
|
e5a128a7f6 | ||
|
|
f5e1e10ebd | ||
|
|
500952d4d4 | ||
|
|
1cc4abc24e | ||
|
|
00945de270 | ||
|
|
5804d8cc9f | ||
|
|
5610bd170a | ||
|
|
21d19d4ecd | ||
|
|
f3dfac6bc7 | ||
|
|
4565192d0b | ||
|
|
d7ac4966c9 | ||
|
|
64119a956a | ||
|
|
c4dea2cc85 | ||
|
|
b0cc42fddd | ||
|
|
db669114b2 | ||
|
|
ca6b207816 | ||
|
|
b091dc52b7 | ||
|
|
4d44b6f53c | ||
|
|
be34c555a5 | ||
|
|
c03d977028 | ||
|
|
afd184f936 | ||
|
|
c09c68e1ac | ||
|
|
b84ba15f4c | ||
|
|
51af25666d | ||
|
|
b3a52f6a4b | ||
|
|
090143fdae | ||
|
|
b5f881e2c5 | ||
|
|
d9b856bd43 | ||
|
|
5e4068b141 | ||
|
|
a2f1b511c1 | ||
|
|
4d20d5f8b8 | ||
|
|
f00fb103ba | ||
|
|
b1d9344574 | ||
|
|
56ac024cba | ||
|
|
32ab1d79c8 | ||
|
|
42c4f76c0d | ||
|
|
4cc2a15231 | ||
|
|
54fbc7d609 | ||
|
|
8e9440a104 | ||
|
|
00d49d5fa4 | ||
|
|
78325c8729 | ||
|
|
1e18e3bc52 | ||
|
|
8ada2a15ef | ||
|
|
95d5308934 | ||
|
|
e5076f0c64 | ||
|
|
2ba707c336 | ||
|
|
d3041cf03d | ||
|
|
58295398e0 | ||
|
|
067bf7885a | ||
|
|
d324b94ddb | ||
|
|
4985889c58 | ||
|
|
7f5d52dce5 | ||
|
|
fae709a254 | ||
|
|
45355f6c42 | ||
|
|
db492b6316 | ||
|
|
c54e1c57d7 | ||
|
|
0900df463a | ||
|
|
13c2cc8118 | ||
|
|
431d365d20 |
75
.gitea/workflows/build-and-deploy.yml
Normal file
75
.gitea/workflows/build-and-deploy.yml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
name: Build and Deploy Java Gradle Application
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 📄 Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 📄 Checkout configuration
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.PROD_PROPERTIES_SSH_KEY }}
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
git clone -b hexagonal-reforged ssh://gitea@gitea.takiguchi.ovh:12960/Codiki/codiki-properties.git --config core.sshCommand='ssh -o StrictHostKeyChecking=no'
|
||||||
|
|
||||||
|
- name: 📄 Edit configuration
|
||||||
|
run: |
|
||||||
|
sed -i "s/<POSTGRES_PASSWORD>/$(cat ./codiki-properties/passwords/postgresql/codiki_user)/g" ./codiki-properties/application-prod.yml
|
||||||
|
cp ./codiki-properties/application-prod.yml ./backend/codiki-launcher/src/main/resources/application.yml
|
||||||
|
sed -i "s/<POSTGRES_ADMIN_PASSWORD>/$(cat ./codiki-properties/passwords/postgresql/codiki_admin)/g" ./docker-compose.yml
|
||||||
|
|
||||||
|
- name: 🔨 Build backend docker image
|
||||||
|
run: |
|
||||||
|
sudo /usr/bin/docker build -t codiki-backend -f ./Dockerfile-backend . --no-cache
|
||||||
|
|
||||||
|
- name: 📦 Extract backend docker image into archive
|
||||||
|
run: |
|
||||||
|
sudo /usr/bin/docker save codiki-backend:latest -o ./codiki-backend.tar
|
||||||
|
|
||||||
|
- name: 🔨 Build frontend docker image
|
||||||
|
run: |
|
||||||
|
sudo /usr/bin/docker build -t codiki-frontend -f ./Dockerfile-frontend . --no-cache
|
||||||
|
|
||||||
|
- name: 📦 Extract frontend docker image into archive
|
||||||
|
run: |
|
||||||
|
sudo /usr/bin/docker save codiki-frontend:latest -o ./codiki-frontend.tar
|
||||||
|
|
||||||
|
- name: 📤 Transfer artifacts to remote server
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||||
|
REMOTE_USER: ${{ secrets.PROD_REMOTE_USER }}
|
||||||
|
REMOTE_HOST: ${{ secrets.PROD_REMOTE_HOST }}
|
||||||
|
REMOTE_PORT: ${{ secrets.PROD_REMOTE_PORT }}
|
||||||
|
REMOTE_PATH: ${{ secrets.PROD_REMOTE_PATH }}
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
scp -o StrictHostKeyChecking=no -P $REMOTE_PORT ./codiki-backend.tar $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH
|
||||||
|
scp -o StrictHostKeyChecking=no -P $REMOTE_PORT ./codiki-frontend.tar $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH
|
||||||
|
scp -o StrictHostKeyChecking=no -P $REMOTE_PORT ./docker-compose.yml $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH
|
||||||
|
|
||||||
|
- name: 🚀 Launch application onto remote server
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||||
|
REMOTE_USER: ${{ secrets.PROD_REMOTE_USER }}
|
||||||
|
REMOTE_HOST: ${{ secrets.PROD_REMOTE_HOST }}
|
||||||
|
REMOTE_PORT: ${{ secrets.PROD_REMOTE_PORT }}
|
||||||
|
REMOTE_PATH: ${{ secrets.PROD_REMOTE_PATH }}
|
||||||
|
run: |
|
||||||
|
ssh -o StrictHostKeyChecking=no $REMOTE_HOST -l $REMOTE_USER -p $REMOTE_PORT << EOC
|
||||||
|
cd $REMOTE_PATH
|
||||||
|
sudo /usr/bin/docker load < $REMOTE_PATH/codiki-backend.tar
|
||||||
|
sudo /usr/bin/docker load < $REMOTE_PATH/codiki-frontend.tar
|
||||||
|
sudo /usr/bin/docker compose down
|
||||||
|
sudo /usr/bin/docker compose up --detach
|
||||||
|
EOC
|
||||||
56
.gitignore
vendored
56
.gitignore
vendored
@@ -38,3 +38,59 @@ build/
|
|||||||
**/.angular
|
**/.angular
|
||||||
|
|
||||||
**/pictures-folder
|
**/pictures-folder
|
||||||
|
|
||||||
|
|
||||||
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# Compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
/node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
.idea/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
/.angular/cache
|
||||||
|
.sass-cache/
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
**/ci/bin/
|
||||||
|
|
||||||
|
|
||||||
|
# Linux start script should use lf
|
||||||
|
/gradlew text eol=lf
|
||||||
|
# These are Windows script files and should use crlf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
# Binary files should be left untouched
|
||||||
|
*.jar binary
|
||||||
|
|
||||||
|
**/.gradle
|
||||||
16
Dockerfile-backend
Normal file
16
Dockerfile-backend
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
FROM gradle:9.0.0-jdk21 AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY backend/gradlew /app/
|
||||||
|
COPY backend/build.gradle.kts /app/
|
||||||
|
COPY backend/settings.gradle.kts /app/
|
||||||
|
COPY backend/codiki-application /app/codiki-application
|
||||||
|
COPY backend/codiki-domain /app/codiki-domain
|
||||||
|
COPY backend/codiki-exposition /app/codiki-exposition
|
||||||
|
COPY backend/codiki-infrastructure /app/codiki-infrastructure
|
||||||
|
COPY backend/codiki-launcher /app/codiki-launcher
|
||||||
|
WORKDIR /app
|
||||||
|
RUN gradle build jar
|
||||||
|
|
||||||
|
FROM eclipse-temurin:21-jre-alpine AS final
|
||||||
|
COPY --from=builder /app/codiki-launcher/build/libs/codiki-launcher.jar /app/codiki.jar
|
||||||
|
CMD ["java", "-jar", "/app/codiki.jar"]
|
||||||
12
Dockerfile-frontend
Normal file
12
Dockerfile-frontend
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM node:24-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY frontend /app
|
||||||
|
RUN npm install
|
||||||
|
RUN npm run build-prod-en
|
||||||
|
RUN npm run build-prod-fr
|
||||||
|
|
||||||
|
FROM nginx:1.29-alpine AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/dist/codiki/en/browser /usr/share/nginx/html/en/
|
||||||
|
COPY --from=builder /app/dist/codiki/fr/browser/fr /usr/share/nginx/html/fr/
|
||||||
|
COPY frontend/conf/nginx.conf /etc/nginx/nginx.conf
|
||||||
84
Jenkinsfile
vendored
Normal file
84
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('Configuration') {
|
||||||
|
steps {
|
||||||
|
dir('codiki-properties') {
|
||||||
|
git url:'https://gitea.takiguchi.ovh/Codiki/codiki-properties.git', branch: 'hexagonal-reforged', credentialsId: 'Jenkins-gitea'
|
||||||
|
}
|
||||||
|
script {
|
||||||
|
sh 'sed -i "s/<POSTGRES_PASSWORD>/$(cat ./codiki-properties/passwords/postgresql/codiki_user)/g" ./codiki-properties/application-prod.yml'
|
||||||
|
sh 'cp ./codiki-properties/application-prod.yml ./backend/codiki-launcher/src/main/resources/application-prod.yml'
|
||||||
|
sh 'sed -i "s/<POSTGRES_PASSWORD>/$(cat ./codiki-properties/passwords/postgresql/codiki_admin)/g" ./docker-compose.yml'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
sh """
|
||||||
|
sudo /usr/bin/docker build -t codiki-backend -f ./Dockerfile-backend . --no-cache
|
||||||
|
sudo /usr/bin/docker build -t codiki-frontend -f ./Dockerfile-frontend . --no-cache
|
||||||
|
sudo /usr/bin/docker save codiki-backend:latest -o ./codiki-backend.tar
|
||||||
|
sudo /usr/bin/docker save codiki-frontend:latest -o ./codiki-frontend.tar
|
||||||
|
sudo chown jenkins:jenkins ./codiki-backend.tar
|
||||||
|
sudo chown jenkins:jenkins ./codiki-frontend.tar
|
||||||
|
chmod 644 ./codiki-backend.tar
|
||||||
|
chmod 644 ./codiki-frontend.tar
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Deploy') {
|
||||||
|
steps {
|
||||||
|
sshPublisher(
|
||||||
|
publishers: [
|
||||||
|
sshPublisherDesc(
|
||||||
|
configName: 'DebianServer [codiki]',
|
||||||
|
transfers: [
|
||||||
|
sshTransfer(
|
||||||
|
cleanRemote: false,
|
||||||
|
excludes: '',
|
||||||
|
execCommand: '',
|
||||||
|
execTimeout: 120000,
|
||||||
|
flatten: false,
|
||||||
|
makeEmptyDirs: false,
|
||||||
|
noDefaultExcludes: false,
|
||||||
|
patternSeparator: '[, ]+',
|
||||||
|
remoteDirectory: '',
|
||||||
|
remoteDirectorySDF: false,
|
||||||
|
removePrefix: '',
|
||||||
|
sourceFiles: 'codiki-backend.tar,codiki-frontend.tar,docker-compose.yml'
|
||||||
|
),
|
||||||
|
sshTransfer(
|
||||||
|
cleanRemote: false,
|
||||||
|
excludes: '',
|
||||||
|
execCommand: """
|
||||||
|
cd /opt/codiki
|
||||||
|
sudo /usr/bin/docker load < /opt/codiki/codiki-backend.tar
|
||||||
|
sudo /usr/bin/docker load < /opt/codiki/codiki-frontend.tar
|
||||||
|
sudo /usr/bin/docker compose down
|
||||||
|
sudo /usr/bin/docker compose up --detach
|
||||||
|
""",
|
||||||
|
execTimeout: 120000,
|
||||||
|
flatten: false,
|
||||||
|
makeEmptyDirs: false,
|
||||||
|
noDefaultExcludes: false,
|
||||||
|
patternSeparator: '[, ]+',
|
||||||
|
remoteDirectory: '',
|
||||||
|
remoteDirectorySDF: false,
|
||||||
|
removePrefix: '',
|
||||||
|
sourceFiles: ''
|
||||||
|
)
|
||||||
|
],
|
||||||
|
usePromotionTimestamp: false,
|
||||||
|
useWorkspaceInPromotion: false,
|
||||||
|
verbose: true
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
backend/build.gradle.kts
Normal file
56
backend/build.gradle.kts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.2.20"
|
||||||
|
kotlin("plugin.spring") version "2.2.20"
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "org.codiki"
|
||||||
|
version = "0.0.1-SNAPSHOT"
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
apply(plugin = "java")
|
||||||
|
apply(plugin = "org.jetbrains.kotlin.jvm")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(platform("org.springframework.boot:spring-boot-dependencies:3.5.5"))
|
||||||
|
compileOnly("org.projectlombok:lombok:1.18.40")
|
||||||
|
annotationProcessor("org.projectlombok:lombok:1.18.40")
|
||||||
|
testImplementation("org.assertj:assertj-core:3.27.4")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter-api")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter-params")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test> {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyManagement {
|
||||||
|
imports {
|
||||||
|
mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.5")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.addAll("-Xjsr305=strict")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test> {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
11
backend/codiki-application/build.gradle.kts
Normal file
11
backend/codiki-application/build.gradle.kts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
plugins {
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":codiki-domain"))
|
||||||
|
implementation("org.springframework:spring-context")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||||
|
implementation("com.auth0:java-jwt:4.5.0")
|
||||||
|
implementation("org.apache.commons:commons-lang3") //:3.18.0
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.codiki.application.picture;
|
package org.codiki.application.picture;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@ public class PictureUseCases {
|
|||||||
.withId(UUID.randomUUID())
|
.withId(UUID.randomUUID())
|
||||||
.withPublisher(authenticatedUser)
|
.withPublisher(authenticatedUser)
|
||||||
.withContentFile(pictureFile)
|
.withContentFile(pictureFile)
|
||||||
|
.withPublicationDate(ZonedDateTime.now())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
picturePort.save(newPicture);
|
picturePort.save(newPicture);
|
||||||
@@ -48,4 +51,11 @@ public class PictureUseCases {
|
|||||||
public boolean existsById(UUID pictureId) {
|
public boolean existsById(UUID pictureId) {
|
||||||
return picturePort.existsById(pictureId);
|
return picturePort.existsById(pictureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Picture> getAllOfCurrentUser() {
|
||||||
|
User authenticatedUser = userUseCases.getAuthenticatedUser()
|
||||||
|
.orElseThrow(AuthenticationRequiredException::new);
|
||||||
|
|
||||||
|
return picturePort.findAllByPublisherId(authenticatedUser.id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package org.codiki.application.publication;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ParserService {
|
||||||
|
private static final String REG_CODE = "\\[code lg="([a-z]+)"\\](.*)\\[\\/code\\]\\n";
|
||||||
|
private static final String REG_IMAGES = "\\[img src="([^\"| ]+)"( alt="([^\"| ]+)")? \\/\\]";
|
||||||
|
private static final String REG_LINKS = "\\[link href="([^\"| ]+)" txt="([^\"| ]+)" \\/\\]";
|
||||||
|
|
||||||
|
private static final Pattern PATTERN_CODE;
|
||||||
|
private static final Pattern PATTERN_IMAGES;
|
||||||
|
private static final Pattern PATTERN_LINKS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
PATTERN_CODE = Pattern.compile(REG_CODE);
|
||||||
|
PATTERN_IMAGES = Pattern.compile(REG_IMAGES);
|
||||||
|
PATTERN_LINKS = Pattern.compile(REG_LINKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String parse(String pSource) {
|
||||||
|
return unParseDolars(parseCode(parseHeaders(parseImages(parseLinks(parseBackSpaces(escapeHtml4(parseDolars(pSource))))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseDolars(final String pSource) {
|
||||||
|
return pSource.replace("$", "£ø");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String unParseDolars(final String pSource) {
|
||||||
|
return pSource.replace("£ø", "$");
|
||||||
|
}
|
||||||
|
|
||||||
|
String parseHeaders(final String pSource) {
|
||||||
|
String result = pSource;
|
||||||
|
for(int i = 1 ; i <= 3 ; i++) {
|
||||||
|
result = parseHeadersHX(result, i);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String parseHeadersHX(final String pSource, final int pNumHeader) {
|
||||||
|
String result = pSource;
|
||||||
|
|
||||||
|
// (.*)(\[hX\](.*)\[\/hX\])+(.*)
|
||||||
|
final String regex = concat("(.*)(\\[h", pNumHeader, "\\](.*)\\[\\/h", pNumHeader, "\\])+(.*)");
|
||||||
|
|
||||||
|
final Pattern pattern = Pattern.compile(regex);
|
||||||
|
|
||||||
|
Matcher matcher = pattern.matcher(result);
|
||||||
|
|
||||||
|
while(matcher.find()) {
|
||||||
|
// \1<hX>\3</hX>\4
|
||||||
|
result = matcher.replaceFirst(concat(matcher.group(1),
|
||||||
|
"<h", pNumHeader, ">", matcher.group(3), "</h", pNumHeader, ">", matcher.group(4)));
|
||||||
|
matcher = pattern.matcher(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String parseBackSpaces(final String pSource) {
|
||||||
|
return pSource.replaceAll("\r?\n", "<br/>").replaceAll("\\[\\/code\\]<br\\/><br\\/>", "[/code]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
String parseImages(final String pSource) {
|
||||||
|
String result = pSource;
|
||||||
|
|
||||||
|
Matcher matcher = PATTERN_IMAGES.matcher(result);
|
||||||
|
|
||||||
|
while(matcher.find()) {
|
||||||
|
String altStr = matcher.group(3);
|
||||||
|
|
||||||
|
if(altStr == null) {
|
||||||
|
altStr = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
result = matcher.replaceFirst(concat("<img src=\"", matcher.group(1), "\" alt=\"", altStr, "\" />"));
|
||||||
|
matcher = PATTERN_IMAGES.matcher(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String parseLinks(final String pSource) {
|
||||||
|
String result = pSource;
|
||||||
|
|
||||||
|
Matcher matcher = PATTERN_LINKS.matcher(result);
|
||||||
|
|
||||||
|
while(matcher.find()) {
|
||||||
|
result = matcher.replaceFirst(concat("<a href=\"", matcher.group(1), "\">", matcher.group(2), "</a>"));
|
||||||
|
matcher = PATTERN_LINKS.matcher(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String parseCode(final String pSource) {
|
||||||
|
String result = pSource;
|
||||||
|
|
||||||
|
Matcher matcher = PATTERN_CODE.matcher(result);
|
||||||
|
|
||||||
|
while(matcher.find()) {
|
||||||
|
// replace the '<br/>' in group by '\n'
|
||||||
|
String codeContent = matcher.group(2).replaceAll("<br\\/>", "\n");
|
||||||
|
if(codeContent.startsWith("\n")) {
|
||||||
|
codeContent = codeContent.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = matcher.replaceFirst(
|
||||||
|
concat(
|
||||||
|
"<pre class=\"line-numbers\"><code class=\"language-",
|
||||||
|
matcher.group(1),
|
||||||
|
"\">",
|
||||||
|
codeContent,
|
||||||
|
"</code></pre>"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
matcher = PATTERN_CODE.matcher(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate the parameters to form just one single string.
|
||||||
|
*
|
||||||
|
* @param pArgs
|
||||||
|
* The strings to concatenate.
|
||||||
|
* @return The parameters concatenated.
|
||||||
|
*/
|
||||||
|
private static String concat(final Object... pArgs) {
|
||||||
|
final StringBuilder result = new StringBuilder();
|
||||||
|
for (final Object arg : pArgs) {
|
||||||
|
result.append(arg);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,15 @@ package org.codiki.application.publication;
|
|||||||
import static java.util.Objects.isNull;
|
import static java.util.Objects.isNull;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.codiki.domain.publication.model.builder.AuthorBuilder.anAuthor;
|
import static org.codiki.domain.publication.model.builder.AuthorBuilder.anAuthor;
|
||||||
import static org.codiki.domain.publication.model.builder.PublicationBuilder.aPublication;
|
import static org.codiki.domain.publication.model.builder.PublicationBuilder.aPublication;
|
||||||
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
|
|
||||||
import org.codiki.application.category.CategoryUseCases;
|
import org.codiki.application.category.CategoryUseCases;
|
||||||
import org.codiki.application.picture.PictureUseCases;
|
import org.codiki.application.picture.PictureUseCases;
|
||||||
import org.codiki.application.user.UserUseCases;
|
import org.codiki.application.user.UserUseCases;
|
||||||
@@ -31,6 +34,7 @@ public class PublicationUseCases {
|
|||||||
private final CategoryUseCases categoryUseCases;
|
private final CategoryUseCases categoryUseCases;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final KeyGenerator keyGenerator;
|
private final KeyGenerator keyGenerator;
|
||||||
|
private final ParserService parserService;
|
||||||
private final PictureUseCases pictureUseCases;
|
private final PictureUseCases pictureUseCases;
|
||||||
private final PublicationCreationRequestValidator publicationCreationRequestValidator;
|
private final PublicationCreationRequestValidator publicationCreationRequestValidator;
|
||||||
private final PublicationPort publicationPort;
|
private final PublicationPort publicationPort;
|
||||||
@@ -39,19 +43,21 @@ public class PublicationUseCases {
|
|||||||
private final UserUseCases userUseCases;
|
private final UserUseCases userUseCases;
|
||||||
|
|
||||||
public PublicationUseCases(
|
public PublicationUseCases(
|
||||||
CategoryUseCases categoryUseCases,
|
CategoryUseCases categoryUseCases,
|
||||||
Clock clock,
|
Clock clock,
|
||||||
KeyGenerator keyGenerator,
|
KeyGenerator keyGenerator,
|
||||||
PictureUseCases pictureUseCases,
|
ParserService parserService,
|
||||||
PublicationCreationRequestValidator publicationCreationRequestValidator,
|
PictureUseCases pictureUseCases,
|
||||||
PublicationPort publicationPort,
|
PublicationCreationRequestValidator publicationCreationRequestValidator,
|
||||||
PublicationSearchCriteriaFactory publicationSearchCriteriaFactory,
|
PublicationPort publicationPort,
|
||||||
PublicationUpdateRequestValidator publicationUpdateRequestValidator,
|
PublicationSearchCriteriaFactory publicationSearchCriteriaFactory,
|
||||||
UserUseCases userUseCases
|
PublicationUpdateRequestValidator publicationUpdateRequestValidator,
|
||||||
|
UserUseCases userUseCases
|
||||||
) {
|
) {
|
||||||
this.categoryUseCases = categoryUseCases;
|
this.categoryUseCases = categoryUseCases;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.keyGenerator = keyGenerator;
|
this.keyGenerator = keyGenerator;
|
||||||
|
this.parserService = parserService;
|
||||||
this.publicationCreationRequestValidator = publicationCreationRequestValidator;
|
this.publicationCreationRequestValidator = publicationCreationRequestValidator;
|
||||||
this.publicationPort = publicationPort;
|
this.publicationPort = publicationPort;
|
||||||
this.publicationUpdateRequestValidator = publicationUpdateRequestValidator;
|
this.publicationUpdateRequestValidator = publicationUpdateRequestValidator;
|
||||||
@@ -83,6 +89,7 @@ public class PublicationUseCases {
|
|||||||
.withKey(keyGenerator.generateKey())
|
.withKey(keyGenerator.generateKey())
|
||||||
.withTitle(request.title())
|
.withTitle(request.title())
|
||||||
.withText(request.text())
|
.withText(request.text())
|
||||||
|
.withParsedText(parserService.parse(request.text()))
|
||||||
.withDescription(request.description())
|
.withDescription(request.description())
|
||||||
.withCreationDate(ZonedDateTime.now(clock))
|
.withCreationDate(ZonedDateTime.now(clock))
|
||||||
.withIllustrationId(request.illustrationId())
|
.withIllustrationId(request.illustrationId())
|
||||||
@@ -116,6 +123,7 @@ public class PublicationUseCases {
|
|||||||
|
|
||||||
if (!isNull(request.text())) {
|
if (!isNull(request.text())) {
|
||||||
publicationBuilder.withText(request.text());
|
publicationBuilder.withText(request.text());
|
||||||
|
publicationBuilder.withParsedText(parserService.parse(request.text()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isNull(request.description())) {
|
if (!isNull(request.description())) {
|
||||||
@@ -163,7 +171,19 @@ public class PublicationUseCases {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Publication> findById(UUID publicationId) {
|
public Optional<Publication> findById(UUID publicationId) {
|
||||||
return publicationPort.findById(publicationId);
|
return publicationPort.findById(publicationId)
|
||||||
|
.map(publication -> {
|
||||||
|
Publication result = publication;
|
||||||
|
if (isEmpty(publication.parsedText())) {
|
||||||
|
Publication editedPublication = aPublication()
|
||||||
|
.basedOn(publication)
|
||||||
|
.withParsedText(parserService.parse(publication.text()))
|
||||||
|
.build();
|
||||||
|
publicationPort.save(editedPublication);
|
||||||
|
result = editedPublication;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Publication> searchPublications(String searchQuery) {
|
public List<Publication> searchPublications(String searchQuery) {
|
||||||
@@ -171,4 +191,12 @@ public class PublicationUseCases {
|
|||||||
|
|
||||||
return publicationPort.search(criteria);
|
return publicationPort.search(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Publication> getLatest() {
|
||||||
|
return publicationPort.getLatest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String previewContent(String publicationText) {
|
||||||
|
return parserService.parse(publicationText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import java.util.stream.IntStream;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class KeyGeneratorTest {
|
class KeyGeneratorTest {
|
||||||
@@ -16,6 +17,7 @@ class KeyGeneratorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled
|
||||||
public void generateKey_should_generate_random_keys_with_alphanumeric_characters() {
|
public void generateKey_should_generate_random_keys_with_alphanumeric_characters() {
|
||||||
Pattern validationRegex = Pattern.compile("^[0-9A-Z]{10}$");
|
Pattern validationRegex = Pattern.compile("^[0-9A-Z]{10}$");
|
||||||
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package org.codiki.domain.picture.model;
|
package org.codiki.domain.picture.model;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public record Picture(
|
public record Picture(
|
||||||
UUID id,
|
UUID id,
|
||||||
UUID publisherId,
|
UUID publisherId,
|
||||||
|
ZonedDateTime publishedAt,
|
||||||
File contentFile
|
File contentFile
|
||||||
) {}
|
) {}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.codiki.domain.picture.model.builder;
|
package org.codiki.domain.picture.model.builder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.codiki.domain.picture.model.Picture;
|
import org.codiki.domain.picture.model.Picture;
|
||||||
@@ -9,6 +10,7 @@ import org.codiki.domain.user.model.User;
|
|||||||
public class PictureBuilder {
|
public class PictureBuilder {
|
||||||
private UUID id;
|
private UUID id;
|
||||||
private UUID publisherId;
|
private UUID publisherId;
|
||||||
|
private ZonedDateTime publishedAt;
|
||||||
private File contentFile;
|
private File contentFile;
|
||||||
|
|
||||||
private PictureBuilder() {}
|
private PictureBuilder() {}
|
||||||
@@ -37,12 +39,17 @@ public class PictureBuilder {
|
|||||||
return withPublisherId(publisher.id());
|
return withPublisherId(publisher.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PictureBuilder withPublicationDate(ZonedDateTime publishedAt) {
|
||||||
|
this.publishedAt = publishedAt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PictureBuilder withContentFile(File contentFile) {
|
public PictureBuilder withContentFile(File contentFile) {
|
||||||
this.contentFile = contentFile;
|
this.contentFile = contentFile;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Picture build() {
|
public Picture build() {
|
||||||
return new Picture(id, publisherId, contentFile);
|
return new Picture(id, publisherId, publishedAt, contentFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.codiki.domain.picture.port;
|
package org.codiki.domain.picture.port;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -13,4 +14,6 @@ public interface PicturePort {
|
|||||||
void save(Picture picture);
|
void save(Picture picture);
|
||||||
|
|
||||||
void deleteById(UUID pictureId);
|
void deleteById(UUID pictureId);
|
||||||
|
|
||||||
|
List<Picture> findAllByPublisherId(UUID id);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.codiki.domain.publication.exception;
|
||||||
|
|
||||||
|
import org.codiki.domain.exception.FunctionnalException;
|
||||||
|
|
||||||
|
public class BadPublicationSearchCriterionException extends FunctionnalException {
|
||||||
|
public BadPublicationSearchCriterionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import java.util.UUID;
|
|||||||
public record Author(
|
public record Author(
|
||||||
UUID id,
|
UUID id,
|
||||||
String name,
|
String name,
|
||||||
String image
|
String photoId
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ public record Publication(
|
|||||||
String key,
|
String key,
|
||||||
String title,
|
String title,
|
||||||
String text,
|
String text,
|
||||||
|
String parsedText,
|
||||||
String description,
|
String description,
|
||||||
ZonedDateTime creationDate,
|
ZonedDateTime creationDate,
|
||||||
UUID illustrationId,
|
UUID illustrationId,
|
||||||
@@ -40,6 +40,7 @@ public class AuthorBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Author build() {
|
public Author build() {
|
||||||
|
//
|
||||||
return new Author(id, name, image);
|
return new Author(id, name, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
package org.codiki.domain.publication.model.builder;
|
package org.codiki.domain.publication.model.builder;
|
||||||
|
|
||||||
|
import org.codiki.domain.publication.model.Author;
|
||||||
|
import org.codiki.domain.publication.model.Publication;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.codiki.domain.category.model.Category;
|
|
||||||
import org.codiki.domain.publication.model.Author;
|
|
||||||
import org.codiki.domain.publication.model.Publication;
|
|
||||||
|
|
||||||
public class PublicationBuilder {
|
public class PublicationBuilder {
|
||||||
private UUID id;
|
private UUID id;
|
||||||
private String key;
|
private String key;
|
||||||
private String title;
|
private String title;
|
||||||
private String text;
|
private String text;
|
||||||
|
private String parsedText;
|
||||||
private String description;
|
private String description;
|
||||||
private ZonedDateTime creationDate;
|
private ZonedDateTime creationDate;
|
||||||
private UUID illustrationId;
|
private UUID illustrationId;
|
||||||
@@ -30,6 +30,7 @@ public class PublicationBuilder {
|
|||||||
.withKey(publication.key())
|
.withKey(publication.key())
|
||||||
.withTitle(publication.title())
|
.withTitle(publication.title())
|
||||||
.withText(publication.text())
|
.withText(publication.text())
|
||||||
|
.withParsedText(publication.parsedText())
|
||||||
.withDescription(publication.description())
|
.withDescription(publication.description())
|
||||||
.withCreationDate(publication.creationDate())
|
.withCreationDate(publication.creationDate())
|
||||||
.withIllustrationId(publication.illustrationId())
|
.withIllustrationId(publication.illustrationId())
|
||||||
@@ -57,6 +58,11 @@ public class PublicationBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PublicationBuilder withParsedText(String parsedText) {
|
||||||
|
this.parsedText = parsedText;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PublicationBuilder withDescription(String description) {
|
public PublicationBuilder withDescription(String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
return this;
|
return this;
|
||||||
@@ -88,6 +94,7 @@ public class PublicationBuilder {
|
|||||||
key,
|
key,
|
||||||
title,
|
title,
|
||||||
text,
|
text,
|
||||||
|
parsedText,
|
||||||
description,
|
description,
|
||||||
creationDate,
|
creationDate,
|
||||||
illustrationId,
|
illustrationId,
|
||||||
@@ -15,4 +15,6 @@ public interface PublicationPort {
|
|||||||
void delete(Publication publication);
|
void delete(Publication publication);
|
||||||
|
|
||||||
List<Publication> search(List<PublicationSearchCriterion> criteria);
|
List<Publication> search(List<PublicationSearchCriterion> criteria);
|
||||||
|
|
||||||
|
List<Publication> getLatest();
|
||||||
}
|
}
|
||||||
11
backend/codiki-exposition/build.gradle.kts
Normal file
11
backend/codiki-exposition/build.gradle.kts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
plugins {
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":codiki-application"))
|
||||||
|
implementation(project(":codiki-domain"))
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||||
|
implementation("org.apache.tika:tika-core:3.2.3")
|
||||||
|
}
|
||||||
@@ -7,16 +7,10 @@ import static org.springframework.http.HttpStatus.UNAUTHORIZED;
|
|||||||
import org.codiki.domain.category.exception.CategoryDeletionException;
|
import org.codiki.domain.category.exception.CategoryDeletionException;
|
||||||
import org.codiki.domain.category.exception.CategoryEditionException;
|
import org.codiki.domain.category.exception.CategoryEditionException;
|
||||||
import org.codiki.domain.category.exception.CategoryNotFoundException;
|
import org.codiki.domain.category.exception.CategoryNotFoundException;
|
||||||
import org.codiki.domain.exception.LoginFailureException;
|
import org.codiki.domain.exception.*;
|
||||||
import org.codiki.domain.exception.RefreshTokenDoesNotExistException;
|
|
||||||
import org.codiki.domain.exception.RefreshTokenExpiredException;
|
|
||||||
import org.codiki.domain.exception.UserDoesNotExistException;
|
|
||||||
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
||||||
import org.codiki.domain.picture.exception.PictureUploadException;
|
import org.codiki.domain.picture.exception.PictureUploadException;
|
||||||
import org.codiki.domain.publication.exception.NoPublicationSearchResultException;
|
import org.codiki.domain.publication.exception.*;
|
||||||
import org.codiki.domain.publication.exception.PublicationEditionException;
|
|
||||||
import org.codiki.domain.publication.exception.PublicationNotFoundException;
|
|
||||||
import org.codiki.domain.publication.exception.PublicationUpdateForbiddenException;
|
|
||||||
import org.codiki.domain.user.exception.UserAlreadyExistsException;
|
import org.codiki.domain.user.exception.UserAlreadyExistsException;
|
||||||
import org.codiki.domain.user.exception.UserCreationException;
|
import org.codiki.domain.user.exception.UserCreationException;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -28,6 +22,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
|
|||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
|
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
|
||||||
@ExceptionHandler({
|
@ExceptionHandler({
|
||||||
|
BadPublicationSearchCriterionException.class,
|
||||||
CategoryDeletionException.class,
|
CategoryDeletionException.class,
|
||||||
CategoryEditionException.class,
|
CategoryEditionException.class,
|
||||||
CategoryNotFoundException.class,
|
CategoryNotFoundException.class,
|
||||||
@@ -53,7 +48,8 @@ public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHan
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExceptionHandler({
|
@ExceptionHandler({
|
||||||
RefreshTokenExpiredException.class
|
RefreshTokenExpiredException.class,
|
||||||
|
AuthenticationRequiredException.class,
|
||||||
})
|
})
|
||||||
public ProblemDetail handleUnauthorizedExceptions(Exception exception) {
|
public ProblemDetail handleUnauthorizedExceptions(Exception exception) {
|
||||||
return buildProblemDetail(UNAUTHORIZED, exception);
|
return buildProblemDetail(UNAUTHORIZED, exception);
|
||||||
@@ -48,12 +48,14 @@ public class SecurityConfiguration {
|
|||||||
"/api/pictures/{pictureId}",
|
"/api/pictures/{pictureId}",
|
||||||
"/api/publications/{publicationId}",
|
"/api/publications/{publicationId}",
|
||||||
"/api/publications",
|
"/api/publications",
|
||||||
|
"/api/publications/latest",
|
||||||
"/error"
|
"/error"
|
||||||
).permitAll()
|
).permitAll()
|
||||||
.requestMatchers(
|
.requestMatchers(
|
||||||
POST,
|
POST,
|
||||||
"/api/users/login",
|
"/api/users/login",
|
||||||
"/api/users/refresh-token"
|
"/api/users/refresh-token",
|
||||||
|
"/api/users"
|
||||||
).permitAll()
|
).permitAll()
|
||||||
.requestMatchers(
|
.requestMatchers(
|
||||||
POST,
|
POST,
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.codiki.exposition.picture;
|
package org.codiki.exposition.picture;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||||
@@ -8,6 +9,7 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
|||||||
import org.codiki.application.picture.PictureUseCases;
|
import org.codiki.application.picture.PictureUseCases;
|
||||||
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
||||||
import org.codiki.domain.picture.model.Picture;
|
import org.codiki.domain.picture.model.Picture;
|
||||||
|
import org.codiki.exposition.picture.model.PictureDto;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
@@ -44,4 +46,12 @@ public class PictureController {
|
|||||||
.orElseThrow(() -> new PictureNotFoundException(pictureId));
|
.orElseThrow(() -> new PictureNotFoundException(pictureId));
|
||||||
return new FileSystemResource(picture.contentFile());
|
return new FileSystemResource(picture.contentFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/current-user")
|
||||||
|
public List<PictureDto> getAllPicturesOfCurrentUser() {
|
||||||
|
return pictureUseCases.getAllOfCurrentUser()
|
||||||
|
.stream()
|
||||||
|
.map(PictureDto::new)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.codiki.exposition.picture.model;
|
||||||
|
|
||||||
|
import org.codiki.domain.picture.model.Picture;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record PictureDto(
|
||||||
|
UUID id,
|
||||||
|
ZonedDateTime publishedAt
|
||||||
|
) {
|
||||||
|
public PictureDto(Picture picture) {
|
||||||
|
this(picture.id(), picture.publishedAt());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,22 @@
|
|||||||
package org.codiki.exposition.publication;
|
package org.codiki.exposition.publication;
|
||||||
|
|
||||||
|
import org.codiki.application.publication.PublicationUseCases;
|
||||||
|
import org.codiki.domain.publication.exception.NoPublicationSearchResultException;
|
||||||
|
import org.codiki.domain.publication.exception.PublicationNotFoundException;
|
||||||
|
import org.codiki.domain.publication.model.Publication;
|
||||||
|
import org.codiki.domain.publication.model.PublicationEditionRequest;
|
||||||
|
import org.codiki.exposition.publication.model.PreviewContentRequest;
|
||||||
|
import org.codiki.exposition.publication.model.PreviewContentResponse;
|
||||||
|
import org.codiki.exposition.publication.model.PublicationDto;
|
||||||
|
import org.codiki.exposition.publication.model.PublicationEditionRequestDto;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.springframework.http.HttpStatus.CREATED;
|
import static org.springframework.http.HttpStatus.CREATED;
|
||||||
import static org.springframework.http.HttpStatus.NO_CONTENT;
|
import static org.springframework.http.HttpStatus.NO_CONTENT;
|
||||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
import org.codiki.application.publication.PublicationUseCases;
|
|
||||||
import org.codiki.domain.publication.exception.NoPublicationSearchResultException;
|
|
||||||
import org.codiki.domain.publication.exception.PublicationNotFoundException;
|
|
||||||
import org.codiki.domain.publication.model.Publication;
|
|
||||||
import org.codiki.domain.publication.model.PublicationEditionRequest;
|
|
||||||
import org.codiki.exposition.publication.model.PublicationDto;
|
|
||||||
import org.codiki.exposition.publication.model.PublicationEditionRequestDto;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
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.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/publications")
|
@RequestMapping("/api/publications")
|
||||||
@@ -66,7 +60,7 @@ public class PublicationController {
|
|||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public List<PublicationDto> searchPublications(@RequestParam("query") String searchQuery) {
|
public List<PublicationDto> searchPublications(@RequestParam("query") String searchQuery) {
|
||||||
final List<PublicationDto> publications = publicationUseCases.searchPublications(searchQuery)
|
List<PublicationDto> publications = publicationUseCases.searchPublications(searchQuery)
|
||||||
.stream()
|
.stream()
|
||||||
.map(PublicationDto::new)
|
.map(PublicationDto::new)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -77,4 +71,24 @@ public class PublicationController {
|
|||||||
|
|
||||||
return publications;
|
return publications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/latest")
|
||||||
|
public List<PublicationDto> getLatestPublications() {
|
||||||
|
List<PublicationDto> publications = publicationUseCases.getLatest()
|
||||||
|
.stream()
|
||||||
|
.map(PublicationDto::new)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (isEmpty(publications)) {
|
||||||
|
throw new NoPublicationSearchResultException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return publications;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/preview")
|
||||||
|
public PreviewContentResponse previewPublicationContent(@RequestBody PreviewContentRequest request) {
|
||||||
|
String previewContent = publicationUseCases.previewContent(request.text());
|
||||||
|
return new PreviewContentResponse(previewContent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ public record AuthorDto(
|
|||||||
this(
|
this(
|
||||||
author.id(),
|
author.id(),
|
||||||
author.name(),
|
author.name(),
|
||||||
author.image()
|
author.photoId()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package org.codiki.exposition.publication.model;
|
||||||
|
|
||||||
|
public record PreviewContentRequest(
|
||||||
|
String text
|
||||||
|
) {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package org.codiki.exposition.publication.model;
|
||||||
|
|
||||||
|
public record PreviewContentResponse(
|
||||||
|
String text
|
||||||
|
) {}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
package org.codiki.exposition.publication.model;
|
package org.codiki.exposition.publication.model;
|
||||||
|
|
||||||
|
import org.codiki.domain.publication.model.Publication;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.codiki.domain.publication.model.Publication;
|
|
||||||
import org.codiki.exposition.category.model.CategoryDto;
|
|
||||||
|
|
||||||
public record PublicationDto(
|
public record PublicationDto(
|
||||||
UUID id,
|
UUID id,
|
||||||
String key,
|
String key,
|
||||||
String title,
|
String title,
|
||||||
String text,
|
String text,
|
||||||
|
String parsedText,
|
||||||
String description,
|
String description,
|
||||||
ZonedDateTime creationDate,
|
ZonedDateTime creationDate,
|
||||||
UUID illustrationId,
|
UUID illustrationId,
|
||||||
@@ -23,6 +23,7 @@ public record PublicationDto(
|
|||||||
publication.key(),
|
publication.key(),
|
||||||
publication.title(),
|
publication.title(),
|
||||||
publication.text(),
|
publication.text(),
|
||||||
|
publication.parsedText(),
|
||||||
publication.description(),
|
publication.description(),
|
||||||
publication.creationDate(),
|
publication.creationDate(),
|
||||||
publication.illustrationId(),
|
publication.illustrationId(),
|
||||||
13
backend/codiki-infrastructure/build.gradle.kts
Normal file
13
backend/codiki-infrastructure/build.gradle.kts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
plugins {
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
// kotlin("plugin.jpa") version "2.1.20"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// implementation(kotlin("stdlib"))
|
||||||
|
implementation(project(":codiki-application"))
|
||||||
|
implementation(project(":codiki-domain"))
|
||||||
|
implementation("org.springframework:spring-context")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||||
|
implementation("org.postgresql:postgresql:42.7.5")
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.codiki.infrastructure.category.repository;
|
package org.codiki.infrastructure.category.repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.codiki.infrastructure.category.model.CategoryEntity;
|
import org.codiki.infrastructure.category.model.CategoryEntity;
|
||||||
@@ -16,4 +17,7 @@ public interface CategoryRepository extends JpaRepository<CategoryEntity, UUID>
|
|||||||
) > 0
|
) > 0
|
||||||
""", nativeQuery = true)
|
""", nativeQuery = true)
|
||||||
boolean existsAnyAssociatedPublication(@Param("categoryId") UUID categoryId);
|
boolean existsAnyAssociatedPublication(@Param("categoryId") UUID categoryId);
|
||||||
|
|
||||||
|
@Query("SELECT c FROM CategoryEntity c LEFT JOIN FETCH c.subCategories")
|
||||||
|
List<CategoryEntity> findAll();
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.codiki.infrastructure.picture;
|
package org.codiki.infrastructure.picture;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -66,4 +67,12 @@ public class PictureJpaAdapter implements PicturePort {
|
|||||||
public void deleteById(UUID pictureId) {
|
public void deleteById(UUID pictureId) {
|
||||||
repository.deleteById(pictureId);
|
repository.deleteById(pictureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Picture> findAllByPublisherId(UUID id) {
|
||||||
|
return repository.findAllByPublisherId(id)
|
||||||
|
.stream()
|
||||||
|
.map(PictureEntity::toDomain)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.codiki.infrastructure.picture.model;
|
package org.codiki.infrastructure.picture.model;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.codiki.domain.picture.model.Picture;
|
import org.codiki.domain.picture.model.Picture;
|
||||||
@@ -24,13 +25,16 @@ public class PictureEntity {
|
|||||||
private UUID id;
|
private UUID id;
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private UUID publisherId;
|
private UUID publisherId;
|
||||||
|
@Column(nullable = false)
|
||||||
|
private ZonedDateTime publishedAt;
|
||||||
|
|
||||||
public PictureEntity(Picture picture) {
|
public PictureEntity(Picture picture) {
|
||||||
id = picture.id();
|
id = picture.id();
|
||||||
publisherId = picture.publisherId();
|
publisherId = picture.publisherId();
|
||||||
|
publishedAt = picture.publishedAt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Picture toDomain() {
|
public Picture toDomain() {
|
||||||
return new Picture(id, publisherId, null);
|
return new Picture(id, publisherId, publishedAt, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package org.codiki.infrastructure.picture.repository;
|
package org.codiki.infrastructure.picture.repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.codiki.domain.picture.model.Picture;
|
||||||
import org.codiki.infrastructure.picture.model.PictureEntity;
|
import org.codiki.infrastructure.picture.model.PictureEntity;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
public interface PictureRepository extends JpaRepository<PictureEntity, UUID> {
|
public interface PictureRepository extends JpaRepository<PictureEntity, UUID> {
|
||||||
|
List<PictureEntity> findAllByPublisherId(UUID id);
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,30 @@
|
|||||||
package org.codiki.infrastructure.publication;
|
package org.codiki.infrastructure.publication;
|
||||||
|
|
||||||
import static java.util.Collections.reverseOrder;
|
|
||||||
import static java.util.Comparator.comparingInt;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.codiki.domain.publication.model.Publication;
|
import org.codiki.domain.publication.model.Publication;
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
||||||
import org.codiki.domain.publication.port.PublicationPort;
|
import org.codiki.domain.publication.port.PublicationPort;
|
||||||
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
import org.codiki.infrastructure.publication.model.PublicationSearchResult;
|
import org.codiki.infrastructure.publication.model.PublicationSearchResult;
|
||||||
import org.codiki.infrastructure.publication.repository.PublicationRepository;
|
import org.codiki.infrastructure.publication.repository.PublicationRepository;
|
||||||
|
import org.springframework.data.domain.Limit;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static java.util.Collections.reverseOrder;
|
||||||
|
import static java.util.Comparator.comparingInt;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class PublicationJpaAdapter implements PublicationPort {
|
public class PublicationJpaAdapter implements PublicationPort {
|
||||||
private final PublicationRepository repository;
|
private final PublicationRepository repository;
|
||||||
private final PublicationSearchCriteriaJpaAdapter publicationSearchCriteriaJpaAdapter;
|
private final PublicationSearchCriteriaJpaAdapter publicationSearchCriteriaJpaAdapter;
|
||||||
|
|
||||||
public PublicationJpaAdapter(
|
public PublicationJpaAdapter(
|
||||||
PublicationRepository repository,
|
PublicationRepository repository,
|
||||||
PublicationSearchCriteriaJpaAdapter publicationSearchCriteriaJpaAdapter
|
PublicationSearchCriteriaJpaAdapter publicationSearchCriteriaJpaAdapter
|
||||||
) {
|
) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.publicationSearchCriteriaJpaAdapter = publicationSearchCriteriaJpaAdapter;
|
this.publicationSearchCriteriaJpaAdapter = publicationSearchCriteriaJpaAdapter;
|
||||||
@@ -36,7 +39,7 @@ public class PublicationJpaAdapter implements PublicationPort {
|
|||||||
@Override
|
@Override
|
||||||
public Optional<Publication> findById(UUID publicationId) {
|
public Optional<Publication> findById(UUID publicationId) {
|
||||||
return repository.findById(publicationId)
|
return repository.findById(publicationId)
|
||||||
.map(PublicationEntity::toDomain);
|
.map(PublicationEntity::toDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,7 +49,7 @@ public class PublicationJpaAdapter implements PublicationPort {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Publication> search(List<PublicationSearchCriterion> criteria) {
|
public List<Publication> search(List<PublicationSearchCriterion> criteria) {
|
||||||
List<PublicationSearchCriterion> adaptedCriteria = publicationSearchCriteriaJpaAdapter.adaptCriteriaForJpa(criteria);
|
List<PublicationSearchJpaCriterion> adaptedCriteria = publicationSearchCriteriaJpaAdapter.adaptCriteriaForJpa(criteria);
|
||||||
return repository.search(adaptedCriteria)
|
return repository.search(adaptedCriteria)
|
||||||
.stream()
|
.stream()
|
||||||
.map(PublicationEntity::toDomain)
|
.map(PublicationEntity::toDomain)
|
||||||
@@ -55,4 +58,12 @@ public class PublicationJpaAdapter implements PublicationPort {
|
|||||||
.map(PublicationSearchResult::getPublication)
|
.map(PublicationSearchResult::getPublication)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Publication> getLatest() {
|
||||||
|
return repository.getLatest(Limit.of(10))
|
||||||
|
.stream()
|
||||||
|
.map(PublicationEntity::toDomain)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,15 @@ package org.codiki.infrastructure.publication;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.codiki.domain.publication.exception.BadPublicationSearchCriterionException;
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaField;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class PublicationSearchCriteriaJpaAdapter {
|
public class PublicationSearchCriteriaJpaAdapter {
|
||||||
public List<PublicationSearchCriterion> adaptCriteriaForJpa(List<PublicationSearchCriterion> initialCriteria) {
|
public List<PublicationSearchJpaCriterion> adaptCriteriaForJpa(List<PublicationSearchCriterion> initialCriteria) {
|
||||||
List<PublicationSearchCriterion> result = new LinkedList<>();
|
List<PublicationSearchCriterion> result = new LinkedList<>();
|
||||||
|
|
||||||
for (PublicationSearchCriterion criterion : initialCriteria) {
|
for (PublicationSearchCriterion criterion : initialCriteria) {
|
||||||
@@ -29,6 +32,19 @@ public class PublicationSearchCriteriaJpaAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result.stream()
|
||||||
|
.map(this::mapToJpaCriterion)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicationSearchJpaCriterion mapToJpaCriterion(PublicationSearchCriterion criterion) {
|
||||||
|
return new PublicationSearchJpaCriterion(
|
||||||
|
PublicationSearchJpaField.fromDomain(criterion.searchField())
|
||||||
|
.orElseThrow(() -> new BadPublicationSearchCriterionException(
|
||||||
|
String.format("Unknown field research criterion: %s", criterion.searchField()))
|
||||||
|
),
|
||||||
|
criterion.searchType(),
|
||||||
|
criterion.value()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user