diff --git a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908.xml b/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908.xml
deleted file mode 100644
index 4fccad1..0000000
--- a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908.xml
+++ /dev/null
@@ -1,1833 +0,0 @@
-
-
-
-
- 3.51.1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
- 1
- 1
-
-
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- window
-
-
- window
-
-
- window
-
-
-
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- window
-
-
-
- 1
-
-
- window
-
-
- 1
-
-
- 1
- 1
-
-
-
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- window
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- window
-
-
- 1
- window
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- window
-
-
- 1
- window
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- window
-
-
- window
-
-
- window
-
-
-
- window
-
-
- window
-
-
- window
-
-
- window
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- aggregate
-
-
- 1
-
-
- 1
-
-
-
-
-
- 1
- 1
-
-
- window
-
-
- aggregate
-
-
- 1
- 1
-
-
- window
-
-
- 1
-
-
- aggregate
-
-
- window
-
-
- window
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
-
- 1
-
-
- 1
-
-
-
-
- window
-
-
- 1
-
-
- 1
-
-
-
-
-
- 1
-
-
- 1
-
-
- window
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
-
-
- 1
-
-
-
- aggregate
-
-
-
- 1
- 1
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- window
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- aggregate
-
-
- aggregate
-
-
- 1
-
-
- 1
- 2026-06-05.07:13:27
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
-
- 1
- TEXT|0s
-
-
- 2
- TEXT|0s
-
-
- 3
- TEXT|0s
-
-
- 4
- INT|0s
-
-
- 5
- TEXT|0s
-
-
-
\ No newline at end of file
diff --git a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908/storage_v2/_src_/schema/main.uQUzAA.meta b/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908/storage_v2/_src_/schema/main.uQUzAA.meta
deleted file mode 100644
index 8dab49c..0000000
--- a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908/storage_v2/_src_/schema/main.uQUzAA.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-#n:main
-! [0, 0, null, null, -2147483648, -2147483648]
diff --git a/.idea/dataSources/a0abcd0a-1d6f-40e4-88be-f442bcb431ba.xml b/.idea/dataSources/a0abcd0a-1d6f-40e4-88be-f442bcb431ba.xml
deleted file mode 100644
index 9fc8217..0000000
--- a/.idea/dataSources/a0abcd0a-1d6f-40e4-88be-f442bcb431ba.xml
+++ /dev/null
@@ -1,1833 +0,0 @@
-
-
-
-
- 3.51.1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
- 1
- 1
-
-
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- window
-
-
- window
-
-
- window
-
-
-
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- window
-
-
-
- 1
-
-
- window
-
-
- 1
-
-
- 1
- 1
-
-
-
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- window
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- window
-
-
- 1
- window
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- window
-
-
- 1
- window
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- 1
- 1
-
-
- window
-
-
- window
-
-
- window
-
-
-
- window
-
-
- window
-
-
- window
-
-
- window
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- aggregate
-
-
- 1
-
-
- 1
-
-
-
-
-
- 1
- 1
-
-
- window
-
-
- aggregate
-
-
- 1
- 1
-
-
- window
-
-
- 1
-
-
- aggregate
-
-
- window
-
-
- window
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
-
- 1
-
-
- 1
-
-
-
-
- window
-
-
- 1
-
-
- 1
-
-
-
-
-
- 1
-
-
- 1
-
-
- window
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
-
-
- 1
-
-
-
- aggregate
-
-
-
- 1
- 1
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- window
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- window
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
- 1
-
-
- 1
-
-
- 1
-
-
- aggregate
-
-
- aggregate
-
-
- 1
-
-
- 1
- 2026-06-05.07:12:20
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- 2
-
-
- 3
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- 2
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
- R
-
-
- 1
-
-
-
- 1
- TEXT|0s
-
-
- 2
- TEXT|0s
-
-
- 3
- TEXT|0s
-
-
- 4
- INT|0s
-
-
- 5
- TEXT|0s
-
-
-
\ No newline at end of file
diff --git a/.idea/dataSources/a0abcd0a-1d6f-40e4-88be-f442bcb431ba/storage_v2/_src_/schema/main.uQUzAA.meta b/.idea/dataSources/a0abcd0a-1d6f-40e4-88be-f442bcb431ba/storage_v2/_src_/schema/main.uQUzAA.meta
deleted file mode 100644
index 8dab49c..0000000
--- a/.idea/dataSources/a0abcd0a-1d6f-40e4-88be-f442bcb431ba/storage_v2/_src_/schema/main.uQUzAA.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-#n:main
-! [0, 0, null, null, -2147483648, -2147483648]
diff --git a/content/deleteAccount.php b/content/deleteAccount.php
deleted file mode 100644
index c9e0a12..0000000
--- a/content/deleteAccount.php
+++ /dev/null
@@ -1,19 +0,0 @@
-deleteUser($_SESSION["user_email"]);
-}
-
-$_SESSION = [];
-session_destroy();
-
-header("Location: index.php");
-exit();
\ No newline at end of file
diff --git a/index.php b/index.php
index cd4ea48..d02673d 100644
--- a/index.php
+++ b/index.php
@@ -17,12 +17,12 @@ if ($pfad === "register") {
}
if ($pfad === "logout") {
- include_once "content/logout.php";
+ include_once "content/logout-controller.php";
exit();
}
if ($pfad === "deleteAccount") {
- include_once "content/deleteAccount.php";
+ include_once "content/deleteAccount-controller.php";
exit();
}
?>
diff --git a/php/controller/createArticle-controller.php b/php/controller/createArticle-controller.php
index 5e72e68..a39a409 100644
--- a/php/controller/createArticle-controller.php
+++ b/php/controller/createArticle-controller.php
@@ -3,7 +3,6 @@ SESSION_START();
require_once '../model/LocalArticleManager.php';
require_once '../model/ArticleManager.php';
require_once '../validator/article-validator.php';
-require_once "../model/LocalUserManager.php";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$_SESSION["old_title"] = $_POST["title"] ?? '';
diff --git a/php/controller/deleteAccount-controller.php b/php/controller/deleteAccount-controller.php
new file mode 100644
index 0000000..8d42198
--- /dev/null
+++ b/php/controller/deleteAccount-controller.php
@@ -0,0 +1,30 @@
+deleteUser($_SESSION["user_email"]);
+ }
+
+ $_SESSION = [];
+ session_destroy();
+
+ header("Location: index.php");
+ exit();
+
+} catch (Exception $e) {
+
+ $_SESSION["message"] = "internal_error";
+
+ header("Location: index.php?pfad=profile");
+ exit();
+}
\ No newline at end of file
diff --git a/php/controller/login-controller.php b/php/controller/login-controller.php
index 8e2c2ec..28090cf 100644
--- a/php/controller/login-controller.php
+++ b/php/controller/login-controller.php
@@ -1,8 +1,7 @@
findUser($email);
+ $dao = UserManager::getInstance();
- if ($user && password_verify($password, $user["password"])) {
+ $email = $_POST["email"] ?? "";
+ $password = $_POST["password"] ?? "";
+
+ $user = $dao->findUser($email);
+
+ if ($user && password_verify($password, $user["password"])) {
- if (isset($user["vorname"]) && isset($user["nachname"])) {
$_SESSION["user"] = $user["vorname"] . " " . $user["nachname"];
+ $_SESSION["user_email"] = $user["email"];
+
+ header("Location: index.php");
+ exit();
+
} else {
- $_SESSION["user"] = $user["username"] ?? "";
+ $error = "Login fehlgeschlagen. Bitte überprüfe deine Eingaben.";
}
- $_SESSION["user_email"] = $user["email"];
-
- header("Location: index.php");
- exit();
-
- } else {
- $error = "Login fehlgeschlagen. Bitte überprüfe deine Eingaben.";
+ } catch (Exception $e) {
+ $error = "Es ist ein interner Fehler aufgetreten. Bitte versuche es erneut.";
}
}
\ No newline at end of file
diff --git a/content/logout.php b/php/controller/logout-controller.php
similarity index 100%
rename from content/logout.php
rename to php/controller/logout-controller.php
diff --git a/php/controller/profile-controller.php b/php/controller/profile-controller.php
index 720175d..e183b20 100644
--- a/php/controller/profile-controller.php
+++ b/php/controller/profile-controller.php
@@ -1,6 +1,6 @@
findUser($_SESSION["user_email"] ?? "");
@@ -38,15 +38,15 @@ try {
$_GET["edit"] = "1";
} elseif (!userNameValidator($vorname)) {
- $error = "Der Vorname muss 2 bis 50 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten.";
+ $error = "Der Vorname muss 2 bis 20 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten.";
$_GET["edit"] = "1";
} elseif (!userNameValidator($nachname)) {
- $error = "Der Nachname muss 2 bis 50 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten.";
+ $error = "Der Nachname muss 2 bis 20 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten.";
$_GET["edit"] = "1";
} elseif (!userOptionalPasswordValidator($password)) {
- $error = "Das Passwort muss 8 bis 72 Zeichen lang sein.";
+ $error = "Das Passwort muss 5 bis 12 Zeichen lang sein.";
$_GET["edit"] = "1";
} else {
diff --git a/php/controller/profileArticles-controller.php b/php/controller/profileArticles-controller.php
index 49a9ea1..9842500 100644
--- a/php/controller/profileArticles-controller.php
+++ b/php/controller/profileArticles-controller.php
@@ -5,10 +5,10 @@
require_once 'php/model/Article.php';
require_once 'php/model/ArticleManager.php';
-require_once "../model/LocalUserManager.php";
+require_once "php/model/UserManager.php";
try {
- $dao = new LocalUserManager();
+ $dao = UserManager::getInstance();
$user = $dao->findUser($_SESSION["user_email"] ?? "");
$author = $user["email"];
diff --git a/php/controller/register-controller.php b/php/controller/register-controller.php
index 5a0de05..3224eff 100644
--- a/php/controller/register-controller.php
+++ b/php/controller/register-controller.php
@@ -1,6 +1,6 @@
getConnection();
+
+ $db->exec("
+ CREATE TABLE IF NOT EXISTS users (
+ email TEXT PRIMARY KEY,
+ vorname TEXT NOT NULL,
+ nachname TEXT NOT NULL,
+ password TEXT NOT NULL
+ );
+ ");
+
+ unset($db);
+
+ } catch (PDOException $e) {
+ throw new RuntimeException("Benutzerdatenbank konnte nicht erstellt werden.");
+ }
+ }
+
+ /**
+ * Baut eine Verbindung zur SQLite-Datenbank auf.
+ *
+ * @return PDO Datenbankverbindung
+ *
+ * @throws RuntimeException wenn keine Verbindung hergestellt werden kann
+ */
+ private function getConnection()
+ {
+ try {
+ $dsn = 'sqlite:' . __DIR__ . '/../../db/users.db';
+
+ $db = new PDO($dsn, null, null);
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ return $db;
+
+ } catch (PDOException $e) {
+ throw new RuntimeException("Verbindung zur Benutzerdatenbank fehlgeschlagen.");
+ }
+ }
+
+ /**
+ * Gibt die Singleton-Instanz des DatabaseUserManagers zurück.
+ *
+ * @return DatabaseUserManager Instanz des DatabaseUserManagers
+ */
+ public static function getInstance()
+ {
+ if (self::$instance == null) {
+ self::$instance = new DatabaseUserManager();
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Sucht einen Benutzer anhand seiner E-Mail-Adresse.
+ *
+ * @param string $email E-Mail-Adresse des Benutzers
+ *
+ * @return array|null Benutzerdaten als Array oder null,
+ * wenn kein Benutzer gefunden wurde
+ *
+ * @throws RuntimeException wenn der Benutzer nicht geladen werden kann
+ */
public function findUser($email)
{
- // TODO: Implement findUser() method.
+ try {
+ $db = $this->getConnection();
+
+ $sql = "SELECT * FROM users WHERE email = :email";
+ $command = $db->prepare($sql);
+
+ $command->execute([
+ ":email" => $email
+ ]);
+
+ $user = $command->fetch(PDO::FETCH_ASSOC);
+
+ return $user ?: null;
+
+ } catch (PDOException $e) {
+ throw new RuntimeException("Benutzer konnte nicht geladen werden.");
+ }
}
+ /**
+ * Fügt einen neuen Benutzer in die Datenbank ein.
+ *
+ * Die Speicherung erfolgt innerhalb einer Transaktion.
+ * Doppelte E-Mail-Adressen werden durch den Primary Key verhindert.
+ *
+ * @param string $email E-Mail-Adresse des Benutzers
+ * @param string $vorname Vorname des Benutzers
+ * @param string $nachname Nachname des Benutzers
+ * @param string $password Passwort-Hash des Benutzers
+ *
+ * @return void
+ *
+ * @throws InvalidArgumentException wenn die E-Mail-Adresse bereits verwendet wird
+ * @throws RuntimeException wenn der Benutzer nicht gespeichert werden kann
+ */
public function addUser($email, $vorname, $nachname, $password)
{
- // TODO: Implement addUser() method.
+ try {
+ $db = $this->getConnection();
+ $db->beginTransaction();
+
+ $sql = "
+ INSERT INTO users (email, vorname, nachname, password)
+ VALUES (:email, :vorname, :nachname, :password)
+ ";
+
+ $command = $db->prepare($sql);
+
+ $command->execute([
+ ":email" => $email,
+ ":vorname" => $vorname,
+ ":nachname" => $nachname,
+ ":password" => $password
+ ]);
+
+ $db->commit();
+
+ } catch (PDOException $e) {
+ if (isset($db) && $db->inTransaction()) {
+ $db->rollBack();
+ }
+
+ if ($e->getCode() === "23000") {
+ throw new InvalidArgumentException("Diese E-Mail-Adresse wird bereits verwendet.");
+ }
+
+ throw new RuntimeException("Benutzer konnte nicht gespeichert werden.");
+ }
}
+ /**
+ * Aktualisiert die Daten eines bestehenden Benutzers.
+ *
+ * Optional kann zusätzlich das Passwort geändert werden.
+ * Wenn kein neues Passwort übergeben wird, bleibt das alte Passwort erhalten.
+ *
+ * @param string $oldEmail Aktuelle E-Mail-Adresse des Benutzers
+ * @param string $newEmail Neue E-Mail-Adresse des Benutzers
+ * @param string $vorname Neuer Vorname des Benutzers
+ * @param string $nachname Neuer Nachname des Benutzers
+ * @param string|null $password Neues Passwort oder null
+ *
+ * @return bool true, wenn der Benutzer aktualisiert wurde,
+ * sonst false
+ *
+ * @throws InvalidArgumentException wenn die neue E-Mail-Adresse bereits verwendet wird
+ * @throws RuntimeException wenn der Benutzer nicht aktualisiert werden kann
+ */
public function updateUser($oldEmail, $newEmail, $vorname, $nachname, $password = null)
{
- // TODO: Implement updateUser() method.
+ try {
+ $db = $this->getConnection();
+
+ if (!empty($password)) {
+ $sql = "
+ UPDATE users
+ SET email = :newEmail,
+ vorname = :vorname,
+ nachname = :nachname,
+ password = :password
+ WHERE email = :oldEmail
+ ";
+
+ $params = [
+ ":newEmail" => $newEmail,
+ ":vorname" => $vorname,
+ ":nachname" => $nachname,
+ ":password" => password_hash($password, PASSWORD_DEFAULT),
+ ":oldEmail" => $oldEmail
+ ];
+ } else {
+ $sql = "
+ UPDATE users
+ SET email = :newEmail,
+ vorname = :vorname,
+ nachname = :nachname
+ WHERE email = :oldEmail
+ ";
+
+ $params = [
+ ":newEmail" => $newEmail,
+ ":vorname" => $vorname,
+ ":nachname" => $nachname,
+ ":oldEmail" => $oldEmail
+ ];
+ }
+
+ $command = $db->prepare($sql);
+ $command->execute($params);
+
+ return $command->rowCount() > 0;
+
+ } catch (PDOException $e) {
+ if ($e->getCode() === "23000") {
+ throw new InvalidArgumentException("Diese E-Mail-Adresse wird bereits verwendet.");
+ }
+
+ throw new RuntimeException("Benutzer konnte nicht aktualisiert werden.");
+ }
}
+ /**
+ * Löscht einen Benutzer anhand seiner E-Mail-Adresse.
+ *
+ * @param string $email E-Mail-Adresse des zu löschenden Benutzers
+ *
+ * @return bool true, wenn der Benutzer gelöscht wurde,
+ * sonst false
+ *
+ * @throws RuntimeException wenn der Benutzer nicht gelöscht werden kann
+ */
public function deleteUser($email)
{
- // TODO: Implement deleteUser() method.
- }
+ try {
+ $db = $this->getConnection();
+ $sql = "DELETE FROM users WHERE email = :email";
+ $command = $db->prepare($sql);
+
+ $command->execute([
+ ":email" => $email
+ ]);
+
+ return $command->rowCount() > 0;
+
+ } catch (PDOException $e) {
+ throw new RuntimeException("Benutzer konnte nicht gelöscht werden.");
+ }
+ }
}
\ No newline at end of file
diff --git a/php/model/UserManager.php b/php/model/UserManager.php
index 1ff7b28..3068087 100644
--- a/php/model/UserManager.php
+++ b/php/model/UserManager.php
@@ -1,10 +1,32 @@
findUser("mustermann@web.de") == null) {
+ $userManager->addUser(
+ "mustermann@web.de",
+ "Max",
+ "Mustermann",
+ password_hash("test12345", PASSWORD_DEFAULT)
+ );
+ }
+
+ return $userManager;
}
}
\ No newline at end of file
diff --git a/php/validator/user-validator.php b/php/validator/user-validator.php
index 80dd996..0f789cf 100644
--- a/php/validator/user-validator.php
+++ b/php/validator/user-validator.php
@@ -1,13 +1,33 @@
= 8 && $zeichenAnzahl <= 72;
+ return $zeichenAnzahl >= 5 && $zeichenAnzahl <= 12;
}
+/**
+ * Prüft ein optionales Passwort.
+ *
+ * Ein leeres Passwort ist erlaubt und bedeutet,
+ * dass das bestehende Passwort unverändert bleibt.
+ * Falls ein Passwort angegeben wurde, wird es
+ * mit den normalen Passwortregeln geprüft.
+ *
+ * @param string|null $password Zu prüfendes Passwort
+ *
+ * @return bool true wenn das Passwort gültig oder leer ist,
+ * sonst false
+ */
function userOptionalPasswordValidator($password)
{
if (!isset($password) || $password === '') {