diff --git a/.jupyter/api_query/api/table_data_endpoint_api.py b/.jupyter/api_query/api/table_data_endpoint_api.py index 632bf0023c0c979119e43647dec551cf4bc744ad..8f34b37dacac4db3543dd2def4951d0d24501b87 100644 --- a/.jupyter/api_query/api/table_data_endpoint_api.py +++ b/.jupyter/api_query/api/table_data_endpoint_api.py @@ -259,7 +259,7 @@ class TableDataEndpointApi(object): auth_settings = ['bearerAuth'] # noqa: E501 return self.api_client.call_api( - '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'HEAD', + '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'GET', path_params, query_params, header_params, @@ -380,7 +380,7 @@ class TableDataEndpointApi(object): auth_settings = ['bearerAuth'] # noqa: E501 return self.api_client.call_api( - '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'GET', + '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'HEAD', path_params, query_params, header_params, diff --git a/.jupyter/load_test.py b/.jupyter/load_test.py index 7a6ef465509a58a4ee2d018b9e33abe0390ad3cf..8fb57c7e7efe240ee3dcb043e82a9d61cab223a6 100644 --- a/.jupyter/load_test.py +++ b/.jupyter/load_test.py @@ -30,7 +30,7 @@ identifier = IdentifierEndpointApi() persistence = PersistenceEndpointApi() unit = DefaultApi() -token = "" +token = "" # keep def create_user(username): @@ -43,6 +43,14 @@ def create_user(username): return response +def update_password(user_id, password): + response = user.update_password({ + "password": password + }, user_id) + print("updated password for user with id %d" % user_id) + return response + + def auth_user(username): response = authentication.authenticate_user1({ "username": username, @@ -234,6 +242,7 @@ def update_user(user_id): "titles_after": "PhD" }, user_id) print("updated user with id %d" % user_id) + return response def update_theme(user_id): @@ -278,8 +287,10 @@ if __name__ == '__main__': # # create 1 user and 3 containers (public, private, public) # - create_user("test1") + uid = create_user("test1").id auth_user("test1") + update_password(uid, "test1") + update_user(uid) # container 1 cid = create_container().id start_container(cid) @@ -350,7 +361,7 @@ if __name__ == '__main__': # # create 1 user and 1 container and issue queries to own and foreign database # - create_user("test2") + uid = create_user("test2").id auth_user("test2") # container 4 cid = create_container().id diff --git a/.jupyter/tuple_publish.ipynb b/.jupyter/tuple_publish.ipynb index f09ef76bbfc67e73839f2cc9607137df9f3ed0e0..6c1e40eb950061b39f398c4b790bf3a3e4417fc0 100644 --- a/.jupyter/tuple_publish.ipynb +++ b/.jupyter/tuple_publish.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": 8, "metadata": { "pycharm": { "name": "#%%\n" @@ -25,6 +25,7 @@ "source": [ "import time\n", "import csv\n", + "import uuid\n", "from api_broker.BrokerServiceClient import BrokerServiceClient\n", "from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi\n", "from api_authentication.api.user_endpoint_api import UserEndpointApi\n", @@ -54,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 9, "metadata": { "pycharm": { "name": "#%%\n" @@ -82,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 10, "metadata": { "pycharm": { "name": "#%%\n" @@ -97,10 +98,10 @@ " 'authorities': [{'authority': 'ROLE_RESEARCHER'}],\n", " 'containers': None,\n", " 'databases': None,\n", - " 'email': 'martin.weise@tuwien.ac.at',\n", + " 'email': 'martinweiseat@gmail.com',\n", " 'email_verified': False,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'identifiers': None,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", @@ -121,7 +122,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": 11, "metadata": { "pycharm": { "name": "#%%\n" @@ -132,27 +133,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'created': datetime.datetime(2022, 8, 16, 12, 41, 27, 625000, tzinfo=tzutc()),\n", + "{'created': datetime.datetime(2022, 8, 17, 10, 59, 9, 964000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'test'},\n", - " 'hash': '686331331ec9e4de5b84cecc9f323cc04efc6d8766eaea07c0b1e47b817ff4e9',\n", - " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality',\n", + " 'hash': '5188e3aa1d16411f98b0cde473c39e79f54c205da3d0f5cae601e797efd053cb',\n", + " 'id': 2,\n", + " 'internal_name': 'fda-userdb-airquality-9c04db38-1e1b-11ed-b193-8c8caada74c3',\n", " 'is_public': None,\n", - " 'name': 'Airquality'}\n" + " 'name': 'Airquality 9c04db38-1e1b-11ed-b193-8c8caada74c3'}\n" ] } ], "source": [ "response = container.create1({\n", - " \"name\": \"Airquality\",\n", + " \"name\": \"Airquality \" + str(uuid.uuid1()),\n", " \"repository\": \"mariadb\",\n", " \"tag\": \"10.5\"\n", "})\n", @@ -162,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 12, "metadata": { "pycharm": { "name": "#%%\n" @@ -173,21 +174,21 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'created': datetime.datetime(2022, 8, 16, 12, 41, 27, 625000, tzinfo=tzutc()),\n", + "{'created': datetime.datetime(2022, 8, 17, 10, 59, 9, 964000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'test'},\n", - " 'hash': '686331331ec9e4de5b84cecc9f323cc04efc6d8766eaea07c0b1e47b817ff4e9',\n", - " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality',\n", + " 'hash': '5188e3aa1d16411f98b0cde473c39e79f54c205da3d0f5cae601e797efd053cb',\n", + " 'id': 2,\n", + " 'internal_name': 'fda-userdb-airquality-9c04db38-1e1b-11ed-b193-8c8caada74c3',\n", " 'is_public': None,\n", - " 'name': 'Airquality'}\n" + " 'name': 'Airquality 9c04db38-1e1b-11ed-b193-8c8caada74c3'}\n" ] } ], @@ -201,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 13, "metadata": { "pycharm": { "name": "#%%\n" @@ -212,25 +213,25 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'container': {'created': datetime.datetime(2022, 8, 16, 12, 41, 27, 625000, tzinfo=tzutc()),\n", + "{'container': {'created': datetime.datetime(2022, 8, 17, 10, 59, 9, 964000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'test'},\n", - " 'hash': '686331331ec9e4de5b84cecc9f323cc04efc6d8766eaea07c0b1e47b817ff4e9',\n", - " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality',\n", + " 'hash': '5188e3aa1d16411f98b0cde473c39e79f54c205da3d0f5cae601e797efd053cb',\n", + " 'id': 2,\n", + " 'internal_name': 'fda-userdb-airquality-9c04db38-1e1b-11ed-b193-8c8caada74c3',\n", " 'is_public': None,\n", - " 'name': 'Airquality'},\n", - " 'created': datetime.datetime(2022, 8, 16, 12, 41, 34, 450000, tzinfo=tzutc()),\n", + " 'name': 'Airquality 9c04db38-1e1b-11ed-b193-8c8caada74c3'},\n", + " 'created': datetime.datetime(2022, 8, 17, 10, 59, 15, 497000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", @@ -239,15 +240,15 @@ " 'username': 'test'},\n", " 'description': 'Airquality',\n", " 'engine': 'mariadb:10.5',\n", - " 'id': 1,\n", + " 'id': 2,\n", " 'is_public': False,\n", - " 'name': 'Airquality'}\n" + " 'name': 'Airquality a24d3738-1e1b-11ed-b193-8c8caada74c3'}\n" ] } ], "source": [ "response = database.create({\n", - " \"name\": \"Airquality\",\n", + " \"name\": \"Airquality \" + str(uuid.uuid1()),\n", " \"description\": \"Airquality\",\n", " \"is_public\": False\n", "}, container_id)\n", @@ -257,28 +258,28 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 14, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'contact': None,\n", - " 'container': {'created': datetime.datetime(2022, 8, 16, 12, 41, 27, 625000, tzinfo=tzutc()),\n", + " 'container': {'created': datetime.datetime(2022, 8, 17, 10, 59, 9, 964000, tzinfo=tzutc()),\n", " 'databases': None,\n", - " 'hash': '686331331ec9e4de5b84cecc9f323cc04efc6d8766eaea07c0b1e47b817ff4e9',\n", - " 'id': 1,\n", + " 'hash': '5188e3aa1d16411f98b0cde473c39e79f54c205da3d0f5cae601e797efd053cb',\n", + " 'id': 2,\n", " 'image': {'id': 1, 'repository': 'mariadb', 'tag': '10.5'},\n", - " 'internal_name': 'fda-userdb-airquality',\n", + " 'internal_name': 'fda-userdb-airquality-9c04db38-1e1b-11ed-b193-8c8caada74c3',\n", " 'ip_address': None,\n", " 'is_public': None,\n", - " 'name': 'Airquality',\n", - " 'port': 46472,\n", + " 'name': 'Airquality 9c04db38-1e1b-11ed-b193-8c8caada74c3',\n", + " 'port': 11584,\n", " 'state': None},\n", - " 'created': datetime.datetime(2022, 8, 16, 12, 41, 34, 450000, tzinfo=tzutc()),\n", + " 'created': datetime.datetime(2022, 8, 17, 10, 59, 15, 497000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", @@ -287,52 +288,52 @@ " 'username': 'test'},\n", " 'deleted': None,\n", " 'description': 'Airquality',\n", - " 'exchange': 'airquality',\n", - " 'id': 1,\n", + " 'exchange': 'airquality_a24d3738-1e1b-11ed-b193-8c8caada74c3',\n", + " 'id': 2,\n", " 'image': {'compiled': None,\n", - " 'date_formats': [{'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 574000, tzinfo=tzutc()),\n", + " 'date_formats': [{'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 614000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d',\n", " 'example': '2022-01-30',\n", " 'has_time': False,\n", " 'id': 1,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 581000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 622000, tzinfo=tzutc()),\n", " 'database_format': '%d.%c.%Y',\n", " 'example': '30.01.2022',\n", " 'has_time': False,\n", " 'id': 2,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 584000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 625000, tzinfo=tzutc()),\n", " 'database_format': '%d.%c.%y',\n", " 'example': '30.01.22',\n", " 'has_time': False,\n", " 'id': 3,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 587000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 628000, tzinfo=tzutc()),\n", " 'database_format': '%c/%d/%Y',\n", " 'example': '01/30/2022',\n", " 'has_time': False,\n", " 'id': 4,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 590000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 631000, tzinfo=tzutc()),\n", " 'database_format': '%c/%d/%y',\n", " 'example': '01/30/22',\n", " 'has_time': False,\n", " 'id': 5,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 593000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 634000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d %H:%i:%S.%f',\n", " 'example': '2022-01-30 13:44:25.0',\n", " 'has_time': True,\n", " 'id': 6,\n", " 'unix_format': 'yyyy-MM-dd HH:mm:ss.SSSSSS'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 595000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 636000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d %H:%i:%S',\n", " 'example': '2022-01-30 13:44:25',\n", " 'has_time': True,\n", " 'id': 7,\n", " 'unix_format': 'yyyy-MM-dd HH:mm:ss'},\n", - " {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 597000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 640000, tzinfo=tzutc()),\n", " 'database_format': '%d.%c.%Y %H:%i:%S',\n", " 'example': '30.01.2022 13:44:25',\n", " 'has_time': True,\n", @@ -363,11 +364,11 @@ " 'repository': 'mariadb',\n", " 'size': None,\n", " 'tag': '10.5'},\n", - " 'internal_name': 'airquality',\n", + " 'internal_name': 'airquality_a24d3738-1e1b-11ed-b193-8c8caada74c3',\n", " 'is_public': False,\n", " 'language': None,\n", " 'license': None,\n", - " 'name': 'Airquality',\n", + " 'name': 'Airquality a24d3738-1e1b-11ed-b193-8c8caada74c3',\n", " 'publication_year': 2022,\n", " 'publisher': None,\n", " 'subjects': [],\n", @@ -389,7 +390,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 15, "metadata": { "pycharm": { "name": "#%%\n" @@ -400,25 +401,25 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'container': {'created': datetime.datetime(2022, 8, 16, 12, 41, 27, 625000, tzinfo=tzutc()),\n", + "{'container': {'created': datetime.datetime(2022, 8, 17, 10, 59, 9, 964000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'test'},\n", - " 'hash': '686331331ec9e4de5b84cecc9f323cc04efc6d8766eaea07c0b1e47b817ff4e9',\n", - " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality',\n", + " 'hash': '5188e3aa1d16411f98b0cde473c39e79f54c205da3d0f5cae601e797efd053cb',\n", + " 'id': 2,\n", + " 'internal_name': 'fda-userdb-airquality-9c04db38-1e1b-11ed-b193-8c8caada74c3',\n", " 'is_public': None,\n", - " 'name': 'Airquality'},\n", - " 'created': datetime.datetime(2022, 8, 16, 12, 41, 34, 450000, tzinfo=tzutc()),\n", + " 'name': 'Airquality 9c04db38-1e1b-11ed-b193-8c8caada74c3'},\n", + " 'created': datetime.datetime(2022, 8, 17, 10, 59, 15, 497000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", @@ -436,9 +437,9 @@ " 'values of the completed day for the current year are updated '\n", " 'every 30 minutes after midnight (UTC+1).',\n", " 'engine': 'mariadb:10.5',\n", - " 'id': 1,\n", + " 'id': 2,\n", " 'is_public': False,\n", - " 'name': 'Airquality'}\n" + " 'name': 'Airquality a24d3738-1e1b-11ed-b193-8c8caada74c3'}\n" ] } ], @@ -459,7 +460,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 16, "metadata": { "pycharm": { "name": "#%%\n" @@ -472,22 +473,22 @@ "text": [ "{'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'test'},\n", - " 'id': 1,\n", - " 'internal_name': 'airquality',\n", - " 'name': 'Airquality'}\n" + " 'id': 2,\n", + " 'internal_name': 'airquality_a28ac288-1e1b-11ed-b193-8c8caada74c3',\n", + " 'name': 'Airquality a28ac288-1e1b-11ed-b193-8c8caada74c3'}\n" ] } ], "source": [ "response = table.create({\n", - " \"name\": \"Airquality\",\n", + " \"name\": \"Airquality \" + str(uuid.uuid1()),\n", " \"description\": \"Airquality in Zürich, Switzerland\",\n", " \"columns\": [{\n", " \"name\": \"Date\",\n", @@ -535,13 +536,12 @@ " }]\n", "}, container_id, database_id)\n", "table_id = response.id\n", - "table_routing_key = \"airquality\" # todo\n", "print(response)" ] }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 17, "metadata": { "pycharm": { "name": "#%%\n" @@ -561,7 +561,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 1,\n", + " 'id': 9,\n", " 'internal_name': 'id',\n", " 'is_null_allowed': False,\n", " 'is_primary_key': True,\n", @@ -572,7 +572,7 @@ " 'check_expression': None,\n", " 'column_concept': None,\n", " 'column_type': 'date',\n", - " 'date_format': {'created_at': datetime.datetime(2022, 8, 16, 12, 39, 54, 574000, tzinfo=tzutc()),\n", + " 'date_format': {'created_at': datetime.datetime(2022, 8, 17, 10, 21, 43, 614000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d',\n", " 'example': '2022-01-30',\n", " 'has_time': False,\n", @@ -582,7 +582,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 2,\n", + " 'id': 10,\n", " 'internal_name': 'date',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", @@ -598,7 +598,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 3,\n", + " 'id': 11,\n", " 'internal_name': 'location',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", @@ -614,7 +614,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 4,\n", + " 'id': 12,\n", " 'internal_name': 'parameter',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", @@ -630,7 +630,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 5,\n", + " 'id': 13,\n", " 'internal_name': 'interval',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", @@ -646,7 +646,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 6,\n", + " 'id': 14,\n", " 'internal_name': 'unit',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", @@ -662,7 +662,7 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 7,\n", + " 'id': 15,\n", " 'internal_name': 'value',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", @@ -678,17 +678,17 @@ " 'decimal_digits_before': None,\n", " 'enum_values': [],\n", " 'foreign_key': None,\n", - " 'id': 8,\n", + " 'id': 16,\n", " 'internal_name': 'status',\n", " 'is_null_allowed': True,\n", " 'is_primary_key': False,\n", " 'name': 'Status',\n", " 'references': None,\n", " 'unique': False}],\n", - " 'created': datetime.datetime(2022, 8, 16, 12, 41, 36, 714000, tzinfo=tzutc()),\n", + " 'created': datetime.datetime(2022, 8, 17, 10, 59, 15, 923000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'firstname': 'Martin',\n", - " 'id': 2,\n", + " 'id': 3,\n", " 'lastname': 'Weise',\n", " 'orcid': None,\n", " 'theme_dark': False,\n", @@ -696,10 +696,10 @@ " 'titles_before': None,\n", " 'username': 'test'},\n", " 'description': 'Airquality in Zürich, Switzerland',\n", - " 'id': 1,\n", - " 'internal_name': 'airquality',\n", - " 'name': 'Airquality',\n", - " 'topic': 'airquality'}\n" + " 'id': 2,\n", + " 'internal_name': 'airquality_a28ac288-1e1b-11ed-b193-8c8caada74c3',\n", + " 'name': 'Airquality a28ac288-1e1b-11ed-b193-8c8caada74c3',\n", + " 'topic': 'airquality_a28ac288-1e1b-11ed-b193-8c8caada74c3'}\n" ] } ], @@ -711,33 +711,11 @@ }, { "cell_type": "code", - "execution_count": 90, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "None\n" - ] - } - ], - "source": [ - "response = consumer.declare(container_id, database_id, table_id)\n", - "print(response)" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 91, + "execution_count": null, "metadata": { "pycharm": { - "name": "#%%\n" + "name": "#%%\n", + "is_executing": true } }, "outputs": [ @@ -764,287 +742,7 @@ "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.77', 'status': 'tentative'}\n", "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.24', 'status': 'tentative'}\n", "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '33.11', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '36.55', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.2', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '43.51', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '4.38', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '74.05', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '74.11', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.4', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '5.02', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '35.47', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.28', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '42.88', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '5.34', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '140.15', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '118.87', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '39.43', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.8', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '43.51', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.93', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '118.95', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '102.54', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '5.31', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.52', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '9.36', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '51.36', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '45.83', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '28.15', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '44.48', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.25', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '127.62', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '126.47', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.4', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '3.25', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '26.86', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '7.78', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '39.43', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '7.54', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '106.39', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '90.24', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '35.93', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.28', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '42.22', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '8.83', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '96.55', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '82.07', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '5.74', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.83', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '9.71', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '52.2', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '40.44', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.6', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '42.67', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '4.92', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '91.18', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '90.98', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.22', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.89', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '14.27', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.38', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '23.64', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '31.3', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '43.53', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '37.49', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '25.84', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.87', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '32.74', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '23.68', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '50.23', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '43.63', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '8.46', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.94', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '14.73', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '44.16', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '24.75', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '8.99', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '33.56', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.73', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '48.51', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '48.21', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.18', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.37', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '12.28', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.08', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.28', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '40.87', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.82', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.02', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '23', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.63', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '33.81', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '24.59', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '33.48', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '29.23', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '6.82', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.58', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.15', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '46.87', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '32.39', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.8', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '36.18', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '25.41', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '21.56', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.32', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '12.52', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.04', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.82', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '35.95', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.15', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.67', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '18.91', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.42', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '26.31', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '31.73', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '27.49', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '23.63', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '11.26', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.85', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.23', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '33.83', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '17.5', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.39', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '23.67', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '30.84', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.37', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.84', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.17', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.23', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '9.36', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.25', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '15.98', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '38.22', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '11.67', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.45', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '18.39', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.55', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '25.14', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '31.79', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '14.42', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.49', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '8.26', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.49', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '15.04', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '40.22', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '15.54', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '4.45', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.9', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '28.44', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.82', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.22', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.13', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '9.2', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.03', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.02', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '32.79', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.48', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '14.77', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '18.57', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.21', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '26', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '24.42', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.7', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.5', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '7.98', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.03', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '13.69', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '37.7', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '13.42', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '3.05', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.99', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '25.75', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.8', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.53', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.2', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.08', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '11.57', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.45', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.36', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '28.16', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.12', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '15.26', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '19.95', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.27', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '28.54', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '19.92', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '19.28', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.09', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '7.65', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '0.85', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '13.32', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '35.22', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '15.79', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.1', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.84', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.28', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.97', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.08', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '9.93', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.3', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '15.46', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '32.76', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.63', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '11.29', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '27.76', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '13.83', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '31.88', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.36', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '17.21', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '15.17', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '6.81', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.6', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.58', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '38.17', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '16.84', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '6.1', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.85', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '19.93', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.86', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '16.57', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.05', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '9.9', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.49', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '15.13', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '31.77', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.43', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '11.09', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '20.13', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.12', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.98', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '27.65', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '13.91', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.29', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '8.44', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.37', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.51', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '38.26', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '19.98', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.53', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '22.06', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '24.13', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '14.19', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '13.76', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'CO', 'interval': 'h1', 'unit': 'mg/m3', 'value': '0.17', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'SO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.04', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '8.76', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '2.78', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '12.5', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '35.76', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '9.55', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Stampfenbachstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '8.5', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '21.86', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '13.66', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '20.85', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '32.1', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.6', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Schimmelstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '9.2', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '6.38', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '1.75', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '9.51', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Heubeeribüel', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '38.09', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '18.13', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.64', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NO2', 'interval': 'h1', 'unit': 'µg/m3', 'value': '18.36', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'O3', 'interval': 'h1', 'unit': 'µg/m3', 'value': '32.27', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM10', 'interval': 'h1', 'unit': 'µg/m3', 'value': '10.37', 'status': 'tentative'}\n", - "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'PM2.5', 'interval': 'h1', 'unit': 'µg/m3', 'value': '9.75', 'status': 'tentative'}\n" - ] - }, - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[0;31mKeyboardInterrupt\u001B[0m Traceback (most recent call last)", - "Input \u001B[0;32mIn [91]\u001B[0m, in \u001B[0;36m<cell line: 3>\u001B[0;34m()\u001B[0m\n\u001B[1;32m 6\u001B[0m payload \u001B[38;5;241m=\u001B[39m {\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mdate\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m0\u001B[39m], \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mlocation\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m1\u001B[39m], \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mparameter\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m2\u001B[39m], \u001B[38;5;124m'\u001B[39m\u001B[38;5;124minterval\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m3\u001B[39m], \u001B[38;5;124m'\u001B[39m\u001B[38;5;124munit\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m4\u001B[39m],\n\u001B[1;32m 7\u001B[0m \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mvalue\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m5\u001B[39m], \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mstatus\u001B[39m\u001B[38;5;124m'\u001B[39m: row[\u001B[38;5;241m6\u001B[39m]}\n\u001B[1;32m 8\u001B[0m response \u001B[38;5;241m=\u001B[39m broker\u001B[38;5;241m.\u001B[39msend(payload)\n\u001B[0;32m----> 9\u001B[0m \u001B[43mtime\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43msleep\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m1\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 10\u001B[0m \u001B[38;5;28mprint\u001B[39m(payload)\n", - "\u001B[0;31mKeyboardInterrupt\u001B[0m: " + "{'date': '2021-01-01', 'location': 'Rosengartenstrasse', 'parameter': 'NOx', 'interval': 'h1', 'unit': 'ppb', 'value': '36.55', 'status': 'tentative'}\n" ] } ], diff --git a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java index 585a29bde89eced8b367a0e3414c603f7c463c07..6c980b8156898f32a20d4ff61aabdcf45ed14776 100644 --- a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java +++ b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java @@ -174,8 +174,7 @@ public class UserEndpoint { @Operation(summary = "Update user password", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<UserDto> updatePassword(@NotNull @PathVariable("id") Long id, @NotNull @Valid @RequestBody UserPasswordDto data) - throws UserNotFoundException, BrokerUserCreationException, OrcidMalformedException, - UserEmailNotVerifiedException { + throws UserNotFoundException, BrokerUserCreationException, OrcidMalformedException { final User entity = userService.updatePassword(id, data); queueService.modifyUserPassword(entity, data); return ResponseEntity.status(HttpStatus.ACCEPTED) diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/fda-authentication-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java index 626be200182313ad77e725a56fa21d35e8fa0d8f..a70f8ff45d907f3909d46593ce1e8a321837934b 100644 --- a/fda-authentication-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java +++ b/fda-authentication-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java @@ -51,11 +51,11 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { @Override public void grantUserHost(String username) throws BrokerUserCreationException { /* grant */ - final URI grantUrl = URI.create(gatewayConfig.getGatewayEndpoint() + "/api/permissions/%2F/ " + username); + final URI grantUrl = URI.create(gatewayConfig.getGatewayEndpoint() + "/api/broker/permissions/%2F/" + username); final GrantVirtualHostPermissionsDto grantDto = userMapper.signupRequestDtoToGrantComponentDto(); final ResponseEntity<Void> grantResponse = restTemplate.exchange(grantUrl, HttpMethod.PUT, new HttpEntity<>(grantDto, getHeaders()), Void.class); - if (!grantResponse.getStatusCode().equals(HttpStatus.ACCEPTED)) { + if (!grantResponse.getStatusCode().equals(HttpStatus.CREATED)) { log.error("Failed to grant permissions at queue service: {}", grantResponse.getStatusCode()); throw new BrokerUserCreationException("Failed to grant permissions at queue service"); } @@ -70,7 +70,7 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { final String modifyUrl = "/api/broker/users/" + username; final ResponseEntity<Void> response = restTemplate.exchange(modifyUrl, HttpMethod.PUT, new HttpEntity<>(data, getHeaders()), Void.class); - if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { + if (!response.getStatusCode().equals(HttpStatus.NO_CONTENT)) { log.error("Failed to update user password at queue service: {}", response.getStatusCode()); throw new BrokerUserCreationException("Failed to update user password at queue service"); } diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java new file mode 100644 index 0000000000000000000000000000000000000000..7aac059270ba2142163bf2ed98a89141168c36b4 --- /dev/null +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java @@ -0,0 +1,49 @@ +package at.tuwien.api.amqp; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.*; + +import javax.validation.constraints.NotNull; + +@Getter +@Setter +@ToString +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChannelDetailsDto { + + @NotNull + @JsonProperty("connection_name") + @Parameter(name = "connection name") + private String connectionName; + + @NotNull + @Parameter(name = "channel name") + private String name; + + @NotNull + @Parameter(name = "channel node") + private String node; + + @NotNull + @JsonProperty("number") + @Parameter(name = "channel number") + private Integer number; + + @NotNull + @JsonProperty("peer_host") + @Parameter(name = "channel peer host") + private String peerHost; + + @NotNull + @JsonProperty("peer_port") + @Parameter(name = "channel peer port") + private Integer peerPort; + + @NotNull + @Parameter(name = "channel user") + private String user; + +} diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java new file mode 100644 index 0000000000000000000000000000000000000000..cdef980445f853b80d58f60159a690fc6d138a48 --- /dev/null +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java @@ -0,0 +1,54 @@ +package at.tuwien.api.amqp; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.*; + +import javax.validation.constraints.NotNull; + +@Getter +@Setter +@ToString +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ConsumerDto { + + @NotNull + @JsonProperty("ack_required") + @Parameter(name = "acknowledge required") + private Boolean ackRequired; + + @NotNull + @Parameter(name = "active") + private Boolean active; + + @NotNull + @JsonProperty("activity_status") + @Parameter(name = "activity status") + private String activityStatus; + + @NotNull + @JsonProperty("channel_details") + @Parameter(name = "channel details") + private ChannelDetailsDto channelDetails; + + @NotNull + @JsonProperty("consumer_tag") + @Parameter(name = "consumer tag") + private String consumerTag; + + @NotNull + @Parameter(name = "exclusive") + private Boolean exclusive; + + @NotNull + @JsonProperty("prefetch_count") + @Parameter(name = "prefetch count") + private Integer prefetchCount; + + @NotNull + @Parameter(name = "queue") + private QueueBriefDto queue; + +} diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java new file mode 100644 index 0000000000000000000000000000000000000000..44364c19916e085adec32235a32c6318336de8df --- /dev/null +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java @@ -0,0 +1,24 @@ +package at.tuwien.api.amqp; + +import io.swagger.v3.oas.annotations.Parameter; +import lombok.*; + +import javax.validation.constraints.NotNull; + +@Getter +@Setter +@ToString +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class QueueBriefDto { + + @NotNull + @Parameter(name = "queue vhost") + private String vhost; + + @NotNull + @Parameter(name = "queue name") + private String name; + +} diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java index 464843d2fb8cc14872dda8b624c1a9d3d7aa688f..72f9bfd29ec72b3c7e25d78e8b74a8e0ae82a6e8 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java @@ -47,4 +47,9 @@ public class UserBriefDto { @Parameter(name = "theme dark") private Boolean themeDark; + @NotNull + @JsonProperty("email_verified") + @Parameter(name = "mail address verified") + private Boolean emailVerified; + } diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java index 5aa97d86626eadd6684c1002932762129e7d21ac..490af62b4e3936a58df98602189e5eb43628a1da 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java @@ -72,6 +72,7 @@ public class UserDto { @Parameter(name = "mail address") private String email; + @NotNull @JsonProperty("email_verified") @Parameter(name = "mail address verified") private Boolean emailVerified; diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ConsumerEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ConsumerEndpoint.java deleted file mode 100644 index 7fcf45024dc9af3fe910e2939ccf08ca3a748e81..0000000000000000000000000000000000000000 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ConsumerEndpoint.java +++ /dev/null @@ -1,52 +0,0 @@ -package at.tuwien.endpoint; - -import at.tuwien.entities.database.table.Table; -import at.tuwien.exception.*; -import at.tuwien.service.*; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; - -import javax.validation.constraints.NotNull; -import java.security.Principal; - -@Log4j2 -@CrossOrigin(origins = "*") -@RestController -@RequestMapping("/api/container/{id}/database/{databaseId}/table/{tableId}/consumer") -public class ConsumerEndpoint extends AbstractEndpoint { - - private final TableService tableService; - private final MessageQueueService messageQueueService; - - @Autowired - public ConsumerEndpoint(DatabaseService databaseService, IdentifierService identifierService, - TableService tableService, MessageQueueService messageQueueService) { - super(databaseService, identifierService); - this.tableService = tableService; - this.messageQueueService = messageQueueService; - } - - @PostMapping - @Transactional - @Operation(summary = "Declare consumer", security = @SecurityRequirement(name = "bearerAuth")) - public ResponseEntity<Void> declare(@NotNull @PathVariable("id") Long containerId, - @NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId, - @NotNull Principal principal) - throws TableNotFoundException, DatabaseNotFoundException, AmqpException, NotAllowedException { - if (!hasDatabasePermission(containerId, databaseId, "QUEUE_CREATE_CONSUMER", principal)) { - log.error("Missing queue create consumer permission"); - throw new NotAllowedException("Missing queue create consumer permission"); - } - final Table table = tableService.find(containerId, databaseId, tableId); - messageQueueService.createConsumer(table.getTopic(), containerId, databaseId, tableId); - return ResponseEntity.accepted() - .build(); - } - -} diff --git a/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index a6a8a2003ea62692634571d94edd5cc37f177d32..daa14ed009686194a3f0e6edea0aed2f8424830c 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -1,11 +1,13 @@ package at.tuwien.config; +import lombok.Getter; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; +@Getter @Configuration public class GatewayConfig { diff --git a/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java b/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java new file mode 100644 index 0000000000000000000000000000000000000000..8a5bc1c3f10f354b0cf1bd850ed208419bb147e3 --- /dev/null +++ b/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java @@ -0,0 +1,9 @@ +package at.tuwien.gateway; + +import at.tuwien.api.amqp.ConsumerDto; + +import java.util.List; + +public interface BrokerServiceGateway { + List<ConsumerDto> findAllConsumers(); +} diff --git a/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..692b2d5ded32fe9f3137288d56bc220dc8c0c4d6 --- /dev/null +++ b/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java @@ -0,0 +1,60 @@ +package at.tuwien.gateway.impl; + +import at.tuwien.api.amqp.ConsumerDto; +import at.tuwien.config.AmqpConfig; +import at.tuwien.config.GatewayConfig; +import at.tuwien.gateway.BrokerServiceGateway; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +@Service +public class BrokerServiceGatewayImpl implements BrokerServiceGateway { + + private final AmqpConfig amqpConfig; + private final RestTemplate restTemplate; + private final GatewayConfig gatewayConfig; + + @Autowired + public BrokerServiceGatewayImpl(AmqpConfig amqpConfig, RestTemplate restTemplate, GatewayConfig gatewayConfig) { + this.amqpConfig = amqpConfig; + this.restTemplate = restTemplate; + this.gatewayConfig = gatewayConfig; + } + + @Override + public List<ConsumerDto> findAllConsumers() { + final URI findUri = URI.create(gatewayConfig.getGatewayEndpoint() + "/api/broker/consumers/%2F"); + final ResponseEntity<List<ConsumerDto>> response = restTemplate.exchange(findUri, HttpMethod.GET, + new HttpEntity<>(null, getHeaders()), new ParameterizedTypeReference<>() { + }); + return response.getBody(); + } + + /** + * Retrieves the authentication headers from the configuration for the broker service. + * + * @return The headers. + */ + private HttpHeaders getHeaders() { + return new HttpHeaders() {{ + String auth = amqpConfig.getAmqpUsername() + ":" + amqpConfig.getAmqpPassword(); + byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.defaultCharset())); + String authHeader = "Basic " + new String(encodedAuth); + set("Authorization", authHeader); + }}; + } + +} diff --git a/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java b/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java new file mode 100644 index 0000000000000000000000000000000000000000..ebdc5a473931d742f7199067a78468947ee4c597 --- /dev/null +++ b/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java @@ -0,0 +1,4 @@ +package at.tuwien.listener; + +public interface MessageQueueListener { +} diff --git a/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java b/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6f5304684cfa089a70948aa82d359fcb61f30644 --- /dev/null +++ b/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java @@ -0,0 +1,49 @@ +package at.tuwien.listener.impl; + +import at.tuwien.api.amqp.ConsumerDto; +import at.tuwien.entities.database.table.Table; +import at.tuwien.exception.AmqpException; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; +import at.tuwien.service.MessageQueueService; +import at.tuwien.service.TableService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Log4j2 +@Service +public class RabbitMqListenerImpl implements MessageQueueListener { + + private final TableService tableService; + private final MessageQueueService messageQueueService; + private final BrokerServiceGateway brokerServiceGateway; + + @Autowired + public RabbitMqListenerImpl(TableService tableService, MessageQueueService messageQueueService, + BrokerServiceGateway brokerServiceGateway) { + this.tableService = tableService; + this.messageQueueService = messageQueueService; + this.brokerServiceGateway = brokerServiceGateway; + } + + @Scheduled(fixedDelay = 5000) + @Transactional(readOnly = true) + public void updateConsumers() throws AmqpException { + final List<Table> tables = tableService.findAll(); + final List<ConsumerDto> consumers = brokerServiceGateway.findAllConsumers(); + for (Table table : tables) { + if (consumers.stream().anyMatch(c -> c.getQueue().getName().equals(table.getTopic()))) { + log.trace("table {} already has a consumer, skip.", table); + continue; + } + messageQueueService.createConsumer(table.getTopic(), table.getDatabase().getContainer().getId(), + table.getDatabase().getId(), table.getId()); + } + } + +} diff --git a/fda-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/fda-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 1434d7a0853c235ad7cd669f4344bbe10c764383..aff6857f43f39cb9974d91e21ee143a042f3640d 100644 --- a/fda-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/fda-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -164,7 +164,7 @@ public class TableServiceImpl extends HibernateConnector implements TableService dataSource1.close(); } /* save in metadata database */ - final Table table = tableRepository.saveAndFlush(entity); + final Table table = tableRepository.save(entity); log.info("Created table with id {}", table.getId()); log.debug("created table {}", table); /* save in elastic search */ diff --git a/fda-ui/components/TableList.vue b/fda-ui/components/TableList.vue index 1ec27ab34debc7dcaf421b32abfa83e0f85454d7..ab977f80909bb7074292d926420be391d8def3f8 100644 --- a/fda-ui/components/TableList.vue +++ b/fda-ui/components/TableList.vue @@ -55,6 +55,25 @@ </v-list-item-content> </v-list-item-content> </v-list-item> + <v-list-item> + <v-list-item-content> + <v-list-item-title> + AMQP Consumer(s) + </v-list-item-title> + <v-list-item-content class="amqp-consumer"> + {{ tableDetails.consumers.length }} <v-badge + v-if="!tableDetails.consumersUp" + class="ml-1" + color="error" + content="down" /> + <v-badge + v-if="tableDetails.consumersUp" + class="ml-1" + color="success" + content="up" /> + </v-list-item-content> + </v-list-item-content> + </v-list-item> <v-list-item> <v-list-item-content> <v-list-item-title> @@ -184,7 +203,9 @@ export default { description: null, topic: null, columns: [], - created: null + created: null, + consumers: [], + consumersUp: false }, dialogDelete: false, headers: [ @@ -268,6 +289,7 @@ export default { console.debug('table details', this.tableDetails) if (tableId) { this.openPanelByTableId(tableId) + await this.consumerDetails(this.tableDetails.topic) } } catch (err) { this.$toast.error('Failed to load table details') @@ -306,6 +328,23 @@ export default { } this.dialogDelete = false }, + async consumerDetails (topic) { + try { + this.loading = true + const res = await this.$axios.get('/api/broker/consumers/%2F', { + headers: { Authorization: 'Basic ZmRhOmZkYQ==' } + }) + const consumers = res.data.filter(c => c.queue.name === topic) + console.debug('consumers', consumers) + const state = res.data.filter(c => c.queue.name === topic && c.active) + this.tableDetails.consumers = consumers + this.tableDetails.consumersUp = consumers.length === state.length + this.loading = false + } catch (err) { + this.$toast.error('Could not find consumers.') + } + this.dialogDelete = false + }, showDeleteTableDialog (id) { this.deleteTableId = id this.dialogDelete = true @@ -333,4 +372,7 @@ export default { .full-width { width: 100%; } +.amqp-consumer { + display: inline; +} </style> diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue index 1a6cfad60f865d9f1d880b35977720c283e58a42..04380873be406eeaf7c86602a95cddddbb0c713c 100644 --- a/fda-ui/layouts/default.vue +++ b/fda-ui/layouts/default.vue @@ -43,7 +43,9 @@ <v-icon left>mdi-account-plus</v-icon> Signup </v-btn> <v-btn v-if="username" to="/user" plain> - {{ username }} + {{ username }} <sup v-if="user.email_verified"> + <v-icon color="primary" title="E-Mail verified" small>mdi-check-decagram</v-icon> + </sup> </v-btn> <v-menu bottom offset-y left> <template v-slot:activator="{ on, attrs }"> diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue index e2c628149809449cdd710e260d424f282c4cc5ed..6b2011cc5788fd16f5b301e557d3cdca3e0f8717 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue @@ -159,8 +159,7 @@ <v-list-item-content> <v-skeleton-loader v-if="loadingQuery" type="text" class="skeleton-small" /> <span v-if="!loadingQuery"> - {{ creator }} - <sup> + {{ creator }} <sup> <v-icon v-if="database.creator.email_verified" small color="primary">mdi-check-decagram</v-icon> </sup> </span> diff --git a/fda-ui/pages/user/index.vue b/fda-ui/pages/user/index.vue index f85a9a9c4448f2db6bdb89c7ae7eb26029a84881..b95b203dffc41cd7d87233ee794edf03f25848e8 100644 --- a/fda-ui/pages/user/index.vue +++ b/fda-ui/pages/user/index.vue @@ -108,7 +108,7 @@ <v-text-field v-model="user.orcid" :disabled="error" - :rules="[v => validateOrcid(v) || $t('Invalid ORCID')]" + :rules="[v => !!v || $t('Required')]" maxlength="19" hint="e.g. 0000-0002-1825-0097" label="ORCID" /> @@ -178,7 +178,6 @@ </div> </template> <script> -import { isValidOrcid } from '@/utils' export default { data () { return { @@ -264,12 +263,6 @@ export default { } this.loading = false }, - validateOrcid (orcid) { - if (!orcid) { - return true - } - return isValidOrcid(orcid) - }, async resend () { try { this.loading = true diff --git a/fda-ui/utils/index.js b/fda-ui/utils/index.js index 619ebbdbae08796810bc0d7cf3ef929009fa13eb..a36767b8b35b8a19180faec3c7e00a11f9fecd32 100644 --- a/fda-ui/utils/index.js +++ b/fda-ui/utils/index.js @@ -28,32 +28,6 @@ function isNonNegativeInteger (str) { return str >>> 0 === parseFloat(str) } -/** - * https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier - * @param str The ORCID - * @returns {boolean} True if ORCID is valid, false otherwise - */ -function isValidOrcid (str) { - if (str == null) { - return false - } - if (str.length !== 19) { - return false - } - let total = 0 - for (let i = 0; i < str.length; i++) { - const digit = parseInt(str.charAt(i)) - if (isNaN(digit)) { - continue - } - total = (total + digit) * 2 - } - const remainder = total % 11 - const result = (12 - remainder) % 11 - const check = result === 10 ? 'X' : result.toString() - return str.substr(18) === check -} - function formatUser (user) { if (user.firstname && user.lastname) { let name = '' @@ -131,7 +105,6 @@ module.exports = { formatTimestampUTCLabel, formatDateUTC, isNonNegativeInteger, - isValidOrcid, formatUser, formatYearUTC, formatMonthUTC,