Compare commits
122
Commits
| 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 |
No files matched your search
@@ -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
@@ -38,3 +38,59 @@ build/
|
||||
**/.angular
|
||||
|
||||
**/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
|
||||
@@ -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"]
|
||||
@@ -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
|
||||
Vendored
+84
@@ -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
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+10
@@ -1,6 +1,8 @@
|
||||
package org.codiki.application.picture;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -30,6 +32,7 @@ public class PictureUseCases {
|
||||
.withId(UUID.randomUUID())
|
||||
.withPublisher(authenticatedUser)
|
||||
.withContentFile(pictureFile)
|
||||
.withPublicationDate(ZonedDateTime.now())
|
||||
.build();
|
||||
|
||||
picturePort.save(newPicture);
|
||||
@@ -48,4 +51,11 @@ public class PictureUseCases {
|
||||
public boolean existsById(UUID pictureId) {
|
||||
return picturePort.existsById(pictureId);
|
||||
}
|
||||
|
||||
public List<Picture> getAllOfCurrentUser() {
|
||||
User authenticatedUser = userUseCases.getAuthenticatedUser()
|
||||
.orElseThrow(AuthenticationRequiredException::new);
|
||||
|
||||
return picturePort.findAllByPublisherId(authenticatedUser.id());
|
||||
}
|
||||
}
|
||||
File renamed without changes.
Executable
+144
@@ -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();
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+29
-1
@@ -3,12 +3,15 @@ package org.codiki.application.publication;
|
||||
import static java.util.Objects.isNull;
|
||||
import java.time.Clock;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.codiki.domain.publication.model.builder.AuthorBuilder.anAuthor;
|
||||
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.picture.PictureUseCases;
|
||||
import org.codiki.application.user.UserUseCases;
|
||||
@@ -31,6 +34,7 @@ public class PublicationUseCases {
|
||||
private final CategoryUseCases categoryUseCases;
|
||||
private final Clock clock;
|
||||
private final KeyGenerator keyGenerator;
|
||||
private final ParserService parserService;
|
||||
private final PictureUseCases pictureUseCases;
|
||||
private final PublicationCreationRequestValidator publicationCreationRequestValidator;
|
||||
private final PublicationPort publicationPort;
|
||||
@@ -42,6 +46,7 @@ public class PublicationUseCases {
|
||||
CategoryUseCases categoryUseCases,
|
||||
Clock clock,
|
||||
KeyGenerator keyGenerator,
|
||||
ParserService parserService,
|
||||
PictureUseCases pictureUseCases,
|
||||
PublicationCreationRequestValidator publicationCreationRequestValidator,
|
||||
PublicationPort publicationPort,
|
||||
@@ -52,6 +57,7 @@ public class PublicationUseCases {
|
||||
this.categoryUseCases = categoryUseCases;
|
||||
this.clock = clock;
|
||||
this.keyGenerator = keyGenerator;
|
||||
this.parserService = parserService;
|
||||
this.publicationCreationRequestValidator = publicationCreationRequestValidator;
|
||||
this.publicationPort = publicationPort;
|
||||
this.publicationUpdateRequestValidator = publicationUpdateRequestValidator;
|
||||
@@ -83,6 +89,7 @@ public class PublicationUseCases {
|
||||
.withKey(keyGenerator.generateKey())
|
||||
.withTitle(request.title())
|
||||
.withText(request.text())
|
||||
.withParsedText(parserService.parse(request.text()))
|
||||
.withDescription(request.description())
|
||||
.withCreationDate(ZonedDateTime.now(clock))
|
||||
.withIllustrationId(request.illustrationId())
|
||||
@@ -116,6 +123,7 @@ public class PublicationUseCases {
|
||||
|
||||
if (!isNull(request.text())) {
|
||||
publicationBuilder.withText(request.text());
|
||||
publicationBuilder.withParsedText(parserService.parse(request.text()));
|
||||
}
|
||||
|
||||
if (!isNull(request.description())) {
|
||||
@@ -163,7 +171,19 @@ public class PublicationUseCases {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -171,4 +191,12 @@ public class PublicationUseCases {
|
||||
|
||||
return publicationPort.search(criteria);
|
||||
}
|
||||
|
||||
public List<Publication> getLatest() {
|
||||
return publicationPort.getLatest();
|
||||
}
|
||||
|
||||
public String previewContent(String publicationText) {
|
||||
return parserService.parse(publicationText);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
@@ -5,6 +5,7 @@ import java.util.stream.IntStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class KeyGeneratorTest {
|
||||
@@ -16,6 +17,7 @@ class KeyGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void generateKey_should_generate_random_keys_with_alphanumeric_characters() {
|
||||
Pattern validationRegex = Pattern.compile("^[0-9A-Z]{10}$");
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
@@ -1,10 +1,12 @@
|
||||
package org.codiki.domain.picture.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public record Picture(
|
||||
UUID id,
|
||||
UUID publisherId,
|
||||
ZonedDateTime publishedAt,
|
||||
File contentFile
|
||||
) {}
|
||||
+8
-1
@@ -1,6 +1,7 @@
|
||||
package org.codiki.domain.picture.model.builder;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.codiki.domain.picture.model.Picture;
|
||||
@@ -9,6 +10,7 @@ import org.codiki.domain.user.model.User;
|
||||
public class PictureBuilder {
|
||||
private UUID id;
|
||||
private UUID publisherId;
|
||||
private ZonedDateTime publishedAt;
|
||||
private File contentFile;
|
||||
|
||||
private PictureBuilder() {}
|
||||
@@ -37,12 +39,17 @@ public class PictureBuilder {
|
||||
return withPublisherId(publisher.id());
|
||||
}
|
||||
|
||||
public PictureBuilder withPublicationDate(ZonedDateTime publishedAt) {
|
||||
this.publishedAt = publishedAt;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PictureBuilder withContentFile(File contentFile) {
|
||||
this.contentFile = contentFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Picture build() {
|
||||
return new Picture(id, publisherId, contentFile);
|
||||
return new Picture(id, publisherId, publishedAt, contentFile);
|
||||
}
|
||||
}
|
||||
+3
@@ -1,5 +1,6 @@
|
||||
package org.codiki.domain.picture.port;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -13,4 +14,6 @@ public interface PicturePort {
|
||||
void save(Picture picture);
|
||||
|
||||
void deleteById(UUID pictureId);
|
||||
|
||||
List<Picture> findAllByPublisherId(UUID id);
|
||||
}
|
||||
+9
@@ -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);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -5,7 +5,7 @@ import java.util.UUID;
|
||||
public record Author(
|
||||
UUID id,
|
||||
String name,
|
||||
String image
|
||||
String photoId
|
||||
) {
|
||||
|
||||
}
|
||||
+1
@@ -8,6 +8,7 @@ public record Publication(
|
||||
String key,
|
||||
String title,
|
||||
String text,
|
||||
String parsedText,
|
||||
String description,
|
||||
ZonedDateTime creationDate,
|
||||
UUID illustrationId,
|
||||
File renamed without changes.
+1
@@ -40,6 +40,7 @@ public class AuthorBuilder {
|
||||
}
|
||||
|
||||
public Author build() {
|
||||
//
|
||||
return new Author(id, name, image);
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -1,17 +1,17 @@
|
||||
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.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 {
|
||||
private UUID id;
|
||||
private String key;
|
||||
private String title;
|
||||
private String text;
|
||||
private String parsedText;
|
||||
private String description;
|
||||
private ZonedDateTime creationDate;
|
||||
private UUID illustrationId;
|
||||
@@ -30,6 +30,7 @@ public class PublicationBuilder {
|
||||
.withKey(publication.key())
|
||||
.withTitle(publication.title())
|
||||
.withText(publication.text())
|
||||
.withParsedText(publication.parsedText())
|
||||
.withDescription(publication.description())
|
||||
.withCreationDate(publication.creationDate())
|
||||
.withIllustrationId(publication.illustrationId())
|
||||
@@ -57,6 +58,11 @@ public class PublicationBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PublicationBuilder withParsedText(String parsedText) {
|
||||
this.parsedText = parsedText;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PublicationBuilder withDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
@@ -88,6 +94,7 @@ public class PublicationBuilder {
|
||||
key,
|
||||
title,
|
||||
text,
|
||||
parsedText,
|
||||
description,
|
||||
creationDate,
|
||||
illustrationId,
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
@@ -15,4 +15,6 @@ public interface PublicationPort {
|
||||
void delete(Publication publication);
|
||||
|
||||
List<Publication> search(List<PublicationSearchCriterion> criteria);
|
||||
|
||||
List<Publication> getLatest();
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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")
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+5
-9
@@ -7,16 +7,10 @@ import static org.springframework.http.HttpStatus.UNAUTHORIZED;
|
||||
import org.codiki.domain.category.exception.CategoryDeletionException;
|
||||
import org.codiki.domain.category.exception.CategoryEditionException;
|
||||
import org.codiki.domain.category.exception.CategoryNotFoundException;
|
||||
import org.codiki.domain.exception.LoginFailureException;
|
||||
import org.codiki.domain.exception.RefreshTokenDoesNotExistException;
|
||||
import org.codiki.domain.exception.RefreshTokenExpiredException;
|
||||
import org.codiki.domain.exception.UserDoesNotExistException;
|
||||
import org.codiki.domain.exception.*;
|
||||
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
||||
import org.codiki.domain.picture.exception.PictureUploadException;
|
||||
import org.codiki.domain.publication.exception.NoPublicationSearchResultException;
|
||||
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.publication.exception.*;
|
||||
import org.codiki.domain.user.exception.UserAlreadyExistsException;
|
||||
import org.codiki.domain.user.exception.UserCreationException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -28,6 +22,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
|
||||
@RestControllerAdvice
|
||||
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
@ExceptionHandler({
|
||||
BadPublicationSearchCriterionException.class,
|
||||
CategoryDeletionException.class,
|
||||
CategoryEditionException.class,
|
||||
CategoryNotFoundException.class,
|
||||
@@ -53,7 +48,8 @@ public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHan
|
||||
}
|
||||
|
||||
@ExceptionHandler({
|
||||
RefreshTokenExpiredException.class
|
||||
RefreshTokenExpiredException.class,
|
||||
AuthenticationRequiredException.class,
|
||||
})
|
||||
public ProblemDetail handleUnauthorizedExceptions(Exception exception) {
|
||||
return buildProblemDetail(UNAUTHORIZED, exception);
|
||||
File renamed without changes.
+3
-1
@@ -48,12 +48,14 @@ public class SecurityConfiguration {
|
||||
"/api/pictures/{pictureId}",
|
||||
"/api/publications/{publicationId}",
|
||||
"/api/publications",
|
||||
"/api/publications/latest",
|
||||
"/error"
|
||||
).permitAll()
|
||||
.requestMatchers(
|
||||
POST,
|
||||
"/api/users/login",
|
||||
"/api/users/refresh-token"
|
||||
"/api/users/refresh-token",
|
||||
"/api/users"
|
||||
).permitAll()
|
||||
.requestMatchers(
|
||||
POST,
|
||||
File renamed without changes.
File renamed without changes.
+10
@@ -1,6 +1,7 @@
|
||||
package org.codiki.exposition.picture;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
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.domain.picture.exception.PictureNotFoundException;
|
||||
import org.codiki.domain.picture.model.Picture;
|
||||
import org.codiki.exposition.picture.model.PictureDto;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -44,4 +46,12 @@ public class PictureController {
|
||||
.orElseThrow(() -> new PictureNotFoundException(pictureId));
|
||||
return new FileSystemResource(picture.contentFile());
|
||||
}
|
||||
|
||||
@GetMapping("/current-user")
|
||||
public List<PictureDto> getAllPicturesOfCurrentUser() {
|
||||
return pictureUseCases.getAllOfCurrentUser()
|
||||
.stream()
|
||||
.map(PictureDto::new)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
+15
@@ -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());
|
||||
}
|
||||
}
|
||||
+32
-18
@@ -1,28 +1,22 @@
|
||||
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.UUID;
|
||||
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.NO_CONTENT;
|
||||
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
|
||||
@RequestMapping("/api/publications")
|
||||
@@ -66,7 +60,7 @@ public class PublicationController {
|
||||
|
||||
@GetMapping
|
||||
public List<PublicationDto> searchPublications(@RequestParam("query") String searchQuery) {
|
||||
final List<PublicationDto> publications = publicationUseCases.searchPublications(searchQuery)
|
||||
List<PublicationDto> publications = publicationUseCases.searchPublications(searchQuery)
|
||||
.stream()
|
||||
.map(PublicationDto::new)
|
||||
.toList();
|
||||
@@ -77,4 +71,24 @@ public class PublicationController {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ public record AuthorDto(
|
||||
this(
|
||||
author.id(),
|
||||
author.name(),
|
||||
author.image()
|
||||
author.photoId()
|
||||
);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.codiki.exposition.publication.model;
|
||||
|
||||
public record PreviewContentRequest(
|
||||
String text
|
||||
) {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.codiki.exposition.publication.model;
|
||||
|
||||
public record PreviewContentResponse(
|
||||
String text
|
||||
) {}
|
||||
+4
-3
@@ -1,16 +1,16 @@
|
||||
package org.codiki.exposition.publication.model;
|
||||
|
||||
import org.codiki.domain.publication.model.Publication;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.codiki.domain.publication.model.Publication;
|
||||
import org.codiki.exposition.category.model.CategoryDto;
|
||||
|
||||
public record PublicationDto(
|
||||
UUID id,
|
||||
String key,
|
||||
String title,
|
||||
String text,
|
||||
String parsedText,
|
||||
String description,
|
||||
ZonedDateTime creationDate,
|
||||
UUID illustrationId,
|
||||
@@ -23,6 +23,7 @@ public record PublicationDto(
|
||||
publication.key(),
|
||||
publication.title(),
|
||||
publication.text(),
|
||||
publication.parsedText(),
|
||||
publication.description(),
|
||||
publication.creationDate(),
|
||||
publication.illustrationId(),
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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")
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+4
@@ -1,5 +1,6 @@
|
||||
package org.codiki.infrastructure.category.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.codiki.infrastructure.category.model.CategoryEntity;
|
||||
@@ -16,4 +17,7 @@ public interface CategoryRepository extends JpaRepository<CategoryEntity, UUID>
|
||||
) > 0
|
||||
""", nativeQuery = true)
|
||||
boolean existsAnyAssociatedPublication(@Param("categoryId") UUID categoryId);
|
||||
|
||||
@Query("SELECT c FROM CategoryEntity c LEFT JOIN FETCH c.subCategories")
|
||||
List<CategoryEntity> findAll();
|
||||
}
|
||||
File renamed without changes.
+9
@@ -1,6 +1,7 @@
|
||||
package org.codiki.infrastructure.picture;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -66,4 +67,12 @@ public class PictureJpaAdapter implements PicturePort {
|
||||
public void deleteById(UUID pictureId) {
|
||||
repository.deleteById(pictureId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Picture> findAllByPublisherId(UUID id) {
|
||||
return repository.findAllByPublisherId(id)
|
||||
.stream()
|
||||
.map(PictureEntity::toDomain)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
package org.codiki.infrastructure.picture.model;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.codiki.domain.picture.model.Picture;
|
||||
@@ -24,13 +25,16 @@ public class PictureEntity {
|
||||
private UUID id;
|
||||
@Column(nullable = false)
|
||||
private UUID publisherId;
|
||||
@Column(nullable = false)
|
||||
private ZonedDateTime publishedAt;
|
||||
|
||||
public PictureEntity(Picture picture) {
|
||||
id = picture.id();
|
||||
publisherId = picture.publisherId();
|
||||
publishedAt = picture.publishedAt();
|
||||
}
|
||||
|
||||
public Picture toDomain() {
|
||||
return new Picture(id, publisherId, null);
|
||||
return new Picture(id, publisherId, publishedAt, null);
|
||||
}
|
||||
}
|
||||
+3
@@ -1,9 +1,12 @@
|
||||
package org.codiki.infrastructure.picture.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.codiki.domain.picture.model.Picture;
|
||||
import org.codiki.infrastructure.picture.model.PictureEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PictureRepository extends JpaRepository<PictureEntity, UUID> {
|
||||
List<PictureEntity> findAllByPublisherId(UUID id);
|
||||
}
|
||||
+18
-7
@@ -1,19 +1,22 @@
|
||||
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.search.PublicationSearchCriterion;
|
||||
import org.codiki.domain.publication.port.PublicationPort;
|
||||
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.repository.PublicationRepository;
|
||||
import org.springframework.data.domain.Limit;
|
||||
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
|
||||
public class PublicationJpaAdapter implements PublicationPort {
|
||||
private final PublicationRepository repository;
|
||||
@@ -46,7 +49,7 @@ public class PublicationJpaAdapter implements PublicationPort {
|
||||
|
||||
@Override
|
||||
public List<Publication> search(List<PublicationSearchCriterion> criteria) {
|
||||
List<PublicationSearchCriterion> adaptedCriteria = publicationSearchCriteriaJpaAdapter.adaptCriteriaForJpa(criteria);
|
||||
List<PublicationSearchJpaCriterion> adaptedCriteria = publicationSearchCriteriaJpaAdapter.adaptCriteriaForJpa(criteria);
|
||||
return repository.search(adaptedCriteria)
|
||||
.stream()
|
||||
.map(PublicationEntity::toDomain)
|
||||
@@ -55,4 +58,12 @@ public class PublicationJpaAdapter implements PublicationPort {
|
||||
.map(PublicationSearchResult::getPublication)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Publication> getLatest() {
|
||||
return repository.getLatest(Limit.of(10))
|
||||
.stream()
|
||||
.map(PublicationEntity::toDomain)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
+18
-2
@@ -3,12 +3,15 @@ package org.codiki.infrastructure.publication;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.codiki.domain.publication.exception.BadPublicationSearchCriterionException;
|
||||
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;
|
||||
|
||||
@Component
|
||||
public class PublicationSearchCriteriaJpaAdapter {
|
||||
public List<PublicationSearchCriterion> adaptCriteriaForJpa(List<PublicationSearchCriterion> initialCriteria) {
|
||||
public List<PublicationSearchJpaCriterion> adaptCriteriaForJpa(List<PublicationSearchCriterion> initialCriteria) {
|
||||
List<PublicationSearchCriterion> result = new LinkedList<>();
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 286 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user