Adminmasken angefangen
@@ -1,5 +1,5 @@
|
||||
#Mon Mar 23 15:59:12 CET 2026
|
||||
#Mon Mar 23 21:09:40 CET 2026
|
||||
display=\:0
|
||||
host=Mario-Linux
|
||||
process-id=144468
|
||||
host=mario-mint
|
||||
process-id=80279
|
||||
user=mario
|
||||
|
||||
182
.metadata/.log
@@ -44,3 +44,185 @@ Command-line arguments: -os linux -ws gtk -arch x86_64 -clean -product org.ecli
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 15:59:13.162
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
!SESSION 2026-03-23 17:25:44.070 -----------------------------------------------
|
||||
eclipse.buildId=4.39.0.20260305-0817
|
||||
java.version=21.0.6
|
||||
java.vendor=Eclipse Adoptium
|
||||
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=de_DE
|
||||
Framework arguments: -product org.eclipse.epp.package.java.product
|
||||
Command-line arguments: -os linux -ws gtk -arch x86_64 -clean -product org.eclipse.epp.package.java.product
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:25:45.609
|
||||
!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:25:48.467
|
||||
!MESSAGE Logback config file: /home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.7.101.20251017-1242.xml
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:25:48.662
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:25:48.662
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:25:48.852
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:25:48.852
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.springframework.tooling.boot.ls 1 0 2026-03-23 17:26:29.969
|
||||
!MESSAGE DelegatingStreamConnectionProvider - Stopping Boot LS
|
||||
!SESSION 2026-03-23 17:26:31.429 -----------------------------------------------
|
||||
eclipse.buildId=4.39.0.20260305-0817
|
||||
java.version=21.0.6
|
||||
java.vendor=Eclipse Adoptium
|
||||
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=de_DE
|
||||
Framework arguments: -product org.eclipse.epp.package.java.product
|
||||
Command-line arguments: -os linux -ws gtk -arch x86_64 -clean -product org.eclipse.epp.package.java.product
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:26:32.616
|
||||
!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:26:35.371
|
||||
!MESSAGE Logback config file: /home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.7.101.20251017-1242.xml
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:26:35.486
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:26:35.486
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:26:35.621
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:26:35.621
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.springframework.tooling.boot.ls 1 0 2026-03-23 17:29:17.229
|
||||
!MESSAGE DelegatingStreamConnectionProvider - Stopping Boot LS
|
||||
!SESSION 2026-03-23 17:36:46.699 -----------------------------------------------
|
||||
eclipse.buildId=4.39.0.20260305-0817
|
||||
java.version=21.0.6
|
||||
java.vendor=Eclipse Adoptium
|
||||
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=de_DE
|
||||
Framework arguments: -product org.eclipse.epp.package.java.product
|
||||
Command-line arguments: -os linux -ws gtk -arch x86_64 -clean -product org.eclipse.epp.package.java.product
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:36:48.204
|
||||
!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:36:52.468
|
||||
!MESSAGE Logback config file: /home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.7.101.20251017-1242.xml
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:36:52.616
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:36:52.616
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:36:52.744
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:36:52.744
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.springframework.tooling.boot.ls 1 0 2026-03-23 17:38:14.624
|
||||
!MESSAGE DelegatingStreamConnectionProvider - Stopping Boot LS
|
||||
!SESSION 2026-03-23 17:38:45.521 -----------------------------------------------
|
||||
eclipse.buildId=4.39.0.20260305-0817
|
||||
java.version=21.0.6
|
||||
java.vendor=Eclipse Adoptium
|
||||
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=de_DE
|
||||
Framework arguments: -product org.eclipse.epp.package.java.product
|
||||
Command-line arguments: -os linux -ws gtk -arch x86_64 -clean -product org.eclipse.epp.package.java.product
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:38:46.707
|
||||
!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 17:38:49.211
|
||||
!MESSAGE Logback config file: /home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.7.101.20251017-1242.xml
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:38:49.361
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:38:49.361
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 17:38:49.491
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 17:38:49.492
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.jface 2 0 2026-03-23 17:49:15.882
|
||||
!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation.
|
||||
!SUBENTRY 1 org.eclipse.jface 2 0 2026-03-23 17:49:15.882
|
||||
!MESSAGE A conflict occurred for CTRL+SHIFT+T:
|
||||
Binding(CTRL+SHIFT+T,
|
||||
ParameterizedCommand(Command(org.eclipse.jdt.ui.navigate.open.type,Open Type,
|
||||
Open a type in a Java editor,
|
||||
Category(org.eclipse.ui.category.navigate,Navigate,null,true),
|
||||
WorkbenchHandlerServiceHandler("org.eclipse.jdt.ui.navigate.open.type"),
|
||||
,,true),null),
|
||||
org.eclipse.ui.defaultAcceleratorConfiguration,
|
||||
org.eclipse.ui.contexts.window,,,system)
|
||||
Binding(CTRL+SHIFT+T,
|
||||
ParameterizedCommand(Command(org.eclipse.lsp4e.symbolInWorkspace,Go to Symbol in Workspace,
|
||||
,
|
||||
Category(org.eclipse.lsp4e.category,Language Servers,null,true),
|
||||
WorkbenchHandlerServiceHandler("org.eclipse.lsp4e.symbolInWorkspace"),
|
||||
,,true),null),
|
||||
org.eclipse.ui.defaultAcceleratorConfiguration,
|
||||
org.eclipse.ui.contexts.window,,,system)
|
||||
|
||||
!ENTRY org.eclipse.debug.core 4 125 2026-03-23 17:50:18.648
|
||||
!MESSAGE Error logged from Debug Core:
|
||||
!STACK 0
|
||||
java.io.IOException: Stream closed
|
||||
at java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:188)
|
||||
at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:343)
|
||||
at java.base/java.io.BufferedInputStream.implRead(BufferedInputStream.java:420)
|
||||
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:405)
|
||||
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:95)
|
||||
at org.eclipse.debug.internal.core.OutputStreamMonitor.internalRead(OutputStreamMonitor.java:235)
|
||||
at org.eclipse.debug.internal.core.OutputStreamMonitor.read(OutputStreamMonitor.java:211)
|
||||
at java.base/java.lang.Thread.run(Thread.java:1583)
|
||||
|
||||
!ENTRY org.springframework.tooling.boot.ls 1 0 2026-03-23 19:07:16.440
|
||||
!MESSAGE DelegatingStreamConnectionProvider - Stopping Boot LS
|
||||
!SESSION 2026-03-23 21:09:34.939 -----------------------------------------------
|
||||
eclipse.buildId=4.39.0.20260305-0817
|
||||
java.version=21.0.6
|
||||
java.vendor=Eclipse Adoptium
|
||||
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=de_DE
|
||||
Framework arguments: -product org.eclipse.epp.package.java.product
|
||||
Command-line arguments: -os linux -ws gtk -arch x86_64 -clean -product org.eclipse.epp.package.java.product
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 21:09:36.148
|
||||
!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-03-23 21:09:41.162
|
||||
!MESSAGE Logback config file: /home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.7.101.20251017-1242.xml
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 21:09:41.310
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 21:09:41.310
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.ui 2 0 2026-03-23 21:09:41.447
|
||||
!MESSAGE Warnings while parsing the commands from the 'org.eclipse.ui.commands' and 'org.eclipse.ui.actionDefinitions' extension points.
|
||||
!SUBENTRY 1 org.eclipse.ui 2 0 2026-03-23 21:09:41.447
|
||||
!MESSAGE Commands should really have a category: plug-in='org.springframework.tooling.boot.ls', id='spring.initializr.addStarters', categoryId='org.eclipse.lsp4e.commandCategory'
|
||||
|
||||
!ENTRY org.eclipse.jface 2 0 2026-03-23 21:57:04.900
|
||||
!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation.
|
||||
!SUBENTRY 1 org.eclipse.jface 2 0 2026-03-23 21:57:04.900
|
||||
!MESSAGE A conflict occurred for CTRL+SHIFT+T:
|
||||
Binding(CTRL+SHIFT+T,
|
||||
ParameterizedCommand(Command(org.eclipse.jdt.ui.navigate.open.type,Open Type,
|
||||
Open a type in a Java editor,
|
||||
Category(org.eclipse.ui.category.navigate,Navigate,null,true),
|
||||
WorkbenchHandlerServiceHandler("org.eclipse.jdt.ui.navigate.open.type"),
|
||||
,,true),null),
|
||||
org.eclipse.ui.defaultAcceleratorConfiguration,
|
||||
org.eclipse.ui.contexts.window,,,system)
|
||||
Binding(CTRL+SHIFT+T,
|
||||
ParameterizedCommand(Command(org.eclipse.lsp4e.symbolInWorkspace,Go to Symbol in Workspace,
|
||||
,
|
||||
Category(org.eclipse.lsp4e.category,Language Servers,null,true),
|
||||
WorkbenchHandlerServiceHandler("org.eclipse.lsp4e.symbolInWorkspace"),
|
||||
,,true),null),
|
||||
org.eclipse.ui.defaultAcceleratorConfiguration,
|
||||
org.eclipse.ui.contexts.window,,,system)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<dirs>
|
||||
<entry loc="/usr/lib/jvm/java-21-openjdk-amd64" stamp="1774248231673"/>
|
||||
<entry loc="/usr/lib/jvm/java-21-openjdk-amd64" stamp="1774283020812"/>
|
||||
<entry loc="/usr/lib/jvm/java-26-openjdk-amd64" stamp="1774247449025"/>
|
||||
<entry loc="/home/mario/Programme/jdk-21" stamp="1774248849578"/>
|
||||
</dirs>
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<typeInfoHistroy/>
|
||||
<typeInfoHistroy>
|
||||
<typeInfo handle="=xxxthegame/src\/main\/java=/gradle_scope=/main=/=/gradle_used_by_scope=/main,test=/<de.oaa.xxx.aufgaben{DefaultFiller.java[DefaultFiller" modifiers="1" timestamp="1772437686926"/>
|
||||
</typeInfoHistroy>
|
||||
|
||||
@@ -2,9 +2,27 @@
|
||||
<section name="Workbench">
|
||||
<section name="org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart">
|
||||
<item key="group_libraries" value="true"/>
|
||||
<item key="layout" value="2"/>
|
||||
<item key="layout" value="1"/>
|
||||
<item key="rootMode" value="1"/>
|
||||
<item key="linkWithEditor" value="false"/>
|
||||
<item key="memento" value="<?xml version="1.0" encoding="UTF-8"?>
<packageExplorer group_libraries="1" layout="2" linkWithEditor="0" rootMode="1" workingSetName="Aggregate for window 1774277926242">
<customFilters userDefinedPatternsEnabled="false">
<xmlDefinedFilters>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.StaticsFilter" isEnabled="false"/>
<child filterId="org.eclipse.buildship.ui.packageexplorer.filter.gradle.buildfolder" isEnabled="true"/>
<child filterId="org.eclipse.mylyn.java.ui.MembersFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonJavaProjectsFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer_patternFilterId_.*" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonSharedProjectsFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.SyntheticMembersFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.ContainedLibraryFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.internal.ui.PackageExplorer.HideInnerClassFilesFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.internal.ui.PackageExplorer.EmptyInnerPackageFilter" isEnabled="true"/>
<child filterId="org.eclipse.m2e.MavenModuleFilter" isEnabled="false"/>
<child filterId="org.eclipse.buildship.ui.packageexplorer.filter.gradle.subProject" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.ClosedProjectsFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.DeprecatedMembersFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.EmptyLibraryContainerFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.PackageDeclarationFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.ImportDeclarationFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonJavaElementFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.LibraryFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.CuAndClassFileFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.internal.ui.PackageExplorer.EmptyPackageFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonPublicFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.LocalTypesFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.FieldsFilter" isEnabled="false"/>
</xmlDefinedFilters>
</customFilters>
</packageExplorer>"/>
|
||||
<item key="memento" value="<?xml version="1.0" encoding="UTF-8"?>
<packageExplorer group_libraries="1" layout="1" linkWithEditor="0" rootMode="1" workingSetName="Aggregate for window 1774277926242">
<customFilters userDefinedPatternsEnabled="false">
<xmlDefinedFilters>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.StaticsFilter" isEnabled="false"/>
<child filterId="org.eclipse.buildship.ui.packageexplorer.filter.gradle.buildfolder" isEnabled="true"/>
<child filterId="org.eclipse.mylyn.java.ui.MembersFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonJavaProjectsFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer_patternFilterId_.*" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonSharedProjectsFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.SyntheticMembersFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.ContainedLibraryFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.internal.ui.PackageExplorer.HideInnerClassFilesFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.internal.ui.PackageExplorer.EmptyInnerPackageFilter" isEnabled="true"/>
<child filterId="org.eclipse.m2e.MavenModuleFilter" isEnabled="false"/>
<child filterId="org.eclipse.buildship.ui.packageexplorer.filter.gradle.subProject" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.ClosedProjectsFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.DeprecatedMembersFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.EmptyLibraryContainerFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.PackageDeclarationFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.ImportDeclarationFilter" isEnabled="true"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonJavaElementFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.LibraryFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.CuAndClassFileFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.internal.ui.PackageExplorer.EmptyPackageFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.NonPublicFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.LocalTypesFilter" isEnabled="false"/>
<child filterId="org.eclipse.jdt.ui.PackageExplorer.FieldsFilter" isEnabled="false"/>
</xmlDefinedFilters>
</customFilters>
</packageExplorer>"/>
|
||||
</section>
|
||||
<section name="JavaElementSearchActions">
|
||||
</section>
|
||||
<section name="org.eclipse.jdt.internal.ui.dialogs.OpenTypeSelectionDialog2">
|
||||
<item key="ShowStatusLine" value="true"/>
|
||||
<item key="History" value="<?xml version="1.0" encoding="UTF-8"?>
<History/>"/>
|
||||
<item key="WorkingSet" value="<?xml version="1.0" encoding="UTF-8"?>
<workingSet workingSetName=""/>"/>
|
||||
<section name="DialogBoundsSettings">
|
||||
<item key="DIALOG_HEIGHT" value="500"/>
|
||||
<item key="DIALOG_WIDTH" value="600"/>
|
||||
<item key="DIALOG_X_ORIGIN" value="980"/>
|
||||
<item key="DIALOG_Y_ORIGIN" value="351"/>
|
||||
<item key="DIALOG_FONT_NAME" value="1|Ubuntu|10.0|0|GTK|1|"/>
|
||||
</section>
|
||||
</section>
|
||||
<section name="completion_proposal_size">
|
||||
</section>
|
||||
<section name="quick_assist_proposal_size">
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
2026-03-23 15:58:46,968 [Worker-6: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is not available. Remote download required.
|
||||
2026-03-23 15:59:14,530 [Worker-7: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-23 17:25:50,444 [Worker-6: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-23 17:26:37,131 [Worker-5: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-23 17:36:54,482 [Worker-8: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-23 17:38:51,039 [Worker-7: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-23 21:09:44,347 [Worker-7: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<section name="Workbench">
|
||||
<section name="ImportExportAction">
|
||||
<item key="ImportExportPage.STORE_SELECTED_IMPORT_WIZARD_ID" value="org.eclipse.buildship.ui.wizards.project.import"/>
|
||||
<list key="ImportExportPage.STORE_EXPANDED_IMPORT_CATEGORIES">
|
||||
<item value="org.eclipse.buildship.ui.importwizards"/>
|
||||
</list>
|
||||
<section name="ImportExportWizard.dialogBounds">
|
||||
<item key="DIALOG_X_ORIGIN" value="974"/>
|
||||
<item key="DIALOG_Y_ORIGIN" value="343"/>
|
||||
@@ -9,4 +13,11 @@
|
||||
<item key="DIALOG_FONT_NAME" value="1|Ubuntu Sans|11.0|0|GTK|1|"/>
|
||||
</section>
|
||||
</section>
|
||||
<section name="WorkbenchPreferenceDialog.dialogBounds">
|
||||
<item key="DIALOG_X_ORIGIN" value="976"/>
|
||||
<item key="DIALOG_Y_ORIGIN" value="338"/>
|
||||
<item key="DIALOG_WIDTH" value="608"/>
|
||||
<item key="DIALOG_HEIGHT" value="520"/>
|
||||
<item key="DIALOG_FONT_NAME" value="1|Ubuntu|10.0|0|GTK|1|"/>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#Mon Mar 23 15:59:12 CET 2026
|
||||
#Mon Mar 23 21:09:40 CET 2026
|
||||
org.eclipse.core.runtime=2
|
||||
org.eclipse.platform=4.39.0.v20260226-0420
|
||||
|
||||
BIN
bilder/toys/augenbinde.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
bilder/toys/chastitycage.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
bilder/toys/dildo.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
bilder/toys/dilliator.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
bilder/toys/electro_plug.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
bilder/toys/femaleCB.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
bilder/toys/gerte.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
bilder/toys/handfesseln.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
bilder/toys/knebel.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
bilder/toys/maleCB.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
bilder/toys/mastubator.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
bilder/toys/nippelklemmen.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
bilder/toys/paddel.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
bilder/toys/peitsche.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
bilder/toys/plugs.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
bilder/toys/pnsknebel.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
bilder/toys/prostatavibrator.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
bilder/toys/pumpplug.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
bilder/toys/seil.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
bilder/toys/strapon.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
bilder/toys/vibrator.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
504
testdaten.sql
Normal file
@@ -0,0 +1,504 @@
|
||||
-- =============================================================
|
||||
-- XXX The Game – Testdaten
|
||||
-- =============================================================
|
||||
-- Passwort für alle User: Test1234!
|
||||
-- SHA-256("Test1234!") = 11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a
|
||||
-- Hinweis: Login erwartet SHA-256-Hash vom Client
|
||||
-- =============================================================
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- Aufräumen (Reihenfolge wegen FK)
|
||||
DELETE FROM kommentar_like;
|
||||
DELETE FROM kommentar;
|
||||
DELETE FROM pinnwand_like;
|
||||
DELETE FROM pinnwand_eintrag;
|
||||
DELETE FROM feed_post_vote;
|
||||
DELETE FROM feed_post_option;
|
||||
DELETE FROM feed_post_like;
|
||||
DELETE FROM feed_post;
|
||||
DELETE FROM umfrage_stimme;
|
||||
DELETE FROM umfrage_option;
|
||||
DELETE FROM gruppe_beitrag_like;
|
||||
DELETE FROM gruppe_beitrag;
|
||||
DELETE FROM beitrittsanfrage;
|
||||
DELETE FROM gruppe_mitglied;
|
||||
DELETE FROM gruppe;
|
||||
DELETE FROM profile_image_like;
|
||||
DELETE FROM profile_image;
|
||||
DELETE FROM friendship;
|
||||
DELETE FROM registration;
|
||||
DELETE FROM `user`;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
-- =============================================================
|
||||
-- BENUTZER (5 User mit unterschiedlichen Profilen)
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO `user` (
|
||||
user_id, name, email, password, geburtsdatum,
|
||||
groesse, gewicht, geschlecht, neigung, beziehungsstatus, beschreibung,
|
||||
lockee_xp, keyholder_xp, bdsm_xp,
|
||||
sichtbarkeit_grunddaten, sichtbarkeit_galerie, sichtbarkeit_freunde,
|
||||
sichtbarkeit_feed, sichtbarkeit_pinnwand, sichtbarkeit_xp, sichtbarkeit_lockhistorie
|
||||
) VALUES
|
||||
|
||||
-- 1. MaxMuster – dominant, Single
|
||||
('11111111-1111-1111-1111-000000000001',
|
||||
'MaxMuster', 'max@test.de',
|
||||
'11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a',
|
||||
'1990-05-15',
|
||||
182, 80, 'MAENNLICH', 'DOMINANT', 'SINGLE',
|
||||
'Erfahrener Keyholder, der auf striktes aber faires Spiel steht. Immer offen für neue Spielpartner.',
|
||||
120, 850, 300,
|
||||
'ALLE', 'ALLE', 'ALLE', 'ALLE', 'ALLE', 'ALLE', 'ALLE'),
|
||||
|
||||
-- 2. LisaLust – devot, Single
|
||||
('11111111-1111-1111-1111-000000000002',
|
||||
'LisaLust', 'lisa@test.de',
|
||||
'11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a',
|
||||
'1995-08-22',
|
||||
165, 58, 'WEIBLICH', 'DEVOT', 'SINGLE',
|
||||
'Neugierigie Lockee auf der Suche nach einem verlässlichen Keyholder. Mag lange Sperren und herausfordernde Aufgaben.',
|
||||
740, 0, 150,
|
||||
'ALLE', 'NUR_FREUNDE', 'ALLE', 'ALLE', 'ALLE', 'ALLE', 'NUR_FREUNDE'),
|
||||
|
||||
-- 3. SamSwitcher – Switcher, in Beziehung
|
||||
('11111111-1111-1111-1111-000000000003',
|
||||
'SamSwitcher', 'sam@test.de',
|
||||
'11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a',
|
||||
'1988-11-03',
|
||||
175, 70, 'DIVERS', 'SWITCHER', 'IN_EINER_BEZIEHUNG',
|
||||
'Mal oben, mal unten – kommt auf die Stimmung an. Spiele gerne mit meinem Partner zusammen.',
|
||||
430, 390, 600,
|
||||
'ALLE', 'ALLE', 'ALLE', 'NUR_FREUNDE', 'ALLE', 'NUR_FREUNDE', 'ALLE'),
|
||||
|
||||
-- 4. KajaKette – eher devot, Single
|
||||
('11111111-1111-1111-1111-000000000004',
|
||||
'KajaKette', 'kaja@test.de',
|
||||
'11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a',
|
||||
'1998-02-14',
|
||||
170, 62, 'WEIBLICH', 'EHER_DEVOT', 'SINGLE',
|
||||
'Chastity-Enthusiastin mit Fokus auf Community-Locks. Schreibe gerne auf Pinnwände!',
|
||||
920, 50, 80,
|
||||
'ALLE', 'ALLE', 'ALLE', 'ALLE', 'ALLE', 'ALLE', 'ALLE'),
|
||||
|
||||
-- 5. TomTop – eher dominant, verheiratet
|
||||
('11111111-1111-1111-1111-000000000005',
|
||||
'TomTop', 'tom@test.de',
|
||||
'11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a',
|
||||
'1985-07-30',
|
||||
178, 85, 'MAENNLICH', 'EHER_DOMINANT', 'VERHEIRATET',
|
||||
'Verheiratet, spielen als Paar. Biete Keyholder-Service für seriöse Anfragen.',
|
||||
200, 560, 410,
|
||||
'ALLE', 'NUR_FREUNDE', 'NUR_FREUNDE', 'NUR_FREUNDE', 'ALLE', 'ALLE', 'NUR_FREUNDE');
|
||||
|
||||
-- =============================================================
|
||||
-- NICHT AKTIVIERTE REGISTRIERUNG (für Registrierungs-Tests)
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO registration (
|
||||
registration_id, name, email, password, activated, activation_code, geburtsdatum
|
||||
) VALUES
|
||||
('99999999-9999-9999-9999-000000000001',
|
||||
'NeuerUser', 'neu@test.de',
|
||||
'11a1162b984f8cf531e07d9bde6e27f26d6e9c0a2c4c52a6c1f0e2e79cd4e4a',
|
||||
FALSE, '347821', '2000-01-01');
|
||||
|
||||
-- =============================================================
|
||||
-- FREUNDSCHAFTEN
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO friendship (friendship_id, sender_id, receiver_id, status, created_at) VALUES
|
||||
-- Max ↔ Lisa (akzeptiert)
|
||||
('22222222-2222-2222-2222-000000000001',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'ACCEPTED', '2025-11-01 10:00:00'),
|
||||
-- Max ↔ Sam (akzeptiert)
|
||||
('22222222-2222-2222-2222-000000000002',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'ACCEPTED', '2025-11-15 14:30:00'),
|
||||
-- Lisa ↔ Kaja (akzeptiert)
|
||||
('22222222-2222-2222-2222-000000000003',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'ACCEPTED', '2025-12-03 09:15:00'),
|
||||
-- Tom → Kaja (ausstehend)
|
||||
('22222222-2222-2222-2222-000000000004',
|
||||
'11111111-1111-1111-1111-000000000005',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'PENDING', '2026-01-10 18:45:00'),
|
||||
-- Sam ↔ Kaja (akzeptiert)
|
||||
('22222222-2222-2222-2222-000000000005',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'ACCEPTED', '2026-01-20 11:00:00');
|
||||
|
||||
-- =============================================================
|
||||
-- PINNWAND-EINTRÄGE
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO pinnwand_eintrag (eintrag_id, profil_user_id, author_id, text, created_at) VALUES
|
||||
-- Auf Lisas Pinnwand
|
||||
('33333333-3333-3333-3333-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'Hey Lisa! Schön, dich hier zu sehen. Viel Spaß beim Spielen 🔒',
|
||||
'2025-12-10 16:00:00'),
|
||||
('33333333-3333-3333-3333-000000000002',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'Wir sollten mal ein gemeinsames Lock starten! Meld dich 😊',
|
||||
'2026-01-05 12:30:00'),
|
||||
-- Auf Maxs Pinnwand
|
||||
('33333333-3333-3333-3333-000000000003',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'Danke für den tollen Keyholder-Service letzte Woche!',
|
||||
'2026-01-08 20:00:00'),
|
||||
-- Auf Kajas Pinnwand
|
||||
('33333333-3333-3333-3333-000000000004',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'Kaja, du bist die Community-Queen! Immer so aktiv hier.',
|
||||
'2026-02-14 09:00:00');
|
||||
|
||||
-- Pinnwand-Likes
|
||||
INSERT INTO pinnwand_like (like_id, eintrag_id, user_id, liked_at) VALUES
|
||||
('33333333-3333-3333-3333-000000000101',
|
||||
'33333333-3333-3333-3333-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'2025-12-10 16:05:00'),
|
||||
('33333333-3333-3333-3333-000000000102',
|
||||
'33333333-3333-3333-3333-000000000002',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'2026-01-05 13:00:00'),
|
||||
('33333333-3333-3333-3333-000000000103',
|
||||
'33333333-3333-3333-3333-000000000003',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'2026-01-09 10:00:00');
|
||||
|
||||
-- =============================================================
|
||||
-- KOMMENTARE
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO kommentar (kommentar_id, author_id, target_type, target_id, text, created_at) VALUES
|
||||
-- Kommentar auf Pinnwand-Eintrag
|
||||
('44444444-4444-4444-4444-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'PINNWAND',
|
||||
'33333333-3333-3333-3333-000000000001',
|
||||
'Danke Max! Ich freu mich auch 😊',
|
||||
'2025-12-10 17:00:00'),
|
||||
('44444444-4444-4444-4444-000000000002',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'PINNWAND',
|
||||
'33333333-3333-3333-3333-000000000001',
|
||||
'+1, willkommen in der Community!',
|
||||
'2025-12-10 18:30:00'),
|
||||
-- Reply auf Kommentar
|
||||
('44444444-4444-4444-4444-000000000003',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'KOMMENTAR',
|
||||
'44444444-4444-4444-4444-000000000001',
|
||||
'Na logo! Wir machen das 😄',
|
||||
'2025-12-10 17:15:00');
|
||||
|
||||
-- Kommentar-Likes
|
||||
INSERT INTO kommentar_like (like_id, kommentar_id, user_id, liked_at) VALUES
|
||||
('44444444-4444-4444-4444-000000000101',
|
||||
'44444444-4444-4444-4444-000000000001',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'2025-12-10 17:10:00'),
|
||||
('44444444-4444-4444-4444-000000000102',
|
||||
'44444444-4444-4444-4444-000000000002',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'2025-12-10 19:00:00');
|
||||
|
||||
-- =============================================================
|
||||
-- FEED-POSTS (Text + Umfrage)
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO feed_post (post_id, author_id, text, beitrag_typ, multi_choice, is_public, created_at) VALUES
|
||||
-- Öffentlicher Text-Post von Max
|
||||
('55555555-5555-5555-5555-000000000001',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'Wer hat Lust auf ein Cardlock-Turnier nächsten Monat? Community vs. Keyholder! 🃏',
|
||||
'TEXT', NULL, TRUE, '2026-02-01 10:00:00'),
|
||||
|
||||
-- Öffentlicher Text-Post von Lisa
|
||||
('55555555-5555-5555-5555-000000000002',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'48 Stunden geschafft! Das war mein bisher längstes Lock. Ich bin so stolz auf mich! 🔐✨',
|
||||
'TEXT', NULL, TRUE, '2026-02-05 14:30:00'),
|
||||
|
||||
-- Öffentliche Umfrage von Kaja (Single-Choice)
|
||||
('55555555-5555-5555-5555-000000000003',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'Was bevorzugt ihr: Cardlock oder Timelock?',
|
||||
'UMFRAGE', FALSE, TRUE, '2026-02-10 09:00:00'),
|
||||
|
||||
-- Öffentliche Umfrage von Sam (Multi-Choice)
|
||||
('55555555-5555-5555-5555-000000000004',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'Welche Features wollt ihr als nächstes sehen? (Mehrfachauswahl möglich)',
|
||||
'UMFRAGE', TRUE, TRUE, '2026-02-15 20:00:00'),
|
||||
|
||||
-- Nicht-öffentlicher Post von Tom
|
||||
('55555555-5555-5555-5555-000000000005',
|
||||
'11111111-1111-1111-1111-000000000005',
|
||||
'Spielen heute Abend mit meiner Frau eine Runde BDSM. Sie darf den Keyholder spielen!',
|
||||
'TEXT', NULL, FALSE, '2026-02-20 18:00:00');
|
||||
|
||||
-- Umfrage-Optionen
|
||||
INSERT INTO feed_post_option (option_id, post_id, text, reihenfolge) VALUES
|
||||
-- Kajas Umfrage
|
||||
('55555555-5555-5555-5555-000000000101', '55555555-5555-5555-5555-000000000003', 'Cardlock – ich liebe die Ungewissheit!', 0),
|
||||
('55555555-5555-5555-5555-000000000102', '55555555-5555-5555-5555-000000000003', 'Timelock – Struktur ist alles.', 1),
|
||||
('55555555-5555-5555-5555-000000000103', '55555555-5555-5555-5555-000000000003', 'Beides gleich gerne.', 2),
|
||||
-- Sams Umfrage
|
||||
('55555555-5555-5555-5555-000000000104', '55555555-5555-5555-5555-000000000004', 'Mobile App', 0),
|
||||
('55555555-5555-5555-5555-000000000105', '55555555-5555-5555-5555-000000000004', 'Mehr Aufgaben-Vorlagen', 1),
|
||||
('55555555-5555-5555-5555-000000000106', '55555555-5555-5555-5555-000000000004', 'Dark/Light Theme Toggle', 2),
|
||||
('55555555-5555-5555-5555-000000000107', '55555555-5555-5555-5555-000000000004', 'Push-Benachrichtigungen', 3);
|
||||
|
||||
-- Umfrage-Stimmen
|
||||
INSERT INTO feed_post_vote (stimme_id, option_id, post_id, user_id) VALUES
|
||||
-- Kajas Umfrage
|
||||
('55555555-5555-5555-5555-000000000201', '55555555-5555-5555-5555-000000000101', '55555555-5555-5555-5555-000000000003', '11111111-1111-1111-1111-000000000001'),
|
||||
('55555555-5555-5555-5555-000000000202', '55555555-5555-5555-5555-000000000101', '55555555-5555-5555-5555-000000000003', '11111111-1111-1111-1111-000000000002'),
|
||||
('55555555-5555-5555-5555-000000000203', '55555555-5555-5555-5555-000000000102', '55555555-5555-5555-5555-000000000003', '11111111-1111-1111-1111-000000000005'),
|
||||
('55555555-5555-5555-5555-000000000204', '55555555-5555-5555-5555-000000000103', '55555555-5555-5555-5555-000000000003', '11111111-1111-1111-1111-000000000003'),
|
||||
-- Sams Umfrage (Multi-Choice)
|
||||
('55555555-5555-5555-5555-000000000205', '55555555-5555-5555-5555-000000000104', '55555555-5555-5555-5555-000000000004', '11111111-1111-1111-1111-000000000001'),
|
||||
('55555555-5555-5555-5555-000000000206', '55555555-5555-5555-5555-000000000105', '55555555-5555-5555-5555-000000000004', '11111111-1111-1111-1111-000000000001'),
|
||||
('55555555-5555-5555-5555-000000000207', '55555555-5555-5555-5555-000000000104', '55555555-5555-5555-5555-000000000004', '11111111-1111-1111-1111-000000000002'),
|
||||
('55555555-5555-5555-5555-000000000208', '55555555-5555-5555-5555-000000000107', '55555555-5555-5555-5555-000000000004', '11111111-1111-1111-1111-000000000002'),
|
||||
('55555555-5555-5555-5555-000000000209', '55555555-5555-5555-5555-000000000105', '55555555-5555-5555-5555-000000000004', '11111111-1111-1111-1111-000000000004');
|
||||
|
||||
-- Feed-Likes
|
||||
INSERT INTO feed_post_like (like_id, post_id, user_id, liked_at) VALUES
|
||||
('55555555-5555-5555-5555-000000000301', '55555555-5555-5555-5555-000000000001', '11111111-1111-1111-1111-000000000002', '2026-02-01 10:30:00'),
|
||||
('55555555-5555-5555-5555-000000000302', '55555555-5555-5555-5555-000000000001', '11111111-1111-1111-1111-000000000003', '2026-02-01 11:00:00'),
|
||||
('55555555-5555-5555-5555-000000000303', '55555555-5555-5555-5555-000000000001', '11111111-1111-1111-1111-000000000004', '2026-02-01 11:15:00'),
|
||||
('55555555-5555-5555-5555-000000000304', '55555555-5555-5555-5555-000000000002', '11111111-1111-1111-1111-000000000001', '2026-02-05 15:00:00'),
|
||||
('55555555-5555-5555-5555-000000000305', '55555555-5555-5555-5555-000000000002', '11111111-1111-1111-1111-000000000004', '2026-02-05 15:30:00'),
|
||||
('55555555-5555-5555-5555-000000000306', '55555555-5555-5555-5555-000000000002', '11111111-1111-1111-1111-000000000003', '2026-02-05 16:00:00');
|
||||
|
||||
-- Kommentare unter Feed-Posts
|
||||
INSERT INTO kommentar (kommentar_id, author_id, target_type, target_id, text, created_at) VALUES
|
||||
('66666666-6666-6666-6666-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'FEED_POST',
|
||||
'55555555-5555-5555-5555-000000000001',
|
||||
'Bin dabei! Wann genau? 🙋♀️',
|
||||
'2026-02-01 11:00:00'),
|
||||
('66666666-6666-6666-6666-000000000002',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'FEED_POST',
|
||||
'55555555-5555-5555-5555-000000000001',
|
||||
'Klingt mega! Ich schlage vor: 1 Woche Mindestlaufzeit.',
|
||||
'2026-02-01 11:30:00'),
|
||||
('66666666-6666-6666-6666-000000000003',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'FEED_POST',
|
||||
'55555555-5555-5555-5555-000000000002',
|
||||
'Respekt! 48h ist eine echte Leistung 👏',
|
||||
'2026-02-05 15:00:00');
|
||||
|
||||
-- =============================================================
|
||||
-- GRUPPEN
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO gruppe (gruppe_id, name, beschreibung, bild, is_private, created_at, created_by_user_id) VALUES
|
||||
-- Öffentliche Gruppe
|
||||
('77777777-7777-7777-7777-000000000001',
|
||||
'Cardlock Community',
|
||||
'Die Gruppe für alle Cardlock-Fans! Hier tauschen wir Erfahrungen aus, veranstalten Turniere und helfen Neulingen beim Einstieg.',
|
||||
NULL, FALSE, '2025-10-01 12:00:00',
|
||||
'11111111-1111-1111-1111-000000000001'),
|
||||
|
||||
-- Private Gruppe
|
||||
('77777777-7777-7777-7777-000000000002',
|
||||
'Keyholder-Stammtisch',
|
||||
'Privater Austausch unter erfahrenen Keyholdern. Nur auf Einladung.',
|
||||
NULL, TRUE, '2025-11-15 18:00:00',
|
||||
'11111111-1111-1111-1111-000000000005'),
|
||||
|
||||
-- Öffentliche Gruppe
|
||||
('77777777-7777-7777-7777-000000000003',
|
||||
'Anfänger & Fragen',
|
||||
'Neuling? Frag einfach! Hier ist jede Frage willkommen. Keine Scheu.',
|
||||
NULL, FALSE, '2026-01-01 00:00:00',
|
||||
'11111111-1111-1111-1111-000000000004');
|
||||
|
||||
-- =============================================================
|
||||
-- GRUPPENMITGLIEDER
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO gruppe_mitglied (mitglied_id, gruppe_id, user_id, rolle, joined_at) VALUES
|
||||
-- Cardlock Community
|
||||
('77777777-7777-7777-7777-000000000101', '77777777-7777-7777-7777-000000000001', '11111111-1111-1111-1111-000000000001', 'ADMIN', '2025-10-01 12:00:00'),
|
||||
('77777777-7777-7777-7777-000000000102', '77777777-7777-7777-7777-000000000001', '11111111-1111-1111-1111-000000000002', 'MITGLIED', '2025-10-05 09:00:00'),
|
||||
('77777777-7777-7777-7777-000000000103', '77777777-7777-7777-7777-000000000001', '11111111-1111-1111-1111-000000000003', 'MITGLIED', '2025-10-10 14:00:00'),
|
||||
('77777777-7777-7777-7777-000000000104', '77777777-7777-7777-7777-000000000001', '11111111-1111-1111-1111-000000000004', 'MITGLIED', '2025-10-20 11:00:00'),
|
||||
-- Keyholder-Stammtisch
|
||||
('77777777-7777-7777-7777-000000000105', '77777777-7777-7777-7777-000000000002', '11111111-1111-1111-1111-000000000005', 'ADMIN', '2025-11-15 18:00:00'),
|
||||
('77777777-7777-7777-7777-000000000106', '77777777-7777-7777-7777-000000000002', '11111111-1111-1111-1111-000000000001', 'MITGLIED', '2025-11-20 10:00:00'),
|
||||
-- Anfänger & Fragen
|
||||
('77777777-7777-7777-7777-000000000107', '77777777-7777-7777-7777-000000000003', '11111111-1111-1111-1111-000000000004', 'ADMIN', '2026-01-01 00:00:00'),
|
||||
('77777777-7777-7777-7777-000000000108', '77777777-7777-7777-7777-000000000003', '11111111-1111-1111-1111-000000000002', 'MITGLIED', '2026-01-03 08:00:00'),
|
||||
('77777777-7777-7777-7777-000000000109', '77777777-7777-7777-7777-000000000003', '11111111-1111-1111-1111-000000000003', 'MITGLIED', '2026-01-05 12:00:00');
|
||||
|
||||
-- Ausstehende Beitrittsanfrage zur privaten Gruppe
|
||||
INSERT INTO beitrittsanfrage (anfrage_id, gruppe_id, user_id, nachricht, angefragt_at, status) VALUES
|
||||
('77777777-7777-7777-7777-000000000201',
|
||||
'77777777-7777-7777-7777-000000000002',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'Hallo! Ich bin seit 2 Jahren aktiver Keyholder und würde gerne dazugehören.',
|
||||
'2026-02-01 15:00:00', 'AUSSTEHEND'),
|
||||
('77777777-7777-7777-7777-000000000202',
|
||||
'77777777-7777-7777-7777-000000000002',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'Bitte nehmt mich auf! Habe schon ein paar Monate Erfahrung als Keyholderin.',
|
||||
'2026-02-10 09:00:00', 'ABGELEHNT');
|
||||
|
||||
-- =============================================================
|
||||
-- GRUPPEN-BEITRÄGE (Text + Umfrage)
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO gruppe_beitrag (beitrag_id, gruppe_id, author_id, beitrag_typ, text, multi_choice, bild, created_at) VALUES
|
||||
-- Cardlock Community
|
||||
('88888888-8888-8888-8888-000000000001',
|
||||
'77777777-7777-7777-7777-000000000001',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'TEXT',
|
||||
'Willkommen in der Cardlock Community! Stellt euch kurz vor und erzählt, wie ihr zum Cardlock gekommen seid.',
|
||||
NULL, NULL, '2025-10-01 12:05:00'),
|
||||
|
||||
('88888888-8888-8888-8888-000000000002',
|
||||
'77777777-7777-7777-7777-000000000001',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'TEXT',
|
||||
'Ich bin Lisa und liebe Cardlocks seit über einem Jahr! Mein Rekord sind 5 Tage – habt ihr Tipps für längere Sperren?',
|
||||
NULL, NULL, '2025-10-05 10:00:00'),
|
||||
|
||||
('88888888-8888-8888-8888-000000000003',
|
||||
'77777777-7777-7777-7777-000000000001',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'UMFRAGE',
|
||||
'Wie viele Karten startet ihr typischerweise mit?',
|
||||
FALSE, NULL, '2025-10-20 14:00:00'),
|
||||
|
||||
-- Anfänger & Fragen
|
||||
('88888888-8888-8888-8888-000000000004',
|
||||
'77777777-7777-7777-7777-000000000003',
|
||||
'11111111-1111-1111-1111-000000000002',
|
||||
'TEXT',
|
||||
'Frage: Wie erkläre ich Cardlocks am besten meinem Partner, der noch nie davon gehört hat?',
|
||||
NULL, NULL, '2026-01-10 19:00:00'),
|
||||
|
||||
('88888888-8888-8888-8888-000000000005',
|
||||
'77777777-7777-7777-7777-000000000003',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'TEXT',
|
||||
'Gute Frage! Ich würde empfehlen, erst mit einem kurzen Timelock anzufangen. So kann der Partner das Grundkonzept verstehen, ohne direkt mit der Karten-Mechanik überfordert zu werden.',
|
||||
NULL, NULL, '2026-01-10 19:30:00');
|
||||
|
||||
-- Umfrage-Optionen für Gruppen-Beitrag
|
||||
INSERT INTO umfrage_option (option_id, beitrag_id, text, reihenfolge) VALUES
|
||||
('88888888-8888-8888-8888-000000000101', '88888888-8888-8888-8888-000000000003', 'Unter 20 Karten', 0),
|
||||
('88888888-8888-8888-8888-000000000102', '88888888-8888-8888-8888-000000000003', '20–40 Karten', 1),
|
||||
('88888888-8888-8888-8888-000000000103', '88888888-8888-8888-8888-000000000003', '40–60 Karten', 2),
|
||||
('88888888-8888-8888-8888-000000000104', '88888888-8888-8888-8888-000000000003', 'Über 60 Karten', 3);
|
||||
|
||||
-- Umfrage-Stimmen (Gruppen)
|
||||
INSERT INTO umfrage_stimme (stimme_id, option_id, beitrag_id, user_id) VALUES
|
||||
('88888888-8888-8888-8888-000000000201', '88888888-8888-8888-8888-000000000101', '88888888-8888-8888-8888-000000000003', '11111111-1111-1111-1111-000000000002'),
|
||||
('88888888-8888-8888-8888-000000000202', '88888888-8888-8888-8888-000000000102', '88888888-8888-8888-8888-000000000003', '11111111-1111-1111-1111-000000000001'),
|
||||
('88888888-8888-8888-8888-000000000203', '88888888-8888-8888-8888-000000000102', '88888888-8888-8888-8888-000000000003', '11111111-1111-1111-1111-000000000003'),
|
||||
('88888888-8888-8888-8888-000000000204', '88888888-8888-8888-8888-000000000103', '88888888-8888-8888-8888-000000000003', '11111111-1111-1111-1111-000000000004');
|
||||
|
||||
-- Gruppen-Beitrag-Likes
|
||||
INSERT INTO gruppe_beitrag_like (like_id, beitrag_id, user_id, liked_at) VALUES
|
||||
('88888888-8888-8888-8888-000000000301', '88888888-8888-8888-8888-000000000001', '11111111-1111-1111-1111-000000000002', '2025-10-01 12:10:00'),
|
||||
('88888888-8888-8888-8888-000000000302', '88888888-8888-8888-8888-000000000001', '11111111-1111-1111-1111-000000000003', '2025-10-01 13:00:00'),
|
||||
('88888888-8888-8888-8888-000000000303', '88888888-8888-8888-8888-000000000001', '11111111-1111-1111-1111-000000000004', '2025-10-01 14:00:00'),
|
||||
('88888888-8888-8888-8888-000000000304', '88888888-8888-8888-8888-000000000002', '11111111-1111-1111-1111-000000000001', '2025-10-05 10:30:00'),
|
||||
('88888888-8888-8888-8888-000000000305', '88888888-8888-8888-8888-000000000002', '11111111-1111-1111-1111-000000000004', '2025-10-05 11:00:00'),
|
||||
('88888888-8888-8888-8888-000000000306', '88888888-8888-8888-8888-000000000005', '11111111-1111-1111-1111-000000000002', '2026-01-10 19:45:00'),
|
||||
('88888888-8888-8888-8888-000000000307', '88888888-8888-8888-8888-000000000005', '11111111-1111-1111-1111-000000000004', '2026-01-10 20:00:00');
|
||||
|
||||
-- Kommentare auf Gruppen-Beiträge
|
||||
INSERT INTO kommentar (kommentar_id, author_id, target_type, target_id, text, created_at) VALUES
|
||||
('99999999-0000-0000-0000-000000000001',
|
||||
'11111111-1111-1111-1111-000000000003',
|
||||
'GROUP_POST',
|
||||
'88888888-8888-8888-8888-000000000002',
|
||||
'Hi Lisa! Mein Tipp: Fang mit mehr Green Cards an als du denkst. Du wirst es brauchen 😄',
|
||||
'2025-10-05 11:00:00'),
|
||||
('99999999-0000-0000-0000-000000000002',
|
||||
'11111111-1111-1111-1111-000000000001',
|
||||
'GROUP_POST',
|
||||
'88888888-8888-8888-8888-000000000002',
|
||||
'Mentale Vorbereitung ist alles. Schreib dir vorher auf, warum du es tust.',
|
||||
'2025-10-05 12:00:00'),
|
||||
('99999999-0000-0000-0000-000000000003',
|
||||
'11111111-1111-1111-1111-000000000004',
|
||||
'GROUP_POST',
|
||||
'88888888-8888-8888-8888-000000000004',
|
||||
'Ich würde sagen: zeig ihm/ihr einfach die App! Das visuelle Konzept erklärt sich fast von selbst.',
|
||||
'2026-01-10 19:15:00');
|
||||
|
||||
-- =============================================================
|
||||
-- CHASTITY LOCK (ein aktives Cardlock: Lisa gesperrt von Max)
|
||||
-- =============================================================
|
||||
|
||||
INSERT INTO current_lock (
|
||||
lock_id, lock_type, name, lockee, keyholder,
|
||||
test_lock, requires_verification,
|
||||
unlock_code_length, unlock_code,
|
||||
start_time, unlock_time,
|
||||
hygine_opening_duration_minutes, hygine_opening_everyminites,
|
||||
task_mode,
|
||||
keyholder_requested_unlock, emergency_auto_unlocked,
|
||||
-- CARDLOCK-spezifisch
|
||||
initial_cards, pick_every_minute, accumulate_picks,
|
||||
show_remaining_cards, open_picks,
|
||||
available_cards
|
||||
) VALUES (
|
||||
'aaaaaaaa-aaaa-aaaa-aaaa-000000000001',
|
||||
'CARDLOCK',
|
||||
'Lisas Frühlings-Lock',
|
||||
'11111111-1111-1111-1111-000000000002', -- lockee: Lisa
|
||||
'11111111-1111-1111-1111-000000000001', -- keyholder: Max
|
||||
FALSE, FALSE,
|
||||
6, NULL,
|
||||
'2026-03-20 10:00:00', NULL,
|
||||
30, 1440, -- Hygiene alle 24h, 30 Min offen
|
||||
'KEYHOLDER',
|
||||
FALSE, FALSE,
|
||||
-- 30 Karten: 5×GREEN, 15×RED, 5×YELLOW, 3×TASK, 2×FREEZE
|
||||
'["GREEN","GREEN","GREEN","GREEN","GREEN","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","YELLOW","YELLOW","YELLOW","YELLOW","YELLOW","TASK","TASK","TASK","FREEZE","FREEZE"]',
|
||||
240, FALSE, -- Karte alle 4h ziehen, kein Akkumulieren
|
||||
TRUE, 0,
|
||||
'["GREEN","GREEN","GREEN","GREEN","GREEN","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","RED","YELLOW","YELLOW","YELLOW","YELLOW","YELLOW","TASK","TASK","TASK","FREEZE","FREEZE"]'
|
||||
);
|
||||
|
||||
-- =============================================================
|
||||
-- FERTIG
|
||||
-- =============================================================
|
||||
-- Überblick:
|
||||
-- 5 User (max@test.de, lisa@test.de, sam@test.de, kaja@test.de, tom@test.de)
|
||||
-- 1 nicht aktivierte Registrierung (neu@test.de, Code: 347821)
|
||||
-- 5 Freundschaften (4 akzeptiert, 1 ausstehend)
|
||||
-- 4 Pinnwand-Einträge + 3 Likes
|
||||
-- 3 Kommentare auf Pinnwand + 3 auf Feed + 3 auf Gruppen-Beiträge
|
||||
-- 5 Feed-Posts (3 Text, 2 Umfragen) + 6 Likes
|
||||
-- 3 Gruppen (2 öffentlich, 1 privat) mit je 4-6 Mitgliedern
|
||||
-- 5 Gruppen-Beiträge (4 Text, 1 Umfrage) + 7 Likes
|
||||
-- 1 aktives Cardlock (Lisa ← Max)
|
||||
-- =============================================================
|
||||
BIN
testdaten/aufgabengruppen-export.zip
Normal file
BIN
testdaten/toys-export.zip
Normal file
270
xxxthegame/src/main/java/de/oaa/xxx/admin/AdminController.java
Normal file
@@ -0,0 +1,270 @@
|
||||
package de.oaa.xxx.admin;
|
||||
|
||||
import de.oaa.xxx.aufgaben.AufgabenGruppe;
|
||||
import de.oaa.xxx.aufgaben.Toy;
|
||||
import de.oaa.xxx.aufgaben.entity.AufgabenGruppeEntity;
|
||||
import de.oaa.xxx.aufgaben.entity.ToyEntity;
|
||||
import de.oaa.xxx.aufgaben.repository.AufgabenGruppeRepository;
|
||||
import de.oaa.xxx.aufgaben.repository.ToyRepository;
|
||||
import de.oaa.xxx.meldung.MeldungEntity;
|
||||
import de.oaa.xxx.meldung.MeldungRepository;
|
||||
import de.oaa.xxx.meldung.MeldungStatus;
|
||||
import de.oaa.xxx.user.UserEntity;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
@Transactional
|
||||
public class AdminController {
|
||||
|
||||
private final AdminRepository adminRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final MeldungRepository meldungRepository;
|
||||
private final AufgabenGruppeRepository aufgabenGruppeRepository;
|
||||
private final ToyRepository toyRepository;
|
||||
|
||||
public AdminController(AdminRepository adminRepository, UserRepository userRepository,
|
||||
MeldungRepository meldungRepository,
|
||||
AufgabenGruppeRepository aufgabenGruppeRepository,
|
||||
ToyRepository toyRepository) {
|
||||
this.adminRepository = adminRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.meldungRepository = meldungRepository;
|
||||
this.aufgabenGruppeRepository = aufgabenGruppeRepository;
|
||||
this.toyRepository = toyRepository;
|
||||
}
|
||||
|
||||
// ── DTOs ─────────────────────────────────────────────────────────────────
|
||||
|
||||
record AdminDto(UUID adminId, UUID userId, String userName, AdminRolle rolle, LocalDateTime createdAt) {}
|
||||
|
||||
record MeldungDto(UUID meldungId, UUID melderId, String melderName,
|
||||
de.oaa.xxx.meldung.MeldungZielTyp zielTyp, UUID zielId,
|
||||
String grund, LocalDateTime gemeldetAt,
|
||||
MeldungStatus status, UUID bearbeitetVon, LocalDateTime bearbeitetAt) {}
|
||||
|
||||
record CreateAdminRequest(UUID userId, AdminRolle rolle) {}
|
||||
|
||||
record StatusRequest(MeldungStatus status) {}
|
||||
|
||||
// ── Hilfsmethoden ────────────────────────────────────────────────────────
|
||||
|
||||
private AdminEntity requireAdmin(Principal principal) {
|
||||
var user = userRepository.findByEmail(principal.getName()).orElseThrow();
|
||||
return adminRepository.findByUserId(user.getUserId())
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.FORBIDDEN, "Kein Admin"));
|
||||
}
|
||||
|
||||
private AdminEntity requireSuperAdmin(Principal principal) {
|
||||
AdminEntity admin = requireAdmin(principal);
|
||||
if (admin.getRolle() != AdminRolle.SUPERADMIN) {
|
||||
throw new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.FORBIDDEN, "Kein Superadmin");
|
||||
}
|
||||
return admin;
|
||||
}
|
||||
|
||||
private AdminDto toDto(AdminEntity e) {
|
||||
String name = userRepository.findById(e.getUserId()).map(UserEntity::getName).orElse("?");
|
||||
return new AdminDto(e.getAdminId(), e.getUserId(), name, e.getRolle(), e.getCreatedAt());
|
||||
}
|
||||
|
||||
private MeldungDto toMeldungDto(MeldungEntity e) {
|
||||
String melderName = userRepository.findById(e.getMelderId()).map(UserEntity::getName).orElse("?");
|
||||
return new MeldungDto(e.getMeldungId(), e.getMelderId(), melderName,
|
||||
e.getZielTyp(), e.getZielId(), e.getGrund(), e.getGemeldetAt(),
|
||||
e.getStatus(), e.getBearbeitetVon(), e.getBearbeitetAt());
|
||||
}
|
||||
|
||||
// ── /admin/me ────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<AdminDto> me(Principal principal) {
|
||||
var user = userRepository.findByEmail(principal.getName()).orElse(null);
|
||||
if (user == null) return ResponseEntity.status(403).build();
|
||||
return adminRepository.findByUserId(user.getUserId())
|
||||
.map(a -> ResponseEntity.ok(toDto(a)))
|
||||
.orElse(ResponseEntity.status(403).build());
|
||||
}
|
||||
|
||||
// ── Meldungen ────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/meldungen")
|
||||
public ResponseEntity<List<MeldungDto>> getMeldungen(
|
||||
@RequestParam(name = "status", required = false) MeldungStatus status,
|
||||
Principal principal) {
|
||||
requireAdmin(principal);
|
||||
List<MeldungEntity> list = status != null
|
||||
? meldungRepository.findByStatusOrderByGemeldetAtDesc(status)
|
||||
: meldungRepository.findAllByOrderByGemeldetAtDesc();
|
||||
return ResponseEntity.ok(list.stream().map(this::toMeldungDto).toList());
|
||||
}
|
||||
|
||||
@PutMapping("/meldungen/{id}")
|
||||
public ResponseEntity<Void> updateMeldung(@PathVariable("id") UUID id,
|
||||
@RequestBody StatusRequest body,
|
||||
Principal principal) {
|
||||
var admin = requireAdmin(principal);
|
||||
var user = userRepository.findByEmail(principal.getName()).orElseThrow();
|
||||
MeldungEntity meldung = meldungRepository.findById(id)
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.NOT_FOUND));
|
||||
meldung.setStatus(body.status());
|
||||
meldung.setBearbeitetVon(user.getUserId());
|
||||
meldung.setBearbeitetAt(LocalDateTime.now());
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── Aufgabengruppen ──────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/aufgabengruppen")
|
||||
public ResponseEntity<List<de.oaa.xxx.aufgaben.AufgabenGruppe>> getAufgabengruppen(Principal principal) {
|
||||
requireAdmin(principal);
|
||||
List<AufgabenGruppeEntity> list = aufgabenGruppeRepository
|
||||
.findByUserIdIsNull(PageRequest.of(0, 1000)).getContent();
|
||||
return ResponseEntity.ok(list.stream().map(AufgabenGruppeEntity::toAufgabenGruppe).toList());
|
||||
}
|
||||
|
||||
@PostMapping("/aufgabengruppen")
|
||||
public ResponseEntity<de.oaa.xxx.aufgaben.AufgabenGruppeDisplay> createAufgabengruppe(
|
||||
@RequestBody AufgabenGruppe gruppe, Principal principal) {
|
||||
requireAdmin(principal);
|
||||
gruppe.setUserId(null);
|
||||
gruppe.setPrivateGruppe(false);
|
||||
AufgabenGruppeEntity entity = AufgabenGruppeEntity.create(gruppe);
|
||||
aufgabenGruppeRepository.save(entity);
|
||||
return ResponseEntity.status(201).body(entity.toAufgabenGruppeDisplay());
|
||||
}
|
||||
|
||||
@PutMapping("/aufgabengruppen/{id}")
|
||||
public ResponseEntity<Void> updateAufgabengruppe(@PathVariable("id") UUID id,
|
||||
@RequestBody AufgabenGruppe gruppe,
|
||||
Principal principal) {
|
||||
requireAdmin(principal);
|
||||
AufgabenGruppeEntity entity = aufgabenGruppeRepository.findById(id)
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.NOT_FOUND));
|
||||
entity.setName(gruppe.getName());
|
||||
entity.setBeschreibung(gruppe.getBeschreibung());
|
||||
entity.setVon(gruppe.getVon());
|
||||
if (gruppe.getBild() != null) {
|
||||
entity.setBild(java.util.Base64.getDecoder().decode(gruppe.getBild()));
|
||||
}
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@DeleteMapping("/aufgabengruppen/{id}")
|
||||
public ResponseEntity<Void> deleteAufgabengruppe(@PathVariable("id") UUID id, Principal principal) {
|
||||
requireAdmin(principal);
|
||||
AufgabenGruppeEntity entity = aufgabenGruppeRepository.findById(id)
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.NOT_FOUND));
|
||||
if (entity.getUserId() != null) {
|
||||
return ResponseEntity.status(403).build(); // Nur System-Gruppen
|
||||
}
|
||||
aufgabenGruppeRepository.delete(entity);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── Toys ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/toys")
|
||||
public ResponseEntity<List<Toy>> getToys(Principal principal) {
|
||||
requireAdmin(principal);
|
||||
List<ToyEntity> list = toyRepository.findByUserIdIsNull(PageRequest.of(0, 1000, Sort.by(Sort.Direction.ASC, "name"))).getContent();
|
||||
return ResponseEntity.ok(list.stream().map(ToyEntity::toToy).toList());
|
||||
}
|
||||
|
||||
@PostMapping("/toys")
|
||||
public ResponseEntity<Toy> createToy(@RequestBody Toy toy, Principal principal) {
|
||||
requireAdmin(principal);
|
||||
if (toyRepository.existsByNameIgnoreCaseAndUserIdIsNull(toy.getName())) {
|
||||
return ResponseEntity.status(409).build();
|
||||
}
|
||||
toy.setUserId(null);
|
||||
ToyEntity entity = ToyEntity.create(toy);
|
||||
toyRepository.save(entity);
|
||||
return ResponseEntity.status(201).body(entity.toToy());
|
||||
}
|
||||
|
||||
@PutMapping("/toys/{id}")
|
||||
public ResponseEntity<Void> updateToy(@PathVariable("id") UUID id,
|
||||
@RequestBody Toy toy, Principal principal) {
|
||||
requireAdmin(principal);
|
||||
ToyEntity entity = toyRepository.findById(id)
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.NOT_FOUND));
|
||||
if (toyRepository.existsByNameIgnoreCaseAndUserIdIsNullAndToyIdNot(toy.getName(), id)) {
|
||||
return ResponseEntity.status(409).build();
|
||||
}
|
||||
entity.setName(toy.getName());
|
||||
entity.setBeschreibung(toy.getBeschreibung());
|
||||
if (toy.getBild() != null) {
|
||||
entity.setBild(java.util.Base64.getDecoder().decode(toy.getBild()));
|
||||
}
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@DeleteMapping("/toys/{id}")
|
||||
public ResponseEntity<Void> deleteToy(@PathVariable("id") UUID id, Principal principal) {
|
||||
requireAdmin(principal);
|
||||
ToyEntity entity = toyRepository.findById(id)
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.NOT_FOUND));
|
||||
long usage = toyRepository.countAufgabeUsage(id)
|
||||
+ toyRepository.countStrafeUsage(id)
|
||||
+ toyRepository.countSperreUsage(id);
|
||||
if (usage > 0) {
|
||||
return ResponseEntity.status(409).build();
|
||||
}
|
||||
toyRepository.delete(entity);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ── Admin-Verwaltung (nur SUPERADMIN) ────────────────────────────────────
|
||||
|
||||
@GetMapping("/admins")
|
||||
public ResponseEntity<List<AdminDto>> getAdmins(Principal principal) {
|
||||
requireSuperAdmin(principal);
|
||||
return ResponseEntity.ok(adminRepository.findAll().stream().map(this::toDto).toList());
|
||||
}
|
||||
|
||||
@PostMapping("/admins")
|
||||
public ResponseEntity<AdminDto> createAdmin(@RequestBody CreateAdminRequest request, Principal principal) {
|
||||
requireSuperAdmin(principal);
|
||||
if (!userRepository.existsById(request.userId())) {
|
||||
return ResponseEntity.status(404).build();
|
||||
}
|
||||
if (adminRepository.existsByUserId(request.userId())) {
|
||||
return ResponseEntity.status(409).build();
|
||||
}
|
||||
AdminEntity entity = AdminEntity.create(request.userId(), request.rolle());
|
||||
adminRepository.save(entity);
|
||||
return ResponseEntity.status(201).body(toDto(entity));
|
||||
}
|
||||
|
||||
@DeleteMapping("/admins/{id}")
|
||||
public ResponseEntity<Void> deleteAdmin(@PathVariable("id") UUID id, Principal principal) {
|
||||
var requestingUser = userRepository.findByEmail(principal.getName()).orElseThrow();
|
||||
requireSuperAdmin(principal);
|
||||
AdminEntity entity = adminRepository.findById(id)
|
||||
.orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
|
||||
org.springframework.http.HttpStatus.NOT_FOUND));
|
||||
if (entity.getUserId().equals(requestingUser.getUserId())) {
|
||||
return ResponseEntity.status(400).build(); // Selbstlöschung verhindern
|
||||
}
|
||||
adminRepository.delete(entity);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
38
xxxthegame/src/main/java/de/oaa/xxx/admin/AdminEntity.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package de.oaa.xxx.admin;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "admin")
|
||||
public class AdminEntity {
|
||||
|
||||
@Id
|
||||
@Column
|
||||
private UUID adminId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private UUID userId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(length = 20, nullable = false)
|
||||
private AdminRolle rolle;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
public static AdminEntity create(UUID userId, AdminRolle rolle) {
|
||||
AdminEntity entity = new AdminEntity();
|
||||
entity.setAdminId(UUID.randomUUID());
|
||||
entity.setUserId(userId);
|
||||
entity.setRolle(rolle);
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.oaa.xxx.admin;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AdminRepository extends JpaRepository<AdminEntity, UUID> {
|
||||
|
||||
Optional<AdminEntity> findByUserId(UUID userId);
|
||||
|
||||
boolean existsByUserId(UUID userId);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package de.oaa.xxx.admin;
|
||||
|
||||
public enum AdminRolle {
|
||||
ADMIN, SUPERADMIN
|
||||
}
|
||||
@@ -61,6 +61,7 @@ public class SecurityConfig {
|
||||
.requestMatchers("/gruppen.html").authenticated()
|
||||
.requestMatchers("/gruppe.html").authenticated()
|
||||
.requestMatchers("/feed.html").authenticated()
|
||||
.requestMatchers("/admin.html").authenticated()
|
||||
.requestMatchers("/communityvotes.html").authenticated()
|
||||
.requestMatchers("/keyholder.html").authenticated()
|
||||
.requestMatchers("/meine-locks.html").authenticated()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.oaa.xxx.meldung;
|
||||
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/meldung")
|
||||
public class MeldungController {
|
||||
|
||||
private final MeldungRepository meldungRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public MeldungController(MeldungRepository meldungRepository, UserRepository userRepository) {
|
||||
this.meldungRepository = meldungRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
record MeldungRequest(MeldungZielTyp zielTyp, UUID zielId, String grund) {}
|
||||
|
||||
@PostMapping
|
||||
@Transactional
|
||||
public ResponseEntity<Void> melden(@RequestBody MeldungRequest request, Principal principal) {
|
||||
var user = userRepository.findByEmail(principal.getName()).orElseThrow();
|
||||
if (meldungRepository.existsByMelderIdAndZielTypAndZielId(user.getUserId(), request.zielTyp(), request.zielId())) {
|
||||
return ResponseEntity.status(409).build();
|
||||
}
|
||||
meldungRepository.save(MeldungEntity.create(user.getUserId(), request.zielTyp(), request.zielId(), request.grund()));
|
||||
return ResponseEntity.status(201).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package de.oaa.xxx.meldung;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "meldung", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = {"melder_id", "ziel_typ", "ziel_id"})
|
||||
})
|
||||
public class MeldungEntity {
|
||||
|
||||
@Id
|
||||
@Column
|
||||
private UUID meldungId;
|
||||
|
||||
@Column(name = "melder_id", nullable = false)
|
||||
private UUID melderId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "ziel_typ", length = 10, nullable = false)
|
||||
private MeldungZielTyp zielTyp;
|
||||
|
||||
@Column(name = "ziel_id", nullable = false)
|
||||
private UUID zielId;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String grund;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime gemeldetAt;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(length = 20, nullable = false)
|
||||
private MeldungStatus status;
|
||||
|
||||
@Column(name = "bearbeitet_von")
|
||||
private UUID bearbeitetVon;
|
||||
|
||||
@Column(name = "bearbeitet_at")
|
||||
private LocalDateTime bearbeitetAt;
|
||||
|
||||
public static MeldungEntity create(UUID melderId, MeldungZielTyp zielTyp, UUID zielId, String grund) {
|
||||
MeldungEntity entity = new MeldungEntity();
|
||||
entity.setMeldungId(UUID.randomUUID());
|
||||
entity.setMelderId(melderId);
|
||||
entity.setZielTyp(zielTyp);
|
||||
entity.setZielId(zielId);
|
||||
entity.setGrund(grund);
|
||||
entity.setGemeldetAt(LocalDateTime.now());
|
||||
entity.setStatus(MeldungStatus.OFFEN);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package de.oaa.xxx.meldung;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface MeldungRepository extends JpaRepository<MeldungEntity, UUID> {
|
||||
|
||||
List<MeldungEntity> findAllByOrderByGemeldetAtDesc();
|
||||
|
||||
List<MeldungEntity> findByStatusOrderByGemeldetAtDesc(MeldungStatus status);
|
||||
|
||||
boolean existsByMelderIdAndZielTypAndZielId(UUID melderId, MeldungZielTyp zielTyp, UUID zielId);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package de.oaa.xxx.meldung;
|
||||
|
||||
public enum MeldungStatus {
|
||||
OFFEN, BEARBEITET, ABGELEHNT
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package de.oaa.xxx.meldung;
|
||||
|
||||
public enum MeldungZielTyp {
|
||||
POST, PROFIL
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class ActivationController {
|
||||
}
|
||||
|
||||
@GetMapping("/{uuid}")
|
||||
public ResponseEntity<Void> activate(@PathVariable String uuid) {
|
||||
public ResponseEntity<Void> activate(@PathVariable("uuid") String uuid) {
|
||||
try {
|
||||
String email = registrationService.activate(uuid);
|
||||
String redirect = "/login.html?email=" + java.net.URLEncoder.encode(email, java.nio.charset.StandardCharsets.UTF_8);
|
||||
|
||||
@@ -51,16 +51,24 @@ public class RegistrationController {
|
||||
LOGGER.warn("Registrierung abgelehnt – Mindestalter nicht erreicht");
|
||||
return ResponseEntity.status(422).build();
|
||||
}
|
||||
if (registrationRepository.findByEmail(registration.getEmail()).isPresent()
|
||||
|| userRepository.findByEmail(registration.getEmail()).isPresent()) {
|
||||
// Bereits aktivierte User blockieren
|
||||
if (userRepository.findByEmail(registration.getEmail()).isPresent()) {
|
||||
LOGGER.warn("User mit E-Mail {} bereits vorhanden", registration.getEmail());
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
if (registrationRepository.findByName(registration.getName()).isPresent()
|
||||
|| userRepository.findByName(registration.getName()).isPresent()) {
|
||||
if (userRepository.findByName(registration.getName()).isPresent()) {
|
||||
LOGGER.warn("User mit Name {} bereits vorhanden", registration.getName());
|
||||
return ResponseEntity.status(409).build();
|
||||
}
|
||||
// Noch nicht aktivierte Registrierungen mit gleicher E-Mail oder Name überschreiben
|
||||
registrationRepository.findByEmail(registration.getEmail()).ifPresent(old -> {
|
||||
LOGGER.info("Überschreibe nicht aktivierte Registrierung mit E-Mail {}", registration.getEmail());
|
||||
registrationRepository.delete(old);
|
||||
});
|
||||
registrationRepository.findByName(registration.getName()).ifPresent(old -> {
|
||||
LOGGER.info("Überschreibe nicht aktivierte Registrierung mit Name {}", registration.getName());
|
||||
registrationRepository.delete(old);
|
||||
});
|
||||
// Passwort serverseitig mit BCrypt hashen
|
||||
registration.setPassword(passwordEncoder.encode(registration.getPassword()));
|
||||
RegistrationEntity entity = RegistrationEntity.create(registration);
|
||||
@@ -72,7 +80,7 @@ public class RegistrationController {
|
||||
String uuid = entity.getRegistrationId().toString();
|
||||
String activationLink = baseUrl + "/activation/" + uuid;
|
||||
String activatePageUrl = baseUrl + "/activate.html";
|
||||
email.setText(mailTemplateService.buildActivationMail(registration.getName(), activationLink, activatePageUrl, uuid));
|
||||
email.setText(mailTemplateService.buildActivationMail(registration.getName(), activationLink, activatePageUrl, entity.getActivationCode()));
|
||||
|
||||
if (!mailService.send(email)) {
|
||||
registrationRepository.delete(entity);
|
||||
|
||||
@@ -7,6 +7,7 @@ import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -27,6 +28,8 @@ public class RegistrationEntity {
|
||||
private String password;
|
||||
@Column
|
||||
private Boolean activated;
|
||||
@Column(length = 6)
|
||||
private String activationCode;
|
||||
@Column
|
||||
private LocalDate geburtsdatum;
|
||||
|
||||
@@ -50,6 +53,7 @@ public class RegistrationEntity {
|
||||
entity.setRegistrationId(UUID.randomUUID());
|
||||
entity.setEmail(registration.getEmail());
|
||||
entity.setActivated(Boolean.FALSE);
|
||||
entity.setActivationCode(String.format("%06d", new SecureRandom().nextInt(1_000_000)));
|
||||
entity.setName(registration.getName());
|
||||
entity.setPassword(registration.getPassword());
|
||||
entity.setGeburtsdatum(registration.getGeburtsdatum());
|
||||
|
||||
@@ -9,4 +9,5 @@ public interface RegistrationRepository extends JpaRepository<RegistrationEntity
|
||||
|
||||
Optional<RegistrationEntity> findByEmail(String email);
|
||||
Optional<RegistrationEntity> findByName(String name);
|
||||
Optional<RegistrationEntity> findByActivationCode(String activationCode);
|
||||
}
|
||||
|
||||
@@ -32,17 +32,18 @@ public class RegistrationService {
|
||||
* @throws IllegalArgumentException wenn UUID ungültig oder Registration nicht gefunden
|
||||
* @throws IllegalStateException wenn Registration bereits aktiviert
|
||||
*/
|
||||
public String activate(String uuid) {
|
||||
UUID registrationId;
|
||||
public String activate(String token) {
|
||||
RegistrationEntity registration;
|
||||
try {
|
||||
registrationId = UUID.fromString(uuid);
|
||||
UUID registrationId = UUID.fromString(token);
|
||||
registration = registrationRepository.findById(registrationId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Registration nicht gefunden: " + token));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Ungültige UUID: " + uuid);
|
||||
// Kein UUID-Format → nach kurzem Aktivierungscode suchen
|
||||
registration = registrationRepository.findByActivationCode(token)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Aktivierungscode ungültig: " + token));
|
||||
}
|
||||
|
||||
RegistrationEntity registration = registrationRepository.findById(registrationId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Registration nicht gefunden: " + uuid));
|
||||
|
||||
if (Boolean.TRUE.equals(registration.getActivated())) {
|
||||
throw new IllegalStateException("Registration bereits aktiviert");
|
||||
}
|
||||
@@ -52,7 +53,7 @@ public class RegistrationService {
|
||||
registration.setActivated(Boolean.TRUE);
|
||||
registrationRepository.save(registration);
|
||||
|
||||
LOGGER.info("Registration {} aktiviert, User {} angelegt", uuid, registration.getEmail());
|
||||
LOGGER.info("Registration {} aktiviert, User {} angelegt", token, registration.getEmail());
|
||||
return registration.getEmail();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class SseService {
|
||||
}
|
||||
|
||||
public SseEmitter subscribe(UUID userId) {
|
||||
SseEmitter emitter = new SseEmitter(30_000L); // 30 s – Client reconnects automatically
|
||||
SseEmitter emitter = new SseEmitter(300_000L); // 5 min – Client reconnects automatically
|
||||
emitters.computeIfAbsent(userId, k -> new CopyOnWriteArrayList<>()).add(emitter);
|
||||
Runnable cleanup = () -> removeEmitter(userId, emitter);
|
||||
emitter.onCompletion(cleanup);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Datasource
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/xxxthegame?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/xxx_sphere?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
|
||||
spring.datasource.username=${DB_USER:xxx}
|
||||
spring.datasource.password=${DB_PASSWORD:xxxthegame$123!}
|
||||
spring.datasource.password=${DB_PASSWORD:xxx}
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
|
||||
# JPA / Hibernate
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/img/icon.png" type="image/png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>XXX The Game – Aktivierung</title>
|
||||
@@ -19,7 +19,7 @@
|
||||
</p>
|
||||
|
||||
<label for="uuid" style="margin-top:1.5rem;">Aktivierungscode</label>
|
||||
<input type="text" id="uuid" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" autocomplete="off" />
|
||||
<input type="text" id="uuid" placeholder="6-stelliger Code" autocomplete="off" inputmode="numeric" maxlength="6" />
|
||||
|
||||
<button class="full-width" id="activateBtn" onclick="activate()">Jetzt aktivieren</button>
|
||||
|
||||
|
||||
1642
xxxthegame/src/main/resources/static/admin.html
Normal file
@@ -464,6 +464,7 @@
|
||||
<script src="/js/icons.js"></script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
<script src="/js/social-sidebar.js"></script>
|
||||
<script src="/js/meldung.js"></script>
|
||||
<script>
|
||||
// ── State ──
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
@@ -629,6 +630,7 @@
|
||||
} else {
|
||||
html += `<button id="friendActionBtn" onclick="addFriend()">+ Freund hinzufügen</button>`;
|
||||
}
|
||||
html += ` <button onclick="openMeldungDialog('PROFIL','${profile.userId}')" style="background:none;border:1px solid var(--color-secondary);color:var(--color-muted);border-radius:6px;padding:0.4rem 0.8rem;cursor:pointer;font-size:0.85rem;">⚑ Melden</button>`;
|
||||
actions.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/img/icon.png" type="image/png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Feed – XXX The Game</title>
|
||||
@@ -163,9 +163,10 @@
|
||||
</div>
|
||||
|
||||
<script src="/js/shared.js"></script>
|
||||
<script src="/js/icons.js"></script>
|
||||
<script src="/js/icons.js"></script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
<script src="/js/social-sidebar.js"></script>
|
||||
<script src="/js/meldung.js"></script>
|
||||
<script>
|
||||
// ── State ──
|
||||
let myUserId = null;
|
||||
@@ -260,6 +261,9 @@
|
||||
const deleteBtn = canDelete
|
||||
? `<button class="post-action-btn post-delete" onclick="event.stopPropagation(); deletePost('${p.postId}')">🗑</button>`
|
||||
: '';
|
||||
const meldenBtn = p.authorId !== myUserId
|
||||
? `<button class="post-action-btn" onclick="event.stopPropagation(); openMeldungDialog('POST','${p.postId}')" title="Melden" style="color:var(--color-muted)">⚑</button>`
|
||||
: '';
|
||||
|
||||
const gruppeIdAttr = p.gruppeId ? ` data-gruppe-id="${p.gruppeId}"` : '';
|
||||
return `<div class="post-card" id="pc-${p.postId}"${gruppeIdAttr} onclick="openLb('${p.postId}','${p.postType}')" style="cursor:pointer;">
|
||||
@@ -281,6 +285,7 @@
|
||||
<button class="post-action-btn" onclick="event.stopPropagation(); openLb('${p.postId}','${p.postType}')">
|
||||
💬 <span id="kc-${p.postId}">${p.kommentarCount}</span>
|
||||
</button>
|
||||
${meldenBtn}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
87
xxxthegame/src/main/resources/static/js/meldung.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Wiederverwendbares Meldungs-Modul.
|
||||
* Bietet openMeldungDialog(zielTyp, zielId) und renderMeldenBtn(zielTyp, zielId).
|
||||
*/
|
||||
(function () {
|
||||
// Dialog einmalig in den DOM einfügen
|
||||
if (!document.getElementById('meldungDialog')) {
|
||||
document.body.insertAdjacentHTML('beforeend', `
|
||||
<div id="meldungDialog" style="
|
||||
display:none; position:fixed; inset:0; z-index:9999;
|
||||
background:rgba(0,0,0,0.6); align-items:center; justify-content:center;">
|
||||
<div style="background:var(--color-card);border:1px solid var(--color-secondary);
|
||||
border-radius:12px;padding:1.5rem;width:min(420px,90vw);position:relative;">
|
||||
<h3 style="margin:0 0 1rem 0;color:var(--color-primary)">Inhalt melden</h3>
|
||||
<p id="meldungDialogLabel" style="color:var(--color-muted);font-size:0.9rem;margin:0 0 0.75rem 0;"></p>
|
||||
<textarea id="meldungGrund" placeholder="Grund (optional)"
|
||||
style="width:100%;box-sizing:border-box;padding:0.5rem;border-radius:6px;
|
||||
border:1px solid var(--color-secondary);background:var(--color-card);
|
||||
color:var(--color-text);resize:vertical;min-height:80px;font-family:inherit;"></textarea>
|
||||
<div style="display:flex;gap:0.5rem;justify-content:flex-end;margin-top:1rem;">
|
||||
<button id="meldungAbbrechen" style="padding:0.45rem 1rem;border-radius:6px;
|
||||
border:1px solid var(--color-secondary);background:transparent;
|
||||
color:var(--color-text);cursor:pointer;">Abbrechen</button>
|
||||
<button id="meldungSenden" style="padding:0.45rem 1rem;border-radius:6px;
|
||||
border:none;background:var(--color-primary);color:#fff;cursor:pointer;font-weight:600;">
|
||||
Melden</button>
|
||||
</div>
|
||||
<p id="meldungMsg" style="margin:0.5rem 0 0 0;font-size:0.85rem;color:var(--color-primary);display:none;"></p>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
document.getElementById('meldungAbbrechen').addEventListener('click', () => closeMeldungDialog());
|
||||
document.getElementById('meldungDialog').addEventListener('click', function (e) {
|
||||
if (e.target === this) closeMeldungDialog();
|
||||
});
|
||||
}
|
||||
|
||||
let _zielTyp = null, _zielId = null;
|
||||
|
||||
window.openMeldungDialog = function (zielTyp, zielId) {
|
||||
_zielTyp = zielTyp;
|
||||
_zielId = zielId;
|
||||
document.getElementById('meldungGrund').value = '';
|
||||
document.getElementById('meldungMsg').style.display = 'none';
|
||||
document.getElementById('meldungDialogLabel').textContent =
|
||||
zielTyp === 'PROFIL' ? 'Profil melden' : 'Post melden';
|
||||
document.getElementById('meldungDialog').style.display = 'flex';
|
||||
|
||||
document.getElementById('meldungSenden').onclick = async function () {
|
||||
const grund = document.getElementById('meldungGrund').value.trim();
|
||||
const r = await fetch('/meldung', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ zielTyp: _zielTyp, zielId: _zielId, grund: grund || null })
|
||||
});
|
||||
const msg = document.getElementById('meldungMsg');
|
||||
msg.style.display = 'block';
|
||||
if (r.status === 201) {
|
||||
msg.style.color = 'var(--color-success, #2ecc71)';
|
||||
msg.textContent = 'Meldung wurde übermittelt.';
|
||||
setTimeout(closeMeldungDialog, 1500);
|
||||
} else if (r.status === 409) {
|
||||
msg.style.color = 'var(--color-primary)';
|
||||
msg.textContent = 'Du hast diesen Inhalt bereits gemeldet.';
|
||||
} else {
|
||||
msg.style.color = 'var(--color-primary)';
|
||||
msg.textContent = 'Fehler beim Senden.';
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
window.closeMeldungDialog = function () {
|
||||
document.getElementById('meldungDialog').style.display = 'none';
|
||||
};
|
||||
|
||||
/**
|
||||
* Erzeugt einen kleinen "Melden"-Button-HTML-String.
|
||||
* Verwendung: in innerHTML-Templates, wo onclick genutzt werden kann.
|
||||
*/
|
||||
window.renderMeldenBtn = function (zielTyp, zielId) {
|
||||
return `<button onclick="openMeldungDialog('${zielTyp}','${zielId}')"
|
||||
style="background:none;border:none;color:var(--color-muted,#888);
|
||||
font-size:0.8rem;cursor:pointer;padding:0.2rem 0.4rem;border-radius:4px;"
|
||||
title="Melden">⚑ Melden</button>`;
|
||||
};
|
||||
})();
|
||||
@@ -74,6 +74,9 @@
|
||||
</li>`;
|
||||
}).join('');
|
||||
|
||||
const adminCls = path === '/admin.html' ? ' class="active"' : '';
|
||||
const adminItem = `<li id="navAdminLink" style="display:none"><a href="/admin.html"${adminCls}><span class="icon">${I('ADMIN') || '⚙'}</span> Administration</a></li>`;
|
||||
|
||||
document.body.insertAdjacentHTML('afterbegin', `
|
||||
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
||||
<button class="burger" id="burgerBtn" aria-label="Menü öffnen">
|
||||
@@ -89,6 +92,8 @@
|
||||
${socialNav}
|
||||
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;"></li>
|
||||
${nav}
|
||||
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;" id="navAdminDivider" style="display:none"></li>
|
||||
${adminItem}
|
||||
</ul>
|
||||
</aside>
|
||||
`);
|
||||
@@ -155,6 +160,17 @@
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
// Admin-Link
|
||||
try {
|
||||
const adminRes = await fetch('/admin/me');
|
||||
if (adminRes.ok) {
|
||||
const navAdminLink = document.getElementById('navAdminLink');
|
||||
const navAdminDivider = document.getElementById('navAdminDivider');
|
||||
if (navAdminLink) navAdminLink.style.display = '';
|
||||
if (navAdminDivider) navAdminDivider.style.display = '';
|
||||
}
|
||||
} catch (_) {}
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
|
||||
@@ -86,9 +86,17 @@
|
||||
|
||||
es.onerror = () => {
|
||||
es.close();
|
||||
setTimeout(connectSse, 5000);
|
||||
// Vor dem Reconnect prüfen ob noch eingeloggt (verhindert Endlos-Schleife bei abgelaufener Session)
|
||||
setTimeout(() => {
|
||||
fetch('/login/me', { method: 'GET' })
|
||||
.then(r => { if (r.ok) connectSse(); })
|
||||
.catch(() => {});
|
||||
}, 5000);
|
||||
};
|
||||
}
|
||||
|
||||
connectSse();
|
||||
// SSE nur starten wenn authentifiziert – verhindert Fehler-Spam bei nicht eingeloggten Seiten
|
||||
fetch('/login/me', { method: 'GET' })
|
||||
.then(r => { if (r.ok) connectSse(); })
|
||||
.catch(() => {});
|
||||
})();
|
||||
|
||||