From b1fe78f419d1608c25d133f074dcc7c958623bb6 Mon Sep 17 00:00:00 2001
From: Martin Weise <martin.weise@tuwien.ac.at>
Date: Mon, 24 Feb 2025 09:43:11 +0100
Subject: [PATCH] WIP

Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at>
---
 .gitlab-ci.yml                                |   2 +-
 .../target/create-event-listener.jar          | Bin 10140 -> 10140 bytes
 dbrepo-metadata-db/1_setup-schema.sql         |   6 ++--
 helm/dbrepo/files/create-event-listener.jar   | Bin 10140 -> 10140 bytes
 lib/python/dbrepo/RestClient.py               |  31 +++++++++++++++++-
 lib/python/dbrepo/api/dto.py                  |   8 +++++
 lib/python/tests/test_unit_identifier.py      |  12 +++----
 lib/python/tests/test_unit_image.py           |  31 ++++++++++++++++++
 lib/python/tests/test_unit_messages.py        |  31 ++++++++++++++++++
 9 files changed, 110 insertions(+), 11 deletions(-)
 create mode 100644 lib/python/tests/test_unit_image.py
 create mode 100644 lib/python/tests/test_unit_messages.py

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6e084f17d4..3928026c5a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -405,7 +405,7 @@ test-lib:
   script:
     - "pip install pipenv"
     - "pipenv install gunicorn && pipenv install --dev --system --deploy"
-    - cd ./lib/python/ && coverage run --rcfile=.coveragerc -m pytest tests/test_unit_container.py tests/test_unit_concept.py tests/test_unit_database.py tests/test_unit_identifier.py tests/test_unit_license.py tests/test_unit_query.py tests/test_unit_rest_client.py tests/test_unit_table.py tests/test_unit_user.py tests/test_unit_view.py tests/test_unit_unit.py && coverage html && coverage xml && coverage report > ./coverage.txt
+    - cd ./lib/python/ && coverage run --rcfile=.coveragerc -m pytest tests/test_unit_container.py tests/test_unit_messages.py tests/test_unit_image.py tests/test_unit_concept.py tests/test_unit_database.py tests/test_unit_identifier.py tests/test_unit_license.py tests/test_unit_query.py tests/test_unit_rest_client.py tests/test_unit_table.py tests/test_unit_user.py tests/test_unit_view.py tests/test_unit_unit.py && coverage html && coverage xml && coverage report > ./coverage.txt
     - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'"
   artifacts:
     when: always
diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar
index 8da93ba40f621cea1db4e46414fd28ef77856fc4..ab18ceb405c9b37ab5d7ed52be8ec5faafd4554d 100644
GIT binary patch
delta 663
zcmbQ^KgVAvz?+#xgn@yBgQ3?aB8uZ?8N);&rTT+GhYSSvmM{B1LEhsMlh{k&4-0r+
z@N|98-8Gdb_ms+QrTTo02)AQ_{GMhvr`PJ|Z)RD{U2^391*_QEQ;sTeHP3WaIP>$%
zgiWejGH%QbmA<<u)!EQWX<4scvEBLYe^T2|#Y?vzG`!Rr=CDtw{%T0lsZVDft$TLi
zLYwuLwP6*#^>22v$G&{M<Ye~jO+UAk^`)|JJ2c0Zq4i+$R_%>W&h?*T9rp`%&6fZ4
z|4GbxG0ocoZ)3Ec*6kPHRnRnRubZ+1r@~6##Df!aMNGx!+MJx6_@LMCk5Ri=)xPR8
zCNuthSgm~TR{HUNSr5sON~2fb`~!YI*V~e5x2v|_zvaE6{INgvJ+*<N^RFITut@KH
z$kct=uiB>6-7}dPP^!AUA|RFbww-{TX6Scui*0e6>n-%RDw|~Zw}#(%wRw8s6qn{b
zGZL0O*fxWQEmEw1Q=y=vk=COWi%vC({^QH5v!mnY{Pt~D>DJJGuXw9_nqP-_$+btl
zJk9=~c;I4S;9vm7!{m*OD$G4T5tDB)>VjzwCOI&z$)w8M>k~0KkVy+n*D;xZ>8(s&
zV0k9yvtarXb2o_IoWL@N3C#G<#?1+4@CwZ0Wp0=hwt1E8eP*!U9>rN;T2pB<2P_Rt
zKB8m=7GzX50co3Tp==ALE0p!X^h#w@u>3=1h&nkH7cf6nB?>HmNF^9dOQ`08=?>Lc
eF#ST+5lri-g@If#xm7I@tnZ~-2AB>}_W%HA*Ar|2

delta 663
zcmbQ^KgVAvz?+#xgn@yBgJDHbSX8}+#+r#jO7*An4l4-kiT-5&f!Sfsk{ut{dh+L9
zX`f>EE_+X2K#t78Tbcj%9r27cU3E*Yp;fl5E%M#LSwglS!%Oa&m?d{g9KCo*Q9!I_
z-}xK1B^fuTUe3O}Fj?5pR^i#&m0bID%>HC{Tg7-kejzaPQpSRSPJ8K92Fb4P3T_u<
zWS+I%buPoE-ktBx<9%N$FNyV@zEO0q;`}Gu=){A04Ub-IyB8L*c<KJ1=N8=OIC_--
zXMNGWHSdhJsonbJbLwuMy3b42t=7$94Pp+LZd__qzn+yPTU9wl{jr9`+C!UK_}KPk
zpW(gn@WW>1gSXtz^UI!)xY9c7+i&(2hl}6$<lg`Nw;^2V%LIR+`np4QFK6jXWd{b&
z|Gw+oJ)W=5rwrELj(M?cn)IF5s~XP=bWE7C>p!>5?gf@MbHa}aN0l5ur2Xbhr<l9e
zUI|~W9eaE(o6J0ywphsYiD%@wQ!bjOexg2CKi=zJy>HHM-)5C|jn@wpcj@cyouKey
ziK>L8yF4f!xEL5X7(nqbc_X6=^YWmu$u}5vnO6jbP3B;d1JjyJs$e>hNefKZF`0nr
ztxR5E^-RoX!Sp5OZjkuq1eQ5WV8(woZcZ?RS6~(|vrUB0=2f!ynL#3xdlYAZX-%cc
z9I!Mn`G}GgSddZK1Z<#%vMrcjp{xg{S1Ox=>4(Y?b#f{$V1BAf6j=Qsm0&O}p_&U8
h?@)~e(=SvV!L*KA7|0cqTh$W5{FiDOU^+zI0{~@CAUFU3

diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql
index f874c4e263..17d303ea7d 100644
--- a/dbrepo-metadata-db/1_setup-schema.sql
+++ b/dbrepo-metadata-db/1_setup-schema.sql
@@ -331,9 +331,9 @@ CREATE TABLE IF NOT EXISTS `mdb_identifiers`
 (
     id                VARCHAR(36)                                  NOT NULL DEFAULT UUID(),
     dbid              VARCHAR(36)                                  NOT NULL,
-    qid               VARCHAR(36)                                  NOT NULL,
-    vid               VARCHAR(36)                                  NOT NULL,
-    tid               VARCHAR(36)                                  NOT NULL,
+    qid               VARCHAR(36),
+    vid               VARCHAR(36),
+    tid               VARCHAR(36),
     publisher         VARCHAR(255)                                 NOT NULL,
     language          VARCHAR(2),
     publication_year  INT                                          NOT NULL,
diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar
index 8da93ba40f621cea1db4e46414fd28ef77856fc4..ab18ceb405c9b37ab5d7ed52be8ec5faafd4554d 100644
GIT binary patch
delta 663
zcmbQ^KgVAvz?+#xgn@yBgQ3?aB8uZ?8N);&rTT+GhYSSvmM{B1LEhsMlh{k&4-0r+
z@N|98-8Gdb_ms+QrTTo02)AQ_{GMhvr`PJ|Z)RD{U2^391*_QEQ;sTeHP3WaIP>$%
zgiWejGH%QbmA<<u)!EQWX<4scvEBLYe^T2|#Y?vzG`!Rr=CDtw{%T0lsZVDft$TLi
zLYwuLwP6*#^>22v$G&{M<Ye~jO+UAk^`)|JJ2c0Zq4i+$R_%>W&h?*T9rp`%&6fZ4
z|4GbxG0ocoZ)3Ec*6kPHRnRnRubZ+1r@~6##Df!aMNGx!+MJx6_@LMCk5Ri=)xPR8
zCNuthSgm~TR{HUNSr5sON~2fb`~!YI*V~e5x2v|_zvaE6{INgvJ+*<N^RFITut@KH
z$kct=uiB>6-7}dPP^!AUA|RFbww-{TX6Scui*0e6>n-%RDw|~Zw}#(%wRw8s6qn{b
zGZL0O*fxWQEmEw1Q=y=vk=COWi%vC({^QH5v!mnY{Pt~D>DJJGuXw9_nqP-_$+btl
zJk9=~c;I4S;9vm7!{m*OD$G4T5tDB)>VjzwCOI&z$)w8M>k~0KkVy+n*D;xZ>8(s&
zV0k9yvtarXb2o_IoWL@N3C#G<#?1+4@CwZ0Wp0=hwt1E8eP*!U9>rN;T2pB<2P_Rt
zKB8m=7GzX50co3Tp==ALE0p!X^h#w@u>3=1h&nkH7cf6nB?>HmNF^9dOQ`08=?>Lc
eF#ST+5lri-g@If#xm7I@tnZ~-2AB>}_W%HA*Ar|2

delta 663
zcmbQ^KgVAvz?+#xgn@yBgJDHbSX8}+#+r#jO7*An4l4-kiT-5&f!Sfsk{ut{dh+L9
zX`f>EE_+X2K#t78Tbcj%9r27cU3E*Yp;fl5E%M#LSwglS!%Oa&m?d{g9KCo*Q9!I_
z-}xK1B^fuTUe3O}Fj?5pR^i#&m0bID%>HC{Tg7-kejzaPQpSRSPJ8K92Fb4P3T_u<
zWS+I%buPoE-ktBx<9%N$FNyV@zEO0q;`}Gu=){A04Ub-IyB8L*c<KJ1=N8=OIC_--
zXMNGWHSdhJsonbJbLwuMy3b42t=7$94Pp+LZd__qzn+yPTU9wl{jr9`+C!UK_}KPk
zpW(gn@WW>1gSXtz^UI!)xY9c7+i&(2hl}6$<lg`Nw;^2V%LIR+`np4QFK6jXWd{b&
z|Gw+oJ)W=5rwrELj(M?cn)IF5s~XP=bWE7C>p!>5?gf@MbHa}aN0l5ur2Xbhr<l9e
zUI|~W9eaE(o6J0ywphsYiD%@wQ!bjOexg2CKi=zJy>HHM-)5C|jn@wpcj@cyouKey
ziK>L8yF4f!xEL5X7(nqbc_X6=^YWmu$u}5vnO6jbP3B;d1JjyJs$e>hNefKZF`0nr
ztxR5E^-RoX!Sp5OZjkuq1eQ5WV8(woZcZ?RS6~(|vrUB0=2f!ynL#3xdlYAZX-%cc
z9I!Mn`G}GgSddZK1Z<#%vMrcjp{xg{S1Ox=>4(Y?b#f{$V1BAf6j=Qsm0&O}p_&U8
h?@)~e(=SvV!L*KA7|0cqTh$W5{FiDOU^+zI0{~@CAUFU3

diff --git a/lib/python/dbrepo/RestClient.py b/lib/python/dbrepo/RestClient.py
index 9e609a7092..0cd8afe272 100644
--- a/lib/python/dbrepo/RestClient.py
+++ b/lib/python/dbrepo/RestClient.py
@@ -1713,7 +1713,7 @@ class RestClient:
         :raises FormatNotAvailable: If the service could not represent the output.
         :raises ResponseCodeError: If something went wrong with the retrieval of the identifiers.
         """
-        url = f'/api/identifiers'
+        url = f'/api/identifier'
         params = []
         if database_id is not None:
             params.append(('dbid', database_id))
@@ -1745,6 +1745,35 @@ class RestClient:
         raise ResponseCodeError(f'Failed to get identifiers: response code: {response.status_code} is not '
                                 f'200 (OK): {response.text}')
 
+    def get_images(self) -> List[ImageBrief] | str:
+        """
+        Get list of container images.
+
+        :returns: List of images, if successful.
+        """
+        url = f'/api/image'
+        response = self._wrapper(method="get", url=url, headers={'Accept': 'application/json'})
+        if response.status_code == 200:
+            body = response.json()
+            return TypeAdapter(List[ImageBrief]).validate_python(body)
+        raise ResponseCodeError(f'Failed to get images: response code: {response.status_code} is not '
+                                f'200 (OK): {response.text}')
+
+    def get_messages(self) -> List[Message] | str:
+        """
+        Get list of messages.
+
+        :returns: List of messages, if successful.
+        """
+        url = f'/api/message'
+        response = self._wrapper(method="get", url=url, headers={'Accept': 'application/json'})
+        if response.status_code == 200:
+            body = response.json()
+            return TypeAdapter(List[Message]).validate_python(body)
+        raise ResponseCodeError(f'Failed to get messages: response code: {response.status_code} is not '
+                                f'200 (OK): {response.text}')
+
+
     def update_table_column(self, database_id: str, table_id: str, column_id: str, concept_uri: str = None,
                             unit_uri: str = None) -> Column:
         """
diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py
index ac071cb412..c378a6d9aa 100644
--- a/lib/python/dbrepo/api/dto.py
+++ b/lib/python/dbrepo/api/dto.py
@@ -665,6 +665,14 @@ class Identifier(BaseModel):
     publication_day: Optional[int] = None
     publication_month: Optional[int] = None
 
+class Message(BaseModel):
+    id: int
+    type: str
+    link: Optional[str] = None
+    link_text: Optional[str] = None
+    display_start: Optional[Timestamp] = None
+    display_end: Optional[Timestamp] = None
+
 
 class IdentifierBrief(BaseModel):
     id: str
diff --git a/lib/python/tests/test_unit_identifier.py b/lib/python/tests/test_unit_identifier.py
index 6509bcac5a..9ac386437c 100644
--- a/lib/python/tests/test_unit_identifier.py
+++ b/lib/python/tests/test_unit_identifier.py
@@ -187,7 +187,7 @@ class IdentifierUnitTest(unittest.TestCase):
                               status=IdentifierStatusType.PUBLISHED,
                               owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'))]
             # mock
-            mock.get('/api/identifiers', json=[exp[0].model_dump()], headers={"Accept": "application/json"})
+            mock.get('/api/identifier', json=[exp[0].model_dump()], headers={"Accept": "application/json"})
             # test
             response = RestClient().get_identifiers(database_id="6bd39359-b154-456d-b9c2-caa516a45732",
                                                     view_id="e5229d24-584a-43e8-b9f6-d349c3053f9c",
@@ -199,7 +199,7 @@ class IdentifierUnitTest(unittest.TestCase):
         with requests_mock.Mocker() as mock:
             exp = []
             # mock
-            mock.get('/api/identifiers', json=[], headers={"Accept": "application/json"})
+            mock.get('/api/identifier', json=[], headers={"Accept": "application/json"})
             # test
             response = RestClient().get_identifiers(database_id="6bd39359-b154-456d-b9c2-caa516a45732",
                                                     subset_id="0831bf54-9dd9-46fe-8c2c-c539332ea177")
@@ -209,7 +209,7 @@ class IdentifierUnitTest(unittest.TestCase):
         with requests_mock.Mocker() as mock:
             exp = []
             # mock
-            mock.get('/api/identifiers', json=[], headers={"Accept": "application/json"})
+            mock.get('/api/identifier', json=[], headers={"Accept": "application/json"})
             # test
             response = RestClient().get_identifiers(database_id="6bd39359-b154-456d-b9c2-caa516a45732",
                                                     table_id="b3230b86-4743-498d-9015-3fad58049692")
@@ -239,7 +239,7 @@ class IdentifierUnitTest(unittest.TestCase):
     def test_get_identifiers_404_fails(self):
         with requests_mock.Mocker() as mock:
             # mock
-            mock.get('/api/identifiers', status_code=404)
+            mock.get('/api/identifier', status_code=404)
             # test
             try:
                 RestClient().get_identifiers()
@@ -249,7 +249,7 @@ class IdentifierUnitTest(unittest.TestCase):
     def test_get_identifiers_406_fails(self):
         with requests_mock.Mocker() as mock:
             # mock
-            mock.get('/api/identifiers', status_code=406)
+            mock.get('/api/identifier', status_code=406)
             # test
             try:
                 RestClient().get_identifiers()
@@ -259,7 +259,7 @@ class IdentifierUnitTest(unittest.TestCase):
     def test_get_identifiers_unknown_fails(self):
         with requests_mock.Mocker() as mock:
             # mock
-            mock.get('/api/identifiers', status_code=202)
+            mock.get('/api/identifier', status_code=202)
             # test
             try:
                 RestClient().get_identifiers()
diff --git a/lib/python/tests/test_unit_image.py b/lib/python/tests/test_unit_image.py
new file mode 100644
index 0000000000..2802efc690
--- /dev/null
+++ b/lib/python/tests/test_unit_image.py
@@ -0,0 +1,31 @@
+import unittest
+
+import requests_mock
+
+from dbrepo.RestClient import RestClient
+
+from dbrepo.api.dto import ImageBrief
+
+
+class ImageUnitTest(unittest.TestCase):
+
+    def test_get_images_empty_succeeds(self):
+        with requests_mock.Mocker() as mock:
+            # mock
+            mock.get('/api/image', json=[])
+            # test
+            response = RestClient().get_images()
+            self.assertEqual([], response)
+
+    def test_get_images_succeeds(self):
+        with requests_mock.Mocker() as mock:
+            exp = [ImageBrief(id=1, name="mariadb", version="11.1.3", jdbc_method="mariadb", default=False)]
+            # mock
+            mock.get('/api/image', json=[exp[0].model_dump()])
+            # test
+            response = RestClient().get_images()
+            self.assertEqual(exp, response)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/lib/python/tests/test_unit_messages.py b/lib/python/tests/test_unit_messages.py
new file mode 100644
index 0000000000..cf863dcb6c
--- /dev/null
+++ b/lib/python/tests/test_unit_messages.py
@@ -0,0 +1,31 @@
+import unittest
+
+import requests_mock
+
+from dbrepo.RestClient import RestClient
+
+from dbrepo.api.dto import Message
+
+
+class ImageUnitTest(unittest.TestCase):
+
+    def test_get_message_empty_succeeds(self):
+        with requests_mock.Mocker() as mock:
+            # mock
+            mock.get('/api/message', json=[])
+            # test
+            response = RestClient().get_messages()
+            self.assertEqual([], response)
+
+    def test_get_images_succeeds(self):
+        with requests_mock.Mocker() as mock:
+            exp = [Message(id=1, type="info")]
+            # mock
+            mock.get('/api/message', json=[exp[0].model_dump()])
+            # test
+            response = RestClient().get_messages()
+            self.assertEqual(exp, response)
+
+
+if __name__ == "__main__":
+    unittest.main()
-- 
GitLab