From e980dbf884056b9206e88cd5d1d45edc0f55d2ac Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 3 Jan 2026 22:03:04 +0100 Subject: [PATCH 001/165] working on tag creation Signed-off-by: Stephan Richter --- .gitea/workflows/docker.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index 364f1524..619850b4 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -25,8 +25,10 @@ jobs: - name: Tag image for upload run: | DATE=$(cat /tmp/date) + TAG=$DATE_${{ gitea.ref_name }} + echo $TAG docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} - docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:$DATE_${{ gitea.ref_name }} + docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG - name: Login to registry uses: docker/login-action@v2 @@ -38,5 +40,7 @@ jobs: - name: Push to registry run: | DATE=$(cat /tmp/date) + TAG=$DATE_${{ gitea.ref_name }} + echo $TAG docker push ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} - docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$DATE_${{ gitea.ref_name }} + docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG From dceb84669b85d2d47980a13295c4aedfd6b55666 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 3 Jan 2026 22:13:21 +0100 Subject: [PATCH 002/165] debugging Signed-off-by: Stephan Richter --- .gitea/workflows/docker.yaml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index 619850b4..a2bae65f 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -19,14 +19,12 @@ jobs: - name: Store tag date run: | - DATE=$(date +%Y%m%d_%H%M) - echo $DATE | tee /tmp/date + echo $(date +%Y%m%d_%H%M)_${{ gitea.ref_name }} > /tmp/tag - name: Tag image for upload run: | - DATE=$(cat /tmp/date) - TAG=$DATE_${{ gitea.ref_name }} - echo $TAG + TAG=$(cat /tmp/tag) + echo using '"'$TAG'"' as tag docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG @@ -39,8 +37,7 @@ jobs: - name: Push to registry run: | - DATE=$(cat /tmp/date) - TAG=$DATE_${{ gitea.ref_name }} - echo $TAG + TAG=$(cat /tmp/tag) + echo using '"'$TAG'"' as tag docker push ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG From bd95c3d0c447f4ad54d3a566b515ddc989c7dd65 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 3 Jan 2026 22:14:22 +0100 Subject: [PATCH 003/165] debugging Signed-off-by: Stephan Richter --- Dockerfile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4062135c..0e148d8c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,26 +11,26 @@ RUN npm install && npm run build -FROM alpine AS java_build -RUN apk add bash git gradle fontconfig font-opensans openjdk21-jre -ADD . /Umbrella -WORKDIR /Umbrella -COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web -RUN gradle --no-daemon build +#FROM alpine AS java_build +#RUN apk add bash git gradle fontconfig font-opensans openjdk21-jre +#ADD . /Umbrella +#WORKDIR /Umbrella +#COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web +#RUN gradle --no-daemon build -FROM alpine -RUN apk add bash fontconfig font-opensans graphviz openjdk21-jre weasyprint -RUN adduser -D umbrella -COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/ -RUN chown -R umbrella /home/umbrella -ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar -USER umbrella -WORKDIR /home/umbrella -RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json -EXPOSE 80 -CMD java -jar jar/backend.jar +#FROM alpine +#RUN apk add bash fontconfig font-opensans graphviz openjdk21-jre weasyprint +#RUN adduser -D umbrella +#COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/ +#RUN chown -R umbrella /home/umbrella +#ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar +#USER umbrella +#WORKDIR /home/umbrella +#RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json +#EXPOSE 80 +#CMD java -jar jar/backend.jar From 8d2f3ef88ea9ea18fc435d9b4def31ba250dfccc Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 3 Jan 2026 22:17:30 +0100 Subject: [PATCH 004/165] fixed tagging Signed-off-by: Stephan Richter --- .gitea/workflows/docker.yaml | 6 +++--- Dockerfile | 34 +++++++++++++++++----------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index a2bae65f..b3d2bd8c 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -19,12 +19,13 @@ jobs: - name: Store tag date run: | - echo $(date +%Y%m%d_%H%M)_${{ gitea.ref_name }} > /tmp/tag + TAG=$(date +%Y%m%d_%H%M)_${{ gitea.ref_name }} + echo $TAG > /tmp/tag + echo Using '"'$TAG'"' as tag. - name: Tag image for upload run: | TAG=$(cat /tmp/tag) - echo using '"'$TAG'"' as tag docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} docker tag umbrella ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG @@ -38,6 +39,5 @@ jobs: - name: Push to registry run: | TAG=$(cat /tmp/tag) - echo using '"'$TAG'"' as tag docker push ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG diff --git a/Dockerfile b/Dockerfile index 0e148d8c..4062135c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,26 +11,26 @@ RUN npm install && npm run build -#FROM alpine AS java_build -#RUN apk add bash git gradle fontconfig font-opensans openjdk21-jre -#ADD . /Umbrella -#WORKDIR /Umbrella -#COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web -#RUN gradle --no-daemon build +FROM alpine AS java_build +RUN apk add bash git gradle fontconfig font-opensans openjdk21-jre +ADD . /Umbrella +WORKDIR /Umbrella +COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web +RUN gradle --no-daemon build -#FROM alpine -#RUN apk add bash fontconfig font-opensans graphviz openjdk21-jre weasyprint -#RUN adduser -D umbrella -#COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/ -#RUN chown -R umbrella /home/umbrella -#ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar -#USER umbrella -#WORKDIR /home/umbrella -#RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json -#EXPOSE 80 -#CMD java -jar jar/backend.jar +FROM alpine +RUN apk add bash fontconfig font-opensans graphviz openjdk21-jre weasyprint +RUN adduser -D umbrella +COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/ +RUN chown -R umbrella /home/umbrella +ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar +USER umbrella +WORKDIR /home/umbrella +RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json +EXPOSE 80 +CMD java -jar jar/backend.jar From f4adf2ca3c88778ef3db2f7a9d1b6cdbde5a3c1a Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Mon, 5 Jan 2026 10:34:42 +0100 Subject: [PATCH 005/165] bugfix: altered patch key for updating template in document Signed-off-by: Stephan Richter --- Dockerfile | 4 ++-- .../main/java/de/srsoftware/umbrella/core/model/Document.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 40ff6f95..63433f22 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM alpine:3.22 AS svelte_build -RUN apk add bash git npm +RUN apk add npm RUN adduser -Dh /home/svelte svelte ADD . /home/svelte/Umbrella RUN chown -R svelte /home/svelte/Umbrella @@ -9,7 +9,7 @@ RUN npm install && npm run build FROM alpine AS java_build -RUN apk add bash git gradle fontconfig font-opensans openjdk21-jre +RUN apk add gradle fontconfig font-opensans openjdk21-jre ADD . /Umbrella WORKDIR /Umbrella COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Document.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Document.java index a49d2545..e444703b 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Document.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Document.java @@ -207,7 +207,7 @@ public final class Document implements Mappable { case SENDER: if (json.get(key) instanceof JSONObject nested) sender.patch(nested); break; case STATE: state = State.of(json.getInt(key)).orElseThrow(() -> new UmbrellaException(HTTP_UNPROCESSABLE,"Invalid state")); break; case POS: if (json.get(key) instanceof JSONObject nested) positions.patch(nested); break; - case TEMPLATE_ID: if (json.get(key) instanceof String templateId) template = templateId; break; + case TEMPLATE: if (json.get(key) instanceof String templateId) template = templateId; break; default: key = null; } if (key != null) dirtyFields.add(key); From 64065803858539dce7b47add0bc449bd26283759 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Mon, 5 Jan 2026 23:15:50 +0100 Subject: [PATCH 006/165] added call to make.eldorado.srsoftware.de Signed-off-by: Stephan Richter --- .gitea/workflows/docker.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index ad8cc97a..22dc15c1 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -41,6 +41,11 @@ jobs: docker push ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }} docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG + - name: Restart umbrella.srsoftware.de + if: github.ref == 'refs/heads/dev' + run: | + curl -X POST -H "Authorization: Bearer ${{ secrets.ELDORADO_MAKE_BEARER }}" -d umbrella_25_start https://make.eldorado.srsoftware.de/launch + Clean-Registry: runs-on: ubuntu-latest steps: From bdb3443240ccfa10951f4b6cc1e36cf6386db55f Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 10 Jan 2026 22:45:44 +0100 Subject: [PATCH 007/165] added another fix: - public wiki pages now show login form for guests - private wiki pages now also show when opened via url (i.e. not by link within umbrella) Signed-off-by: Stephan Richter --- frontend/src/routes/wiki/GuestView.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/routes/wiki/GuestView.svelte b/frontend/src/routes/wiki/GuestView.svelte index 72f9b4cd..b0750231 100644 --- a/frontend/src/routes/wiki/GuestView.svelte +++ b/frontend/src/routes/wiki/GuestView.svelte @@ -1,4 +1,6 @@
    {#each sortedTasks as task} - + {/each}
diff --git a/frontend/src/routes/task/View.svelte b/frontend/src/routes/task/View.svelte index 4a1feb3f..dce5c0f6 100644 --- a/frontend/src/routes/task/View.svelte +++ b/frontend/src/routes/task/View.svelte @@ -21,7 +21,7 @@ let { id } = $props(); let children = $state(null); let dummy = $derived(updateOn(id)); - let estimated_time = $state({sum:0}); + let est_time = $state({sum:0}); let project = $state(null); const router = useTinyRouter(); let showSettings = $state(router.fullPath.endsWith('/edit')); @@ -251,9 +251,9 @@
{t('due_date')}
{task.due_date}
{/if} - {#if task.estimated_time} + {#if task.est_time}
{t('estimated_time')}
-
{task.estimated_time} h
+
{task.est_time} h
{/if} {#if showSettings}
{t('extended_settings')}
@@ -284,7 +284,7 @@
{t('estimated_time')}
- update({estimated_time:task.estimated_time})} /> h + update({est_time:task.est_time})} /> h
{t('priority')}
@@ -320,7 +320,7 @@
{#if children} - + {/if}
diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java index 8217099f..78826217 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java @@ -3,11 +3,11 @@ package de.srsoftware.umbrella.legacy; import static de.srsoftware.tools.Optionals.nullable; -import static de.srsoftware.umbrella.core.Constants.TOKEN; import static de.srsoftware.umbrella.core.ModuleRegistry.companyService; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; -import static de.srsoftware.umbrella.core.Paths.JSON; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.TOKEN; +import static de.srsoftware.umbrella.core.constants.Path.JSON; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java index 497650d4..b9ec4cf3 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java @@ -3,12 +3,12 @@ package de.srsoftware.umbrella.legacy; import static de.srsoftware.tools.Optionals.nullable; -import static de.srsoftware.umbrella.core.Constants.TOKEN; -import static de.srsoftware.umbrella.core.Constants.URI; import static de.srsoftware.umbrella.core.ModuleRegistry.noteService; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; import static de.srsoftware.umbrella.core.Util.markdown; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException; +import static de.srsoftware.umbrella.core.constants.Field.TOKEN; +import static de.srsoftware.umbrella.core.constants.Field.URI; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidField; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; @@ -53,9 +53,9 @@ public class NotesLegacy extends BaseHandler { } private boolean postNotesHtml(HttpExchange ex, Map params) throws IOException { - if (!(params.get(URI) instanceof String uri)) throw invalidFieldException(URI,"URI of the form \"module:entry-id\""); + if (!(params.get(URI) instanceof String uri)) throw invalidField(URI,"URI of the form \"module:entry-id\""); var parts = uri.split(":",2); - if (parts.length<2) throw invalidFieldException(URI,"URI of the form \"module:entry-id\""); + if (parts.length<2) throw invalidField(URI,"URI of the form \"module:entry-id\""); var module = parts[0]; var entryId = parts[1]; var notes = noteService().getNotes(module,entryId); diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java index aec94ba9..1c2242c2 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java @@ -3,11 +3,12 @@ package de.srsoftware.umbrella.legacy; import static de.srsoftware.tools.Optionals.nullable; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.ModuleRegistry.projectService; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; -import static de.srsoftware.umbrella.core.Paths.JSON; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.TOKEN; +import static de.srsoftware.umbrella.core.constants.Field.USERS; +import static de.srsoftware.umbrella.core.constants.Path.JSON; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java index ec3d1667..772489d0 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java @@ -4,12 +4,11 @@ package de.srsoftware.umbrella.legacy; import static de.srsoftware.tools.Optionals.nullable; -import static de.srsoftware.umbrella.core.Constants.DESCRIPTION; -import static de.srsoftware.umbrella.core.Constants.TOKEN; import static de.srsoftware.umbrella.core.ModuleRegistry.taskService; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; -import static de.srsoftware.umbrella.core.Paths.JSON; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Path.JSON; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.unprocessable; import com.sun.net.httpserver.HttpExchange; @@ -63,6 +62,6 @@ public class TaskLegacy extends BaseHandler { var taskIds = taskIdMap.values().stream().map(Object::toString).map(Long::parseLong).toList(); return sendContent(ex,mapValues(taskService().load(taskIds))); } - throw unprocessable("Invalid request"); + throw unprocessable("Invalid request"); } } diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java index 445cc5e6..c78824f1 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java @@ -3,11 +3,13 @@ package de.srsoftware.umbrella.legacy; import static de.srsoftware.tools.MimeType.MIME_FORM_URL; import static de.srsoftware.tools.Query.decode; -import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Constants.TOKEN; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; -import static de.srsoftware.umbrella.core.Paths.*; import static de.srsoftware.umbrella.core.Util.request; +import static de.srsoftware.umbrella.core.constants.Constants.HOME; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.REDIRECT; +import static de.srsoftware.umbrella.core.constants.Field.TOKEN; +import static de.srsoftware.umbrella.core.constants.Path.*; import static de.srsoftware.umbrella.user.Paths.*; import static java.lang.Long.parseLong; import static java.lang.System.Logger.Level.*; @@ -17,9 +19,9 @@ import static java.time.temporal.ChronoUnit.DAYS; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; -import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; +import de.srsoftware.umbrella.core.constants.Path; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Session; import de.srsoftware.umbrella.core.model.Token; @@ -41,7 +43,7 @@ public class UserLegacy extends BaseHandler { } @Override - public boolean doGet(Path path, HttpExchange ex) throws IOException { + public boolean doGet(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { var head = path.pop(); return switch (head){ case null -> sendRedirect(ex, url(ex).replaceAll("/legacy/.*","")); @@ -49,7 +51,7 @@ public class UserLegacy extends BaseHandler { allowOrigin(ex, "*"); // add CORS header yield load(path,ex); } - case LOGIN -> getLogin(ex); + case Path.LOGIN -> getLogin(ex); case LOGOUT-> logout(ex); case MODULES -> getModules(ex); case SEARCH -> sendRedirect(ex,url(ex).replaceAll("/legacy/","/")); @@ -58,7 +60,7 @@ public class UserLegacy extends BaseHandler { } @Override - public boolean doPost(Path path, HttpExchange ex) throws IOException { + public boolean doPost(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { try { return switch (path.pop()) { case JSON -> jsonUser(ex); @@ -136,7 +138,7 @@ public class UserLegacy extends BaseHandler { for (var entry : userMap.entrySet()){ return sendContent(ex,entry.getValue()); } - throw UmbrellaException.notFound("Failed to load user(s) for id(s): {0}",ids); + throw UmbrellaException.notFound("Failed to load user(s) for id(s): {id}", ID,ids); } private boolean legacyNotify(HttpExchange ex) throws UmbrellaException, IOException { @@ -206,12 +208,12 @@ public class UserLegacy extends BaseHandler { var expiredToken = new SessionToken(token.toString(),"/", Instant.now().minus(1, DAYS),true); expiredToken.addTo(ex); if (returnTo instanceof String location) return sendRedirect(ex,location); - return sendContent(ex, Map.of(REDIRECT,"home")); + return sendContent(ex, Map.of(REDIRECT,HOME)); } catch (UmbrellaException e) { return send(ex,e); } if (returnTo instanceof String location) return sendRedirect(ex,location); - return sendContent(ex,Map.of(REDIRECT,"home")); + return sendContent(ex,Map.of(REDIRECT,HOME)); } private boolean postSearch(HttpExchange ex) throws IOException, UmbrellaException { @@ -282,7 +284,7 @@ public class UserLegacy extends BaseHandler { var session = userService().load(Token.of(token)); var user = userService().load(session); var userMap = user.toMap(); - userMap.put(TOKEN,Map.of(TOKEN,token,EXPIRATION,session.expiration().getEpochSecond())); + userMap.put(TOKEN,Map.of(TOKEN,token, EXPIRATION,session.expiration().getEpochSecond())); return sendContent(ex,userMap); } } diff --git a/messages/src/main/java/de/srsoftware/umbrella/message/MessageSystem.java b/messages/src/main/java/de/srsoftware/umbrella/message/MessageSystem.java index 6df9e4eb..d70e3865 100644 --- a/messages/src/main/java/de/srsoftware/umbrella/message/MessageSystem.java +++ b/messages/src/main/java/de/srsoftware/umbrella/message/MessageSystem.java @@ -3,8 +3,8 @@ package de.srsoftware.umbrella.message; import static de.srsoftware.tools.PathHandler.CONTENT_TYPE; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfigException; +import static de.srsoftware.umbrella.core.constants.Constants.UTF8; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfig; import static de.srsoftware.umbrella.message.Constants.*; import static java.lang.System.Logger.Level.*; @@ -72,7 +72,7 @@ public class MessageSystem implements PostBox { private final HashMap> exceptions = new HashMap<>(); public MessageSystem(Configuration config) throws UmbrellaException { - var dbFile = config.get(CONFIG_DB).orElseThrow(() -> missingConfigException(CONFIG_DB)); + var dbFile = config.get(CONFIG_DB).orElseThrow(() -> missingConfig(CONFIG_DB)); db = new SqliteMessageDb(connect(dbFile)); debugAddress = config.get(DEBUG_ADDREESS).map(Object::toString).orElse(null); port = config.get(CONFIG_SMTP_PORT,587); diff --git a/messages/src/main/java/de/srsoftware/umbrella/message/SqliteMessageDb.java b/messages/src/main/java/de/srsoftware/umbrella/message/SqliteMessageDb.java index b21460ef..deeba630 100644 --- a/messages/src/main/java/de/srsoftware/umbrella/message/SqliteMessageDb.java +++ b/messages/src/main/java/de/srsoftware/umbrella/message/SqliteMessageDb.java @@ -3,13 +3,16 @@ package de.srsoftware.umbrella.message; import static de.srsoftware.tools.jdbc.Condition.equal; import static de.srsoftware.tools.jdbc.Query.*; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; +import static de.srsoftware.umbrella.core.constants.Constants.TABLE_SETTINGS; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.message.model.Settings.Times; import static java.lang.System.Logger.Level.WARNING; import static java.text.MessageFormat.format; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.message.model.Settings; @@ -40,7 +43,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} Integer PRIMARY KEY, {2} VARCHAR(255) NOT N stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_SUBMISSIONS).causedBy(e); + throw failedToCreateTable(TABLE_SUBMISSIONS).causedBy(e); } } @@ -54,7 +57,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_SETTINGS).causedBy(e); + throw failedToCreateTable(TABLE_SETTINGS).causedBy(e); } Integer version = null; @@ -68,7 +71,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) } return version; } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_ENTITY,DB_VERSION).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT,DB_VERSION).causedBy(e); } } @@ -87,7 +90,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) if (settings != null) return settings; throw new UmbrellaException(500,"No submission settings stored for {0}",user); } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_USER_SETTINGS,user).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.SETTINGS), OWNER,user).causedBy(e); } } @@ -114,7 +117,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) replaceInto(TABLE_SUBMISSIONS, USER_ID, VALUE).values(user.id(),times).execute(db).close(); return settings; } catch (SQLException e) { - throw databaseException(FAILED_TO_STORE_ENTITY,"submission data").causedBy(e); + throw failedToStoreObject("submission data").causedBy(e); } } } diff --git a/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java b/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java index 6ad54848..ab85ce45 100644 --- a/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java +++ b/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java @@ -2,12 +2,11 @@ package de.srsoftware.umbrella.notes; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Constants.FULLTEXT; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; -import static de.srsoftware.umbrella.core.Paths.SEARCH; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Path.SEARCH; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.notes.Constants.CONFIG_DATABASE; @@ -34,7 +33,7 @@ public class NoteModule extends BaseHandler implements NoteService { public NoteModule(Configuration config) { super(); - var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); + var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); notesDb = new SqliteDb(connect(dbFile)); ModuleRegistry.add(this); } @@ -122,7 +121,7 @@ public class NoteModule extends BaseHandler implements NoteService { var head = path.pop(); long noteId = Long.parseLong(head); String text = body(ex); - if (text.isBlank()) throw missingFieldException("Note text"); + if (text.isBlank()) throw missingField("Note text"); var note = notesDb.load(noteId); if (note.authorId() != user.get().id()) throw forbidden("You are not allowed to edit notes of another user!"); note = new Note(note.id(),note.module(),note.entityId(),note.authorId(),text,LocalDateTime.now()); @@ -146,9 +145,9 @@ public class NoteModule extends BaseHandler implements NoteService { if (SEARCH.equals(module)) return postSearch(ex,user.get()); if (module == null) throw unprocessable("Module missing in path."); var entityId = path.pop(); - if (entityId == null || entityId.isBlank()) throw missingFieldException(ENTITY_ID); + if (entityId == null || entityId.isBlank()) throw missingField(ENTITY_ID); String text = body(ex); - if (text.isBlank()) throw missingFieldException("Note text"); + if (text.isBlank()) throw missingField("Note text"); var note = new Note(0,module,entityId,user.get().id(),text, LocalDateTime.now()); note = save(note); return sendContent(ex, note); @@ -170,7 +169,7 @@ public class NoteModule extends BaseHandler implements NoteService { private boolean postSearch(HttpExchange ex, UmbrellaUser user) throws IOException { var json = json(ex); - if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY); + if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingField(KEY); var keys = Arrays.asList(key.split(" ")); var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val; var notes = notesDb.find(user.id(),keys,fulltext); diff --git a/notes/src/main/java/de/srsoftware/umbrella/notes/SqliteDb.java b/notes/src/main/java/de/srsoftware/umbrella/notes/SqliteDb.java index 4f42ad5d..0d06d269 100644 --- a/notes/src/main/java/de/srsoftware/umbrella/notes/SqliteDb.java +++ b/notes/src/main/java/de/srsoftware/umbrella/notes/SqliteDb.java @@ -5,9 +5,12 @@ import static de.srsoftware.tools.jdbc.Condition.equal; import static de.srsoftware.tools.jdbc.Condition.like; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Text.NOTE; +import static de.srsoftware.umbrella.core.constants.Text.NOTE_WITH_ID; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.notes.Constants.*; import static java.lang.System.Logger.Level.*; import static java.text.MessageFormat.format; @@ -15,6 +18,7 @@ import static java.time.ZoneOffset.UTC; import de.srsoftware.tools.jdbc.Query; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.model.Note; import java.sql.Connection; import java.sql.SQLException; @@ -55,7 +59,7 @@ ADD COLUMN entity_id VARCHAR(255); stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_COLUMN,"(not existing)",ENTITY_ID,TABLE_NOTES).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_COLUMN,"old","(not existing)","new", ENTITY_ID, TABLE,TABLE_NOTES).causedBy(e); } } @@ -69,7 +73,7 @@ ADD COLUMN module VARCHAR(20); stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_COLUMN,"(not existing)",MODULE,TABLE_NOTES).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_COLUMN,"old","(not existing)","new", MODULE, TABLE,TABLE_NOTES).causedBy(e); } } @@ -84,7 +88,7 @@ SET module = SUBSTR(uri, 1, INSTR(uri, ':') - 1), stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException("Failed to fill \"{0}\" and \"{1}\" columns",MODULE,ENTITY_ID).causedBy(e); + throw databaseException("Failed to fill \"{a}\" and \"{b}\" columns","a", MODULE,"b", ENTITY_ID).causedBy(e); } } @@ -101,7 +105,7 @@ CREATE TABLE IF NOT EXISTS notes ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_NOTES).causedBy(e); + throw failedToCreateTable(TABLE_NOTES).causedBy(e); } } @@ -120,7 +124,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_NOTES).causedBy(e); + throw failedToCreateTable(TABLE_NOTES).causedBy(e); } } @@ -132,7 +136,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( .execute(db); return noteId; } catch (SQLException e){ - throw databaseException(FAILED_TO_DROP_ENTITY,"note",noteId); + throw failedToDropObject(t(NOTE_WITH_ID, ID,noteId)).causedBy(e); } } @@ -143,7 +147,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( .where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)) .execute(db); } catch (SQLException e){ - throw databaseException(FAILED_TO_DROP_NOTES,module,entityId).causedBy(e); + throw databaseException(FAILED_TO_DROP_NOTES,MODULE,module, ID,entityId).causedBy(e); } } @@ -154,7 +158,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY,"uri","column").causedBy(e); + throw databaseException(FAILED_TO_DROP_OBJECT, t("uri column")).causedBy(e); } } @@ -172,7 +176,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( rs.close(); return notes; } catch (SQLException e) { - throw databaseException(FAILED_TO_SEARCH_DB,TABLE_NOTES).causedBy(e); + throw failedToSearchDb(t(TABLE_NOTES)).causedBy(e); } } @@ -181,7 +185,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( try { var notes = new HashMap(); var rs = select(ALL).from(TABLE_NOTES).where(USER_ID,equal(authorId)) - .sort(format("{0} DESC",ID)).skip(offset).limit(limit).exec(db); + .sort(format("{0} DESC", ID)).skip(offset).limit(limit).exec(db); while (rs.next()) { var note = Note.of(rs); notes.put(note.id(),note); @@ -189,7 +193,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( rs.close(); return notes; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,TABLE_NOTES).causedBy(e); + throw failedToLoadObject(TABLE_NOTES).causedBy(e); } } @@ -207,7 +211,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( rs.close(); return notes; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,TABLE_NOTES).causedBy(e); + throw failedToLoadObject(TABLE_NOTES).causedBy(e); } } @@ -220,7 +224,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( rs.close(); return note; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY_BY_ID,"note",noteId).causedBy(e); + throw failedToLoadObject(t(Text.NOTE),noteId).causedBy(e); } } @@ -244,7 +248,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( } return note; } catch (SQLException e){ - throw databaseException(FAILED_TO_STORE_ENTITY,"note").causedBy(e); + throw failedToStoreObject(t(Text.NOTE)).causedBy(e); } } @@ -254,7 +258,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( update(TABLE_NOTES).set(ENTITY_ID).where(MODULE,equal(module)).where(ENTITY_ID,equal(oldId)).prepare(db).apply(newId).close(); LOG.log(DEBUG,"Updated note @ {0}.{1} → {0}.{2}",module,oldId,newId); } catch (SQLException e) { - throw databaseException("Failed to update {0}.{1} → {0}.{2}",module,oldId,newId).causedBy(e); + throw databaseException("Failed to update {module}.{a} → {module}.{b}", MODULE,module,"a",oldId,"b",newId).causedBy(e); } } } diff --git a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java index 31de4591..fd65404f 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java @@ -2,16 +2,20 @@ package de.srsoftware.umbrella.project; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.ModuleRegistry.*; -import static de.srsoftware.umbrella.core.Paths.LIST; -import static de.srsoftware.umbrella.core.Paths.SEARCH; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.SETTINGS; +import static de.srsoftware.umbrella.core.constants.Field.TAGS; +import static de.srsoftware.umbrella.core.constants.Module.PROJECT; +import static de.srsoftware.umbrella.core.constants.Path.*; +import static de.srsoftware.umbrella.core.constants.Text.*; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Permission.*; import static de.srsoftware.umbrella.core.model.Permission.OWNER; import static de.srsoftware.umbrella.core.model.Status.OPEN; import static de.srsoftware.umbrella.core.model.Status.PREDEFINED; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus; import static de.srsoftware.umbrella.messagebus.events.Event.EventType.CREATE; import static de.srsoftware.umbrella.messagebus.events.Event.EventType.UPDATE; @@ -21,11 +25,12 @@ import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; -import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; -import de.srsoftware.umbrella.core.BaseHandler; -import de.srsoftware.umbrella.core.ModuleRegistry; +import de.srsoftware.umbrella.core.*; import de.srsoftware.umbrella.core.api.ProjectService; +import de.srsoftware.umbrella.core.constants.Field; +import de.srsoftware.umbrella.core.constants.Path; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.messagebus.events.ProjectEvent; @@ -40,7 +45,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { public ProjectModule(Configuration config) throws UmbrellaException { super(); - var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); + var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); projectDb = new SqliteDb(connect(dbFile)); ModuleRegistry.add(this); } @@ -53,7 +58,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { } @Override - public boolean doGet(Path path, HttpExchange ex) throws IOException { + public boolean doGet(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -77,7 +82,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { } @Override - public boolean doPatch(Path path, HttpExchange ex) throws IOException { + public boolean doPatch(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -100,7 +105,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { } @Override - public boolean doPost(Path path, HttpExchange ex) throws IOException { + public boolean doPost(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -115,7 +120,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { var projectId = Long.parseLong(head); head = path.pop(); yield switch (head){ - case STATE -> postNewState(ex,projectId,user.get()); + case Path.STATE -> postNewState(ex,projectId,user.get()); case null, default -> super.doGet(path, ex); }; } @@ -135,9 +140,9 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean getProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException { var project = loadMembers(projectDb.load(projectId)); - if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name()); + if (!project.hasMember(user)) throw notAmember(t(PROJECT_WITH_ID,ID,project.name())); var map = project.toMap(); - project.companyId().map(companyService()::get).map(Company::toMap).ifPresent(data -> map.put(COMPANY,data)); + project.companyId().map(companyService()::get).map(Company::toMap).ifPresent(data -> map.put(Field.COMPANY,data)); return sendContent(ex,map); } @@ -149,7 +154,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean listCompanyProjects(HttpExchange ex, UmbrellaUser user, long companyId) throws IOException, UmbrellaException { var company = companyService().get(companyId); - if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + if (!companyService().membership(companyId,user.id())) throw notAmember(t(COMPANY_WITH_ID,ID,company.name())); var projects = listCompanyProjects(companyId,false); return sendContent(ex,mapValues(projects)); } @@ -193,9 +198,9 @@ public class ProjectModule extends BaseHandler implements ProjectService { try { userId = Long.parseLong(key); } catch (NumberFormatException e) { - throw invalidFieldException(USER_ID,"long"); + throw invalidField(USER_ID,t(LONG)); } - if (!(json.get(key) instanceof Number number)) throw invalidFieldException(PERMISSION,"int"); + if (!(json.get(key) instanceof Number number)) throw invalidField(PERMISSION,t(Text.NUMBER)); var permission = Permission.of(number.intValue()); if (permission == OWNER) { // if a new person is about to become the project owner for (var member : members.values()){ // alter the previous owners to editors @@ -209,7 +214,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean patchProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException { var project = loadMembers(projectDb.load(projectId)); - if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name()); + if (!project.hasMember(user)) throw notAmember(t(PROJECT_WITH_ID,ID,project.name())); var json = json(ex); if (json.has(DROP_MEMBER) && json.get(DROP_MEMBER) instanceof Number id) dropMember(project,id.longValue()); if (json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject memberJson) patchMembers(project,memberJson); @@ -223,17 +228,17 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean postNewState(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException { var project = loadMembers(load(projectId)); - if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name()); + if (!project.hasMember(user)) throw notAmember(t(PROJECT_WITH_ID,ID,project.name())); var json = json(ex); - if (!(json.has(CODE) && json.get(CODE) instanceof Number code)) throw missingFieldException(CODE); - if (!(json.has(NAME) && json.get(NAME) instanceof String name)) throw missingFieldException(NAME); + if (!(json.has(Field.CODE) && json.get(Field.CODE) instanceof Number code)) throw missingField(Field.CODE); + if (!(json.has(NAME) && json.get(NAME) instanceof String name)) throw missingField(NAME); var newState = new Status(name,code.intValue()); return sendContent(ex, projectDb.save(projectId,newState)); } private boolean postProject(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { var json = json(ex); - if (!(json.has(NAME) && json.get(NAME) instanceof String name)) throw missingFieldException(NAME); + if (!(json.has(NAME) && json.get(NAME) instanceof String name)) throw missingField(NAME); String description = null; if (json.has(DESCRIPTION)){ var desc = json.get(DESCRIPTION); @@ -242,7 +247,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { } Long companyId = null; if (json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number number){ - if (!companyService().membership(number.longValue(), user.id())) throw forbidden("You are not a member of company {0}!",number); + if (!companyService().membership(number.longValue(), user.id())) throw notAmember(t(COMPANY_WITH_ID, ID,number)); companyId = number.longValue(); } var showClosed = false; @@ -271,7 +276,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY); + if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingField(KEY); var keys = Arrays.asList(key.split(" ")); var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val; var projects = projectDb.find(user.id(),keys,fulltext); diff --git a/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java b/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java index 2c64ad97..12673ad1 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java @@ -4,22 +4,22 @@ package de.srsoftware.umbrella.project; import static de.srsoftware.tools.jdbc.Condition.*; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; -import static de.srsoftware.umbrella.core.ModuleRegistry.translator; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.notFound; +import static de.srsoftware.umbrella.core.constants.Constants.TABLE_SETTINGS; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TYPE; +import static de.srsoftware.umbrella.core.constants.Text.*; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Status.COMPLETE; import static de.srsoftware.umbrella.core.model.Status.OPEN; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.project.Constants.*; import static java.text.MessageFormat.format; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.constants.Field; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; -import de.srsoftware.umbrella.core.model.Permission; -import de.srsoftware.umbrella.core.model.Project; -import de.srsoftware.umbrella.core.model.Status; -import de.srsoftware.umbrella.core.model.UmbrellaUser; +import de.srsoftware.umbrella.core.model.*; import java.sql.Connection; import java.sql.SQLException; import java.util.Collection; @@ -48,7 +48,7 @@ public class SqliteDb extends BaseDb implements ProjectDb { stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_PROJECTS).causedBy(e); + throw failedToCreateTable(TABLE_PROJECTS).causedBy(e); } } @@ -66,7 +66,7 @@ PRIMARY KEY (project_id, code) stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_CUSTOM_STATES).causedBy(e); + throw failedToCreateTable(TABLE_CUSTOM_STATES).causedBy(e); } } @@ -98,7 +98,7 @@ CREATE TABLE IF NOT EXISTS {0} ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_PROJECT_USERS).causedBy(e); + throw failedToCreateTable(TABLE_PROJECT_USERS).causedBy(e); } } @@ -111,7 +111,7 @@ CREATE TABLE IF NOT EXISTS {0} ( .where(USER_ID,equal(userId)) .execute(db); } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY_OF_ENTITY,"member",userId,"project",projectId).causedBy(e); + throw failedToDropObjectFromObject("member",userId,t(PROJECT),projectId).causedBy(e); } } @@ -124,7 +124,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return result; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITY_MEMBERS,PROJECT,project.name()).causedBy(e); + throw failedToLoadMembers(t(PROJECT_WITH_ID,ID,project.name())).causedBy(e); } } @@ -136,7 +136,7 @@ CREATE TABLE IF NOT EXISTS {0} ( if (rs.next()) project = Project.of(rs); rs.close(); - if (project == null) throw notFound("no_project_for_id",projectId); + if (project == null) throw notFound("No project for id {id}", ID,projectId); rs = select(ALL).from(TABLE_CUSTOM_STATES).where(PROJECT_ID,equal(projectId)).exec(db); var states = project.allowedStates(); @@ -151,7 +151,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return project; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,"project").causedBy(e); + throw failedToLoadObject(t(PROJECT),projectId).causedBy(e); } } @@ -173,7 +173,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return projects; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,"items").causedBy(e); + throw failedToLoadObject("items").causedBy(e); } } @@ -181,9 +181,9 @@ CREATE TABLE IF NOT EXISTS {0} ( public Map find(long userId, Collection keys, boolean fulltext) { try { var projects = new HashMap(); - var query = select(ALL).from(TABLE_PROJECTS).leftJoin(ID,TABLE_PROJECT_USERS,PROJECT_ID).where(USER_ID, equal(userId)); + var query = select(ALL).from(TABLE_PROJECTS).leftJoin(ID,TABLE_PROJECT_USERS, PROJECT_ID).where(USER_ID, equal(userId)); if (fulltext) { - for (var key : keys) query.where(format("CONCAT({0},\" \",{1})",NAME,DESCRIPTION),like("%"+key+"%")); + for (var key : keys) query.where(format("CONCAT({0},\" \",{1})", NAME, DESCRIPTION),like("%"+key+"%")); } else { for (var key : keys) query.where(NAME,like("%"+key+"%")); } @@ -195,7 +195,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return projects; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,"items").causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,t(ITEMS)).causedBy(e); } } @@ -203,7 +203,7 @@ CREATE TABLE IF NOT EXISTS {0} ( public Map ofUser(long userId, boolean includeClosed) throws UmbrellaException { try { var projects = new HashMap(); - var query = select(ALL).from(TABLE_PROJECTS).leftJoin(ID,TABLE_PROJECT_USERS,PROJECT_ID).where(USER_ID, equal(userId)); + var query = select(ALL).from(TABLE_PROJECTS).leftJoin(ID,TABLE_PROJECT_USERS, PROJECT_ID).where(USER_ID, equal(userId)); if (!includeClosed) query = query.where(STATUS,lessThan(COMPLETE.code())); var rs = query.exec(db); while (rs.next()){ @@ -213,7 +213,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return projects; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES).causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, t("projects")).causedBy(e); } } @@ -234,29 +234,29 @@ CREATE TABLE IF NOT EXISTS {0} ( return new Project(id, prj.name(), prj.description(),prj.status(),prj.companyId().orElse(null),prj.showClosed(),prj.members(),prj.allowedStates()); } } catch (SQLException e) { - throw databaseException(FAILED_TO_STORE_ENTITY,PROJECT).causedBy(e); + throw failedToStoreObject(prj).causedBy(e); } } else { // Update try { if (prj.isDirty(MEMBERS)){ - var query = replaceInto(TABLE_PROJECT_USERS,PROJECT_ID,USER_ID,PERMISSIONS); + var query = replaceInto(TABLE_PROJECT_USERS, PROJECT_ID, USER_ID,PERMISSIONS); for (var member : prj.members().entrySet()) query.values(prj.id(),member.getKey(),member.getValue().permission().code()); query.execute(db).close(); prj.clean(MEMBERS); } if (prj.isDirty(TAG_COLORS)){ - replaceInto(TABLE_SETTINGS,KEY,VALUE).values(colorKey(prj.id()),new JSONObject(prj.tagColors()).toString()).execute(db).close(); + replaceInto(TABLE_SETTINGS, KEY,VALUE).values(colorKey(prj.id()),new JSONObject(prj.tagColors()).toString()).execute(db).close(); prj.clean(TAG_COLORS); } if (prj.isDirty()){ - update(TABLE_PROJECTS).set(NAME,DESCRIPTION,STATUS,COMPANY_ID,SHOW_CLOSED).where(ID,equal(prj.id())).prepare(db) + update(TABLE_PROJECTS).set(NAME, DESCRIPTION, STATUS, COMPANY_ID, SHOW_CLOSED).where(ID,equal(prj.id())).prepare(db) .apply(prj.name(),prj.description(),prj.status(),prj.companyId(),prj.showClosed()) .execute(); prj.clean(); } return prj; } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_ENTITY, translator().translate(user.language(),"project")).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, t(PROJECT_WITH_ID, ID,prj.name())).causedBy(e); } } return null; @@ -266,7 +266,7 @@ CREATE TABLE IF NOT EXISTS {0} ( @Override public Status save(long projectId, Status newState) { try { - insertInto(TABLE_CUSTOM_STATES,PROJECT_ID,CODE,NAME).values(projectId,newState.code(),newState.name()).execute(db).close(); + insertInto(TABLE_CUSTOM_STATES, PROJECT_ID, Field.CODE, NAME).values(projectId,newState.code(),newState.name()).execute(db).close(); return newState; } catch (SQLException e) { throw databaseException(FAILED_TO_CREATE_STATE).causedBy(e); diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java index cb178c81..917a62f9 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java @@ -9,10 +9,8 @@ public class Constants { public static final String BELOW = "below"; public static final String CONFIG_DATABASE = "umbrella.modules.stock.database"; public static final String CONFIG_ITEM_DB = "umbrella.modules.items.database"; - public static final String ITEM = "item"; public static final String ITEM_ID = "item_id"; public static final String ITEMS = "items"; - public static final String LOCATIONS = "locations"; public static final String MOVE_ITEM = "move_item"; public static final String MOVE_LOCATION = "move_location"; public static final String OF_USER = "of_user"; diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/ItemDb.java b/stock/src/main/java/de/srsoftware/umbrella/stock/ItemDb.java index a290ed4f..779253ed 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/ItemDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/ItemDb.java @@ -4,16 +4,18 @@ package de.srsoftware.umbrella.stock; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.tools.jdbc.Query.select; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Field.COMPANY_ID; -import static de.srsoftware.umbrella.core.Field.UNIT_PRICE; import static de.srsoftware.umbrella.core.ModuleRegistry.companyService; import static de.srsoftware.umbrella.core.ModuleRegistry.translator; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Text.T_UNIT_PRICE; +import static de.srsoftware.umbrella.core.constants.Text.UNIT; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; import static de.srsoftware.umbrella.stock.Constants.TABLE_ITEMS; import static java.lang.System.Logger.Level.DEBUG; import de.srsoftware.tools.Tuple; +import de.srsoftware.umbrella.core.constants.Field; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.model.*; import java.sql.Connection; import java.sql.SQLException; @@ -36,7 +38,7 @@ public class ItemDb { while (rs.next()){ var id = rs.getLong(ID); var companyId = rs.getLong(COMPANY_ID); - var code = rs.getString(CODE); + var code = rs.getString(Field.CODE); var name = rs.getString(NAME); var description = rs.getString(DESCRIPTION); var unit = rs.getString(UNIT); @@ -73,8 +75,8 @@ public class ItemDb { LOG.log(DEBUG, " using location: {0}",location.resolve().name()); var stockItem = new Item(0,company,0,location,code,name,description); var props = stockItem.properties(); - var keyUnitPrice = translator().translate(lang,UNIT_PRICE); - var keyUnit = translator().translate(lang,UNIT); + var keyUnitPrice = translator().translate(lang,T_UNIT_PRICE); + var keyUnit = translator().translate(lang, Text.UNIT); var keyTax = translator().translate(lang,TAX_RATE); var keyLegacyId = translator().translate(lang,"legacy_id"); props.add(new Property(0,keyUnitPrice,unitPrice/100d,company.currency())); @@ -86,7 +88,7 @@ public class ItemDb { } rs.close(); } catch (SQLException e) { - throw databaseException("Failed to migrate items from itemDB to stockDB!"); + throw databaseException("Failed to migrate items from ItemDB to stockDB!"); } } } diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java index 9bc8e05f..ddbeddac 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java @@ -7,11 +7,18 @@ import static de.srsoftware.tools.jdbc.Condition.*; import static de.srsoftware.tools.jdbc.Condition.like; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; import static de.srsoftware.umbrella.core.ModuleRegistry.noteService; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.notFound; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.LOCATIONS; +import static de.srsoftware.umbrella.core.constants.Field.TYPE; +import static de.srsoftware.umbrella.core.constants.Field.UNIT; +import static de.srsoftware.umbrella.core.constants.Text.*; +import static de.srsoftware.umbrella.core.constants.Text.ITEMS; +import static de.srsoftware.umbrella.core.constants.Text.LOCATION; +import static de.srsoftware.umbrella.core.constants.Text.PROPERTY; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.stock.Constants.*; import static java.lang.System.Logger.Level.*; import static java.text.MessageFormat.format; @@ -19,6 +26,8 @@ import static java.text.MessageFormat.format; import de.srsoftware.tools.jdbc.Query; import de.srsoftware.umbrella.core.BaseDb; import de.srsoftware.umbrella.core.api.Owner; +import de.srsoftware.umbrella.core.constants.Field; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.core.model.Location; import java.sql.Connection; @@ -35,7 +44,7 @@ public class SqliteDb extends BaseDb implements StockDb { public String owner() { var parts = id.split(":"); - if (parts.length != 3) throw databaseException("Expected legacy location id to be of the form ss:dd:ss, encountered {0}!",id); + if (parts.length != 3) throw databaseException("Expected legacy location id to be of the form ss:dd:ss, encountered {ID}!", ID,id); return String.join(":", parts[0], parts[1]); } }; @@ -48,26 +57,26 @@ public class SqliteDb extends BaseDb implements StockDb { public Property addNewProperty(long itemId, String name, Object value, String unit) { try { db.setAutoCommit(false); - var rs = insertInto(TABLE_PROPERTIES,NAME,TYPE,UNIT).values(name,0,unit).execute(db).getGeneratedKeys(); + var rs = insertInto(TABLE_PROPERTIES, NAME, TYPE,UNIT).values(name,0,unit).execute(db).getGeneratedKeys(); Long propertyId = null; if (rs.next()) propertyId = rs.getLong(1); rs.close(); - if (propertyId == null || propertyId == 0) throw databaseException(FAILED_TO_STORE_ENTITY,"property"); + if (propertyId == null || propertyId == 0) throw failedToStoreObject(t(PROPERTY)); insertInto(TABLE_ITEM_PROPERTIES,ITEM_ID,PROPERTY_ID,VALUE).values(itemId,propertyId,value).execute(db).close(); db.setAutoCommit(true); return new Property(propertyId,name,value,unit); } catch (SQLException e) { - throw databaseException(FAILED_TO_STORE_ENTITY,"property").causedBy(e); + throw failedToStoreObject(t(PROPERTY)).causedBy(e); } } private void createDescriptionColumn(){ try { var sql = "ALTER TABLE {0} ADD COLUMN {1} TEXT"; - sql = format(sql,TABLE_ITEMS,DESCRIPTION); + sql = format(sql,TABLE_ITEMS, DESCRIPTION); db.prepareStatement(sql).execute(); } catch (SQLException e) { - throw databaseException(FAILED_TO_ADD_COLUMN,DESCRIPTION,TABLE_ITEMS).causedBy(e); + throw databaseException(FAILED_TO_ADD_COLUMN, NAME, DESCRIPTION, TABLE,TABLE_ITEMS).causedBy(e); } } @@ -84,7 +93,7 @@ public class SqliteDb extends BaseDb implements StockDb { {3} VARCHAR(255), {4} VARCHAR(255) NOT NULL, {5} LONG NOT NULL)"""; - sql = format(sql, ID, OWNER, OWNER_NUMBER, CODE, NAME, LOCATION_ID); + sql = format(sql, ID, OWNER, OWNER_NUMBER, Field.CODE, NAME, LOCATION_ID); db.prepareStatement(sql).execute(); } @@ -117,10 +126,10 @@ public class SqliteDb extends BaseDb implements StockDb { private void createItemsTable() { try { var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) NOT NULL, {3} TEXT, {4} VARCHAR(255))"; - sql = format(sql, TABLE_ITEMS, ID, CODE, NAME, LOCATION_ID); + sql = format(sql, TABLE_ITEMS, ID, Field.CODE, NAME, LOCATION_ID); db.prepareStatement(sql).execute(); } catch (SQLException e) { - throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_ITEMS).causedBy(e); + throw failedToCreateTable(TABLE_ITEMS).causedBy(e); } } @@ -130,7 +139,7 @@ public class SqliteDb extends BaseDb implements StockDb { sql = format(sql, TABLE_ITEM_PROPERTIES, ITEM_ID, PROPERTY_ID,VALUE); db.prepareStatement(sql).execute(); } catch (SQLException e) { - throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_ITEM_PROPERTIES).causedBy(e); + throw failedToCreateTable(TABLE_ITEM_PROPERTIES).causedBy(e); } } @@ -140,7 +149,7 @@ public class SqliteDb extends BaseDb implements StockDb { sql = format(sql, TABLE_LOCATIONS, ID, LOCATION_ID, NAME, DESCRIPTION); db.prepareStatement(sql).execute(); } catch (SQLException e) { - throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_LOCATIONS).causedBy(e); + throw failedToCreateTable(TABLE_LOCATIONS).causedBy(e); } } @@ -150,7 +159,7 @@ public class SqliteDb extends BaseDb implements StockDb { sql = format(sql, TABLE_PROPERTIES, ID, NAME, TYPE, UNIT); db.prepareStatement(sql).execute(); } catch (SQLException e) { - throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_PROPERTIES).causedBy(e); + throw failedToCreateTable(TABLE_PROPERTIES).causedBy(e); } } @@ -179,7 +188,7 @@ public class SqliteDb extends BaseDb implements StockDb { Query.delete().from(TABLE_LOCATIONS).where(ID,equal(location.id())).execute(db); return location; } catch (SQLException e){ - throw databaseException(FAILED_TO_DROP_ENTITY,location.name()).causedBy(e); + throw failedToDropObject(location.name()).causedBy(e); } } @@ -187,7 +196,7 @@ public class SqliteDb extends BaseDb implements StockDb { try { db.prepareStatement("DROP TABLE IF EXISTS tokens").execute(); } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY,"table tokens").causedBy(e); + throw failedToDropObject("table tokens").causedBy(e); } } @@ -199,7 +208,7 @@ public class SqliteDb extends BaseDb implements StockDb { var query = select(ALL).from(TABLE_ITEMS).where(OWNER, in(ownerCodes)); if (fulltext) { query.leftJoin(ID,TABLE_ITEM_PROPERTIES,ITEM_ID); - for (var key : keys) query.where(format("CONCAT({0},\" \",{1},\" \",{2})",NAME,DESCRIPTION,VALUE),like("%"+key+"%")); + for (var key : keys) query.where(format("CONCAT({0},\" \",{1},\" \",{2})", NAME, DESCRIPTION,VALUE),like("%"+key+"%")); } else { for (var key : keys) query.where(NAME,like("%"+key+"%")); } @@ -211,7 +220,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return items; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,ITEMS).causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,t(ITEMS)).causedBy(e); } } @@ -224,7 +233,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return list; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_CHILD_LOCATIONS,parentId).causedBy(e); + throw databaseException(FAILED_TO_LOAD_CHILD_LOCATIONS,PARENT,parentId).causedBy(e); } } @@ -237,7 +246,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return list; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"locations",company.name()).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.LOCATIONS), OWNER,company.name()).causedBy(e); } } @@ -252,7 +261,7 @@ public class SqliteDb extends BaseDb implements StockDb { for (var item : list) loadProperties(item); return list; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,ITEMS,location).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,ITEMS, OWNER,location).causedBy(e); } } @@ -268,7 +277,7 @@ public class SqliteDb extends BaseDb implements StockDb { for (var item : list) loadProperties(item); return list; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,ITEMS,company).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,ITEMS, OWNER,company).causedBy(e); } } @@ -280,7 +289,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return item; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,PROPERTIES,item.name()).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.PROPERTIES), OWNER,item.name()).causedBy(e); } } @@ -303,9 +312,9 @@ public class SqliteDb extends BaseDb implements StockDb { if (rs.next()) result = Item.of(rs); rs.close(); if (result != null) return result; - throw notFound(FAILED_TO_LOAD_ENTITY,ITEM); + throw notFound(FAILED_TO_LOAD_OBJECT, OBJECT,t(Text.ITEM)); } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,ITEM).causedBy(e); + throw failedToLoadObject(t(Text.ITEM)).causedBy(e); } } @@ -316,9 +325,9 @@ public class SqliteDb extends BaseDb implements StockDb { if (rs.next()) loc = DbLocation.of(rs); rs.close(); if (loc != null) return loc; - throw notFound(FAILED_TO_LOAD_ENTITY_BY_ID,LOCATION,locationId); + throw failedToLoadObject(t(LOCATION),locationId); } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITY_BY_ID,LOCATION,locationId).causedBy(e); + throw failedToLoadObject(t(LOCATION),locationId).causedBy(e); } } @@ -331,7 +340,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return list; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITY,PROPERTIES).causedBy(e); + throw failedToLoadObject(t(Text.PROPERTIES)).causedBy(e); } } @@ -344,7 +353,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return list; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,LOCATIONS,user.name()).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.LOCATIONS), OWNER,user.name()).causedBy(e); } } @@ -356,7 +365,7 @@ public class SqliteDb extends BaseDb implements StockDb { rs.close(); return number +1L; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"last item number",owner).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,"last item number", OWNER,owner).causedBy(e); } } @@ -379,7 +388,7 @@ public class SqliteDb extends BaseDb implements StockDb { location = parent; } } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"path",target).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.PATH), OWNER,target).causedBy(e); } return root; } @@ -404,16 +413,16 @@ public class SqliteDb extends BaseDb implements StockDb { var parentId = is0(location.parent()) ? null : location.parent(); if (location.id() == 0) { // new location try { - var rs = insertInto(TABLE_LOCATIONS,OWNER,PARENT_LOCATION_ID,NAME,DESCRIPTION) + var rs = insertInto(TABLE_LOCATIONS, OWNER, PARENT_LOCATION_ID, NAME, DESCRIPTION) .values(location.owner().dbCode(),parentId,location.name(),location.description()) .execute(db).getGeneratedKeys(); long id = 0; if (rs.next()) id = rs.getLong(1); rs.close(); - if (id == 0) throw databaseException(FAILED_TO_STORE_ENTITY,location.name()); + if (id == 0) throw failedToStoreObject(location.name()); return location.id(id); } catch (SQLException e){ - throw databaseException(FAILED_TO_STORE_ENTITY,location.name()).causedBy(e); + throw failedToStoreObject(location.name()).causedBy(e); } } else { try { @@ -425,7 +434,7 @@ public class SqliteDb extends BaseDb implements StockDb { .close(); return location.clear(); } catch (SQLException e){ - throw databaseException(FAILED_TO_UPDATE_ENTITY,location.name()).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT,location.name()).causedBy(e); } } } @@ -435,22 +444,22 @@ public class SqliteDb extends BaseDb implements StockDb { if (item.id() == 0){ var number = nextItemNumberFor(item.location().resolve().owner()); try { - var rs = insertInto(TABLE_ITEMS, OWNER, OWNER_NUMBER, CODE, NAME, DESCRIPTION, LOCATION_ID) + var rs = insertInto(TABLE_ITEMS, OWNER, OWNER_NUMBER, Field.CODE, NAME, DESCRIPTION, LOCATION_ID) .values(item.owner().dbCode(), number, item.code(), item.name(), item.description(), item.location().id()) .execute(db).getGeneratedKeys(); if (rs.next()) item.id(rs.getLong(1)).ownerNumber(number); rs.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_STORE_ENTITY,item.name()).causedBy(e); + throw failedToStoreObject(item.name()).causedBy(e); } } else if (item.isDirty()) { try { var location = item.location(); var query = update(TABLE_ITEMS).where(ID, equal(item.id())); if (location == null) { - query.set(CODE,NAME,DESCRIPTION); + query.set(Field.CODE, NAME, DESCRIPTION); } else { - query.set(CODE,NAME,DESCRIPTION,LOCATION_ID); + query.set(Field.CODE, NAME, DESCRIPTION, LOCATION_ID); } var pq = query.prepare(db); if (location == null) { @@ -460,7 +469,7 @@ public class SqliteDb extends BaseDb implements StockDb { } item.clear(); } catch (SQLException e){ - throw databaseException(FAILED_TO_UPDATE_ENTITY,item.name()).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT,item.name()).causedBy(e); } } saveProperties(item); @@ -483,7 +492,7 @@ public class SqliteDb extends BaseDb implements StockDb { if (rs.next()) propId = rs.getLong(1); rs.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,property.name()).causedBy(e); + throw failedToLoadObject(property.name()).causedBy(e); } } if (is0(propId)) return addNewProperty(item.id(), property.name(), property.value(), property.unit()); @@ -497,7 +506,7 @@ public class SqliteDb extends BaseDb implements StockDb { var rs = select(ALL).from(TABLE_PROPERTIES).where(ID,equal(existingPropId)).exec(db); if (rs.next()) prop = Property.of(rs); rs.close(); - if (prop == null) throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"property "+existingPropId,"item "+itemId); + if (prop == null) throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,"property "+existingPropId, OWNER,"item "+itemId); if ("".equals(value)){ Query.delete().from(TABLE_ITEM_PROPERTIES).where(ITEM_ID,equal(itemId)).where(PROPERTY_ID,equal(existingPropId)).execute(db); } else { @@ -505,30 +514,30 @@ public class SqliteDb extends BaseDb implements StockDb { } return prop.value(value); } catch (SQLException e) { - throw databaseException(FAILED_TO_ADD_PROPERTY_TO_ITEM,itemId).causedBy(e); + throw databaseException(FAILED_TO_ADD_PROPERTY_TO_ITEM, OBJECT,itemId).causedBy(e); } } private HashMap transformItems(Map oldLocationIdsToNew) throws SQLException { var rs = select(ALL).from(TABLE_ITEMS).exec(db); - var insert = insertInto("items_temp",OWNER, OWNER_NUMBER, LOCATION_ID, CODE, NAME); + var insert = insertInto("items_temp", OWNER, OWNER_NUMBER, LOCATION_ID, Field.CODE, NAME); var oldToNew = new HashMap(); // maps from old item ids to new ones while (rs.next()){ var oldId = rs.getString(ID); var parts = oldId.split(":"); - if (parts.length != 3) throw databaseException(UNEXPECTED_ITEM_ID_FORMAT,oldId); + if (parts.length != 3) throw databaseException(UNEXPECTED_ITEM_ID_FORMAT,OBJECT,oldId); var owner = String.join(":",parts[0], parts[1]); long ownerNumber; try { ownerNumber = Long.parseLong(parts[2]); } catch (NumberFormatException e) { - throw databaseException(UNEXPECTED_ITEM_ID_FORMAT,oldId).causedBy(e); + throw databaseException(UNEXPECTED_ITEM_ID_FORMAT,OBJECT,oldId).causedBy(e); } var oldLocationId = rs.getString(LOCATION_ID); var locationId = oldLocationIdsToNew.get(oldLocationId); - if (locationId == null) throw databaseException(UNKNOWN_ITEM_LOCATION,oldId,parts[0],parts[1],oldLocationId); - var rs2 = insert.values(owner, ownerNumber, locationId, rs.getString(CODE), rs.getString(NAME)).execute(db).getGeneratedKeys(); + if (locationId == null) throw databaseException(UNKNOWN_ITEM_LOCATION, OBJECT,oldId, OWNER,parts[0]+" "+parts[1], Field.LOCATION,oldLocationId); + var rs2 = insert.values(owner, ownerNumber, locationId, rs.getString(Field.CODE), rs.getString(NAME)).execute(db).getGeneratedKeys(); oldToNew.put(oldId,rs2.getLong(1)); rs2.close(); } @@ -572,7 +581,7 @@ public class SqliteDb extends BaseDb implements StockDb { while (rs.next()){ var oldItemId = rs.getString(ITEM_ID); var itemId = oldItemIdsToNew.get(oldItemId); - if (itemId == null) throw databaseException(MISSING_NEW_ITEM_ID,oldItemId); + if (itemId == null) throw databaseException(MISSING_NEW_ITEM_ID, ID,oldItemId); insert.values(itemId, rs.getLong(PROPERTY_ID), rs.getString(VALUE)); } rs.close(); @@ -598,7 +607,7 @@ public class SqliteDb extends BaseDb implements StockDb { db.rollback(); } catch (SQLException ignored) { } - throw databaseException(FAILED_TO_UPDATE_TABLE,TABLE_LOCATIONS).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT, t(TABLE_WITH_NAME,NAME,TABLE_LOCATIONS)).causedBy(e); } } diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java index 261441d3..4b46a2b6 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java @@ -4,13 +4,15 @@ package de.srsoftware.umbrella.stock; import static de.srsoftware.tools.Optionals.is0; import static de.srsoftware.tools.Optionals.nullIfEmpty; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Field.ITEM; import static de.srsoftware.umbrella.core.ModuleRegistry.companyService; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; -import static de.srsoftware.umbrella.core.Paths.LIST; -import static de.srsoftware.umbrella.core.Paths.SEARCH; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.ITEM; +import static de.srsoftware.umbrella.core.constants.Module.COMPANY; +import static de.srsoftware.umbrella.core.constants.Module.USER; +import static de.srsoftware.umbrella.core.constants.Path.*; +import static de.srsoftware.umbrella.core.constants.Path.PROPERTY; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.stock.Constants.*; import static java.lang.System.Logger.Level.WARNING; @@ -19,12 +21,12 @@ import static java.util.Comparator.comparing; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; import de.srsoftware.configuration.JsonConfig; -import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; -import de.srsoftware.umbrella.core.BaseHandler; -import de.srsoftware.umbrella.core.ModuleRegistry; +import de.srsoftware.umbrella.core.*; import de.srsoftware.umbrella.core.api.Owner; import de.srsoftware.umbrella.core.api.StockService; +import de.srsoftware.umbrella.core.constants.Field; +import de.srsoftware.umbrella.core.constants.Path; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.core.model.Location; @@ -39,7 +41,7 @@ public class StockModule extends BaseHandler implements StockService { public StockModule(Configuration config) throws UmbrellaException { super(); - var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); + var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); stockDb = new SqliteDb(connect(dbFile)); Optional itemDbConfig = config.get(CONFIG_ITEM_DB); itemDbConfig.map(ItemDb::new).ifPresent(itemDb -> itemDb.migrateTo(stockDb)); @@ -64,14 +66,14 @@ public class StockModule extends BaseHandler implements StockService { private boolean deleteLocation(UmbrellaUser user, Location locationRef, HttpExchange ex) throws IOException { var location = locationRef.resolve(); var owner = location.owner().resolve(); - if (!assigned(owner,user)) throw forbidden("You are not allowed to modify \"{0}\"",location); - if (!stockDb.listItemsAt(location).isEmpty()) throw forbidden("\"{0}\" cannot be deleted, as it contains items!",location); - if (!stockDb.listChildLocations(location.id()).isEmpty()) throw forbidden("\"{0}\" cannot be deleted, as it contains other locations!",location); + if (!assigned(owner,user)) throw forbidden("You are not allowed to modify \"{location}\"", Field.LOCATION,location); + if (!stockDb.listItemsAt(location).isEmpty()) throw forbidden("\"{location}\" cannot be deleted, as it contains items!", Field.LOCATION,location); + if (!stockDb.listChildLocations(location.id()).isEmpty()) throw forbidden("\"{location}\" cannot be deleted, as it contains other locations!", Field.LOCATION,location); return sendContent(ex,stockDb.delete(location)); } @Override - public boolean doDelete(Path path, HttpExchange ex) throws IOException { + public boolean doDelete(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -79,7 +81,7 @@ public class StockModule extends BaseHandler implements StockService { if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { - case LOCATION -> { + case Path.LOCATION -> { try { var location = Location.of(Long.parseLong(path.pop())); yield deleteLocation(user.get(), location, ex); @@ -95,7 +97,7 @@ public class StockModule extends BaseHandler implements StockService { } @Override - public boolean doGet(Path path, HttpExchange ex) throws IOException { + public boolean doGet(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -103,7 +105,7 @@ public class StockModule extends BaseHandler implements StockService { if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { - case COMPANY -> { + case Path.COMPANY -> { try { var company = companyService().get(Long.parseLong(path.pop())); yield getItem(user.get(),company,path,ex); @@ -111,7 +113,7 @@ public class StockModule extends BaseHandler implements StockService { yield super.doGet(path,ex); } } - case LOCATION -> { + case Path.LOCATION -> { try { var location = Location.of(Long.parseLong(path.pop())); yield getLocationEntities(location, ex); @@ -119,9 +121,9 @@ public class StockModule extends BaseHandler implements StockService { yield super.doGet(path,ex); } } - case LOCATIONS -> getLocations(path,user.get(),ex); - case PROPERTIES -> getProperties(ex); - case USER -> { + case Path.LOCATIONS -> getLocations(path,user.get(),ex); + case Path.PROPERTIES -> getProperties(ex); + case Path.USER -> { try { var userId = Long.parseLong(path.pop()); if (userId != user.get().id()) throw forbidden("You are not allowed to access items of another user!"); @@ -138,7 +140,7 @@ public class StockModule extends BaseHandler implements StockService { } @Override - public boolean doPatch(Path path, HttpExchange ex) throws IOException { + public boolean doPatch(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -146,7 +148,7 @@ public class StockModule extends BaseHandler implements StockService { if (user.isEmpty()) return unauthorized(ex); return switch (path.pop()){ case MOVE_ITEM -> patchMoveItem(user.get(), path,ex); - case LOCATION -> { + case Path.LOCATION -> { try { var id = Long.parseLong(path.pop()); yield patchLocation(id, user.get(), ex); @@ -164,7 +166,7 @@ public class StockModule extends BaseHandler implements StockService { } @Override - public boolean doPost(Path path, HttpExchange ex) throws IOException { + public boolean doPost(de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); @@ -172,9 +174,9 @@ public class StockModule extends BaseHandler implements StockService { if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { - case ITEM -> postItem(user.get(), ex); + case Path.ITEM -> postItem(user.get(), ex); case LIST -> postItemList(user.get(), path, ex); - case LOCATION -> postLocation(user.get(),ex); + case Path.LOCATION -> postLocation(user.get(),ex); case PROPERTY -> postProperty(user.get(),ex); case SEARCH -> postSearch(user.get(),ex); case null, default -> super.doPost(path,ex); @@ -189,10 +191,10 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex, stockDb.listChildLocations(parentId).stream().sorted(comparing(l -> l.name().toLowerCase())).map(DbLocation::toMap)); } - private boolean getItem(UmbrellaUser user, Owner owner, Path path, HttpExchange ex) throws IOException { - if (!assigned(owner,user)) throw forbidden("You are not allowed to access items of {0}",owner); + private boolean getItem(UmbrellaUser user, Owner owner, de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { + if (!assigned(owner,user)) throw forbidden("You are not allowed to access items of {owner}", OWNER,owner); return switch (path.pop()){ - case ITEM -> { + case Path.ITEM -> { try { var itemId = Long.parseLong(path.pop()); var item = stockDb.loadItem(owner.dbCode(),itemId); @@ -211,13 +213,13 @@ public class StockModule extends BaseHandler implements StockService { List userIds = switch (owner.type()){ case COMPANY -> companyService().getMembers(owner.id()).stream().map(UmbrellaUser::id).toList(); case USER -> List.of(owner.id()); - case null, default -> throw unprocessable("Unprocessable owner type: {0}",owner.type()); + case null, default -> throw unprocessable("Unprocessable owner type: {type}", TYPE,owner.type()); }; var pathToLocation = stockDb.pathToLocation(location); - return sendContent(ex,Map.of(ITEMS,items,USERS,userIds,PATH,pathToLocation,LOCATION,location.resolve().toMap())); + return sendContent(ex,Map.of(ITEMS,items,USERS,userIds, PATH,pathToLocation, Field.LOCATION,location.resolve().toMap())); } - private boolean getLocations(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { + private boolean getLocations(de.srsoftware.tools.Path path, UmbrellaUser user, HttpExchange ex) throws IOException { var head = path.pop(); return switch (head){ case BELOW -> { @@ -242,17 +244,17 @@ public class StockModule extends BaseHandler implements StockService { var result = new ArrayList(); var userLocations = stockDb.listUserLocations(user); result.add(Map.of( - PARENT, Map.of(USER, user.id()), + PARENT, Map.of(Field.USER, user.id()), NAME,user.name(), - LOCATIONS,userLocations.stream().map(DbLocation::toMap).toList())); + Field.LOCATIONS,userLocations.stream().map(DbLocation::toMap).toList())); var companies = companyService().listCompaniesOf(user); companies.values().stream().sorted(comparing(a -> a.name().toLowerCase())).forEach(company -> { var locations = stockDb.listCompanyLocations(company); result.add(Map.of( - PARENT, Map.of(COMPANY, company.id()), + PARENT, Map.of(Field.COMPANY, company.id()), NAME,company.name(), - LOCATIONS,locations.stream().sorted(comparing(a -> a.name().toLowerCase())).map(DbLocation::toMap).toList())); + Field.LOCATIONS,locations.stream().sorted(comparing(a -> a.name().toLowerCase())).map(DbLocation::toMap).toList())); }); return sendContent(ex, result); @@ -265,7 +267,7 @@ public class StockModule extends BaseHandler implements StockService { private boolean patchItem(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.get(ID) instanceof Number id)) throw missingFieldException(ID); + if (!(json.get(ID) instanceof Number id)) throw missingField(ID); json.remove(ID); var item = stockDb.loadItem(id.longValue()); @@ -273,20 +275,20 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex,stockDb.save(item)); } - private boolean patchMoveItem(UmbrellaUser user, Path path, HttpExchange ex) throws IOException { + private boolean patchMoveItem(UmbrellaUser user, de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.get(ITEM) instanceof Number itemId)) throw missingFieldException(ITEM); - if (!(json.get(TARGET) instanceof Number locationId)) throw missingFieldException(TARGET); + if (!(json.get(ITEM) instanceof Number itemId)) throw missingField(ITEM); + if (!(json.get(TARGET) instanceof Number locationId)) throw missingField(TARGET); var item = stockDb.loadItem(itemId.longValue()); var itemOwner = item.owner().resolve(); - if (!assigned(itemOwner,user)) throw forbidden("You are not allowed to alter the location of \"{0}\"!",item.name()); + if (!assigned(itemOwner,user)) throw forbidden("You are not allowed to alter the location of \"{name}\"!", NAME,item.name()); var target = stockDb.loadLocation(locationId.longValue()); var locOwner = target.resolve().owner().resolve(); - if (!assigned(locOwner,user)) throw forbidden("You are not allowed to modify \"{0}\"!",target.name()); + if (!assigned(locOwner,user)) throw forbidden("You are not allowed to modify \"{name}\"!", NAME,target.name()); - if (!locOwner.equals(itemOwner)) throw unprocessable("You may not move items from one owner ({0}) to another ({1})",itemOwner,locOwner); + if (!locOwner.equals(itemOwner)) throw unprocessable("You may not move items from one owner ({owner}) to another ({object})", OWNER,itemOwner, OBJECT,locOwner); stockDb.save(item.location(target)); return sendContent(ex,item); @@ -296,7 +298,7 @@ public class StockModule extends BaseHandler implements StockService { var json = json(ex); var location = stockDb.loadLocation(locationId); var owner = location.owner().resolve(); - if (!assigned(owner,user)) throw forbidden("You are not allowed to edit \"{0}\"!",location.name()); + if (!assigned(owner,user)) throw forbidden("You are not allowed to edit \"{location}\"!", Field.LOCATION,location.name()); if (json.has(PARENT_LOCATION_ID) && json.get(PARENT_LOCATION_ID) instanceof Number parentId){ if (parentId.longValue() != 0L) { @@ -308,8 +310,8 @@ public class StockModule extends BaseHandler implements StockService { current = is0(current.parent()) ? null : stockDb.loadLocation(current.parent()); } var targetOwner = target.owner().resolve(); - if (!assigned(targetOwner, user)) throw forbidden("You are not allowed to edit \"{0}\"!", target.name()); - if (!targetOwner.equals(owner)) throw unprocessable("You may not move locations from one owner ({0}) to another ({1})", owner, targetOwner); + if (!assigned(targetOwner, user)) throw forbidden("You are not allowed to edit \"{name}\"!", NAME, target.name()); + if (!targetOwner.equals(owner)) throw unprocessable("You may not move locations from one owner ({a}) to another ({b})","a", owner,"b", targetOwner); LOG.log(WARNING,"Not checking, if location is moved to on of its own children!"); } } @@ -320,22 +322,22 @@ public class StockModule extends BaseHandler implements StockService { private boolean postItem(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingFieldException(NAME); + if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingField(NAME); var description = json.has(DESCRIPTION) && json.get(DESCRIPTION) instanceof String d ? d : null; - if (!json.has(CODE) || !(json.get(CODE) instanceof String code)) throw missingFieldException(CODE); - if (!json.has(LOCATION) || !(json.get(LOCATION) instanceof JSONObject locationData)) throw missingFieldException(LOCATION); + if (!json.has(Field.CODE) || !(json.get(Field.CODE) instanceof String code)) throw missingField(Field.CODE); + if (!json.has(Field.LOCATION) || !(json.get(Field.LOCATION) instanceof JSONObject locationData)) throw missingField(Field.LOCATION); var location = stockDb.loadLocation(locationData.getLong(ID)); var owner = location.owner().resolve(); - if (!assigned(owner,user)) throw forbidden("You are not allowed to add items to {0}!",location); + if (!assigned(owner,user)) throw forbidden("You are not allowed to add items to {location}!", Field.LOCATION,location); var newItem = new Item(0,owner,0,location,code,name,description); return sendContent(ex,stockDb.save(newItem)); } - private boolean postItemList(UmbrellaUser user, Path path, HttpExchange ex) throws IOException { + private boolean postItemList(UmbrellaUser user, de.srsoftware.tools.Path path, HttpExchange ex) throws IOException { var json = json(ex); - if (!json.has(COMPANY_ID) || !(json.get(COMPANY_ID) instanceof Number company_id)) throw missingFieldException(COMPANY_ID); + if (!json.has(COMPANY_ID) || !(json.get(COMPANY_ID) instanceof Number company_id)) throw missingField(COMPANY_ID); var company = companyService().get(company_id.longValue()); - if (!companyService().membership(company_id.longValue(),user.id())) throw forbidden("You are not a member of {0}!", company.name()); + if (!companyService().membership(company_id.longValue(),user.id())) throw notAmember(company.name()); var map = new HashMap(); var items = stockDb.listItemsOf(company) .stream() @@ -346,10 +348,10 @@ public class StockModule extends BaseHandler implements StockService { private boolean postLocation(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.get(NAME) instanceof String name)) throw missingFieldException(NAME); - if (!(json.get(PARENT) instanceof JSONObject parentData)) throw missingFieldException(PARENT); - var key = parentData.keySet().stream().findFirst().orElseThrow(() -> missingFieldException(PARENT)); - if (!(parentData.get(key) instanceof Number id)) throw missingFieldException(key); + if (!(json.get(NAME) instanceof String name)) throw missingField(NAME); + if (!(json.get(PARENT) instanceof JSONObject parentData)) throw missingField(PARENT); + var key = parentData.keySet().stream().findFirst().orElseThrow(() -> missingField(PARENT)); + if (!(parentData.get(key) instanceof Number id)) throw missingField(key); Location parent; Owner owner; switch (key){ @@ -361,11 +363,11 @@ public class StockModule extends BaseHandler implements StockService { owner = userService().loadUser(id.longValue()); parent = null; break; - case LOCATION: + case Path.LOCATION: parent = stockDb.loadLocation(id.longValue()); owner = parent.resolve().owner().resolve(); break; - default: throw unprocessable("Unknown parent object: {0} → {1}",key,id); + default: throw unprocessable("Unknown parent object: {key} → {id}", KEY,key, ID,id); }; var loc = new DbLocation(0,owner,parent == null?null:parent.id(),name,null); return sendContent(ex,stockDb.save(loc)); @@ -373,12 +375,12 @@ public class StockModule extends BaseHandler implements StockService { private boolean postProperty(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.get(ITEM) instanceof JSONObject itemData)) throw missingFieldException(ITEM); - if (!(itemData.get(ID) instanceof Number itemId)) throw missingFieldException(ID); - if (!(json.get("add_prop") instanceof JSONObject propData)) throw missingFieldException("add_prop"); - if (!propData.has(VALUE)) throw missingFieldException(VALUE); + if (!(json.get(ITEM) instanceof JSONObject itemData)) throw missingField(ITEM); + if (!(itemData.get(ID) instanceof Number itemId)) throw missingField(ID); + if (!(json.get("add_prop") instanceof JSONObject propData)) throw missingField("add_prop"); + if (!propData.has(VALUE)) throw missingField(VALUE); var value = propData.get(VALUE); - if (value == null) throw missingFieldException(VALUE); + if (value == null) throw missingField(VALUE); Property property = null; if (propData.get("existing_prop_id") instanceof Number existingPropId && existingPropId.longValue() != 0L){ @@ -394,7 +396,7 @@ public class StockModule extends BaseHandler implements StockService { private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY); + if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingField(KEY); var keys = Arrays.asList(key.split(" ")); var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val; Set owners = new HashSet<>(companyService().listCompaniesOf(user).values()); diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java b/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java index 9fbf67b7..48f8163a 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java @@ -8,10 +8,14 @@ import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.Dialect.SQLITE; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.umbrella.bookmarks.Constants.*; -import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Constants.USER_ID; import static de.srsoftware.umbrella.core.Errors.*; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TAGS; +import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK; +import static de.srsoftware.umbrella.core.constants.Text.TABLE_WITH_NAME; +import static de.srsoftware.umbrella.core.constants.Text.USER_WITH_ID; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.tags.Constants.*; import static java.lang.System.Logger.Level.*; import static java.text.MessageFormat.format; @@ -21,6 +25,8 @@ import de.srsoftware.tools.Tuple; import de.srsoftware.tools.jdbc.Query; import de.srsoftware.umbrella.bookmarks.BookmarkDb; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.constants.Text; +import de.srsoftware.umbrella.core.model.Translatable; import java.sql.Connection; import java.sql.SQLException; import java.time.LocalDateTime; @@ -33,7 +39,6 @@ public class SqliteDb extends BaseDb implements TagDB{ public SqliteDb(Connection tagDb, Connection bmDb) { super(tagDb); bookmarks = new de.srsoftware.umbrella.bookmarks.SqliteDb(bmDb); - createTables(); } @Override @@ -61,14 +66,14 @@ public class SqliteDb extends BaseDb implements TagDB{ var pattern = Pattern.compile("/([^/]+)/(\\d+)/view"); try { LocalDateTime earliestDate = LocalDateTime.of(2000,1,1,0,0); - var rs = select(ALL).from(TABLE_URLS).leftJoin(HASH,TABLE_URL_COMMENTS,URL_HASH).leftJoin(COMMENT_HASH,TABLE_COMMENTS,HASH).where(TIMESTAMP,moreThan(0)).limit(1).exec(db); + var rs = select(ALL).from(TABLE_URLS).leftJoin(HASH,TABLE_URL_COMMENTS,URL_HASH).leftJoin(COMMENT_HASH,TABLE_COMMENTS, HASH).where(TIMESTAMP,moreThan(0)).limit(1).exec(db); if (rs.next()) earliestDate = LocalDateTime.ofEpochSecond(rs.getLong(1),0,UTC); rs.close(); var sql = "CREATE TABLE IF NOT EXISTS tags_new (TAG)"; db.prepareStatement(sql).execute(); // IMPORT BOOKMARKS - var commentedURLS = select(ALL).from(TABLE_URLS).leftJoin(HASH,TABLE_URL_COMMENTS,URL_HASH).leftJoin(COMMENT_HASH,TABLE_COMMENTS,HASH).exec(db); + var commentedURLS = select(ALL).from(TABLE_URLS).leftJoin(HASH,TABLE_URL_COMMENTS,URL_HASH).leftJoin(COMMENT_HASH,TABLE_COMMENTS, HASH).exec(db); while (commentedURLS.next()){ var userId = commentedURLS.getLong(USER_ID); @@ -92,10 +97,10 @@ public class SqliteDb extends BaseDb implements TagDB{ } var urlTags = select(ALL).from(TABLE_TAGS).where(URL_HASH,equal(urlHash)).where(USER_ID,equal(userId)).exec(db); - var insertQuery = insertInto(TABLE_TAGS_NEW,TAG,MODULE,ENTITY_ID,USER_ID).ignoreDuplicates(SQLITE); + var insertQuery = insertInto(TABLE_TAGS_NEW,TAG, MODULE, ENTITY_ID, USER_ID).ignoreDuplicates(SQLITE); while (urlTags.next()){ var tag = urlTags.getString(TAG); - insertQuery.values(tag,BOOKMARK,bm.urlId(),userId); + insertQuery.values(tag, BOOKMARK,bm.urlId(),userId); if (module != null && entityId != 0) insertQuery.values(tag,module,entityId,userId); } insertQuery.execute(db).close(); @@ -103,7 +108,7 @@ public class SqliteDb extends BaseDb implements TagDB{ } commentedURLS.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_TABLE,TABLE_URLS).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT, Translatable.t(TABLE_WITH_NAME,NAME,TABLE_URLS)).causedBy(e); } } @@ -114,7 +119,7 @@ public class SqliteDb extends BaseDb implements TagDB{ stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,"Comments (legacy)").causedBy(e); + throw failedToCreateTable("Comments (legacy)").causedBy(e); } } @@ -125,7 +130,7 @@ public class SqliteDb extends BaseDb implements TagDB{ stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,"Tags (legacy)").causedBy(e); + throw failedToCreateTable("Tags (legacy)").causedBy(e); } } @@ -136,7 +141,7 @@ public class SqliteDb extends BaseDb implements TagDB{ stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,"URLs (legacy)").causedBy(e); + throw failedToCreateTable("URLs (legacy)").causedBy(e); } } @@ -147,7 +152,7 @@ public class SqliteDb extends BaseDb implements TagDB{ stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,"URL_comments (legacy)").causedBy(e); + throw failedToCreateTable("URL_comments (legacy)").causedBy(e); } } @@ -166,7 +171,7 @@ CREATE TABLE IF NOT EXISTS {0} ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_TAGS_NEW).causedBy(e); + throw failedToCreateTable(TABLE_TAGS_NEW).causedBy(e); } } @@ -179,7 +184,7 @@ CREATE TABLE IF NOT EXISTS {0} ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY,table).causedBy(e); + throw failedToDropObject(table).causedBy(e); } } @@ -190,7 +195,7 @@ CREATE TABLE IF NOT EXISTS {0} ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_TAGS).causedBy(e); + throw failedToCreateTable(TABLE_TAGS).causedBy(e); } } @@ -206,7 +211,7 @@ CREATE TABLE IF NOT EXISTS {0} ( .execute(db); return tag; } catch (SQLException e){ - throw databaseException(FAILED_TO_DROP_ENTITY,tag); + throw failedToDropObject(tag); } } @@ -217,7 +222,7 @@ CREATE TABLE IF NOT EXISTS {0} ( .where(MODULE,iEqual(module)).where(ENTITY_ID,equal(entityId)) .execute(db); } catch (SQLException e){ - throw databaseException(FAILED_TO_DROP_ENTITY_OF_ENTITY,entityId,module).causedBy(e); + throw failedToDropObject(Translatable.t("{module}.{id}", MODULE,module, ID,entityId)).causedBy(e); } } @@ -241,7 +246,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return result; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"uses",tag).causedBy(e); + throw failedToDropObject(Translatable.t("uses of {tag}",TAG,tag)).causedBy(e); } } @@ -261,7 +266,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return tags; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,"tags").causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,TAGS).causedBy(e); } } @@ -279,7 +284,8 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return list; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"tags",userId).causedBy(e); + + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.TAGS), OWNER, Translatable.t(USER_WITH_ID, ID,userId)).causedBy(e); } } @@ -299,14 +305,14 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return tags; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,"tags").causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,t(Text.TAGS)).causedBy(e); } } @Override public void save(Collection userIds, String module, long entityId, Collection tags) { try { - var query = replaceInto(TABLE_TAGS,USER_ID,MODULE,ENTITY_ID,TAG); + var query = replaceInto(TABLE_TAGS, USER_ID, MODULE, ENTITY_ID,TAG); for (var tag : tags) { if (userIds == null) { // tags not assigned to a user are available to all users query.values(null, module, entityId, tag); @@ -316,7 +322,7 @@ CREATE TABLE IF NOT EXISTS {0} ( } query.execute(db).close(); } catch (SQLException e){ - throw databaseException(FAILED_TO_STORE_ENTITY,String.join(", ",tags)).causedBy(e); + throw failedToStoreObject(String.join(", ",tags)).causedBy(e); } } @@ -326,7 +332,7 @@ CREATE TABLE IF NOT EXISTS {0} ( update(TABLE_TAGS).set(ENTITY_ID).where(MODULE,iEqual(module)).where(ENTITY_ID,equal(oldId)).prepare(db).apply(newId).close(); LOG.log(DEBUG,"Updated tag @ {0}.{1} → {0}.{2}",module,oldId,newId); } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_ENTITY,format("{0}.{1} → {0}.{2}",module,oldId,newId)).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT,format("{0}.{1} → {0}.{2}",module,oldId,newId)).causedBy(e); } } } diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java index c8e3ddae..dab9e5ce 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java @@ -2,11 +2,11 @@ package de.srsoftware.umbrella.tags; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.unprocessable; +import static de.srsoftware.umbrella.core.constants.Field.USER_LIST; +import static de.srsoftware.umbrella.core.constants.Path.USES; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.tags.Constants.*; import com.sun.net.httpserver.HttpExchange; @@ -28,8 +28,8 @@ public class TagModule extends BaseHandler implements TagService { public TagModule(Configuration config) { super(); - var tagDbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); - var bmDbFile = config.get(de.srsoftware.umbrella.bookmarks.Constants.CONFIG_DATABASE).orElseThrow(() -> missingFieldException(de.srsoftware.umbrella.bookmarks.Constants.CONFIG_DATABASE)); + var tagDbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); + var bmDbFile = config.get(de.srsoftware.umbrella.bookmarks.Constants.CONFIG_DATABASE).orElseThrow(() -> missingField(de.srsoftware.umbrella.bookmarks.Constants.CONFIG_DATABASE)); tagDb = new SqliteDb(connect(tagDbFile),connect(bmDbFile)); ModuleRegistry.add(this); } @@ -90,9 +90,9 @@ public class TagModule extends BaseHandler implements TagService { var head = path.pop(); long entityId = Long.parseLong(head); var json = json(ex); - if (!(json.has(TAG) && json.get(TAG) instanceof String tag && !tag.isBlank())) throw missingFieldException(TAG); + if (!(json.has(TAG) && json.get(TAG) instanceof String tag && !tag.isBlank())) throw missingField(TAG); List userList = null; - if (!json.has(USER_LIST)) throw missingFieldException(USER_LIST); + if (!json.has(USER_LIST)) throw missingField(USER_LIST); var ul = json.isNull(USER_LIST) ? null : json.get(USER_LIST); if (ul instanceof JSONArray arr){ userList = arr.toList().stream() diff --git a/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java b/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java index 779329b7..b068c832 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java @@ -5,17 +5,23 @@ package de.srsoftware.umbrella.task; import static de.srsoftware.tools.jdbc.Condition.*; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.notFound; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TASK; +import static de.srsoftware.umbrella.core.constants.Field.TYPE; +import static de.srsoftware.umbrella.core.constants.Text.*; +import static de.srsoftware.umbrella.core.constants.Text.TASKS; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.failedToCreateTable; import static de.srsoftware.umbrella.core.model.Status.*; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.project.Constants.*; import static de.srsoftware.umbrella.task.Constants.*; import static java.text.MessageFormat.format; import de.srsoftware.tools.jdbc.Query; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import java.sql.Connection; @@ -55,16 +61,16 @@ public class SqliteDb extends BaseDb implements TaskDb { stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_TASK_DEPENDENCIES).causedBy(e); + throw failedToCreateTable(TABLE_TASK_DEPENDENCIES).causedBy(e); } } private void createPriorityColumn() { - var sql = format("ALTER TABLE {0} ADD {1} INT NOT NULL DEFAULT 0",TABLE_TASKS,PRIORITY); + var sql = format("ALTER TABLE {0} ADD {1} INT NOT NULL DEFAULT 0",TABLE_TASKS, PRIORITY); try { db.prepareStatement(sql).execute(); } catch (SQLException e) { - throw databaseException(FAILED_TO_ADD_COLUMN,PRIORITY,TABLE_TASKS).causedBy(e); + throw databaseException(FAILED_TO_ADD_COLUMN, NAME, PRIORITY, TABLE,TABLE_TASKS).causedBy(e); } } @@ -88,7 +94,7 @@ public class SqliteDb extends BaseDb implements TaskDb { stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_PROJECTS).causedBy(e); + throw failedToCreateTable(TABLE_PROJECTS).causedBy(e); } } @@ -105,7 +111,7 @@ CREATE TABLE IF NOT EXISTS {0} ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_PROJECT_USERS).causedBy(e); + throw failedToCreateTable(TABLE_PROJECT_USERS).causedBy(e); } } @@ -116,23 +122,23 @@ CREATE TABLE IF NOT EXISTS {0} ( long count = 0; if (rs.next()) count = rs.getLong(1); rs.close(); - if (count>0) throw new UmbrellaException("Task \"{0}\" has child tasks and thus cannot be deleted!",task.name()); + if (count>0) throw unprocessable("Task \"{task}\" has child tasks and thus cannot be deleted!", TASK,task.name()); Query.delete().from(TABLE_TASKS).where(ID,equal(task.id())).execute(db); Query.delete().from(TABLE_TASKS_USERS).where(TASK_ID,equal(task.id())).execute(db); } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY,"task").causedBy(e); + throw failedToDropObject(task).causedBy(e); } } @Override - public void dropMember(long projectId, long userId) { + public void dropMember(long taskId, long userId) { try { Query.delete().from(TABLE_TASKS_USERS) - .where(TASK_ID,equal(projectId)) + .where(TASK_ID,equal(taskId)) .where(USER_ID,equal(userId)) .execute(db); } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY_OF_ENTITY,USER_ID,userId,PROJECT,projectId).causedBy(e); + throw failedToDropObjectFromObject(USER_ID,userId,t(Text.TASK),taskId).causedBy(e); } } @@ -143,7 +149,7 @@ CREATE TABLE IF NOT EXISTS {0} ( var query = select(ALL).from(TABLE_TASKS).leftJoin(ID,TABLE_TASKS_USERS,TASK_ID) .where(USER_ID,equal(userId)); if (fulltext) { - for (var key : keys) query.where(format("CONCAT({0},\" \",{1})",NAME,DESCRIPTION),like("%"+key+"%")); + for (var key : keys) query.where(format("CONCAT({0},\" \",{1})", NAME, DESCRIPTION),like("%"+key+"%")); } else { for (var key : keys) query.where(NAME,like("%"+key+"%")); } @@ -155,7 +161,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return tasks; } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,TASKS,USER).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(TASKS), OWNER,t(Text.USER)).causedBy(e); } } @@ -168,7 +174,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return result; } catch (SQLException e){ - throw databaseException(FAILED_TO_LIST_ENTITIES,"task members").causedBy(e); + throw failedToLoadObject("task members").causedBy(e); } } @@ -183,7 +189,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return loadDependencies(tasks); } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,TASKS,"project_ids").causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(TASKS), OWNER,"project_ids").causedBy(e); } } @@ -203,7 +209,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return loadDependencies(tasks); } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,TASKS,"project "+projectId).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(TASKS), OWNER, t(PROJECT_WITH_ID, ID,projectId)).causedBy(e); } } @@ -222,7 +228,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return loadDependencies(tasks); } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"child tasks",parentTaskId).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,"child tasks", OWNER,parentTaskId).causedBy(e); } } @@ -241,7 +247,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return loadDependencies(tasks); } catch (SQLException e){ - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"project "+projectId).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(TASKS), OWNER, t(PROJECT_WITH_ID, ID,projectId)).causedBy(e); } } @@ -256,7 +262,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return map; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER,"user "+userId).causedBy(e); + throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(TASKS), OWNER, t(USER_WITH_ID, ID,userId)).causedBy(e); } } @@ -264,7 +270,7 @@ CREATE TABLE IF NOT EXISTS {0} ( public Task load(long taskId) throws UmbrellaException { var map = load(List.of(taskId)); var task = map.get(taskId); - if (task == null) throw notFound(FAILED_TO_LOAD_ENTITY_BY_ID,TASK,taskId); + if (task == null) throw notFound(FAILED_TO_LOAD_OBJECT_BY_ID, OBJECT,t(Text.TASK), ID,taskId); return task; } @@ -280,7 +286,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return loadDependencies(map); } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,TASK).causedBy(e); + throw failedToLoadObject(t(TASKS)).causedBy(e); } } @@ -295,7 +301,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return tasks; } catch (SQLException e) { - throw databaseException(FAILED_TO_LOAD_ENTITY,"task dependencies").causedBy(e); + throw failedToLoadObject("task dependencies").causedBy(e); } } @@ -303,18 +309,18 @@ CREATE TABLE IF NOT EXISTS {0} ( public Task save(Task task) { try { if (task.id() == 0){ // new task - var rs = insertInto(TABLE_TASKS,PROJECT_ID,PARENT_TASK_ID,NAME,DESCRIPTION,STATUS,EST_TIME,START_DATE,DUE_DATE,SHOW_CLOSED,NO_INDEX,PRIORITY) + var rs = insertInto(TABLE_TASKS, PROJECT_ID, PARENT_TASK_ID, NAME, DESCRIPTION, STATUS, EST_TIME, START_DATE, DUE_DATE, SHOW_CLOSED, NO_INDEX, PRIORITY) .values(task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.priority()) .execute(db) .getGeneratedKeys(); Long taskId = null; if (rs.next()) taskId=rs.getLong(1); rs.close(); - if (taskId == null) throw new UmbrellaException("Failed to save task {0}",task.name()); + if (taskId == null) throw failedToStoreObject(task.name()); return new Task(taskId,task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.members(), task.priority()); } if (task.isDirty(MEMBERS)){ - var query = replaceInto(TABLE_TASKS_USERS,TASK_ID,USER_ID,PERMISSIONS); + var query = replaceInto(TABLE_TASKS_USERS,TASK_ID, USER_ID,PERMISSIONS); for (var member : task.members().entrySet()) query.values(task.id(),member.getKey(),member.getValue().permission().code()); query.execute(db).close(); task.clean(MEMBERS); @@ -336,7 +342,7 @@ CREATE TABLE IF NOT EXISTS {0} ( task.clean(REQUIRED_TASKS_IDS); } if (task.isDirty()) { - update(TABLE_TASKS).set(PROJECT_ID,PARENT_TASK_ID,NAME,DESCRIPTION,STATUS,EST_TIME,START_DATE,DUE_DATE,SHOW_CLOSED,NO_INDEX,PRIORITY) + update(TABLE_TASKS).set(PROJECT_ID, PARENT_TASK_ID, NAME, DESCRIPTION, STATUS, EST_TIME, START_DATE, DUE_DATE, SHOW_CLOSED, NO_INDEX, PRIORITY) .where(ID,equal(task.id())).prepare(db) .apply(task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.priority()) .close(); @@ -344,16 +350,16 @@ CREATE TABLE IF NOT EXISTS {0} ( } return task; } catch (SQLException e){ - throw databaseException(FAILED_TO_STORE_ENTITY,task.name()).causedBy(e); + throw failedToStoreObject(task.name()).causedBy(e); } } @Override public void setMember(long taskId, long userId, Permission permission) { try { - replaceInto(TABLE_TASKS_USERS,TASK_ID,USER_ID,PERMISSIONS).values(taskId,userId,permission.code()).execute(db).close(); + replaceInto(TABLE_TASKS_USERS,TASK_ID, USER_ID,PERMISSIONS).values(taskId,userId,permission.code()).execute(db).close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_STORE_ENTITY,PERMISSIONS).causedBy(e); + throw failedToStoreObject(PERMISSIONS).causedBy(e); } } } diff --git a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java index de70beef..5a619e8e 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java @@ -3,14 +3,19 @@ package de.srsoftware.umbrella.task; import static de.srsoftware.tools.Optionals.*; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.ModuleRegistry.*; -import static de.srsoftware.umbrella.core.Paths.*; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_NOT_IMPLEMENTED; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TAGS; +import static de.srsoftware.umbrella.core.constants.Field.TASKS; +import static de.srsoftware.umbrella.core.constants.Module.TASK; +import static de.srsoftware.umbrella.core.constants.Path.*; +import static de.srsoftware.umbrella.core.constants.Text.LONG; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Permission.*; import static de.srsoftware.umbrella.core.model.Permission.OWNER; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus; import static de.srsoftware.umbrella.messagebus.events.Event.EventType.CREATE; import static de.srsoftware.umbrella.messagebus.events.Event.EventType.UPDATE; @@ -27,6 +32,7 @@ import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.api.*; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.core.model.Task; @@ -62,7 +68,7 @@ public class TaskModule extends BaseHandler implements TaskService { public TaskModule(Configuration config) throws UmbrellaException { super(); - var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); + var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); taskDb = new SqliteDb(connect(dbFile)); ModuleRegistry.add(this); } @@ -77,7 +83,7 @@ public class TaskModule extends BaseHandler implements TaskService { private boolean deleteTask(HttpExchange ex, long taskId, UmbrellaUser user) throws IOException { var task = loadMembers(taskDb.load(taskId)); var member = task.members().get(user.id()); - if (member == null || !member.mayWrite()) throw forbidden("You are not allowed to delete {0}", task.name()); + if (member == null || !member.mayWrite()) throw forbidden("You are not allowed to delete {object}", OBJECT, task.name()); taskDb.delete(task); noteService().deleteEntity(TASK, "" + taskId); tagService().deleteEntity(TASK, taskId); @@ -170,17 +176,17 @@ public class TaskModule extends BaseHandler implements TaskService { } private void dropMember(Task task, long userId) { - if (task.members().get(userId).permission() == OWNER) throw forbidden("You may not remove the owner of the task"); + if (task.members().get(userId).permission() == OWNER) throw forbidden("You may not remove the owner of {object}", OBJECT,task.name()); taskDb.dropMember(task.id(), userId); task.members().remove(userId); } private boolean estimatedTimes(UmbrellaUser user, HttpExchange ex) throws IOException, UmbrellaException { var json = json(ex); - if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID); + if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingField(COMPANY_ID); var companyId = cid.longValue(); var company = companyService().get(companyId); - if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + if (!companyService().membership(companyId,user.id())) throw notAmember(company.name()); var projectMap = projectService().listCompanyProjects(companyId, false); var taskMap = taskDb.listTasks(projectMap.keySet()); var taskTree = new HashMap>(); @@ -218,7 +224,7 @@ public class TaskModule extends BaseHandler implements TaskService { private boolean getTask(HttpExchange ex, long taskId, UmbrellaUser user) throws IOException { var task = loadMembers(taskDb.load(taskId)); - if (!task.hasMember(user)) throw forbidden("You are not a member of {0}",task.name()); + if (!task.hasMember(user)) throw notAmember(task.name()); return sendContent(ex, task); } @@ -229,12 +235,12 @@ public class TaskModule extends BaseHandler implements TaskService { if (params.get(OFFSET) instanceof String o) try { offset = Long.parseLong(o); } catch (NumberFormatException e) { - throw invalidFieldException(OFFSET, "number"); + throw invalidField(OFFSET, t(Text.NUMBER)); } if (params.get(LIMIT) instanceof String l) try { limit = Long.parseLong(l); } catch (NumberFormatException e) { - throw invalidFieldException(LIMIT, "number"); + throw invalidField(LIMIT, t(Text.NUMBER)); } var tasks = taskDb.listUserTasks(user.id(), limit, offset, false); var mapped = loadMembers(tasks).stream().map(Task::toMap); @@ -311,12 +317,12 @@ public class TaskModule extends BaseHandler implements TaskService { try { userId = Long.parseLong(key); } catch (NumberFormatException e) { - throw invalidFieldException(USER_ID, "long"); + throw invalidField(USER_ID, t(LONG)); } var permission = switch (json.get(key)) { case Number code -> Permission.of(code.intValue()); case String name -> Permission.valueOf(name); - default -> throw invalidFieldException(PERMISSION, "int / String"); + default -> throw invalidField(PERMISSION, "int / String"); }; if (permission == OWNER) { // if a new person is about to become the task owner for (var member : members.values()) { // alter the previous owners to editors @@ -336,7 +342,7 @@ public class TaskModule extends BaseHandler implements TaskService { private boolean patchTask(HttpExchange ex, long taskId, UmbrellaUser user) throws IOException { var task = loadMembers(taskDb.load(taskId)); var member = task.members().get(user.id()); - if (member == null || member.permission() == READ_ONLY) throw forbidden("You are not a allowed to edit {0}!", task.name()); + if (member == null || member.permission() == READ_ONLY) throw forbidden("You are not a allowed to edit {object}!", OBJECT, task.name()); var json = json(ex); if (json.has(DROP_MEMBER) && json.get(DROP_MEMBER) instanceof Number id) dropMember(task, id.longValue()); if (json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject memberJson) patchMembers(task, memberJson); @@ -350,7 +356,7 @@ public class TaskModule extends BaseHandler implements TaskService { private boolean postNewTask(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingFieldException(PROJECT_ID); + if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingField(PROJECT_ID); long projectId = pid.longValue(); var project = projectService().load(projectId); @@ -364,7 +370,7 @@ public class TaskModule extends BaseHandler implements TaskService { taskService().loadMembers(parentTask); members = parentTask.members(); member = members.get(user.id()); - if (member == null || member.permission() == READ_ONLY) throw forbidden("You are not allowed to add sub-stasks to {0}", parentTask.name()); + if (member == null || member.permission() == READ_ONLY) throw forbidden("You are not allowed to add sub-stasks to {object}", OBJECT, parentTask.name()); } var newMembers = new HashMap(); @@ -412,7 +418,7 @@ public class TaskModule extends BaseHandler implements TaskService { private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY); + if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingField(KEY); var projectId = json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid ? pid.longValue() : null; var keys = Arrays.asList(key.split(" ")); var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val; diff --git a/time/src/main/java/de/srsoftware/umbrella/time/Constants.java b/time/src/main/java/de/srsoftware/umbrella/time/Constants.java index 5859381b..89632140 100644 --- a/time/src/main/java/de/srsoftware/umbrella/time/Constants.java +++ b/time/src/main/java/de/srsoftware/umbrella/time/Constants.java @@ -4,7 +4,6 @@ package de.srsoftware.umbrella.time; public class Constants { private Constants(){} - public static final String CHILDREN = "children"; public static final String CLOSED = "closed"; public static final String CONFIG_DATABASE = "umbrella.modules.time.database"; public static final String DOCUMENTS = "documents"; @@ -14,8 +13,6 @@ public class Constants { public static final String TABLE_TASK_TIMES = "task_times"; public static final String TABLE_TIMES = "times"; public static final String TASK_ID = "task_id"; - public static final String TASKS = "tasks"; - public static final String TIME_ID = "time_id"; public static final String TIMES = "times"; public static final String TRACK_TASK = "track_task"; diff --git a/time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java b/time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java index a9b3e91e..d68ca5a9 100644 --- a/time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java +++ b/time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java @@ -4,10 +4,13 @@ package de.srsoftware.umbrella.time; import static de.srsoftware.tools.jdbc.Condition.*; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; -import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; -import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TIME_ID; +import static de.srsoftware.umbrella.core.constants.Text.TIME_WITH_ID; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Time.State.Complete; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.time.Constants.*; import static java.text.MessageFormat.format; @@ -50,7 +53,7 @@ CREATE TABLE IF NOT EXISTS {0} ( stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_TASK_TIMES).causedBy(e); + throw failedToCreateTable(TABLE_TASK_TIMES).causedBy(e); } } @@ -65,13 +68,13 @@ CREATE TABLE IF NOT EXISTS {0} ( {6} TIMESTAMP, {7} INT NOT NULL DEFAULT {8} )"""; - sql = format(sql,TABLE_TIMES,ID,USER_ID,SUBJECT,DESCRIPTION,START_TIME,END_TIME,STATE, Time.State.Started.code()); + sql = format(sql,TABLE_TIMES, ID, USER_ID, SUBJECT, DESCRIPTION,START_TIME, END_TIME, STATE, Time.State.Started.code()); try { var stmt = db.prepareStatement(sql); stmt.execute(); stmt.close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_CREATE_TABLE,TABLE_TIMES).causedBy(e); + throw failedToCreateTable(TABLE_TIMES).causedBy(e); } } @@ -84,7 +87,7 @@ CREATE TABLE IF NOT EXISTS {0} ( db.setAutoCommit(false); return timeId; } catch (SQLException e) { - throw databaseException(FAILED_TO_DROP_ENTITY,"time "+timeId).causedBy(e); + throw failedToDropObject(t(TIME_WITH_ID, ID,timeId)).causedBy(e); } } @@ -93,7 +96,7 @@ CREATE TABLE IF NOT EXISTS {0} ( try { var query = select(ALL).from(TABLE_TIMES).where(USER_ID,equal(userId)); if (fulltext) { - for (var key : keys) query.where(format("CONCAT({0},\" \",{1})",SUBJECT,DESCRIPTION),like("%"+key+"%")); + for (var key : keys) query.where(format("CONCAT({0},\" \",{1})", SUBJECT, DESCRIPTION),like("%"+key+"%")); } else { for (var key : keys) query.where(SUBJECT,like("%"+key+"%")); } @@ -106,7 +109,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return times; } catch (Exception e) { - throw databaseException(FAILED_TO_SEARCH_DB,TABLE_TIMES).causedBy(e); + throw failedToSearchDb(t(TIMES)).causedBy(e); } } @@ -133,7 +136,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return times; } catch (Exception e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,TIMES).causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,TIMES).causedBy(e); } } @@ -157,7 +160,7 @@ CREATE TABLE IF NOT EXISTS {0} ( rs.close(); return times; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,TIMES).causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,TIMES).causedBy(e); } } @@ -172,10 +175,10 @@ CREATE TABLE IF NOT EXISTS {0} ( rs = select(ALL).from(TABLE_TASK_TIMES).where(TIME_ID,equal(timeId)).exec(db); while (rs.next()) time.taskIds().add(rs.getLong(TASK_ID)); rs.close(); - if (time == null) throw UmbrellaException.notFound("No time found with id = {0}",timeId); + if (time == null) throw notFound("No time found with id = {id}", ID,timeId); return time; } catch (SQLException e) { - throw databaseException(FAILED_TO_LIST_ENTITIES,TIMES).causedBy(e); + throw databaseException(FAILED_TO_LIST_ENTITIES, TYPE,TIMES).causedBy(e); } } @@ -199,7 +202,7 @@ CREATE TABLE IF NOT EXISTS {0} ( query.execute(db).close(); return track; } catch (SQLException e){ - throw databaseException(FAILED_TO_STORE_ENTITY,"time").causedBy(e); + throw failedToStoreObject("time").causedBy(e); } } @@ -213,7 +216,7 @@ CREATE TABLE IF NOT EXISTS {0} ( .apply(timeState.code()) .close(); } catch (SQLException e) { - throw databaseException(FAILED_TO_UPDATE_ENTITY,TIMES).causedBy(e); + throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT,TIMES).causedBy(e); } } } diff --git a/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java b/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java index 4b255bbc..7f94dc7f 100644 --- a/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java +++ b/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java @@ -2,13 +2,17 @@ package de.srsoftware.umbrella.time; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; -import static de.srsoftware.umbrella.core.Constants.*; +import static de.srsoftware.umbrella.core.Errors.FAILED_TO_LOAD_OBJECT_BY_ID; import static de.srsoftware.umbrella.core.ModuleRegistry.*; -import static de.srsoftware.umbrella.core.Paths.*; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TASKS; +import static de.srsoftware.umbrella.core.constants.Path.*; +import static de.srsoftware.umbrella.core.constants.Text.TIME_WITH_ID; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Time.State.Open; import static de.srsoftware.umbrella.core.model.Time.State.Started; +import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.time.Constants.*; import com.sun.net.httpserver.HttpExchange; @@ -18,6 +22,7 @@ import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.api.*; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import java.io.IOException; @@ -31,7 +36,7 @@ public class TimeModule extends BaseHandler implements TimeService { public TimeModule( Configuration config) throws UmbrellaException { super(); - var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); + var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); timeDb = new SqliteDb(connect(dbFile)); ModuleRegistry.add(this); } @@ -59,7 +64,7 @@ public class TimeModule extends BaseHandler implements TimeService { var timeId = Long.parseLong(head); return deleteTime(user.get(),timeId,ex); } catch (NumberFormatException e){ - return send(ex,invalidFieldException(TIME_ID,"long value")); + return send(ex,invalidField(TIME_ID,"long value")); } catch (UmbrellaException e){ return send(ex,e); } @@ -98,7 +103,7 @@ public class TimeModule extends BaseHandler implements TimeService { var timeId = Long.parseLong(head); return patchTime(user.get(), timeId, ex); } catch (NumberFormatException e) { - return send(ex, invalidFieldException(TIME_ID, "long value")); + return send(ex, invalidField(TIME_ID, "long value")); } } catch (UmbrellaException e){ return send(ex,e); @@ -143,10 +148,10 @@ public class TimeModule extends BaseHandler implements TimeService { throw unprocessable("Expected two time ids as body"); } var time1 = timeDb.load(id1); - if (time1.userId() != user.id()) throw forbidden("You are not owner of time {0}",time1.id()); + if (time1.userId() != user.id()) throw notAmember(t(TIME_WITH_ID, ID, time1.id())); if (time1.state() != Open) throw forbidden("Time is not editable"); var time2 = timeDb.load(id2); - if (time2.userId() != user.id()) throw forbidden("You are not owner of time {0}",time2.id()); + if (time2.userId() != user.id()) throw forbidden("You are not owner of time {id}", ID,time2.id()); if (time2.state() != Open) throw forbidden("Time is not editable"); if (time1.start() > time2.start()) { @@ -196,16 +201,16 @@ public class TimeModule extends BaseHandler implements TimeService { private boolean getStartedTime(UmbrellaUser user, HttpExchange ex) throws IOException { var startedTime = getStartedTime(user); if (startedTime.isPresent()) return sendContent(ex,startedTime.get()); - return send(ex,UmbrellaException.notFound("no started time")); + return send(ex, UmbrellaException.notFound("no started time")); } private boolean listTimes(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { var json = json(ex); - if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID); + if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingField(COMPANY_ID); var companyId = cid.longValue(); var company = companyService().get(companyId); - if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); - if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingFieldException(PROJECT_ID); + if (!companyService().membership(companyId,user.id())) throw notAmember(company.name()); + if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingField(PROJECT_ID); long projectId = pid.longValue(); Map tasksOfProject = taskService().listProjectTasks(projectId); @@ -235,12 +240,12 @@ public class TimeModule extends BaseHandler implements TimeService { private boolean patchTimes(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); - if (!json.has(IDS) || !(json.get(IDS) instanceof JSONArray ids)) throw missingFieldException(IDS); + if (!json.has(IDS) || !(json.get(IDS) instanceof JSONArray ids)) throw missingField(IDS); var times = new HashSet