diff --git a/.docs/.swagger/api.yaml b/.docs/.swagger/api.yaml index 7ba582ed3fba3ec1282918bff9f937f57dca36e2..607276e81a651c7f1fd0b91a1894d7a2c8aef9b4 100644 --- a/.docs/.swagger/api.yaml +++ b/.docs/.swagger/api.yaml @@ -1,4 +1,17 @@ -openapi: 3.0.3 +components: + securitySchemes: + basicAuth: + in: header + scheme: basic + type: http + bearerAuth: + bearerFormat: JWT + in: header + scheme: bearer + type: http +externalDocs: + description: Sourcecode Documentation + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/ info: contact: email: andreas.rauber@tuwien.ac.at @@ -6,142 +19,67 @@ info: description: The REST API license: name: Apache 2.0 - url: 'https://www.apache.org/licenses/LICENSE-2.0' + url: https://www.apache.org/licenses/LICENSE-2.0 title: DBRepo REST API version: 1.4.4 +openapi: 3.1.0 servers: - description: Test Instance - url: 'https://test.dbrepo.tuwien.ac.at' + url: https://test.dbrepo.tuwien.ac.at - description: Local Instance - url: 'http://localhost' -externalDocs: - description: Sourcecode Documentation - url: 'https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/' + url: http://localhost paths: - /api/analyse/datatypes: - get: - consumes: - - application/json - description: This is a simple API which returns the datatypes of a (path) csv file - operationId: analyse_datatypes - parameters: - - example: filename_s3_key - in: query - name: filename - required: true - schema: - type: string - - example: ',' - in: query - name: separator - required: true - schema: - type: string - - example: 'false' - in: query - name: enum - required: false - schema: - type: boolean - - example: '2.5' - in: query - name: enum_tol - required: false - schema: - type: float - produces: - - application/json + /api/database: + post: + tags: + - database-endpoint + summary: Create database + operationId: create + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDatabaseDto' + required: true responses: - '202': - content: - application/json: - schema: - $ref: '#/components/schemas/DataTypesDto' - description: Determined data types successfully - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to determine data types - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to find file in Storage Service - '500': + "201": + description: Created a database content: application/json: schema: - $ref: '#/components/schemas/ErrorDto' - description: Unexpected system error - security: - - bearerAuth: [] - - basicAuth: [] - summary: Determine datatypes - tags: - - analyse-endpoint - /api/analyse/keys: - get: - consumes: - - application/json - description: >- - This is a simple API which returns the primary keys + ranking of a - (path) csv file - operationId: analyse_keys - parameters: - - example: filename_s3_key - in: query - name: filename - required: true - schema: - type: string - - example: ',' - in: query - name: separator - required: true - schema: - type: string - produces: - - application/json - responses: - '202': + $ref: '#/components/schemas/DatabaseDto' + "400": + description: Database create query is malformed or image is not supported content: application/json: schema: - $ref: '#/components/schemas/KeysDto' - description: Determined keys successfully - '400': + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to create query store in database content: application/json: schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to determine keys - '404': + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database content: application/json: schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to find file in Storage Service or is empty - '500': + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find container in metadata database content: application/json: schema: - $ref: '#/components/schemas/ErrorDto' - description: Unexpected system error + $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - summary: Determine primary keys - tags: - - analyse-endpoint - '/api/database/{databaseId}/view/{viewId}/data': - get: + /api/database/{databaseId}/access/{userId}: + put: tags: - - view-endpoint - summary: Retrieve view data - operationId: getData + - access-endpoint + summary: Update access to some database + operationId: update_1 parameters: - name: databaseId in: path @@ -149,75 +87,58 @@ paths: schema: type: integer format: int64 - - name: viewId + - name: userId in: path required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false schema: type: string - format: date-time + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDatabaseAccessDto' + required: true responses: - '200': - description: Retrieved view data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Request pagination is malformed + "400": + description: Update access query or database connection is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to retrieve view data + "417": + description: Failed to update access in database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find view in metadata database + "503": + description: Failed to establish connection with metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: View schema could not be mapped + "403": + description: Not allowed to update access content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + "404": + description: Failed to find database/user in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Update access succeeded security: - basicAuth: [] - - bearerAuth: [] - head: + post: tags: - - view-endpoint - summary: Retrieve view data - operationId: getData_1 + - access-endpoint + summary: Give access to some database + operationId: create_4 parameters: - name: databaseId in: path @@ -225,76 +146,62 @@ paths: schema: type: integer format: int64 - - name: viewId + - name: userId in: path required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false schema: type: string - format: date-time + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDatabaseAccessDto' + required: true responses: - '200': - description: Retrieved view data + "417": + description: Failed to give access in the database content: application/json: schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Request pagination is malformed + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Granting access succeeded content: - application/json: + '*/*': schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to retrieve view data + type: object + "503": + description: Failed to establish connection to metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find view in metadata database + "403": + description: Not allowed to give access content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: View schema could not be mapped + "404": + description: Failed to find database/user in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + "400": + description: Granting access query or database connection is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - basicAuth: [] - - bearerAuth: [] - '/api/database/{databaseId}/table/{tableId}/data': - get: + delete: tags: - - table-endpoint - summary: Retrieve table data - operationId: getData_2 + - access-endpoint + summary: Revoke access to some database + operationId: revoke parameters: - name: databaseId in: path @@ -302,442 +209,297 @@ paths: schema: type: integer format: int64 - - name: tableId + - name: userId in: path required: true - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false schema: type: string - format: date-time - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 + format: uuid responses: - '200': - description: Retrieved table data + "400": + description: Revoke access query or database connection is malformed content: application/json: schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Request pagination or table data select query is malformed + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to revoke access in database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + "403": + description: Not allowed to revoke access content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': + "503": description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - - bearerAuth: [] - put: + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Revoked access successfully + content: + '*/*': + schema: + type: object + security: + - basicAuth: [] + /api/user/{userId}: + get: tags: - - table-endpoint - summary: Update a raw data tuple - description: >- - Updates a raw data tuple in a table with at least WRITE_OWN access. Then - update the table statistics. - operationId: updateRawTuple + - user-endpoint + summary: Get a user info + operationId: find_2 parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId + - name: userId in: path required: true schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TupleUpdateDto' - required: true + type: string + format: uuid responses: - '202': - description: Updated table data - '400': - description: Request pagination or table data select query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Update table data not allowed + "403": + description: Find user is not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + "200": + description: Found user content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + $ref: '#/components/schemas/UserDto' + "404": + description: User was not found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - basicAuth: [] - bearerAuth: [] - post: + - basicAuth: [] + put: tags: - - table-endpoint - summary: Insert a raw data tuple - description: >- - Inserts a raw data tuple into a table with at least WRITE_OWN access. - Then update the table statistics. - operationId: insertRawTuple + - user-endpoint + summary: Modify user information + operationId: modify parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId + - name: userId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: schema: - $ref: '#/components/schemas/TupleDto' + $ref: '#/components/schemas/UserUpdateDto' required: true responses: - '201': - description: Created table data - '400': - description: Request pagination or table data select query is malformed + "404": + description: Failed to find database/user in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Create table data not allowed + "403": + description: Not allowed to modify user metadata content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database or blob in storage service + "400": + description: Modify user query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: >- - Failed to establish connection with the metadata service or storage - service + "202": + description: Modified user information content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/UserDto' security: - - basicAuth: [] - bearerAuth: [] - delete: + - basicAuth: [] + /api/user/{userId}/password: + put: tags: - - table-endpoint - summary: Delete table data - description: >- - Deletes a raw data tuple in a table with at least WRITE_OWN access. Then - update the table statistics. - operationId: deleteRawTuple + - user-endpoint + summary: Modify user password + operationId: password parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId + - name: userId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: schema: - $ref: '#/components/schemas/TupleDeleteDto' + $ref: '#/components/schemas/UserPasswordDto' required: true responses: - '202': - description: Deleted table data - '400': - description: Request pagination or table data select query is malformed + "403": + description: Not allowed to change foreign user password content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Delete table data not allowed + "404": + description: Failed to find database/user in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + "503": + description: Failed to get user in auth service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + "202": + description: Modified user password + content: + application/json: + schema: + $ref: '#/components/schemas/UserDto' + "502": + description: Connection to auth service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - basicAuth: [] - bearerAuth: [] - head: + - basicAuth: [] + /api/user/token: + put: tags: - - table-endpoint - summary: Retrieve table data - operationId: getData_3 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 + - user-endpoint + summary: Refresh user token + operationId: refreshToken + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RefreshTokenRequestDto' + required: true responses: - '200': - description: Retrieved table data + "202": + description: Refreshed user token content: application/json: schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Request pagination or table data select query is malformed + $ref: '#/components/schemas/TokenDto' + "502": + description: Connection to auth service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + "403": + description: Invalid refresh token content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + post: + tags: + - user-endpoint + summary: Obtain user token + operationId: getToken + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LoginRequestDto' + required: true + responses: + "404": + description: Failed to find user in auth database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - - bearerAuth: [] - '/api/database/{databaseId}/subset/{subsetId}/data': - get: - tags: - - subset-endpoint - summary: Retrieved subset data - operationId: getData_4 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: subsetId - in: path - required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - responses: - '200': - description: Retrieved subset data + "503": + description: Failed to get user in auth service content: application/json: schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Malformed select query + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Obtained user token content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to retrieve subset data + $ref: '#/components/schemas/TokenDto' + "403": + description: Not allowed to get token content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: >- - Failed to find database in metadata database or query in query store - of the data database + "428": + description: Account is not fully setup in auth service (requires password change?) content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to communicate with database + "502": + description: Connection to auth service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - head: + /api/ontology/{ontologyId}: + get: tags: - - subset-endpoint - summary: Retrieved subset data - operationId: getData_5 + - ontology-endpoint + summary: Find one ontology + operationId: find_3 parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: subsetId + - name: ontologyId in: path required: true schema: type: integer format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 responses: - '200': - description: Retrieved subset data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Malformed select query - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to retrieve subset data - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: >- - Failed to find database in metadata database or query in query store - of the data database + "404": + description: Could not find ontology content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to communicate with database + "200": + description: Find one ontology content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/database/{databaseId}/subset/{queryId}': + $ref: '#/components/schemas/OntologyDto' put: tags: - - subset-endpoint - summary: Persist subset - operationId: persist + - ontology-endpoint + summary: Update an ontology + operationId: update parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: queryId + - name: ontologyId in: path required: true schema: @@ -747,67 +509,58 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/QueryPersistDto' + $ref: '#/components/schemas/OntologyModifyDto' required: true responses: - '202': - description: Persisted subset - content: - application/json: - schema: - $ref: '#/components/schemas/QueryDto' - '400': - description: Malformed select query - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to persist subset - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: >- - Failed to find database in metadata database or query in query store - of the data database - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '417': - description: Failed to persist subset + "404": + description: Could not find ontology content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to communicate with database + "202": + description: Updated ontology successfully content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/OntologyDto' security: - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/table/{tableId}/data/import': - post: + delete: tags: - - table-endpoint - summary: Import data from a dataset - description: >- - Deletes a raw data tuple in a table with at least WRITE_OWN access. Then - update the table statistics. - operationId: importDataset + - ontology-endpoint + summary: Delete an ontology + operationId: delete parameters: - - name: databaseId + - name: ontologyId in: path required: true schema: type: integer format: int64 - - name: tableId + responses: + "404": + description: Could not find ontology + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Deleted ontology successfully + content: + application/json: {} + security: + - bearerAuth: [] + - basicAuth: [] + /api/message/{messageId}: + put: + tags: + - message-endpoint + summary: Update maintenance message + operationId: update_1 + parameters: + - name: messageId in: path required: true schema: @@ -817,476 +570,430 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ImportCsvDto' + $ref: '#/components/schemas/BannerMessageUpdateDto' required: true responses: - '202': - description: Imported dataset successfully - '400': - description: Dataset query is malformed + "202": + description: Updated message content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Import table dataset not allowed + $ref: '#/components/schemas/BannerMessageBriefDto' + "404": + description: Could not find message content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - message-endpoint + summary: Delete maintenance message + operationId: delete_1 + parameters: + - name: messageId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "202": + description: Deleted message content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + application/json: {} + "404": + description: Could not find message content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - basicAuth: [] - bearerAuth: [] - '/api/database/{databaseId}/subset': + - basicAuth: [] + /api/image/{imageId}: get: tags: - - subset-endpoint - summary: Find subsets - operationId: list + - image-endpoint + summary: Find some image + operationId: findById parameters: - - name: databaseId + - name: imageId in: path required: true schema: type: integer format: int64 - - name: persisted - in: query - required: false - schema: - type: boolean responses: - '200': - description: Found subsets + "404": + description: Image could not be found content: application/json: schema: - type: string - '403': - description: Not allowed to find subsets + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found image content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: >- - Failed to find database in metadata database or query in query store - of the data database + $ref: '#/components/schemas/ImageDto' + put: + tags: + - image-endpoint + summary: Update some image + operationId: update_2 + parameters: + - name: imageId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImageChangeDto' + required: true + responses: + "404": + description: Image could not be found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to communicate with database + "202": + description: Updated image successfully content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/ImageDto' security: - - basicAuth: [] - bearerAuth: [] - post: + - basicAuth: [] + delete: tags: - - subset-endpoint - summary: Create subset - operationId: create + - image-endpoint + summary: Delete some image + operationId: delete_2 parameters: - - name: databaseId + - name: imageId in: path required: true schema: type: integer format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false + responses: + "202": + description: Deleted image successfully + "404": + description: Image could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/identifier/{identifierId}: + get: + tags: + - identifier-endpoint + summary: Find some identifier + operationId: find_6 + parameters: + - name: identifierId + in: path + required: true schema: type: integer format: int64 - - name: timestamp - in: query - required: false + - name: Accept + in: header + required: true schema: type: string - format: date-time - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ExecuteStatementDto' - required: true responses: - '201': - description: Created subset - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - '400': - description: Malformed select query + "406": + description: Failed to find acceptable representation content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to find subset + "422": + description: Failed to retrieve from database sidecar content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: >- - Failed to find database in metadata database or query in query store - of the data database + "503": + description: Failed to find in data service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '417': - description: Failed to insert query into query store of data database + "200": + description: Found identifier successfully content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '501': - description: Failed to execute query as it contains non-supported keywords - content: - application/json: + $ref: '#/components/schemas/IdentifierDto' + application/ld+json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to communicate with database + $ref: '#/components/schemas/LdDatasetDto' + text/csv: {} + text/xml: {} + text/bibliography: {} + text/bibliography; style=apa: {} + text/bibliography; style=ieee: {} + text/bibliography; style=bibtex: {} + "404": + description: Identifier could not be found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - - bearerAuth: [] - '/api/database/{databaseId}/table/{tableId}/statistic': - get: - tags: - - table-endpoint - summary: Generate table statistic - operationId: statistic - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Generated table statistic + "502": + description: Connection to data service failed content: application/json: schema: - $ref: '#/components/schemas/TableStatisticDto' - '400': - description: Failed to obtain column statistic + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: "Identifier could not be exported, the requested style is not known" content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + "410": + description: Failed to retrieve from S3 endpoint content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + "409": + description: Exported resource was not found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '/api/database/{databaseId}/table/{tableId}/history': - get: + put: tags: - - table-endpoint - summary: Find table history - description: >- - Lists the insert/delete operations performed. Authentication is only - required for tables in private databases - operationId: getHistory + - identifier-endpoint + summary: Save identifier + operationId: save parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId + - name: identifierId in: path required: true schema: type: integer format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierSaveDto' + required: true responses: - '200': - description: Found table history + "403": + description: Insufficient access rights or authorities + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "405": + description: Creating identifier not permitted content: application/json: schema: - type: string - '400': - description: Invalid pagination request + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Identifier form contains invalid request data content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Find table history not allowed + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table history in data database + "202": + description: Saved identifier content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + $ref: '#/components/schemas/IdentifierDto' + "503": + description: Failed to save in search service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - basicAuth: [] - bearerAuth: [] - '/api/database/{databaseId}/table/{tableId}/export': - get: + - basicAuth: [] + delete: tags: - - table-endpoint - summary: Export table data - operationId: exportData + - identifier-endpoint + summary: Delete some identifier + operationId: delete_3 parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId + - name: identifierId in: path required: true schema: type: integer format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time responses: - '200': - description: Exported table data + "502": + description: Connection to search service failed content: application/json: schema: - type: string - format: binary - '400': - description: Request pagination or table data select query is malformed + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Deleting identifier not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Export table data not allowed + "503": + description: Failed to delete in search service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find table in metadata database + "202": + description: Deleted identifier content: - application/json: + '*/*': schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to establish connection with the metadata service + type: object + "404": + description: Identifier or database could not be found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - basicAuth: [] - bearerAuth: [] - '/api/database/{databaseId}/subset/{subsetId}': - get: + - basicAuth: [] + /api/identifier/{identifierId}/publish: + put: tags: - - subset-endpoint - summary: Find subset - operationId: findById + - identifier-endpoint + summary: Publish identifier + operationId: publish parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: subsetId + - name: identifierId in: path required: true schema: type: integer format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time responses: - '200': - description: Found subset + "403": + description: Insufficient access rights or authorities content: application/json: schema: - $ref: '#/components/schemas/QueryDto' - text/csv: {} - '400': - description: Malformed select query + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to find subset + "405": + description: Creating identifier not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: >- - Failed to find database in metadata database or query in query store - of the data database + "400": + description: Identifier form contains invalid request data content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '406': - description: Failed to find acceptable representation + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to communicate with database + "202": + description: Published identifier + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierDto' + "503": + description: Failed to save in search service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - basicAuth: [] - bearerAuth: [] - /api/database: - get: + - basicAuth: [] + /api/database/{databaseId}/visibility: + put: tags: - database-endpoint - summary: List databases - operationId: list1 + summary: Update database visibility + operationId: visibility parameters: - - name: internal_name - in: query - required: false + - name: databaseId + in: path + required: true schema: - type: string - responses: - '200': - description: List of databases - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DatabaseDto' - post: - tags: - - database-endpoint - summary: Create database - operationId: create_5 + type: integer + format: int64 requestBody: content: application/json: schema: - $ref: '#/components/schemas/DatabaseCreateDto' + $ref: '#/components/schemas/DatabaseModifyVisibilityDto' required: true responses: - '201': - description: Created a new database + "202": + description: Visibility modified successfully content: application/json: schema: $ref: '#/components/schemas/DatabaseDto' - '400': - description: Database create query is malformed or image is not supported - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: >- - Database create permission is missing or grant permissions at broker - service failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to fin container/user/database in metadata database + "403": + description: Visibility modification is not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: Query store could not be created + "502": + description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "404": + description: Failed to find database in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': + "503": description: Failed to save in search service content: application/json: @@ -1295,32 +1002,12 @@ paths: security: - bearerAuth: [] - basicAuth: [] - head: - tags: - - database-endpoint - summary: List databases - operationId: list_1 - parameters: - - name: internal_name - in: query - required: false - schema: - type: string - responses: - '200': - description: List of databases - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DatabaseDto' - '/api/database/{databaseId}/access/{userId}': - get: + /api/database/{databaseId}/table/{tableId}: + delete: tags: - - access-endpoint - summary: Check access to some database - operationId: find + - table-endpoint + summary: Delete table + operationId: delete_1 parameters: - name: databaseId in: path @@ -1328,103 +1015,45 @@ paths: schema: type: integer format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - '200': - description: Found database access - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseAccessDto' - '403': - description: No access to this database - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - put: - tags: - - access-endpoint - summary: Modify access to some database - operationId: update_4 - parameters: - - name: databaseId + - name: tableId in: path required: true schema: type: integer format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseAccessDto' - required: true responses: - '202': - description: Modify access succeeded - '400': - description: Modify access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: >- - Modify access not permitted when no access is granted in the first - place + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database or user not found + "202": + description: Deleted table content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: >- - Access could not be updated due to connection error in the data - service + $ref: '#/components/schemas/DatabaseDto' + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Access could not be updated in the data service + "400": + description: Deletion query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - post: + /api/database/{databaseId}/table/{tableId}/column/{columnId}: + put: tags: - - access-endpoint - summary: Give access to some database - operationId: create_8 + - table-endpoint + summary: Update a table column semantic mapping + operationId: update_3 parameters: - name: databaseId in: path @@ -1432,53 +1061,57 @@ paths: schema: type: integer format: int64 - - name: userId + - name: tableId in: path required: true schema: - type: string - format: uuid + type: integer + format: int64 + - name: columnId + in: path + required: true + schema: + type: integer + format: int64 requestBody: content: application/json: schema: - $ref: '#/components/schemas/UpdateDatabaseAccessDto' + $ref: '#/components/schemas/ColumnSemanticsUpdateDto' required: true responses: - '202': - description: Granting access succeeded - '400': - description: Granting access query or database connection is malformed + "400": + description: Update semantic concept query is malformed or update unit of measurement query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Failed giving access + "502": + description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database or user not found + "403": + description: Access to the database is forbidden content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '405': - description: Granting access not permitted + "202": + description: Updated column semantics successfully content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Access could not be created due to connection error + $ref: '#/components/schemas/ColumnDto' + "404": + description: Failed to find user/table/database/ontology in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Access could not be created in the data service + "503": + description: Failed to save in search service content: application/json: schema: @@ -1486,11 +1119,12 @@ paths: security: - bearerAuth: [] - basicAuth: [] - delete: + /api/database/{databaseId}/owner: + put: tags: - - access-endpoint - summary: Revoke access to some database - operationId: revoke + - database-endpoint + summary: Update database owner + operationId: transfer parameters: - name: databaseId in: path @@ -1498,41 +1132,39 @@ paths: schema: type: integer format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseTransferDto' + required: true responses: - '202': - description: Revoked access successfully - '400': - description: Modify access query or database connection is malformed + "403": + description: Transfer of ownership is not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Revoke of access not permitted as no access was found + "202": + description: Transfer of ownership was successful content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'User, database with access was not found' + $ref: '#/components/schemas/DatabaseDto' + "404": + description: Database or user could not be found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Access could not be created due to connection error + "502": + description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Access could not be revoked in the data service + "503": + description: Failed to save in search service content: application/json: schema: @@ -1540,11 +1172,12 @@ paths: security: - bearerAuth: [] - basicAuth: [] - head: + /api/database/{databaseId}/metadata/view: + put: tags: - - access-endpoint - summary: Check access to some database - operationId: find_1 + - database-endpoint + summary: Refresh database views metadata + operationId: refreshViewMetadata parameters: - name: databaseId in: path @@ -1552,62 +1185,33 @@ paths: schema: type: integer format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid responses: - '200': - description: Found database access - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseAccessDto' - '403': - description: No access to this database + "403": + description: Refresh view metadata is not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database not found + "502": + description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/user/{userId}': - get: - tags: - - user-endpoint - summary: Get a user info - operationId: find_2 - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - '200': - description: Found user + "200": + description: Refreshed database views metadata content: application/json: schema: - $ref: '#/components/schemas/UserDto' - '403': - description: Find user is not permitted + $ref: '#/components/schemas/DatabaseDto' + "404": + description: Failed to find database in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: User was not found + "503": + description: Failed to save in search service content: application/json: schema: @@ -1615,45 +1219,52 @@ paths: security: - bearerAuth: [] - basicAuth: [] + /api/database/{databaseId}/metadata/table: put: tags: - - user-endpoint - summary: Modify user information - operationId: modify + - database-endpoint + summary: Refresh database tables metadata + operationId: refreshTableMetadata parameters: - - name: userId + - name: databaseId in: path required: true schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateDto' - required: true + type: integer + format: int64 responses: - '202': - description: Modified user information + "200": + description: Refreshed database tables metadata content: application/json: schema: - $ref: '#/components/schemas/UserDto' - '400': - description: Modify user query is malformed + $ref: '#/components/schemas/DatabaseDto' + "400": + description: Failed to parse payload at search service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to modify user metadata + "403": + description: Not allowed to refresh table metadata content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database/user in metadata database + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to fin user/database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service content: application/json: schema: @@ -1661,52 +1272,58 @@ paths: security: - bearerAuth: [] - basicAuth: [] - '/api/user/{userId}/password': + /api/database/{databaseId}/image: put: tags: - - user-endpoint - summary: Modify user password - operationId: password + - database-endpoint + summary: Update database image + operationId: modifyImage parameters: - - name: userId + - name: databaseId in: path required: true schema: - type: string - format: uuid + type: integer + format: int64 requestBody: content: application/json: schema: - $ref: '#/components/schemas/UserPasswordDto' + $ref: '#/components/schemas/DatabaseModifyImageDto' required: true responses: - '202': - description: Modified user password + "404": + description: Database or user could not be found content: application/json: schema: - $ref: '#/components/schemas/UserDto' - '403': - description: Not allowed to change foreign user password + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database/user in metadata database + "202": + description: Modify of image was successful + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "410": + description: File was not found in the Storage Service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to auth service failed + "403": + description: Modify of image is not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to get user in auth service + "503": + description: Failed to save in search service content: application/json: schema: @@ -1714,311 +1331,192 @@ paths: security: - bearerAuth: [] - basicAuth: [] - /api/user/token: - put: + /api/user: + get: tags: - user-endpoint - summary: Refresh user token - operationId: refreshToken - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/RefreshTokenRequestDto' - required: true + summary: Find all users + operationId: findAll responses: - '202': - description: Refreshed user token - content: - application/json: - schema: - $ref: '#/components/schemas/TokenDto' - '403': - description: Invalid refresh token - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to auth service failed + "200": + description: List users content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + type: array + items: + $ref: '#/components/schemas/UserBriefDto' post: tags: - user-endpoint - summary: Obtain user token - operationId: getToken + summary: Create user + operationId: create requestBody: content: application/json: schema: - $ref: '#/components/schemas/LoginRequestDto' + $ref: '#/components/schemas/SignupRequestDto' required: true responses: - '202': - description: Obtained user token + "503": + description: Failed to create in auth service content: application/json: schema: - $ref: '#/components/schemas/TokenDto' - '403': - description: Not allowed to get token + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: User with e-mail already exists content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find user in auth database + "502": + description: Failed to create in auth service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '428': - description: >- - Account is not fully setup in auth service (requires password - change?) + "404": + description: default role not found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to auth service failed + "400": + description: Parameters are not well-formed (likely email) + content: + application/json: {} + "201": + description: Created user content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to get user in auth service + $ref: '#/components/schemas/UserBriefDto' + "409": + description: User with username already exists content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '/api/ontology/{ontologyId}': + /api/ontology: get: tags: - ontology-endpoint - summary: Find one ontology - operationId: find_3 - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 + summary: List all ontologies + operationId: findAll_2 responses: - '200': - description: Find one ontology - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - '404': - description: Could not find ontology + "200": + description: List all ontologies content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - put: + type: array + items: + $ref: '#/components/schemas/OntologyDto' + post: tags: - ontology-endpoint - summary: Update an ontology - operationId: update - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 + summary: Register a new ontology + operationId: create_1 requestBody: content: application/json: schema: - $ref: '#/components/schemas/OntologyModifyDto' + $ref: '#/components/schemas/OntologyCreateDto' required: true responses: - '202': - description: Updated ontology successfully + "201": + description: Registered ontology successfully content: application/json: schema: $ref: '#/components/schemas/OntologyDto' - '404': - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' security: - bearerAuth: [] - basicAuth: [] - delete: + /api/message: + get: tags: - - ontology-endpoint - summary: Delete an ontology - operationId: delete + - message-endpoint + summary: Find maintenance messages + operationId: list_2 parameters: - - name: ontologyId - in: path - required: true + - name: filter + in: query + required: false schema: - type: integer - format: int64 + type: string responses: - '202': - description: Deleted ontology successfully - content: - application/json: {} - '404': - description: Could not find ontology + "200": + description: List messages content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/message/{messageId}': - put: + type: array + items: + $ref: '#/components/schemas/BannerMessageDto' + post: tags: - message-endpoint - summary: Update maintenance message - operationId: update_1 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 + summary: Create maintenance message + operationId: create_2 requestBody: content: application/json: schema: - $ref: '#/components/schemas/BannerMessageUpdateDto' + $ref: '#/components/schemas/BannerMessageCreateDto' required: true responses: - '202': - description: Updated message + "201": + description: Created message content: application/json: schema: $ref: '#/components/schemas/BannerMessageBriefDto' - '404': - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - message-endpoint - summary: Delete maintenance message - operationId: delete_1 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '202': - description: Deleted message - content: - application/json: {} - '404': - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' security: - bearerAuth: [] - basicAuth: [] - '/api/image/{imageId}': + /api/image: get: tags: - image-endpoint - summary: Find some image - operationId: findById1 - parameters: - - name: imageId - in: path - required: true - schema: - type: integer - format: int64 + summary: Find all images + operationId: findAll_3 responses: - '200': - description: Found image - content: - application/json: - schema: - $ref: '#/components/schemas/ImageDto' - '404': - description: Image could not be found + "200": + description: List images content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - put: + type: array + items: + $ref: '#/components/schemas/ContainerImage' + post: tags: - image-endpoint - summary: Update some image - operationId: update_2 - parameters: - - name: imageId - in: path - required: true - schema: - type: integer - format: int64 + summary: Create image + operationId: create_3 requestBody: content: application/json: schema: - $ref: '#/components/schemas/ImageChangeDto' + $ref: '#/components/schemas/ImageCreateDto' required: true responses: - '202': - description: Updated image successfully + "201": + description: Created image content: application/json: schema: $ref: '#/components/schemas/ImageDto' - '404': - description: Image could not be found + "400": + description: Image specification is invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - image-endpoint - summary: Delete some image - operationId: delete_2 - parameters: - - name: imageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '202': - description: Deleted image successfully - '404': - description: Image could not be found + "409": + description: Image already exists content: application/json: schema: @@ -2026,16 +1524,34 @@ paths: security: - bearerAuth: [] - basicAuth: [] - '/api/identifier/{identifierId}': + /api/identifier: get: tags: - identifier-endpoint - summary: Find some identifier - operationId: find_6 + summary: Find all identifiers + operationId: findAll_4 parameters: - - name: identifierId - in: path - required: true + - name: dbid + in: query + required: false + schema: + type: integer + format: int64 + - name: qid + in: query + required: false + schema: + type: integer + format: int64 + - name: vid + in: query + required: false + schema: + type: integer + format: int64 + - name: tid + in: query + required: false schema: type: integer format: int64 @@ -2045,172 +1561,71 @@ paths: schema: type: string responses: - '200': - description: Found identifier successfully + "200": + description: Found identifiers successfully content: application/json: schema: - $ref: '#/components/schemas/IdentifierDto' + type: string application/ld+json: schema: - $ref: '#/components/schemas/LdDatasetDto' - text/csv: {} - text/xml: {} - text/bibliography: {} - text/bibliography; style=apa: {} - text/bibliography; style=ieee: {} - text/bibliography; style=bibtex: {} - '400': - description: 'Identifier could not be exported, the requested style is not known' - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Identifier could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '406': - description: Failed to find acceptable representation - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '409': - description: Exported resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '410': - description: Failed to retrieve from S3 endpoint - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '422': - description: Failed to retrieve from database sidecar - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to data service failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to find in data service + type: string + "406": + description: "Identifier could not be exported, the requested style is not known" content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - put: + post: tags: - identifier-endpoint - summary: Save identifier - operationId: save - parameters: - - name: identifierId - in: path - required: true - schema: - type: integer - format: int64 + summary: Draft identifier + operationId: create_4 requestBody: content: application/json: schema: - $ref: '#/components/schemas/IdentifierSaveDto' + $ref: '#/components/schemas/IdentifierCreateDto' required: true responses: - '202': - description: Saved identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - '400': - description: Identifier form contains invalid request data - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': + "403": description: Insufficient access rights or authorities content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Failed to find database, table or view' - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '405': - description: Creating identifier not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': + "502": description: Connection to search service failed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "405": + description: Creating identifier not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - identifier-endpoint - summary: Delete some identifier - operationId: delete_3 - parameters: - - name: identifierId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '202': - description: Deleted identifier - content: - '*/*': - schema: - type: object - '403': - description: Deleting identifier not permitted + "400": + description: Identifier form contains invalid request data content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Identifier or database could not be found + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "201": + description: Drafted identifier content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to delete in search service + $ref: '#/components/schemas/IdentifierDto' + "503": + description: Failed to save in search service content: application/json: schema: @@ -2218,71 +1633,61 @@ paths: security: - bearerAuth: [] - basicAuth: [] - '/api/identifier/{identifierId}/publish': - put: + /api/database/{databaseId}/view: + get: tags: - - identifier-endpoint - summary: Publish identifier - operationId: publish + - view-endpoint + summary: Find view schemas + operationId: getSchema parameters: - - name: identifierId + - name: databaseId in: path required: true schema: type: integer format: int64 responses: - '202': - description: Published identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - '400': - description: Identifier form contains invalid request data + "417": + description: View schema could not be retrieved content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Insufficient access rights or authorities + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Failed to find database, table or view' + "409": + description: View schema could not be mapped to known columns content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '405': - description: Creating identifier not permitted + "404": + description: Failed to find database/view in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "400": + description: Database schema is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "200": + description: Found view schemas content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/database/{databaseId}/visibility': - put: + type: string + post: tags: - - database-endpoint - summary: Update database visibility - operationId: visibility + - view-endpoint + summary: Create view + operationId: create_1 parameters: - name: databaseId in: path @@ -2294,48 +1699,48 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/DatabaseModifyVisibilityDto' + $ref: '#/components/schemas/ViewCreateDto' required: true responses: - '202': - description: Visibility modified successfully + "400": + description: View schema is malformed content: application/json: schema: - $ref: '#/components/schemas/DatabaseDto' - '403': - description: Visibility modification is not permitted + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database in metadata database + "409": + description: View schema could not be mapped content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "202": + description: Created view content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/ViewDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/table/{tableId}': + - bearerAuth: [] + /api/database/{databaseId}/table: get: tags: - table-endpoint - summary: Get information about table - operationId: findById_2 + summary: Find table schemas + operationId: getSchema_1 parameters: - name: databaseId in: path @@ -2343,51 +1748,48 @@ paths: schema: type: integer format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 responses: - '200': - description: Find table successfully + "403": + description: Find table schema not allowed content: application/json: schema: - $ref: '#/components/schemas/TableDto' - '403': - description: Access to the database is forbidden + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Table, database or container could not be found' + "417": + description: Failed to parse table schema content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "200": + description: Got table schemas + content: + application/json: + schema: + type: string + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "400": + description: Schema data malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - put: + post: tags: - table-endpoint - summary: Update table statistics - operationId: updateStatistic + summary: Create table + operationId: create_2 parameters: - name: databaseId in: path @@ -2395,162 +1797,167 @@ paths: schema: type: integer format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TableCreateDto' + required: true responses: - '202': - description: Updated table statistics successfully - '400': - description: Failed to map column statistic to known columns + "400": + description: Table schema or query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database/table in metadata database + "409": + description: Table name already exists in database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "404": + description: Failed to find database in metadata database or table in data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Created table + content: + application/json: + schema: + $ref: '#/components/schemas/TableDto' security: - - bearerAuth: [] - basicAuth: [] - delete: + /api/container: + get: tags: - - table-endpoint - summary: Delete a table - operationId: delete_5 + - container-endpoint + summary: Find all containers + operationId: findAll_6 parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true + - name: limit + in: query + required: false schema: type: integer - format: int64 + format: int32 responses: - '202': - description: Delete table successfully - '400': - description: Delete table query resulted in an invalid query statement - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Access to the database is forbidden + "200": + description: List containers content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Table, database or container could not be found' + type: array + items: + type: string + post: + tags: + - container-endpoint + summary: Create container + operationId: create_9 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ContainerCreateDto' + required: true + responses: + "404": + description: Container image or user could not be found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "409": + description: Container name already exists content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "201": + description: Created a new container content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/ContainerBriefDto' security: - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/table/{tableId}/column/{columnId}': - put: + /api/unit: + get: tags: - - table-endpoint - summary: Update a table column semantic mapping - operationId: update_3 + - unit-endpoint + summary: List semantic units + operationId: findAll_1 + responses: + "200": + description: Find all semantic units + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UnitDto' + /api/ontology/{ontologyId}/entity: + get: + tags: + - ontology-endpoint + summary: Find entities + operationId: find_4 parameters: - - name: databaseId + - name: ontologyId in: path required: true schema: type: integer format: int64 - - name: tableId - in: path - required: true + - name: label + in: query + required: false schema: - type: integer - format: int64 - - name: columnId - in: path - required: true + type: string + - name: uri + in: query + required: false schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ColumnSemanticsUpdateDto' - required: true + type: string responses: - '202': - description: Updated column semantics successfully - content: - application/json: - schema: - $ref: '#/components/schemas/ColumnDto' - '400': - description: >- - Update semantic concept query is malformed or update unit of - measurement query is malformed + "404": + description: Could not find ontology content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Access to the database is forbidden + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find user/table/database/ontology in metadata database + "200": + description: Found entities content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + type: array + items: + $ref: '#/components/schemas/EntityDto' + "400": + description: Filter params are invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "417": + description: Generated query or uri is malformed content: application/json: schema: @@ -2558,65 +1965,97 @@ paths: security: - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/owner': - put: + /api/oai: + get: tags: - - database-endpoint - summary: Update database owner - operationId: transfer + - metadata-endpoint + summary: Get the record + operationId: identify_1_1_1_1 parameters: - - name: databaseId + - name: verb + in: query + - name: parameters + in: query + required: true + schema: + $ref: '#/components/schemas/OaiListIdentifiersParameters' + responses: + "200": + description: List containers + content: + text/xml: {} + /api/message/message/{messageId}: + get: + tags: + - message-endpoint + summary: Find one maintenance message + operationId: find_5 + parameters: + - name: messageId in: path required: true schema: type: integer format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseTransferDto' - required: true responses: - '202': - description: Transfer of ownership was successful + "200": + description: Get messages content: application/json: schema: - $ref: '#/components/schemas/DatabaseDto' - '403': - description: Transfer of ownership is not permitted + $ref: '#/components/schemas/BannerMessageDto' + "404": + description: Could not find message content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database or user could not be found + /api/license: + get: + tags: + - license-endpoint + summary: Get all licenses + operationId: list_3 + responses: + "200": + description: List of licenses content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + type: array + items: + type: string + /api/identifier/retrieve: + get: + tags: + - identifier-endpoint + summary: Retrieve metadata from identifier + operationId: retrieve + parameters: + - name: url + in: query + required: true + schema: + type: string + responses: + "200": + description: Retrieved metadata from identifier content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + $ref: '#/components/schemas/IdentifierDto' + "404": + description: Failed to find metadata for identifier content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/database/{databaseId}/metadata/view': + /api/database/{databaseId}: put: tags: - database-endpoint - summary: Refresh database views metadata - operationId: refreshViewMetadata + summary: Update user password in database + operationId: update parameters: - name: databaseId in: path @@ -2624,46 +2063,41 @@ paths: schema: type: integer format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserPasswordDto' + required: true responses: - '200': - description: Refreshed database views metadata - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - '403': - description: Refresh view metadata is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': + "404": description: Failed to find database in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "202": + description: Updated user password in database + "503": + description: Failed to communicate with database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "417": + description: Failed to update user password in database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/metadata/table': - put: + /api/database/{databaseId}/view/{viewId}: + delete: tags: - - database-endpoint - summary: Refresh database tables metadata - operationId: refreshTableMetadata + - view-endpoint + summary: Delete view + operationId: delete parameters: - name: databaseId in: path @@ -2671,52 +2105,48 @@ paths: schema: type: integer format: int64 + - name: viewId + in: path + required: true + schema: + type: integer + format: int64 responses: - '200': - description: Refreshed database tables metadata - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - '400': - description: Failed to parse payload at search service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to refresh table metadata + "202": + description: Deleted view + "409": + description: View schema could not be mapped content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to fin user/database in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "404": + description: Failed to find view in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "400": + description: Database schema is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/image': - put: + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/suggest: + get: tags: - - database-endpoint - summary: Update database image - operationId: modifyImage + - table-endpoint + summary: Suggest table semantics + operationId: analyseTable parameters: - name: databaseId in: path @@ -2724,45 +2154,41 @@ paths: schema: type: integer format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseModifyImageDto' - required: true + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 responses: - '202': - description: Modify of image was successful - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - '403': - description: Modify of image is not permitted + "200": + description: Suggested table semantics successfully content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database or user could not be found + type: array + items: + $ref: '#/components/schemas/TableColumnEntityDto' + "400": + description: Failed to parse statistic in search service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '410': - description: File was not found in the Storage Service + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "404": + description: Failed to find database/table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "417": + description: Generated query is malformed content: application/json: schema: @@ -2770,314 +2196,289 @@ paths: security: - bearerAuth: [] - basicAuth: [] - /api/user: + /api/database/{databaseId}/table/{tableId}/column/{columnId}/suggest: get: tags: - - user-endpoint - summary: Find all users - operationId: findAll + - table-endpoint + summary: Suggest table column semantics + operationId: analyseTableColumn + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: columnId + in: path + required: true + schema: + type: integer + format: int64 responses: - '200': - description: List users + "200": + description: Suggested table column semantics successfully content: application/json: schema: type: array items: - $ref: '#/components/schemas/UserBriefDto' - post: - tags: - - user-endpoint - summary: Create user - operationId: create1 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/SignupRequestDto' - required: true - responses: - '201': - description: Created user + $ref: '#/components/schemas/TableColumnEntityDto' + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: - $ref: '#/components/schemas/UserBriefDto' - '400': - description: Parameters are not well-formed (likely email) - content: - application/json: {} - '404': - description: default role not found + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: User with username already exists + "400": + description: Generated query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '417': - description: User with e-mail already exists + security: + - bearerAuth: [] + - basicAuth: [] + /api/container/{containerId}: + get: + tags: + - container-endpoint + summary: Find some container + operationId: findById_3 + parameters: + - name: containerId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: Found container content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Failed to create in auth service + $ref: '#/components/schemas/ContainerDto' + "404": + description: Container image could not be found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to create in auth service + delete: + tags: + - container-endpoint + summary: Delete some container + operationId: delete_6 + parameters: + - name: containerId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Container not found content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - /api/ontology: + "202": + description: Deleted container successfully + content: + '*/*': + schema: + type: object + security: + - bearerAuth: [] + - basicAuth: [] + /api/concept: get: tags: - - ontology-endpoint - summary: List all ontologies - operationId: findAll_2 + - concept-endpoint + summary: List semantic concepts + operationId: findAll_7 responses: - '200': - description: List all ontologies + "200": + description: Find all semantic concepts content: application/json: schema: type: array items: - $ref: '#/components/schemas/OntologyDto' - post: - tags: - - ontology-endpoint - summary: Register a new ontology - operationId: create_1 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyCreateDto' - required: true - responses: - '201': - description: Registered ontology successfully - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/message: + $ref: '#/components/schemas/ConceptDto' + /api/database/{databaseId}/view/{viewId}/data: get: tags: - - message-endpoint - summary: Find maintenance messages - operationId: list_2 + - view-endpoint + summary: Retrieve view data + operationId: getData parameters: - - name: filter + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: viewId + in: path + required: true + schema: + type: integer + format: int64 + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + - name: timestamp in: query required: false schema: type: string + format: date-time responses: - '200': - description: List messages + "403": + description: Not allowed to retrieve view data content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/BannerMessageDto' - post: - tags: - - message-endpoint - summary: Create maintenance message - operationId: create_2 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageCreateDto' - required: true - responses: - '201': - description: Created message + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: View schema could not be mapped content: application/json: schema: - $ref: '#/components/schemas/BannerMessageBriefDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/image: - get: - tags: - - image-endpoint - summary: Find all images - operationId: findAll_3 - responses: - '200': - description: List images + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/ContainerImage' - post: - tags: - - image-endpoint - summary: Create image - operationId: create_3 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ImageCreateDto' - required: true - responses: - '201': - description: Created image + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find view in metadata database content: application/json: schema: - $ref: '#/components/schemas/ImageDto' - '400': - description: Image specification is invalid + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Request pagination is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: Image already exists + "200": + description: Retrieved view data content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/QueryResultDto' security: - - bearerAuth: [] - basicAuth: [] - /api/identifier: - get: + - bearerAuth: [] + head: tags: - - identifier-endpoint - summary: Find all identifiers - operationId: findAll_4 + - view-endpoint + summary: Retrieve view data + operationId: getData_1 parameters: - - name: dbid - in: query - required: false + - name: databaseId + in: path + required: true schema: type: integer format: int64 - - name: qid - in: query - required: false + - name: viewId + in: path + required: true schema: type: integer format: int64 - - name: vid + - name: page in: query required: false schema: type: integer format: int64 - - name: tid + - name: size in: query required: false schema: type: integer format: int64 - - name: Accept - in: header - required: true + - name: timestamp + in: query + required: false schema: type: string + format: date-time responses: - '200': - description: Found identifiers successfully - content: - application/json: - schema: - type: string - application/ld+json: - schema: - type: string - '406': - description: 'Identifier could not be exported, the requested style is not known' - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - post: - tags: - - identifier-endpoint - summary: Draft identifier - operationId: create_4 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierCreateDto' - required: true - responses: - '201': - description: Drafted identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - '400': - description: Identifier form contains invalid request data + "403": + description: Not allowed to retrieve view data content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Insufficient access rights or authorities + "409": + description: View schema could not be mapped content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Failed to find database, table or view' + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '405': - description: Creating identifier not permitted + "404": + description: Failed to find view in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "400": + description: Request pagination is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "200": + description: Retrieved view data content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/QueryResultDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/view': + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/data: get: tags: - - view-endpoint - summary: Find all views - operationId: findAll_5 + - table-endpoint + summary: Retrieve table data + operationId: getData_2 parameters: - name: databaseId in: path @@ -3085,29 +2486,63 @@ paths: schema: type: integer format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 responses: - '200': - description: Find views successfully + "200": + description: Retrieved table data content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/ViewBriefDto' - '404': - description: Database or user could not be found + $ref: '#/components/schemas/QueryResultDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - post: + - bearerAuth: [] + put: tags: - - view-endpoint - summary: Create a view - operationId: create_6 + - table-endpoint + summary: Update table data + operationId: updateTuple parameters: - name: databaseId in: path @@ -3115,76 +2550,53 @@ paths: schema: type: integer format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 requestBody: content: application/json: schema: - $ref: '#/components/schemas/ViewCreateDto' + $ref: '#/components/schemas/TupleUpdateDto' required: true responses: - '201': - description: Create view successfully - content: - application/json: - schema: - $ref: '#/components/schemas/ViewBriefDto' - '400': - description: Create view query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '401': - description: Credentials missing - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Credentials missing - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database/user in metadata database. - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '405': - description: Create view is not permitted + "403": + description: Update table data not allowed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '423': - description: Create view resulted in an invalid query statement + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "202": + description: Updated table data + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/table': - get: + - bearerAuth: [] + post: tags: - table-endpoint - summary: List all tables - operationId: list_4 + summary: Create table data + operationId: createTuple parameters: - name: databaseId in: path @@ -3192,35 +2604,53 @@ paths: schema: type: integer format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TupleDto' + required: true responses: - '200': - description: List tables + "403": + description: Create table data not allowed content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/TableBriefDto' - '403': - description: List tables not permitted + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Created table data + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Database could not be found + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - post: + - bearerAuth: [] + delete: tags: - table-endpoint - summary: Create a table - operationId: create_7 + summary: Delete table data + operationId: deleteTuple parameters: - name: databaseId in: path @@ -3228,278 +2658,312 @@ paths: schema: type: integer format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 requestBody: content: application/json: schema: - $ref: '#/components/schemas/TableCreateDto' + $ref: '#/components/schemas/TupleDeleteDto' required: true responses: - '201': - description: Created a new table + "403": + description: Delete table data not allowed content: application/json: schema: - $ref: '#/components/schemas/TableBriefDto' - '400': - description: Create table query is malformed + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Create table not permitted + "202": + description: Deleted table data + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Database, container or user could not be found' + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: Create table conflicts with existing table name + security: + - basicAuth: [] + - bearerAuth: [] + head: + tags: + - table-endpoint + summary: Retrieve table data + operationId: getData_3 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + responses: + "200": + description: Retrieved table data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - /api/container: + - bearerAuth: [] + /api/database/{databaseId}/subset/{subsetId}/data: get: tags: - - container-endpoint - summary: Find all containers - operationId: findAll_6 + - subset-endpoint + summary: Retrieved subset data + operationId: getData_4 parameters: - - name: limit + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: subsetId + in: path + required: true + schema: + type: integer + format: int64 + - name: page in: query required: false schema: type: integer - format: int32 + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 responses: - '200': - description: List containers + "400": + description: Malformed select query content: application/json: schema: - type: array - items: - type: string - post: - tags: - - container-endpoint - summary: Create container - operationId: create_9 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerCreateDto' - required: true - responses: - '201': - description: Created a new container + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to retrieve subset data content: application/json: schema: - $ref: '#/components/schemas/ContainerBriefDto' - '404': - description: Container image or user could not be found + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: Container name already exists + "503": + description: Failed to communicate with database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/unit: - get: - tags: - - unit-endpoint - summary: List semantic units - operationId: findAll_1 - responses: - '200': - description: Find all semantic units + "200": + description: Retrieved subset data content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/UnitDto' - '/api/ontology/{ontologyId}/entity': - get: + $ref: '#/components/schemas/QueryResultDto' + security: + - bearerAuth: [] + - basicAuth: [] + head: tags: - - ontology-endpoint - summary: Find entities - operationId: find_4 + - subset-endpoint + summary: Retrieved subset data + operationId: getData_5 parameters: - - name: ontologyId + - name: databaseId in: path required: true schema: type: integer format: int64 - - name: label + - name: subsetId + in: path + required: true + schema: + type: integer + format: int64 + - name: page in: query required: false schema: - type: string - - name: uri + type: integer + format: int64 + - name: size in: query required: false schema: - type: string + type: integer + format: int64 responses: - '200': - description: Found entities + "400": + description: Malformed select query content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/EntityDto' - '400': - description: Filter params are invalid + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to retrieve subset data content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Could not find ontology + "404": + description: Failed to find database in metadata database or query in query store of the data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '417': - description: Generated query or uri is malformed + "503": + description: Failed to communicate with database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '422': - description: Ontology does not have rdf or sparql endpoint + "200": + description: Retrieved subset data content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/QueryResultDto' security: - bearerAuth: [] - basicAuth: [] - /api/oai: - get: + /api/database/{databaseId}/subset/{queryId}: + put: tags: - - metadata-endpoint - summary: Get the record - operationId: identify_1_1_1_1 + - subset-endpoint + summary: Persist subset + operationId: persist parameters: - - name: verb - in: query - - name: parameters - in: query + - name: databaseId + in: path required: true schema: - $ref: '#/components/schemas/OaiListIdentifiersParameters' - responses: - '200': - description: List containers - content: - text/xml: {} - '/api/message/message/{messageId}': - get: - tags: - - message-endpoint - summary: Find one maintenance message - operationId: find_5 - parameters: - - name: messageId + type: integer + format: int64 + - name: queryId in: path required: true schema: type: integer format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/QueryPersistDto' + required: true responses: - '200': - description: Get messages + "202": + description: Persisted subset content: application/json: schema: - $ref: '#/components/schemas/BannerMessageDto' - '404': - description: Could not find message + $ref: '#/components/schemas/QueryDto' + "400": + description: Malformed select query content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - /api/license: - get: - tags: - - license-endpoint - summary: Get all licenses - operationId: list_3 - responses: - '200': - description: List of licenses + "404": + description: Failed to find database in metadata database or query in query store of the data database content: application/json: schema: - type: array - items: - type: string - /api/identifier/retrieve: - get: - tags: - - identifier-endpoint - summary: Retrieve metadata from identifier - operationId: retrieve - parameters: - - name: url - in: query - required: true - schema: - type: string - responses: - '200': - description: Retrieved metadata from identifier + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to persist subset content: application/json: schema: - $ref: '#/components/schemas/IdentifierDto' - '404': - description: Failed to find metadata for identifier + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to persist subset content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '/api/database/{databaseId}': - get: + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/table/{tableId}/data/import: + post: tags: - - database-endpoint - summary: Find some database - operationId: findById_1 + - table-endpoint + summary: Import dataset + operationId: importData parameters: - name: databaseId in: path @@ -3507,40 +2971,54 @@ paths: schema: type: integer format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImportCsvDto' + required: true responses: - '200': - description: Database found successfully + "403": + description: Import table dataset not allowed content: application/json: schema: - $ref: '#/components/schemas/DatabaseDto' - '404': - description: Database or exchange could not be found + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to the broker service could not be established + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to find queue information in broker service + "400": + description: Import dataset query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Import dataset successfully security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/view/{viewId}': + - bearerAuth: [] + /api/database/{databaseId}/subset: get: tags: - - view-endpoint - summary: Find one view - operationId: find_7 + - subset-endpoint + summary: Find subsets + operationId: list parameters: - name: databaseId in: path @@ -3548,39 +3026,44 @@ paths: schema: type: integer format: int64 - - name: viewId - in: path - required: true + - name: persisted + in: query + required: false schema: - type: integer - format: int64 + type: boolean responses: - '200': - description: Find view successfully + "404": + description: Failed to find database in metadata database or query in query store of the data database content: application/json: schema: - $ref: '#/components/schemas/ViewDto' - '403': - description: Find view is not permitted + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Database, view or user could not be found' + "403": + description: Not allowed to find subsets content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found subsets + content: + application/json: + schema: + type: string security: - - bearerAuth: [] - basicAuth: [] - delete: + - bearerAuth: [] + post: tags: - - view-endpoint - summary: Delete one view - operationId: delete_4 + - subset-endpoint + summary: Create subset + operationId: create_3 parameters: - name: databaseId in: path @@ -3588,66 +3071,82 @@ paths: schema: type: integer format: int64 - - name: viewId - in: path - required: true + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false schema: type: integer format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ExecuteStatementDto' + required: true responses: - '202': - description: Delete view successfully - '400': - description: Delete view query is malformed + "400": + description: Malformed select query content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Deletion not allowed + "404": + description: Failed to find database in metadata database or query in query store of the data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: 'Database, view or user could not be found' + "503": + description: Failed to communicate with database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '405': - description: Delete view is not permitted + "403": + description: Not allowed to find subset content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '423': - description: Delete view resulted in an invalid query statement + "201": + description: Created subset content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + $ref: '#/components/schemas/QueryResultDto' + "417": + description: Failed to insert query into query store of data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + "501": + description: Failed to execute query as it contains non-supported keywords content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/table/{tableId}/suggest': + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/history: get: tags: - table-endpoint - summary: Suggest table semantics - operationId: analyseTable + summary: Find table history + operationId: getHistory parameters: - name: databaseId in: path @@ -3662,47 +3161,39 @@ paths: type: integer format: int64 responses: - '200': - description: Suggested table semantics successfully - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/TableColumnEntityDto' - '400': - description: Failed to parse statistic in search service + "404": + description: Failed to find table history in data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database/table in metadata database + "200": + description: Found table history content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '417': - description: Generated query is malformed + type: string + "403": + description: Find table history not allowed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '422': - description: Ontology does not have rdf or sparql endpoint + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/database/{databaseId}/table/{tableId}/column/{columnId}/suggest': + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/export: get: tags: - table-endpoint - summary: Suggest table column semantics - operationId: analyseTableColumn + summary: Export table data + operationId: exportData parameters: - name: databaseId in: path @@ -3716,138 +3207,264 @@ paths: schema: type: integer format: int64 - - name: columnId - in: path - required: true + - name: timestamp + in: query + required: false schema: - type: integer - format: int64 + type: string + format: date-time responses: - '200': - description: Suggested table column semantics successfully + "404": + description: Failed to find table in metadata database content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/TableColumnEntityDto' - '400': - description: Generated query is malformed + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Exported table data + content: + application/json: + schema: + type: string + format: binary + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find database/table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '422': - description: Ontology does not have rdf or sparql endpoint + "403": + description: Export table data not allowed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' security: - - bearerAuth: [] - basicAuth: [] - '/api/container/{containerId}': + - bearerAuth: [] + /api/database/{databaseId}/subset/{subsetId}: get: tags: - - container-endpoint - summary: Find some container - operationId: findById_3 + - subset-endpoint + summary: Find subset + operationId: findById parameters: - - name: containerId + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: subsetId in: path required: true schema: type: integer format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time responses: - '200': - description: Found container + "400": + description: Malformed select query content: application/json: schema: - $ref: '#/components/schemas/ContainerDto' - '404': - description: Container image could not be found + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - delete: - tags: - - container-endpoint - summary: Delete some container - operationId: delete_6 + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to find subset + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "406": + description: Failed to find acceptable representation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found subset + content: + application/json: + schema: + $ref: '#/components/schemas/QueryDto' + text/csv: {} + security: + - basicAuth: [] + - bearerAuth: [] + /api/search: + get: + consumes: + - application/json + description: Performs a fuzzy search + operationId: post_fuzzy_search parameters: - - name: containerId - in: path + - in: query required: true schema: - type: integer - format: int64 + properties: + q: + example: air quality + type: string + type: string + produces: + - application/json responses: - '202': - description: Deleted container successfully + "200": content: - '*/*': + application/json: schema: + properties: + results: + items: + type: object + type: array type: object - '404': - description: Container not found + description: OK, contains the elements formatted as an array of JSON arrays + "415": + description: Wrong accept type + summary: Performs a fuzzy search + tags: + - search-endpoint + /api/search/database/{database_id}: + delete: + consumes: + - application/json + description: Deletes a database + operationId: delete_database + produces: + - application/json + responses: + "202": content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + properties: + id: + example: 1 + implementation: int64 + type: integer + required: + - id + type: object + description: Deleted database successfully + "404": + content: + application/json: + schema: + properties: + message: + example: Message + type: string + success: + example: false + type: boolean + required: + - success + - message + type: object + description: Database not found security: - bearerAuth: [] - basicAuth: [] - /api/concept: - get: + summary: Deletes a database tags: - - concept-endpoint - summary: List semantic concepts - operationId: findAll_7 - responses: - '200': - description: Find all semantic concepts - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ConceptDto' - /api/search: - get: + - database-endpoint + put: consumes: - application/json - description: Performs a fuzzy search - operationId: post_fuzzy_search + description: Updates a database + operationId: update_database parameters: - - in: query - name: q + - in: body + name: body required: true schema: - type: string + properties: + internal_name: + example: air_quality_abcd + type: string + name: + example: Air Quality + type: string + type: object produces: - application/json responses: - '200': + "202": content: application/json: schema: - $ref: '#/components/schemas/SearchResultDto' - description: 'OK, contains the elements formatted as an array of JSON arrays' - '415': - description: Wrong accept type - summary: Performs a fuzzy search + properties: + id: + example: 1 + implementation: int64 + type: integer + required: + - id + type: object + description: Updated database successfully + "400": + content: + application/json: + schema: + properties: + message: + example: Message + type: string + success: + example: false + type: boolean + required: + - success + - message + type: object + description: Invalid schema + "404": + content: + application/json: + schema: + properties: + message: + example: Message + type: string + success: + example: false + type: boolean + required: + - success + - message + type: object + description: Database not found + security: + - bearerAuth: [] + - basicAuth: [] + summary: Updates a database tags: - - search-endpoint - '/api/search/{index}': + - database-endpoint + /api/search/{index}: get: consumes: - application/json @@ -3889,16 +3506,33 @@ paths: produces: - application/json responses: - '200': + "200": content: application/json: schema: - $ref: '#/components/schemas/IndexDto' - description: 'OK, contains the elements formatted as an array of JSON arrays' + properties: + results: + items: + type: object + type: array + type: + description: Same as the requested type + enum: + - database + - table + - view + - column + - user + - identifier + - concept + - unit + type: string + type: object + description: OK, contains the elements formatted as an array of JSON arrays summary: Gets the index tags: - search-endpoint - '/api/search/{type}': + /api/search/{type}: post: consumes: - application/json @@ -3932,11 +3566,17 @@ paths: name: body required: true schema: - $ref: '#/components/schemas/SearchRequestDto' + properties: + field_value_pairs: + type: object + search_term: + example: air quality + type: string + type: object produces: - application/json responses: - '200': + "200": content: application/json: schema: @@ -3958,11 +3598,11 @@ paths: - unit type: string type: object - description: 'OK, contains the elements formatted as an array of JSON arrays' + description: OK, contains the elements formatted as an array of JSON arrays summary: Performs a general search tags: - search-endpoint - '/api/search/{type}/fields': + /api/search/{type}/fields: get: operationId: get_fields parameters: @@ -3982,18 +3622,207 @@ paths: - unit type: string responses: - '200': + "200": content: application/json: schema: - $ref: '#/components/schemas/IndexFieldsDto' + properties: + results: + items: + properties: + attr_friendly_name: + example: Name + type: string + attr_name: + example: name + type: string + type: + description: OpenSearch data types. + example: string + type: string + type: object + type: array + type: object description: List of fields - '404': + "404": description: Invalid type. summary: Get searchable fields tags: - search-endpoint - '/sidecar/export/{filename}': + /health: + get: + consumes: + - application/json + description: | + Return UP if the instance is ready to serve connections. + produces: + - application/json + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/Health' + description: OK, service is up and running + "404": + description: Service is not yet ready + summary: Return a healthcheck + tags: + - actuator + /api/analyse/database/{database_id}/table/{table_id}/statistics: + get: + operationId: analyse_table_stat + parameters: + - example: 1 + in: path + name: database_id + required: true + schema: + format: int64 + type: integer + - example: 1 + in: path + name: table_id + required: true + schema: + format: int64 + type: integer + responses: + "202": + content: + application/json: + schema: + $ref: '#/components/schemas/TableStats' + description: Determined statistics + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Missing parameters + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Table not found + security: + - bearerAuth: [] + - basicAuth: [] + summary: Determine table statistics + tags: + - analyse-endpoint + /api/analyse/datatypes: + get: + consumes: + - application/json + description: This is a simple API which returns the datatypes of a (path) csv file + operationId: analyse_datatypes + parameters: + - example: filename_s3_key + in: query + name: filename + required: true + schema: + type: string + - example: ',' + in: query + name: separator + required: true + schema: + type: string + - example: "false" + in: query + name: enum + required: false + schema: + type: boolean + - example: "2.5" + in: query + name: enum_tol + required: false + schema: + type: float + produces: + - application/json + responses: + "202": + content: + application/json: + schema: + $ref: '#/components/schemas/DataTypesDto' + description: Determined data types successfully + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to determine data types + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to find file in Storage Service + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Unexpected system error + summary: Determine datatypes + tags: + - analyse-endpoint + /api/analyse/keys: + get: + consumes: + - application/json + description: This is a simple API which returns the primary keys + ranking of a (path) csv file + operationId: analyse_keys + parameters: + - example: filename_s3_key + in: query + name: filename + required: true + schema: + type: string + - example: ',' + in: query + name: separator + required: true + schema: + type: string + produces: + - application/json + responses: + "202": + content: + application/json: + schema: + $ref: '#/components/schemas/KeysDto' + description: Determined keys successfully + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to determine keys + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to find file in Storage Service or is empty + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Unexpected system error + summary: Determine primary keys + tags: + - analyse-endpoint + /sidecar/export/{filename}: post: consumes: - application/json @@ -4007,10 +3836,10 @@ paths: produces: - application/json responses: - '202': + "202": content: {} description: Exported the .csv - '400': + "400": description: The Storage Service could not be contacted or .csv was not found. security: - bearerAuth: [] @@ -4018,7 +3847,7 @@ paths: summary: Exports a .csv to the Storage Service tags: - sidecar - '/sidecar/import/{filename}': + /sidecar/import/{filename}: post: consumes: - application/json @@ -4032,10 +3861,10 @@ paths: produces: - application/json responses: - '202': + "202": content: {} description: Imported the .csv - '400': + "400": description: The Storage Service could not be contacted or .csv was not found. security: - bearerAuth: [] @@ -4043,5627 +3872,3 @@ paths: summary: Imports a .csv from the Storage Service tags: - sidecar -components: - securitySchemes: - basicAuth: - in: header - scheme: basic - type: http - bearerAuth: - bearerFormat: JWT - in: header - scheme: bearer - type: http - schemas: - DataTypesDto: - properties: - columns: - $ref: '#/components/schemas/SuggestedColumnDto' - line_termination: - example: "\r\n" - type: string - separator: - example: ',' - type: string - type: object - ErrorDto: - properties: - message: - example: Message - type: string - success: - example: false - type: boolean - type: object - KeysDto: - properties: - keys: - items: - properties: - column_name: - format: int64 - type: integer - type: array - required: - - keys - type: object - SuggestedColumnDto: - properties: - column_name: - type: string - type: object - QueryResultDto: - required: - - headers - - id - - result - type: object - properties: - result: - type: array - items: - type: object - additionalProperties: - type: object - headers: - type: array - items: - type: object - additionalProperties: - type: integer - format: int32 - id: - type: integer - format: int64 - ApiErrorDto: - required: - - code - - message - - status - type: object - properties: - status: - type: string - example: NOT_FOUND - enum: - - 100 CONTINUE - - 101 SWITCHING_PROTOCOLS - - 102 PROCESSING - - 103 EARLY_HINTS - - 103 CHECKPOINT - - 200 OK - - 201 CREATED - - 202 ACCEPTED - - 203 NON_AUTHORITATIVE_INFORMATION - - 204 NO_CONTENT - - 205 RESET_CONTENT - - 206 PARTIAL_CONTENT - - 207 MULTI_STATUS - - 208 ALREADY_REPORTED - - 226 IM_USED - - 300 MULTIPLE_CHOICES - - 301 MOVED_PERMANENTLY - - 302 FOUND - - 302 MOVED_TEMPORARILY - - 303 SEE_OTHER - - 304 NOT_MODIFIED - - 305 USE_PROXY - - 307 TEMPORARY_REDIRECT - - 308 PERMANENT_REDIRECT - - 400 BAD_REQUEST - - 401 UNAUTHORIZED - - 402 PAYMENT_REQUIRED - - 403 FORBIDDEN - - 404 NOT_FOUND - - 405 METHOD_NOT_ALLOWED - - 406 NOT_ACCEPTABLE - - 407 PROXY_AUTHENTICATION_REQUIRED - - 408 REQUEST_TIMEOUT - - 409 CONFLICT - - 410 GONE - - 411 LENGTH_REQUIRED - - 412 PRECONDITION_FAILED - - 413 PAYLOAD_TOO_LARGE - - 413 REQUEST_ENTITY_TOO_LARGE - - 414 URI_TOO_LONG - - 414 REQUEST_URI_TOO_LONG - - 415 UNSUPPORTED_MEDIA_TYPE - - 416 REQUESTED_RANGE_NOT_SATISFIABLE - - 417 EXPECTATION_FAILED - - 418 I_AM_A_TEAPOT - - 419 INSUFFICIENT_SPACE_ON_RESOURCE - - 420 METHOD_FAILURE - - 421 DESTINATION_LOCKED - - 422 UNPROCESSABLE_ENTITY - - 423 LOCKED - - 424 FAILED_DEPENDENCY - - 425 TOO_EARLY - - 426 UPGRADE_REQUIRED - - 428 PRECONDITION_REQUIRED - - 429 TOO_MANY_REQUESTS - - 431 REQUEST_HEADER_FIELDS_TOO_LARGE - - 451 UNAVAILABLE_FOR_LEGAL_REASONS - - 500 INTERNAL_SERVER_ERROR - - 501 NOT_IMPLEMENTED - - 502 BAD_GATEWAY - - 503 SERVICE_UNAVAILABLE - - 504 GATEWAY_TIMEOUT - - 505 HTTP_VERSION_NOT_SUPPORTED - - 506 VARIANT_ALSO_NEGOTIATES - - 507 INSUFFICIENT_STORAGE - - 508 LOOP_DETECTED - - 509 BANDWIDTH_LIMIT_EXCEEDED - - 510 NOT_EXTENDED - - 511 NETWORK_AUTHENTICATION_REQUIRED - message: - type: string - example: Error message - code: - type: string - example: error.service.code - TupleUpdateDto: - required: - - data - - keys - type: object - properties: - data: - type: object - additionalProperties: - type: object - keys: - type: object - additionalProperties: - type: object - QueryPersistDto: - required: - - persist - type: object - properties: - persist: - type: boolean - example: true - CreatorDto: - required: - - creator_name - - id - type: object - properties: - id: - type: integer - format: int64 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - creator_name: - type: string - example: 'Carberry, Josiah' - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: - type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: - type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - name_identifier_scheme_uri: - type: string - example: 'https://orcid.org/' - affiliation_identifier: - type: string - example: 'https://ror.org/05gq02987' - affiliation_identifier_scheme: - type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - affiliation_identifier_scheme_uri: - type: string - example: 'https://ror.org/' - IdentifierDescriptionDto: - required: - - id - type: object - properties: - id: - type: integer - format: int64 - description: - type: string - example: 'Air quality reports at Stephansplatz, Vienna' - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - IdentifierDto: - required: - - created - - created_by - - creator - - creators - - database_id - - execution - - id - - last_modified - - publication_year - - publisher - - query - - query_hash - - query_normalized - - titles - - type - type: object - properties: - id: - type: integer - format: int64 - type: - type: string - enum: - - database - - subset - - table - - view - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderDto' - query: - type: string - example: >- - SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location` - = "09:STEF" - execution: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - doi: - type: string - example: 10.1038/nphys1170 - publisher: - type: string - example: TU Wien - creator: - $ref: '#/components/schemas/UserDto' - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - creators: - type: array - items: - $ref: '#/components/schemas/CreatorDto' - status: - type: string - enum: - - draft - - published - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - example: 1 - table_id: - type: integer - format: int64 - example: 1 - view_id: - type: integer - format: int64 - example: 1 - query_normalized: - type: string - example: >- - SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location` - = "09:STEF" - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierDto' - query_hash: - type: string - description: query hash in sha512 - result_hash: - type: string - example: 34fe82cda2c53f13f8d90cfd7a3469e3a939ff311add50dce30d9136397bf8e5 - result_number: - type: integer - format: int64 - example: 1 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - created_by: - type: string - format: uuid - last_modified: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - IdentifierFunderDto: - required: - - funder_name - - id - type: object - properties: - id: - type: integer - format: int64 - funder_name: - type: string - example: European Commission - funder_identifier: - type: string - example: 'http://doi.org/10.13039/501100000780' - funder_identifier_type: - type: string - example: Crossref Funder ID - enum: - - Crossref Funder ID - - ROR - - GND - - ISNI - - Other - scheme_uri: - type: string - example: 'http://doi.org/' - award_number: - type: string - example: '824087' - award_title: - type: string - example: EOSC-Life - IdentifierTitleDto: - required: - - id - type: object - properties: - id: - type: integer - format: int64 - title: - type: string - example: Airquality Demonstrator - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - LicenseDto: - required: - - identifier - - uri - type: object - properties: - identifier: - type: string - example: MIT - uri: - type: string - example: 'https://opensource.org/licenses/MIT' - description: - type: string - example: >- - A short and simple permissive license with conditions only requiring - preservation of copyright and license notices. Licensed works, - modifications, and larger works may be distributed under different - terms and without source code. - QueryDto: - required: - - created - - creator - - database_id - - execution - - id - - identifiers - - is_persisted - - last_modified - - query - - query_hash - - query_normalized - type: object - properties: - id: - type: integer - format: int64 - creator: - $ref: '#/components/schemas/UserDto' - execution: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - query: - type: string - example: SELECT `id` FROM `air_quality` - type: - type: string - example: query - enum: - - query - - view - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - database_id: - type: integer - format: int64 - query_normalized: - type: string - example: SELECT `id` FROM `air_quality` - query_hash: - type: string - example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 - is_persisted: - type: boolean - example: true - result_hash: - type: string - example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 - result_number: - type: integer - format: int64 - example: 1 - last_modified: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - RelatedIdentifierDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - UserAttributesDto: - required: - - language - - theme - type: object - properties: - theme: - type: string - example: light - orcid: - type: string - example: 'https://orcid.org/0000-0002-1825-0097' - affiliation: - type: string - example: Brown University - language: - type: string - example: en - UserDto: - required: - - attributes - - id - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - attributes: - $ref: '#/components/schemas/UserAttributesDto' - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - TupleDto: - required: - - data - type: object - properties: - data: - type: object - additionalProperties: - type: object - ImportCsvDto: - required: - - location - - separator - type: object - properties: - location: - type: string - example: file.csv - separator: - type: string - example: ',' - quote: - type: string - example: '"' - skip_lines: - minimum: 0 - type: integer - format: int64 - false_element: - type: string - true_element: - type: string - null_element: - type: string - example: NA - line_termination: - type: string - example: \r\n - ExecuteStatementDto: - required: - - statement - type: object - properties: - statement: - type: string - example: SELECT `id` FROM `air_quality` - ColumnStatisticDto: - required: - - mean - - median - - std_dev - - val_max - - val_min - type: object - properties: - mean: - type: number - median: - type: number - std_dev: - type: number - val_min: - type: number - val_max: - type: number - TableStatisticDto: - required: - - columns - - rows - type: object - properties: - columns: - type: object - additionalProperties: - $ref: '#/components/schemas/ColumnStatisticDto' - rows: - type: integer - format: int64 - TupleDeleteDto: - required: - - keys - type: object - properties: - keys: - type: object - additionalProperties: - type: object - ColumnBriefDto: - required: - - column_type - - database_id - - id - - internal_name - - name - - table_id - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: date - alias: - type: string - database_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - internal_name: - type: string - example: mdb_date - column_type: - type: string - example: date - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - ColumnDto: - required: - - auto_generated - - column_type - - database_id - - id - - internal_name - - is_null_allowed - - is_public - - name - - ordinal_position - - table_id - type: object - properties: - id: - type: integer - format: int64 - name: - maxLength: 64 - minLength: 0 - type: string - example: Date - alias: - type: string - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - mean: - type: number - example: 45.4 - median: - type: number - example: 51 - concept: - $ref: '#/components/schemas/ConceptDto' - unit: - $ref: '#/components/schemas/UnitDto' - description: - maxLength: 2048 - minLength: 0 - type: string - example: Column comment - enums: - type: array - items: - type: string - sets: - type: array - items: - type: string - database_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - ordinal_position: - type: integer - format: int32 - example: 0 - internal_name: - maxLength: 64 - minLength: 0 - type: string - example: mdb_date - date_format: - $ref: '#/components/schemas/ImageDateDto' - auto_generated: - type: boolean - example: false - index_length: - type: integer - format: int64 - length: - type: integer - format: int64 - column_type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - data_length: - type: integer - format: int64 - example: 34300 - max_data_length: - type: integer - format: int64 - example: 34300 - num_rows: - type: integer - format: int64 - example: 32 - val_min: - type: number - example: 0 - val_max: - type: number - example: 100 - std_dev: - type: number - example: 5.32 - is_public: - type: boolean - example: true - is_null_allowed: - type: boolean - example: false - ConceptDto: - required: - - columns - - created - - id - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - ConstraintsDto: - type: object - properties: - uniques: - type: array - items: - $ref: '#/components/schemas/UniqueDto' - checks: - uniqueItems: true - type: array - items: - type: string - foreign_keys: - type: array - items: - $ref: '#/components/schemas/ForeignKeyDto' - primary_key: - uniqueItems: true - type: array - items: - $ref: '#/components/schemas/PrimaryKeyDto' - ContainerDto: - required: - - created - - host - - id - - image - - internal_name - - name - - sidecar_host - - sidecar_port - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - host: - type: string - port: - type: integer - format: int32 - image: - $ref: '#/components/schemas/ImageDto' - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - internal_name: - type: string - example: data-db - sidecar_host: - type: string - sidecar_port: - type: integer - format: int32 - ui_host: - type: string - ui_port: - type: integer - format: int32 - DatabaseAccessDto: - required: - - created - - type - - user - type: object - properties: - user: - $ref: '#/components/schemas/UserDto' - type: - type: string - enum: - - read - - write_own - - write_all - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - DatabaseDto: - required: - - contact - - container - - created - - creator - - exchange_name - - id - - internal_name - - is_public - - name - - owner - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality - tables: - type: array - items: - $ref: '#/components/schemas/TableDto' - views: - type: array - items: - $ref: '#/components/schemas/ViewDto' - container: - $ref: '#/components/schemas/ContainerDto' - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccessDto' - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - subsets: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - creator: - $ref: '#/components/schemas/UserDto' - contact: - $ref: '#/components/schemas/UserDto' - owner: - $ref: '#/components/schemas/UserDto' - image: - type: array - items: - type: string - format: byte - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - exchange_name: - type: string - example: dbrepo - exchange_type: - type: string - example: topic - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - ForeignKeyBriefDto: - type: object - properties: - id: - type: integer - format: int64 - ForeignKeyDto: - required: - - name - - referenced_table - - references - - table - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - references: - type: array - items: - $ref: '#/components/schemas/ForeignKeyReferenceDto' - table: - $ref: '#/components/schemas/TableBriefDto' - referenced_table: - $ref: '#/components/schemas/TableBriefDto' - on_update: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - on_delete: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - ForeignKeyReferenceDto: - required: - - column - - foreign_key - - referenced_column - type: object - properties: - id: - type: integer - format: int64 - column: - $ref: '#/components/schemas/ColumnBriefDto' - foreign_key: - $ref: '#/components/schemas/ForeignKeyBriefDto' - referenced_column: - $ref: '#/components/schemas/ColumnBriefDto' - ImageDateDto: - required: - - created_at - - database_format - - has_time - - id - - unix_format - type: object - properties: - id: - type: integer - format: int64 - database_format: - type: string - example: '%d.%c.%Y' - unix_format: - type: string - example: dd.MM.YYYY - has_time: - type: boolean - example: false - created_at: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - ImageDto: - required: - - default_port - - dialect - - driver_class - - id - - jdbc_method - - name - - registry - - version - type: object - properties: - id: - type: integer - format: int64 - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - example: '10.5' - dialect: - type: string - example: org.hibernate.dialect.MariaDBDialect - driver_class: - type: string - example: org.mariadb.jdbc.Driver - date_formats: - type: array - items: - $ref: '#/components/schemas/ImageDateDto' - jdbc_method: - type: string - example: mariadb - default_port: - type: integer - format: int32 - example: 3306 - PrimaryKeyDto: - required: - - column - - table - type: object - properties: - id: - type: integer - format: int64 - table: - $ref: '#/components/schemas/TableBriefDto' - column: - $ref: '#/components/schemas/ColumnBriefDto' - TableBriefDto: - required: - - database_id - - id - - internal_name - - is_versioned - - name - - owner - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality in Austria - owner: - $ref: '#/components/schemas/UserBriefDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_versioned: - type: boolean - example: true - TableDto: - required: - - columns - - constraints - - created - - created_by - - creator - - database_id - - id - - internal_name - - is_public - - is_versioned - - name - - owner - - queue_name - - routing_key - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - alias: - type: string - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - creator: - $ref: '#/components/schemas/UserDto' - owner: - $ref: '#/components/schemas/UserDto' - description: - maxLength: 2048 - minLength: 0 - type: string - example: Air Quality in Austria - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - constraints: - $ref: '#/components/schemas/ConstraintsDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_versioned: - type: boolean - example: true - created_by: - type: string - format: uuid - queue_name: - type: string - example: air_quality - queue_type: - type: string - example: quorum - routing_key: - type: string - example: dbrepo.1.2 - is_public: - type: boolean - example: true - num_rows: - type: integer - format: int64 - example: 5 - data_length: - type: integer - description: in bytes - format: int64 - example: 16384 - max_data_length: - type: integer - description: in bytes - format: int64 - example: 0 - avg_row_length: - type: integer - description: in bytes - format: int64 - example: 3276 - UniqueDto: - required: - - columns - - id - - name - - table - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - table: - $ref: '#/components/schemas/TableBriefDto' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - UnitDto: - required: - - columns - - created - - id - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - UserBriefDto: - required: - - id - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - orcid: - type: string - example: 0000-0002-1825-0097 - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - ViewColumnDto: - required: - - auto_generated - - column_type - - database_id - - id - - internal_name - - is_null_allowed - - is_public - - name - - ordinal_position - type: object - properties: - id: - type: integer - format: int64 - name: - maxLength: 64 - minLength: 0 - type: string - example: Date - alias: - type: string - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - concept: - $ref: '#/components/schemas/ConceptDto' - unit: - $ref: '#/components/schemas/UnitDto' - description: - maxLength: 2048 - minLength: 0 - type: string - example: Column comment - database_id: - type: integer - format: int64 - ordinal_position: - type: integer - format: int32 - example: 0 - internal_name: - maxLength: 64 - minLength: 0 - type: string - example: mdb_date - date_format: - $ref: '#/components/schemas/ImageDateDto' - auto_generated: - type: boolean - example: false - index_length: - type: integer - format: int64 - length: - type: integer - format: int64 - column_type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - is_public: - type: boolean - example: true - is_null_allowed: - type: boolean - example: false - ViewDto: - required: - - columns - - created - - creator - - database - - database_id - - id - - internal_name - - name - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - database: - $ref: '#/components/schemas/DatabaseDto' - name: - type: string - example: Air Quality - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - creator: - $ref: '#/components/schemas/UserDto' - columns: - type: array - items: - $ref: '#/components/schemas/ViewColumnDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 - last_modified: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - UserUpdateDto: - required: - - language - - theme - type: object - properties: - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - orcid: - type: string - example: 0000-0002-1825-0097 - theme: - type: string - example: dark - language: - type: string - example: en - UserPasswordDto: - required: - - password - type: object - properties: - password: - type: string - RefreshTokenRequestDto: - required: - - refresh_token - type: object - properties: - refresh_token: - type: string - example: refresh_token - TokenDto: - required: - - access_token - - expires_in - - id_token - - not-before-policy - - refresh_expires_in - - refresh_token - - scope - - session_state - - token_type - type: object - properties: - scope: - type: string - access_token: - type: string - expires_in: - type: integer - format: int64 - refresh_token: - type: string - refresh_expires_in: - type: integer - format: int64 - id_token: - type: string - session_state: - type: string - token_type: - type: string - not-before-policy: - type: integer - format: int64 - OntologyModifyDto: - required: - - prefix - - uri - type: object - properties: - uri: - type: string - example: Ontology URI - prefix: - type: string - example: Ontology prefix - sparql_endpoint: - type: string - example: Ontology SPARQL endpoint - rdf_path: - type: string - example: rdf/om-2.0.rdf - OntologyDto: - required: - - created - - id - - prefix - - rdf - - sparql - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - example: 'http://www.wikidata.org/' - prefix: - type: string - example: wd - sparql: - type: boolean - example: true - rdf: - type: boolean - example: false - creator: - $ref: '#/components/schemas/UserBriefDto' - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - uri_pattern: - type: string - example: 'http://www.wikidata.org/entity/.*' - sparql_endpoint: - type: string - example: 'https://query.wikidata.org/sparql' - rdf_path: - type: string - example: rdf/om-2.0.rdf - BannerMessageUpdateDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: 'https://example.com' - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - display_end: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - BannerMessageBriefDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: 'https://example.com' - link_text: - type: string - example: More - ImageChangeDto: - required: - - dialect - - driver_class - - jdbc_method - - registry - type: object - properties: - registry: - type: string - example: docker.io/library - defaultPort: - maximum: 65535 - minimum: 1024 - type: integer - format: int32 - example: 5432 - dialect: - type: string - example: Postgres - driver_class: - type: string - example: org.postgresql.Driver - jdbc_method: - type: string - example: postgresql - CreatorSaveDto: - required: - - creator_name - - id - type: object - properties: - id: - type: integer - format: int64 - example: 1 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Wesleyan University - creator_name: - type: string - example: 'Carberry, Josiah' - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: - type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: - type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - affiliation_identifier: - type: string - example: 'https://ror.org/04d836q62' - affiliation_identifier_scheme: - type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - IdentifierFunderSaveDto: - required: - - funder_name - - id - type: object - properties: - id: - type: integer - format: int64 - example: 1 - funder_name: - type: string - example: European Commission - funder_identifier: - type: string - example: 'http://doi.org/10.13039/501100000780' - funder_identifier_type: - type: string - example: Crossref Funder ID - enum: - - Crossref Funder ID - - ROR - - GND - - ISNI - - Other - scheme_uri: - type: string - example: 'http://doi.org/' - award_number: - type: string - example: '824087' - award_title: - type: string - example: EOSC-Life - IdentifierSaveDescriptionDto: - required: - - description - - id - type: object - properties: - id: - type: integer - format: int64 - example: 1 - description: - type: string - example: 'Air quality reports at Stephansplatz, Vienna' - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - IdentifierSaveDto: - required: - - creators - - database_id - - id - - publication_year - - publisher - - titles - - type - type: object - properties: - id: - type: integer - format: int64 - example: 1 - type: - type: string - example: database - enum: - - database - - subset - - table - - view - doi: - type: string - example: 10.1111/11111111 - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderSaveDto' - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - publisher: - type: string - example: TU Wien - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - creators: - type: array - items: - $ref: '#/components/schemas/CreatorSaveDto' - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - view_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierSaveDto' - IdentifierSaveTitleDto: - required: - - id - - title - type: object - properties: - id: - type: integer - format: int64 - example: 1 - title: - type: string - example: Airquality Demonstrator - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Subtitle - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - RelatedIdentifierSaveDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - example: 1 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - DatabaseModifyVisibilityDto: - required: - - is_public - type: object - properties: - is_public: - type: boolean - example: true - ColumnSemanticsUpdateDto: - type: object - properties: - concept_uri: - type: string - unit_uri: - type: string - DatabaseTransferDto: - required: - - id - type: object - properties: - id: - type: string - format: uuid - DatabaseModifyImageDto: - type: object - properties: - key: - type: string - UpdateDatabaseAccessDto: - required: - - type - type: object - properties: - type: - type: string - enum: - - read - - write_own - - write_all - SignupRequestDto: - required: - - email - - password - - username - type: object - properties: - username: - pattern: '^[a-z0-9]{3,}$' - type: string - example: user - email: - type: string - example: user@example.com - password: - type: string - LoginRequestDto: - required: - - password - - username - type: object - properties: - username: - type: string - example: user - password: - type: string - OntologyCreateDto: - required: - - prefix - - uri - type: object - properties: - uri: - type: string - example: Ontology URI - prefix: - type: string - example: Ontology prefix - sparql_endpoint: - type: string - example: Ontology SPARQL endpoint - BannerMessageCreateDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: 'https://example.com' - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - display_end: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - ImageCreateDto: - required: - - default_port - - dialect - - driver_class - - jdbc_method - - name - - registry - - version - type: object - properties: - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - dialect: - type: string - driver_class: - type: string - jdbc_method: - type: string - default_port: - maximum: 65535 - minimum: 1024 - type: integer - format: int32 - IdentifierCreateDto: - required: - - creators - - database_id - - publication_year - - publisher - - titles - - type - type: object - properties: - type: - type: string - example: database - enum: - - database - - subset - - table - - view - doi: - type: string - example: 10.1111/11111111 - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderSaveDto' - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - publisher: - type: string - example: TU Wien - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - creators: - type: array - items: - $ref: '#/components/schemas/CreatorSaveDto' - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - view_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierSaveDto' - DatabaseCreateDto: - required: - - container_id - - is_public - - name - type: object - properties: - name: - type: string - example: Air Quality - container_id: - type: integer - format: int64 - example: 1 - is_public: - type: boolean - example: true - ViewCreateDto: - required: - - is_public - - name - - query - type: object - properties: - name: - maxLength: 64 - minLength: 1 - type: string - example: Air Quality - query: - type: string - example: SELECT `id` FROM `air_quality` - is_public: - type: boolean - example: true - ViewBriefDto: - required: - - created - - creator - - database_id - - id - - internal_name - - name - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - identifier: - $ref: '#/components/schemas/IdentifierDto' - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - creator: - $ref: '#/components/schemas/UserDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 - last_modified: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - ColumnCreateDto: - required: - - name - - null_allowed - - type - type: object - properties: - name: - type: string - example: Date - type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - description: - maxLength: 2048 - minLength: 0 - type: string - example: Formatted as YYYY-MM-dd - dfid: - type: integer - description: date format id - format: int64 - enums: - type: array - description: 'enum values, only considered when type = ENUM' - items: - type: string - description: 'enum values, only considered when type = ENUM' - sets: - type: array - description: 'set values, only considered when type = SET' - items: - type: string - description: 'set values, only considered when type = SET' - index_length: - type: integer - format: int64 - null_allowed: - type: boolean - example: true - concept_uri: - type: string - unit_uri: - type: string - ConstraintsCreateDto: - required: - - checks - - foreign_keys - - primary_key - - uniques - type: object - properties: - uniques: - type: array - items: - type: array - items: - type: string - checks: - uniqueItems: true - type: array - items: - type: string - foreign_keys: - type: array - items: - $ref: '#/components/schemas/ForeignKeyCreateDto' - primary_key: - uniqueItems: true - type: array - items: - type: string - ForeignKeyCreateDto: - required: - - columns - - referenced_columns - - referenced_table - type: object - properties: - columns: - type: array - items: - type: string - referenced_table: - type: string - referenced_columns: - type: array - items: - type: string - on_update: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - on_delete: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - TableCreateDto: - required: - - columns - - constraints - - name - type: object - properties: - name: - maxLength: 64 - minLength: 1 - type: string - example: Air Quality - description: - maxLength: 180 - minLength: 0 - type: string - example: Air Quality in Austria - columns: - type: array - items: - $ref: '#/components/schemas/ColumnCreateDto' - constraints: - $ref: '#/components/schemas/ConstraintsCreateDto' - need_sequence: - type: boolean - ContainerCreateDto: - required: - - host - - image_id - - name - - privileged_password - - privileged_username - - sidecar_host - - sidecar_port - type: object - properties: - name: - type: string - example: Air Quality - host: - type: string - description: Hostname of container - port: - type: integer - description: Port of container - format: int32 - image_id: - type: integer - description: Image ID - format: int64 - sidecar_host: - type: string - sidecar_port: - type: integer - format: int32 - ui_host: - type: string - ui_port: - type: integer - format: int32 - privileged_username: - type: string - description: Username of privileged user - example: root - privileged_password: - type: string - description: Password of privileged user - ContainerBriefDto: - required: - - created - - hash - - id - - image - - internal_name - - name - - running - type: object - properties: - id: - type: integer - format: int64 - hash: - type: string - example: f829dd8a884182d0da846f365dee1221fd16610a14c81b8f9f295ff162749e50 - name: - type: string - example: Air Quality - image: - $ref: '#/components/schemas/ImageBriefDto' - running: - type: boolean - example: true - created: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - internal_name: - type: string - example: air-quality - ImageBriefDto: - required: - - id - - jdbc_method - - name - - version - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: mariadb - version: - type: string - example: '10.5' - jdbc_method: - type: string - example: mariadb - EntityDto: - required: - - label - - uri - type: object - properties: - uri: - type: string - example: 'https://www.wikidata.org/entity/Q1686799' - label: - type: string - example: Apache Jena - description: - type: string - example: open source semantic web framework for Java - OaiListIdentifiersParameters: - type: object - properties: - metadataPrefix: - type: string - from: - type: string - until: - type: string - set: - type: string - resumptionToken: - type: string - fromDate: - type: string - format: date-time - untilDate: - type: string - format: date-time - parametersString: - type: string - BannerMessageDto: - required: - - id - - message - - type - type: object - properties: - id: - type: integer - format: int64 - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: 'https://example.com' - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - display_end: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - Constraints: - type: object - properties: - uniques: - type: array - items: - $ref: '#/components/schemas/Unique' - foreignKeys: - type: array - items: - $ref: '#/components/schemas/ForeignKey' - checks: - uniqueItems: true - type: array - items: - type: string - primaryKey: - type: array - items: - $ref: '#/components/schemas/PrimaryKey' - Container: - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - internalName: - type: string - host: - type: string - port: - type: integer - format: int32 - sidecarHost: - type: string - sidecarPort: - type: integer - format: int32 - uiHost: - type: string - uiPort: - type: integer - format: int32 - uiAdditionalFlags: - type: string - databases: - type: array - items: - $ref: '#/components/schemas/Database' - image: - $ref: '#/components/schemas/ContainerImage' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - privilegedUsername: - type: string - privilegedPassword: - type: string - ContainerImage: - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - registry: - type: string - version: - type: string - driverClass: - type: string - dialect: - type: string - jdbcMethod: - type: string - defaultPort: - type: integer - format: int32 - dateFormats: - type: array - items: - $ref: '#/components/schemas/ContainerImageDate' - containers: - type: array - items: - $ref: '#/components/schemas/Container' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - ContainerImageDate: - type: object - properties: - id: - type: integer - format: int64 - iid: - type: integer - format: int64 - image: - $ref: '#/components/schemas/ContainerImage' - example: - type: string - hasTime: - type: boolean - databaseFormat: - type: string - unixFormat: - type: string - createdAt: - type: string - format: date-time - Creator: - type: object - properties: - id: - type: integer - format: int64 - firstname: - type: string - lastname: - type: string - creatorName: - type: string - nameType: - type: string - enum: - - PERSONAL - - ORGANIZATIONAL - nameIdentifier: - type: string - nameIdentifierScheme: - type: string - enum: - - ORCID - - ROR - - ISNI - - GRID - nameIdentifierSchemeUri: - type: string - affiliation: - type: string - affiliationIdentifier: - type: string - affiliationIdentifierScheme: - type: string - enum: - - ROR - - GRID - - ISNI - affiliationIdentifierSchemeUri: - type: string - identifier: - $ref: '#/components/schemas/Identifier' - apaName: - type: string - bibtexName: - type: string - ieeeName: - type: string - Database: - type: object - properties: - id: - type: integer - format: int64 - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - ownedBy: - type: string - format: uuid - owner: - $ref: '#/components/schemas/User' - cid: - type: integer - format: int64 - container: - $ref: '#/components/schemas/Container' - name: - type: string - internalName: - type: string - exchangeName: - type: string - description: - type: string - contactPerson: - type: string - format: uuid - contact: - $ref: '#/components/schemas/User' - identifiers: - type: array - items: - $ref: '#/components/schemas/Identifier' - subsets: - type: array - items: - $ref: '#/components/schemas/Identifier' - tables: - type: array - items: - $ref: '#/components/schemas/Table' - views: - type: array - items: - $ref: '#/components/schemas/View' - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccess' - isPublic: - type: boolean - image: - type: array - items: - type: string - format: byte - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - DatabaseAccess: - type: object - properties: - huserid: - type: string - format: uuid - user: - $ref: '#/components/schemas/User' - hdbid: - type: integer - format: int64 - database: - $ref: '#/components/schemas/Database' - type: - type: string - enum: - - AccessType.READ - - AccessType.WRITE_OWN - - AccessType.WRITE_ALL - created: - type: string - format: date-time - ForeignKey: - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - table: - $ref: '#/components/schemas/Table' - referencedTable: - $ref: '#/components/schemas/Table' - references: - type: array - items: - $ref: '#/components/schemas/ForeignKeyReference' - onUpdate: - type: string - enum: - - ReferenceType.RESTRICT - - ReferenceType.CASCADE - - ReferenceType.SET_NULL - - ReferenceType.NO_ACTION - - ReferenceType.SET_DEFAULT - onDelete: - type: string - enum: - - ReferenceType.RESTRICT - - ReferenceType.CASCADE - - ReferenceType.SET_NULL - - ReferenceType.NO_ACTION - - ReferenceType.SET_DEFAULT - ForeignKeyReference: - type: object - properties: - id: - type: integer - format: int64 - foreignKey: - $ref: '#/components/schemas/ForeignKey' - column: - $ref: '#/components/schemas/TableColumn' - referencedColumn: - $ref: '#/components/schemas/TableColumn' - Identifier: - type: object - properties: - id: - type: integer - format: int64 - queryId: - type: integer - format: int64 - tableId: - type: integer - format: int64 - viewId: - type: integer - format: int64 - creators: - type: array - items: - $ref: '#/components/schemas/Creator' - publisher: - type: string - status: - type: string - enum: - - DRAFT - - PUBLISHED - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierTitle' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierDescription' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunder' - licenses: - type: array - items: - $ref: '#/components/schemas/License' - type: - type: string - enum: - - DATABASE - - SUBSET - - TABLE - - VIEW - query: - type: string - queryNormalized: - type: string - queryHash: - type: string - resultHash: - type: string - execution: - type: string - format: date-time - resultNumber: - type: integer - format: int64 - publicationYear: - type: integer - format: int32 - publicationMonth: - type: integer - format: int32 - publicationDay: - type: integer - format: int32 - database: - $ref: '#/components/schemas/Database' - relatedIdentifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifier' - doi: - type: string - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - IdentifierDescription: - type: object - properties: - id: - type: integer - format: int64 - description: - type: string - descriptionType: - type: string - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - identifier: - $ref: '#/components/schemas/Identifier' - IdentifierFunder: - type: object - properties: - id: - type: integer - format: int64 - funderName: - type: string - funderIdentifier: - type: string - funderIdentifierType: - type: string - enum: - - CROSSREF_FUNDER_ID - - ROR - - GND - - ISNI - - OTHER - schemeUri: - type: string - awardNumber: - type: string - awardTitle: - type: string - identifier: - $ref: '#/components/schemas/Identifier' - IdentifierTitle: - type: object - properties: - id: - type: integer - format: int64 - title: - type: string - titleType: - type: string - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - identifier: - $ref: '#/components/schemas/Identifier' - License: - type: object - properties: - identifier: - type: string - uri: - type: string - description: - type: string - PrimaryKey: - type: object - properties: - id: - type: integer - format: int64 - table: - $ref: '#/components/schemas/Table' - column: - $ref: '#/components/schemas/TableColumn' - RelatedIdentifier: - type: object - properties: - id: - type: integer - format: int64 - value: - type: string - type: - type: string - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - identifier: - $ref: '#/components/schemas/Identifier' - Table: - type: object - properties: - id: - type: integer - format: int64 - tdbid: - type: integer - format: int64 - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - ownedBy: - type: string - format: uuid - owner: - $ref: '#/components/schemas/User' - name: - type: string - internalName: - type: string - queueName: - type: string - description: - type: string - database: - $ref: '#/components/schemas/Database' - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - identifiers: - type: array - items: - $ref: '#/components/schemas/Identifier' - constraints: - $ref: '#/components/schemas/Constraints' - isVersioned: - type: boolean - numRows: - type: integer - format: int64 - dataLength: - type: integer - format: int64 - maxDataLength: - type: integer - format: int64 - avgRowLength: - type: integer - format: int64 - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - TableColumn: - type: object - properties: - id: - type: integer - format: int64 - dateFormat: - $ref: '#/components/schemas/ContainerImageDate' - table: - $ref: '#/components/schemas/Table' - name: - type: string - autoGenerated: - type: boolean - internalName: - type: string - description: - type: string - indexLength: - type: integer - format: int64 - alias: - type: string - columnType: - type: string - enum: - - TableColumnType.CHAR - - TableColumnType.VARCHAR - - TableColumnType.BINARY - - TableColumnType.VARBINARY - - TableColumnType.TINYBLOB - - TableColumnType.TINYTEXT - - TableColumnType.TEXT - - TableColumnType.BLOB - - TableColumnType.MEDIUMTEXT - - TableColumnType.MEDIUMBLOB - - TableColumnType.LONGTEXT - - TableColumnType.LONGBLOB - - TableColumnType.ENUM - - TableColumnType.SET - - TableColumnType.BIT - - TableColumnType.TINYINT - - TableColumnType.BOOL - - TableColumnType.SMALLINT - - TableColumnType.MEDIUMINT - - TableColumnType.INT - - TableColumnType.BIGINT - - TableColumnType.FLOAT - - TableColumnType.DOUBLE - - TableColumnType.DECIMAL - - TableColumnType.DATE - - TableColumnType.DATETIME - - TableColumnType.TIMESTAMP - - TableColumnType.TIME - - TableColumnType.YEAR - length: - type: integer - format: int64 - isNullAllowed: - type: boolean - ordinalPosition: - type: integer - format: int32 - created: - type: string - format: date-time - concept: - $ref: '#/components/schemas/TableColumnConcept' - unit: - $ref: '#/components/schemas/TableColumnUnit' - enums: - type: array - items: - type: string - sets: - type: array - items: - type: string - size: - type: integer - format: int64 - d: - type: integer - format: int64 - min: - type: number - max: - type: number - mean: - type: number - median: - type: number - stdDev: - type: number - lastModified: - type: string - format: date-time - TableColumnConcept: - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - TableColumnUnit: - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - Unique: - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - table: - $ref: '#/components/schemas/Table' - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - User: - type: object - properties: - id: - type: string - format: uuid - username: - type: string - firstname: - type: string - lastname: - type: string - email: - type: string - orcid: - type: string - affiliation: - type: string - language: - type: string - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccess' - theme: - type: string - mariadbPassword: - type: string - View: - type: object - properties: - id: - type: integer - format: int64 - vdbid: - type: integer - format: int64 - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - name: - type: string - internalName: - type: string - isPublic: - type: boolean - isInitialView: - type: boolean - query: - type: string - queryHash: - type: string - identifiers: - type: array - items: - $ref: '#/components/schemas/Identifier' - database: - $ref: '#/components/schemas/Database' - columns: - type: array - items: - $ref: '#/components/schemas/ViewColumn' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - ViewColumn: - type: object - properties: - id: - type: integer - format: int64 - dateFormat: - $ref: '#/components/schemas/ContainerImageDate' - view: - $ref: '#/components/schemas/View' - name: - type: string - autoGenerated: - type: boolean - internalName: - type: string - columnType: - type: string - enum: - - TableColumnType.CHAR - - TableColumnType.VARCHAR - - TableColumnType.BINARY - - TableColumnType.VARBINARY - - TableColumnType.TINYBLOB - - TableColumnType.TINYTEXT - - TableColumnType.TEXT - - TableColumnType.BLOB - - TableColumnType.MEDIUMTEXT - - TableColumnType.MEDIUMBLOB - - TableColumnType.LONGTEXT - - TableColumnType.LONGBLOB - - TableColumnType.ENUM - - TableColumnType.SET - - TableColumnType.BIT - - TableColumnType.TINYINT - - TableColumnType.BOOL - - TableColumnType.SMALLINT - - TableColumnType.MEDIUMINT - - TableColumnType.INT - - TableColumnType.BIGINT - - TableColumnType.FLOAT - - TableColumnType.DOUBLE - - TableColumnType.DECIMAL - - TableColumnType.DATE - - TableColumnType.DATETIME - - TableColumnType.TIMESTAMP - - TableColumnType.TIME - - TableColumnType.YEAR - isNullAllowed: - type: boolean - ordinalPosition: - type: integer - format: int32 - size: - type: integer - format: int64 - d: - type: integer - format: int64 - LdCreatorDto: - required: - - '@type' - - name - type: object - properties: - name: - type: string - sameAs: - type: string - givenName: - type: string - familyName: - type: string - '@type': - type: string - LdDatasetDto: - required: - - '@context' - - '@type' - - citation - - creator - - description - - hasPart - - identifier - - name - - temporalCoverage - - url - - version - type: object - properties: - name: - type: string - description: - type: string - url: - type: string - identifier: - type: array - items: - type: string - license: - type: string - creator: - type: array - items: - $ref: '#/components/schemas/LdCreatorDto' - citation: - type: string - hasPart: - type: array - items: - $ref: '#/components/schemas/LdDatasetDto' - temporalCoverage: - type: string - version: - type: string - format: date-time - '@context': - type: string - '@type': - type: string - TableColumnEntityDto: - required: - - column_id - - database_id - - table_id - - uri - type: object - properties: - uri: - type: string - example: 'https://www.wikidata.org/entity/Q1686799' - label: - type: string - example: Apache Jena - description: - type: string - example: open source semantic web framework for Java - database_id: - type: integer - format: int64 - example: 1 - table_id: - type: integer - format: int64 - example: 1 - column_id: - type: integer - format: int64 - example: 1 - IndexDto: - properties: - results: - items: - type: object - type: array - type: - description: Same as the requested type - enum: - - database - - table - - view - - column - - user - - identifier - - concept - - unit - type: string - required: - - results - - type - IndexFieldDto: - properties: - attr_friendly_name: - example: Name - type: string - attr_name: - example: name - type: string - type: - description: OpenSearch data types. - example: string - type: string - required: - - attr_name - - attr_friendly_name - - type - type: object - IndexFieldsDto: - properties: - results: - items: - $ref: '#/components/schemas/IndexFieldDto' - type: array - required: - - results - type: object - SearchRequestDto: - properties: - field_value_pairs: - type: object - search_term: - type: string - required: - - search_term - - field_value_pairs - type: object - SearchResultDto: - properties: - results: - items: - type: object - type: array - required: - - results - type: object diff --git a/.docs/.swagger/openapi-merge.json b/.docs/.swagger/openapi-merge.json deleted file mode 100644 index af25a7582fc3673595a82f6b143a3e7b823a0aa9..0000000000000000000000000000000000000000 --- a/.docs/.swagger/openapi-merge.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "inputs": [ - { - "inputFile": "./api.base.yaml" - }, - { - "inputFile": "./api-analyse.yaml" - }, - { - "inputFile": "./api-data.yaml" - }, - { - "inputFile": "./api-metadata.yaml" - }, - { - "inputFile": "./api-search.yaml" - }, - { - "inputFile": "./api-sidecar.yaml" - } - ], - "output": "./api.yaml" -} diff --git a/.docs/.swagger/swagger-ui.html b/.docs/.swagger/swagger-ui.html index 0bb08a1c07c1bfca6cc820474190dada3580df48..98f7cb441fb441c5b4f559e7f7820d112aed7982 100644 --- a/.docs/.swagger/swagger-ui.html +++ b/.docs/.swagger/swagger-ui.html @@ -7,7 +7,7 @@ <title>DBRepo REST API</title> <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.17.12/swagger-ui.css"/> <link rel="stylesheet" href="./custom.css"/> - <link rel="icon" href="https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/.docs/images/logos/favicon.png" /> + <link rel="icon" href="https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/.docs/images/signet_white.png" /> </head> <body> <div class="swagger-ui"> diff --git a/.docs/api/analyse-service.md b/.docs/api/analyse-service.md index 484271bbfe75062897c6a7a2a4497e084337f3e1..be5efdbf5c8c58dd0c0825e7c1328188d01b1aba 100644 --- a/.docs/api/analyse-service.md +++ b/.docs/api/analyse-service.md @@ -11,19 +11,19 @@ author: Martin Weise * Ports: 5000/tcp * Prometheus: `http://<hostname>:5000/metrics` * Health: `http://<hostname>:5000/health` - * Swagger UI: `http://<hostname>:5000/swagger-ui/` <a href="./swagger/analyse" target="_blank">:fontawesome-solid-square-up-right: view online</a> + * Swagger UI: `http://<hostname>:5000/swagger-ui/` <a href="../swagger/analyse" target="_blank">:fontawesome-solid-square-up-right: view online</a> ## Overview -It suggests data types for the [User Interface](./system-other-ui) when creating a table from a +It suggests data types for the [User Interface](../system-other-ui) when creating a table from a *comma separated values* (CSV) -file. It recommends enumerations for columns and returns e.g. a list of potential primary key candidates. The researcher is able to confirm these suggestions manually. Moreover, the Analyse Service determines basic statistical properties of numerical columns. ### Analysis -After [uploading](./system-services-storage/#buckets) the CSV-file into the `dbrepo-upload` bucket of -the [Storage Service](./system-services-storage), analysis for data types and primary keys follows the flow: +After [uploading](../system-services-storage/#buckets) the CSV-file into the `dbrepo-upload` bucket of +the [Storage Service](../system-services-storage), analysis for data types and primary keys follows the flow: 1. Retrieve the CSV-file from the `dbrepo-upload` bucket of the Storage Service as data stream (=nothing is stored in the service) with the [`boto3`](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) client. @@ -36,16 +36,16 @@ the [Storage Service](./system-services-storage), analysis for data types and pr ### Examples -See the [usage page](./usage-analyse/) for examples. +See the [usage page](../usage-analyse/) for examples. ## Limitations !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](./contact) with us, we happily answer requests for collaboration with attached CV and your programming + in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming experience! ## Security -1. Credentials for the [Storage Service](./system-services-storage) are stored in plaintext environment variables. +1. Credentials for the [Storage Service](../system-services-storage) are stored in plaintext environment variables. diff --git a/.docs/api/data-service.md b/.docs/api/data-service.md index 41efb2151420a4507d6d0e15e6df5e8be7486984..df6b87e2f06bd59e90ce6116a240d538cd8185c4 100644 --- a/.docs/api/data-service.md +++ b/.docs/api/data-service.md @@ -14,7 +14,7 @@ author: Martin Weise - Readiness: `http://<hostname>:9093/actuator/health/readiness` - Liveness: `http://<hostname>:9093/actuator/health/liveness` * Prometheus: `http://<hostname>:9093/actuator/prometheus` - * Swagger UI: `http://<hostname>:9093/swagger-ui/index.html` <a href="./swagger/data" target="_blank">:fontawesome-solid-square-up-right: view online</a> + * Swagger UI: `http://<hostname>:9093/swagger-ui/index.html` <a href="../swagger/data" target="_blank">:fontawesome-solid-square-up-right: view online</a> ## Overview @@ -27,7 +27,7 @@ Data Service up. !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](./contact) with us, we happily answer requests for collaboration with attached CV and your programming + in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming experience! ## Security diff --git a/.docs/api/gateway-service.md b/.docs/api/gateway-service.md index cd3be4f73dd8f4891513615f7b901c055f71fed5..172892e3bdb13411c658093cbc7adf76fbdd6de7 100644 --- a/.docs/api/gateway-service.md +++ b/.docs/api/gateway-service.md @@ -41,7 +41,7 @@ If your TLS private key as a password, you need to specify it in the `dbrepo.con ### User Interface -To serve the [User Interface](./system-other-ui/) under different port than `80`, change the port mapping in +To serve the [User Interface](../system-other-ui/) under different port than `80`, change the port mapping in the `docker-compose.yml` to e.g. port `8000`: ```yaml title="docker-compose.yml" @@ -61,7 +61,7 @@ services: !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](./contact) with us, we happily answer requests for collaboration with attached CV and your programming + in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming experience! diff --git a/.docs/api/index.md b/.docs/api/index.md index 1468c2b20fd0786b0f2a7e80f697adf6ae211b26..8b8d7218b5fe26e2b477aef4a7139b221a061731 100644 --- a/.docs/api/index.md +++ b/.docs/api/index.md @@ -5,7 +5,7 @@ author: Martin Weise # Overview We developed a Python Library for communicating with DBRepo from e.g. Jupyter Notebooks. See -the [Python Library](./usage-python) page for more details. +the [Python Library](../usage-python) page for more details. We give usage examples of the most important use-cases we identified. @@ -30,7 +30,7 @@ A user wants to create an account in DBRepo. button and provide a valid work e-mail address :material-numeric-1-circle-outline: and a username (in lowercase alphanumeric characters) :material-numeric-2-circle-outline:. Choose a secure password in field :material-numeric-3-circle-outline: and repeat it in field :material-numeric-4-circle-outline:. Click "SUBMIT" and - the system creates a user account in Figure 1 with the [default roles](./system-services-authentication/#roles) + the system creates a user account in Figure 1 with the [default roles](../system-services-authentication/#roles) that your administrator has assigned. <figure markdown> @@ -425,7 +425,7 @@ A user wants to import a database dump in `.sql` (or in `.sql.gz`) format into D Setup a new connection in the MySQL Workbench (c.f. Figure 14) by clicking the small ":material-plus-circle-outline:" button :material-numeric-1-circle-outline: to open the dialog. In the opened dialog fill out the connection parameters (for local deployments the hostname is `127.0.0.1` and port `3307` for the - [Data Database](./system-databases-data/) :material-numeric-2-circle-outline:. + [Data Database](../system-databases-data/) :material-numeric-2-circle-outline:. The default credentials are username `root` and password `dbrepo`, type the password in :material-numeric-3-circle-outline: and click the "OK" button. Then finish the setup of the new connection by @@ -470,8 +470,8 @@ A user wants to import a database dump in `.sql` (or in `.sql.gz`) format into D gunzip < dump.sql.gz | mysql -H127.0.0.1 -p3307 -uUSERNAME -pYOURPASSWORD db_name ``` - The [Metadata Service](./system-services-metadata) periodically (by default configuration every 60 seconds) checks - and adds missing tables and views to the [Metadata Database](./system-databases-metadata), the database dump + The [Metadata Service](../system-services-metadata) periodically (by default configuration every 60 seconds) checks + and adds missing tables and views to the [Metadata Database](../system-databases-metadata), the database dump will be visible afterwards. Currently, date formats for columns with time types (e.g. `DATE`, `TIMESTAMP`) are assumed to match the first date format found for the database image. This may need to be manually specified by the administrator. @@ -479,7 +479,7 @@ A user wants to import a database dump in `.sql` (or in `.sql.gz`) format into D !!! example "Specifying a custom date format" In case the pre-defined date formats are not matching the found date format in the database dump, the system - administrator needs to add it manually in the [Metadata Database](./system-databases-metadata). + administrator needs to add it manually in the [Metadata Database](../system-databases-metadata). ```sql INSERT INTO `mdb_images_date` (`iid`, `database_format`, `unix_format`, `example`, `has_time`) @@ -658,7 +658,7 @@ A user wants to create a subset and export it as csv file. ``` Afterwards, you can see the subset in the UI with subset id `@subsetId` and persist it there. Only the administrator - can persist the subset in the [Data Database](./system-databases-data) through JDBC by setting the `persisted` + can persist the subset in the [Data Database](../system-databases-data) through JDBC by setting the `persisted` column to `true` in the `qs_queries` table. === "Python" @@ -732,7 +732,7 @@ A user wants to assign a persistent identifier to a database owned by them. <figcaption>Figure 21: Open the get persisent identifier form.</figcaption> </figure> - First, provide information on the dataset creator(s). Since the [Metadata Service](./system-services-metadata) + First, provide information on the dataset creator(s). Since the [Metadata Service](../system-services-metadata) automatically resolves external PIDs, the easiest way is to provide the correct mandatory data is by filling the name identifier :material-numeric-1-circle-outline:. The creator type :material-numeric-2-circle-outline: denotes either a natural person or organization. Optionally fill out the given @@ -779,7 +779,7 @@ A user wants to assign a persistent identifier to a database owned by them. <figcaption>Figure 25: Related identifiers, license and language of the identifier.</figcaption> </figure> - Optionally add funding information, again the [Metadata Service](./system-services-metadata) + Optionally add funding information, again the [Metadata Service](../system-services-metadata) automatically resolves external PIDs, the easiest way is to provide the correct mandatory data is by filling the funder identifier :material-numeric-1-circle-outline: that attempts to get the funder name :material-numeric-2-circle-outline:. If you provide an award number :material-numeric-3-circle-outline: and/or @@ -817,11 +817,11 @@ A user wants to assign a persistent identifier to a database owned by them. !!! warning - Creating a PID directly in the [Metadata Database](./system-databases-metadata) is not recommended! It bypasses + Creating a PID directly in the [Metadata Database](../system-databases-metadata) is not recommended! It bypasses validation and creation of external PIDs (e.g. DOI) and may lead to inconstistent data locally compared to external systems (e.g. DataCite Fabrica). - Create a local PID directly in the [Metadata Database](./system-databases-metadata) by filling the tables in this + Create a local PID directly in the [Metadata Database](../system-databases-metadata) by filling the tables in this order (they have foreign key dependencies). 1. `mdb_identifiers` ... identifier core information @@ -928,7 +928,7 @@ A user wants a public database to be private and only give specific users access === "JDBC" To change the visibility of a database as administrator with direct JDBC access to - the [Metadata Database](./system-databases-metadata), change the visibility directly by executing the SQL-query + the [Metadata Database](../system-databases-metadata), change the visibility directly by executing the SQL-query in the `fda` schema: ```sql diff --git a/.docs/api/metadata-service.md b/.docs/api/metadata-service.md index 362a9c36bcf6a32ba8262d002716e108d998b2be..33f3db3bfe5be3d473420599ff90b6582a9e4443 100644 --- a/.docs/api/metadata-service.md +++ b/.docs/api/metadata-service.md @@ -14,7 +14,7 @@ author: Martin Weise - Readiness: `http://<hostname>:9099/actuator/health/readiness` - Liveness: `http://<hostname>:9099/actuator/health/liveness` * Prometheus: `http://<hostname>:9099/actuator/prometheus` - * Swagger UI: `http://<hostname>:9099/swagger-ui/index.html` <a href="./swagger/metadata" target="_blank">:fontawesome-solid-square-up-right: view online</a> + * Swagger UI: `http://<hostname>:9099/swagger-ui/index.html` <a href="../swagger/metadata" target="_blank">:fontawesome-solid-square-up-right: view online</a> ## Overview @@ -75,23 +75,23 @@ Executing SQL queries through the Query Endpoint must fulfill some restrictions: ### Semantics -The service provides metadata to the table columns in the [Metadata Database](./system-databases-metadata) from +The service provides metadata to the table columns in the [Metadata Database](../system-databases-metadata) from registered ontologies like Wikidata [`wd:`](https://wikidata.org), Ontology of Units of Measurement [`om2:`](https://www.ontology-of-units-of-measure.org/resource/om-2), Friend of a Friend [`foaf:`](http://xmlns.com/foaf/0.1/), the [`prov:`](http://www.w3.org/ns/prov#) namespace, etc. ### Tables -The service manages tables in the [Data Database](./system-databases-data) and manages the metadata of these tables -in the [Metadata Database](./system-databases-metadata). Any tables that are created outside of DBRepo (e.g. directly via the JDBC API) are +The service manages tables in the [Data Database](../system-databases-data) and manages the metadata of these tables +in the [Metadata Database](../system-databases-metadata). Any tables that are created outside of DBRepo (e.g. directly via the JDBC API) are periodically fetched by this service (based on the `OBTAIN_METADATA_RATE` environment variable, default interval is 60 seconds). ### Users -The service manages users in the [Data Database](./system-databases-data) -and [Metadata Database](./system-databases-metadata), as well as in the [Broker Service](./system-services-broker) -and the [Authentication Service](./system-services-authentication). +The service manages users in the [Data Database](../system-databases-data) +and [Metadata Database](../system-databases-metadata), as well as in the [Broker Service](../system-services-broker) +and the [Authentication Service](../system-services-authentication). The default configuration grants the users only very basic permissions on the databases: @@ -123,8 +123,8 @@ A list of all grants is available in the MariaDB documentation for [`GRANT`](htt ### Views -The service manages views in the [Data Database](./system-databases-data) -and [Metadata Database](./system-databases-metadata). Any views that are created outside of DBRepo (e.g. directly via +The service manages views in the [Data Database](../system-databases-data) +and [Metadata Database](../system-databases-metadata). Any views that are created outside of DBRepo (e.g. directly via the JDBC API) are periodically fetched by this service (based on the `OBTAIN_METADATA_RATE` environment variable, default interval is 60 seconds). @@ -136,7 +136,7 @@ default interval is 60 seconds). !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](./contact) with us, we happily answer requests for collaboration with attached CV and your programming + in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming experience! ## Security diff --git a/.docs/api/open-api.md b/.docs/api/open-api.md index 72395271dea13288dd0065b2a385095faad2955b..f06ec67a0daec31d77ddd0b62716276183c4b728 100644 --- a/.docs/api/open-api.md +++ b/.docs/api/open-api.md @@ -2,12 +2,6 @@ author: Martin Weise --- - - -## tl;dr - -[:simple-swagger: View Swagger-UI](../../swagger/){ .md-button .md-button--primary tabindex=-1 } - -## Overview - -All services are documented using the [OpenAPI 3.1](https://www.openapis.org/) documentation standard. \ No newline at end of file +All services are documented using the +[](https://www.openapis.org/){ tabindex=-1 } +documentation standard. diff --git a/.docs/api/storage-service.md b/.docs/api/storage-service.md index bf40ca83c8cfde0951a3796df0fbb06e0e486478..2219c5fa5759dce36cbb0276594b1f0c5d32ee64 100644 --- a/.docs/api/storage-service.md +++ b/.docs/api/storage-service.md @@ -36,7 +36,7 @@ The default configuration creates two buckets `dbrepo-upload`, `dbrepo-download` !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](./contact) with us, we happily answer requests for collaboration with attached CV and your programming + in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming experience! ## Security diff --git a/.docs/deployment-docker-compose.md b/.docs/deployment-docker-compose.md index 7b6d9922561ddeafee790da540e301b65e09f74c..0d541cd174207c544bd7d9ed007ffefd734b9f9a 100644 --- a/.docs/deployment-docker-compose.md +++ b/.docs/deployment-docker-compose.md @@ -53,7 +53,7 @@ technologies. The conceptualized microservices operate the basic database operat ### Notes -Please note that we only save the state of the databases as well as the [Broker Service](./system-services-broker) +Please note that we only save the state of the databases as well as the [Broker Service](../system-services-broker) since RabbitMQ maintains state inside the container. ## Deployment @@ -147,8 +147,8 @@ Please be warned that the default configuration is not intended for public deplo running system within minutes to play around within the system and explore features. It is strongly advised to change the default `.env` environment variables. -Next, create a [user account](./usage-overview/#create-user-account) and -then [create a database](./usage-overview/#create-database) to [import a dataset](./usage-overview/#import-dataset). +Next, create a [user account](../usage-overview/#create-user-account) and +then [create a database](../usage-overview/#create-database) to [import a dataset](../usage-overview/#import-dataset). ## Security @@ -193,4 +193,4 @@ then [create a database](./usage-overview/#create-database) to [import a dataset !!! info "Alternative Deployments" - Alternatively, you can also deploy DBRepo with [Helm](./deployment-helm/) in your virtual machine instead. + Alternatively, you can also deploy DBRepo with [Helm](../deployment-helm/) in your virtual machine instead. diff --git a/.docs/deployment-helm.md b/.docs/deployment-helm.md index 5b0be43553584e6c6be4f582615bc9afcffd918a..745ad87b944da4afde11fff736e984ecc860f90c 100644 --- a/.docs/deployment-helm.md +++ b/.docs/deployment-helm.md @@ -32,12 +32,12 @@ about values, etc. ## Limitations 1. MariaDB Galera does not (yet) support XA-transactions required by the authentication service (=Keycloak). Therefore - only a single MariaDB pod can be deployed at once for the [auth database](./system-databases-authentication). + only a single MariaDB pod can be deployed at once for the [auth database](../system-databases-authentication). 2. The entire Helm deployment is rootless (=`runAsNonRoot=true`) except for - the [Storage Service](./system-services-storage/) which still requires a root user. + the [Storage Service](../system-services-storage/) which still requires a root user. !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](./contact) with us, we happily answer requests for collaboration with attached CV and your programming + in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming experience! diff --git a/.docs/docker/_header.md b/.docs/docker/_header.md index 3a5b13338af17c5e1f3a146aaba6c3aa35b5a3d4..081bf9697cbe996cb43d86787fc36319c617be1e 100644 --- a/.docs/docker/_header.md +++ b/.docs/docker/_header.md @@ -10,7 +10,7 @@ # Supported tags -* [`1.4.3`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/blob/release-1.4.3/dbrepo-DIR/Dockerfile/) +* [`1.4.x`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/blob/release-__APP_VERSION__/dbrepo-DIR/Dockerfile/) * [`latest`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/blob/release-latest/dbrepo-DIR/Dockerfile/) # Non-supported tags @@ -29,8 +29,8 @@ * **Source of this description:** - [docs repo's `.docs/docker` directory](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tree/release-1.4.3/.docs/docker) - ([history](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/commits/release-1.4.3/.docs/docker)) + [docs repo's `.docs/docker` directory](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tree/release-__APP_VERSION__/.docs/docker) + ([history](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/commits/release-__APP_VERSION__/.docs/docker)) # What is DBRepo? diff --git a/.docs/publications.md b/.docs/publications.md index 4b64d9a5746b2bf9db2c0804e174df08a6e70321..cbaac17564c183597abda9cbf3fccbf61ebfc873 100644 --- a/.docs/publications.md +++ b/.docs/publications.md @@ -14,14 +14,14 @@ hide: Semantic Digital Repository for Relational Databases. *International Journal of Digital Curation*, 17(1), 11. DOI: [10.2218/ijdc.v17i1.825](https://doi.org/10.2218/ijdc.v17i1.825)<br /> - [[BibTeX](./papers/weise2022dbrepo.bib)] [[RIS](./papers/weise2022dbrepo.ris)] [[RDF](./papers/weise2022dbrepo.rdf)] [[EndNote](./papers/weise2022dbrepo.xml)] + [[BibTeX](../papers/weise2022dbrepo.bib)] [[RIS](../papers/weise2022dbrepo.ris)] [[RDF](../papers/weise2022dbrepo.rdf)] [[EndNote](../papers/weise2022dbrepo.xml)] ## Logos DBRepo logo in various formats: -* PNG: [bigger](./images/logo/logo.png) ([smaller](./images/logo/favicon.png)) -* SVG: [bigger](./images/logo/logo.svg) ([smaller](./images/logo/favicon.svg)) +* PNG: [bigger](../images/logo/logo.png) ([smaller](../images/logo/favicon.png)) +* SVG: [bigger](../images/logo/logo.svg) ([smaller](../images/logo/favicon.svg)) ## Refereed diff --git a/.docs/usage-storage.md b/.docs/usage-storage.md index fb409571f79d3c4459fc29c61ab242f83956d125..253fe8e960814e2a91d723dd44c620726df6b7e9 100644 --- a/.docs/usage-storage.md +++ b/.docs/usage-storage.md @@ -53,7 +53,7 @@ $ aws --endpoint-url http://localhost:9000 \ ## Other -Alternatively, you can use the middleware of the [User Interface](./system-other-ui/) to upload files. +Alternatively, you can use the middleware of the [User Interface](../system-other-ui/) to upload files. Alternatively, you can use a S3-compatible client: diff --git a/.docs/usage-upload.md b/.docs/usage-upload.md index 1735e6cced219dced24296bdd42ec0693c6f75a8..f84f853eb617e10c6f0583975670fb788dd0e878 100644 --- a/.docs/usage-upload.md +++ b/.docs/usage-upload.md @@ -11,7 +11,7 @@ We recommend using a TUS-compatible client: * [tus-js-client](https://github.com/tus/tus-js-client) (JavaScript/Node.js) * [tusd](https://github.com/tus/tusd) (Go) -Upload a file to the `dbrepo-upload` bucket in the [Storage Service](./system-services-storage/) using the Node.js +Upload a file to the `dbrepo-upload` bucket in the [Storage Service](../system-services-storage/) using the Node.js middleware. === "Terminal" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1c0328375d3a5b32e209dedf0540f3c16c1b8110..95892b16153fd35f5996f9e5489ef22b26d508b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,8 +5,8 @@ variables: DOCKER_HOST: "unix:///var/run/dind/docker.sock" TESTCONTAINERS_RYUK_DISABLED: "false" DOC_VERSIONS: "latest,1.4.3,1.4.2,1.4.1,1.4.0" - APP_VERSION: "1.4.4" - CHART_VERSION: "1.4.4" + APP_VERSION: "1.4.3" + CHART_VERSION: "1.4.3" image: debian:12-slim @@ -569,6 +569,7 @@ docs-registry: - "apt-get update && apt-get install -y sed" script: - pip install -r ./requirements.txt + - find .docs -type f -exec sed -i -e "s/__APP_VERSION__/${APP_VERSION}/g" {} \; - python3 .docs/docker/release.py release-images: @@ -587,7 +588,7 @@ release-images: - "ifconfig eth0 mtu 1450 up" - "apk add make bash" script: - - "make release-images" + - "make release" release-chart: stage: release @@ -595,14 +596,13 @@ release-chart: only: refs: - /^release-.*/ - except: - refs: - - release-latest before_script: - "echo ${CI_REGISTRY2_PASSWORD} | docker login --username ${CI_REGISTRY2_USER} --password-stdin $CI_REGISTRY2_URL" + - "echo ${CI_GPG_KEYRING} | base64 -d > ~/keyring.gpg" - "apk add sed helm curl" - "helm plugin install https://github.com/sigstore/helm-sigstore" script: + - "helm package --sign --key 'Martin Weise' ./helm/dbrepo --keyring ~/keyring.gpg --destination ./build" - "helm push ./build/dbrepo-${CHART_VERSION}.tgz oci://${CI_REGISTRY2_URL}/helm" - "helm sigstore upload ./build/dbrepo-${CHART_VERSION}.tgz" @@ -617,29 +617,26 @@ release-docs: before_script: - "wget https://github.com/mikefarah/yq/releases/download/v4.2.0/yq_linux_amd64 -O /usr/bin/yq" - "chmod +x /usr/bin/yq" - - "apk add --update alpine-sdk bash sed wget openssh" - - "pip install -r ./requirements.txt" + - "apt-get update && apt-get install -y git make sed wget ssh" - "mkdir -p ./final/${VERSION}/swagger" script: - - "make gen-lib-doc gen-docs-doc" + - "make gen-swagger-doc gen-lib-doc gen-docs-doc" - "cp -r ./lib/python/docs/build/html ./final/${VERSION}/sphinx" # sphinx - "cp .docs/.swagger/api.yaml ./final/${VERSION}/swagger/api.yaml" # swagger - "cp .docs/.swagger/swagger-ui.html ./final/${VERSION}/swagger/index.html" # swagger - "cp .docs/.swagger/custom.css ./final/${VERSION}/swagger/custom.css" # swagger - - "cp -r ./site/* ./final/${VERSION}" # mkdocs + - "cp -r ./site ./final/${VERSION}" # mkdocs - eval $(ssh-agent -s) - - "mkdir -p /root/.ssh" - echo "$CI_KEY_PRIVATE" > /root/.ssh/id_rsa && chmod 0600 /root/.ssh/id_rsa - echo "$CI_KEY_PUBLIC" > /root/.ssh/id_rsa.pub - echo "$CI_DOC_ID" > ~/.ssh/known_hosts - tar czf ./final.tar.gz ./final - "scp -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedAlgorithms=+ssh-rsa final.tar.gz $CI_DOC_USER@$CI_DOC_IP:final.tar.gz" - - "ssh -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedAlgorithms=+ssh-rsa $CI_DOC_USER@$CI_DOC_IP 'rm -rf /system/user/ifs/infrastructures/public_html/dbrepo/*; tar xzf ./final.tar.gz; rm -f ./final.tar.gz; cp -r ./final/* /system/user/ifs/infrastructures/public_html/dbrepo/${VERSION}; rm -rf ./final'" + - "ssh -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedAlgorithms=+ssh-rsa $CI_DOC_USER@$CI_DOC_IP 'rm -rf /system/user/ifs/infrastructures/public_html/dbrepo/*; tar xzf ./final.tar.gz; rm -f ./final.tar.gz; cp -r ./final/* /system/user/ifs/infrastructures/public_html/dbrepo; rm -rf ./final'" release-libs: stage: release image: docker.io/python:3.11-alpine - when: manual only: refs: - /^release-.*/ diff --git a/Makefile b/Makefile index 84d1f85e5d329478a5a0de2c61ec69c2ab494c53..3c178cfa9eaae9a6a54464d1d12288ad7a186e93 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ APP_VERSION ?= 1.4.3 CHART_VERSION ?= 1.4.3 -REPOSITORY_URL ?= docker.io/dbrepo +REPOSITORY_1_URL ?= docker.io/dbrepo +REPOSITORY_2_URL ?= s210.dl.hpc.tuwien.ac.at/dbrepo .PHONY: all all: help diff --git a/build-docs.sh b/build-docs.sh index fba2afc76609716172f53c8bb0125c579a99d8d9..a38121fceb9a4cd1b43c34058755a049a08f8beb 100644 --- a/build-docs.sh +++ b/build-docs.sh @@ -88,7 +88,6 @@ done # finalization echo "===================================================" -echo "Moving HTML redirect and JSON versions to /" -cp ./final/${APP_VERSION}/redirect.html ./final/index.html -cp ./final/${APP_VERSION}/versions.json ./final/versions.json +echo "Moving default version $APP_VERSION docs to /" +cp -r ./final/${APP_VERSION}/* ./final/ echo "===================================================" diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index adf893c96069e0238f9cede9ae366e0094edf68b..8a14b2d86f90cf92fb58a7e42d58d520d7d79f0d 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -167,20 +167,20 @@ }, "boto3": { "hashes": [ - "sha256:8f9c43c54b3dfaa36c4a0d7b42c417227a515bc7a2e163e62802780000a5a3e2", - "sha256:cea2365a25b2b83a97e77f24ac6f922ef62e20636b42f9f6ee9f97188f9c1c03" + "sha256:4eb8019421cb664a6fcbbee6152aa95a28ce8bbc1c4ee263871c09cdd58bf8ee", + "sha256:e9edaf979fbe59737e158f2f0f3f0861ff1d61233f18f6be8ebb483905f24587" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.119" + "version": "==1.34.118" }, "botocore": { "hashes": [ - "sha256:4bdf7926a1290b2650d62899ceba65073dd2693e61c35f5cdeb3a286a0aaa27b", - "sha256:b253f15b24b87b070e176af48e8ef146516090429d30a7d8b136a4c079b28008" + "sha256:0a3d1ec0186f8b516deb39474de3d226d531f77f92a0f56ad79b80219db3ae9e", + "sha256:e3f6c5636a4394768e81e33a16f5c6ae7f364f512415d423f9b9dc67fc638df4" ], "markers": "python_version >= '3.8'", - "version": "==1.34.119" + "version": "==1.34.118" }, "certifi": { "hashes": [ @@ -354,45 +354,45 @@ }, "cryptography": { "hashes": [ - "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad", - "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583", - "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b", - "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c", - "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1", - "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648", - "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949", - "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba", - "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c", - "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9", - "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d", - "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c", - "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e", - "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2", - "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d", - "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7", - "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70", - "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2", - "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7", - "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14", - "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe", - "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e", - "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71", - "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961", - "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7", - "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c", - "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28", - "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842", - "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902", - "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801", - "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a", - "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e" + "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55", + "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785", + "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b", + "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886", + "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82", + "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1", + "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda", + "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f", + "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68", + "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60", + "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7", + "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd", + "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582", + "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc", + "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858", + "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b", + "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2", + "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678", + "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13", + "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4", + "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8", + "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604", + "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477", + "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e", + "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a", + "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9", + "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14", + "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda", + "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da", + "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562", + "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2", + "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9" ], "markers": "python_version >= '3.7'", - "version": "==42.0.8" + "version": "==42.0.7" }, "dbrepo": { "hashes": [ - "sha256:2bdb48c70b4c99b5044fbfc12aa653c1e9281ca8913a433cc08a1e14cb4bd2ef" + "sha256:110db9e4e70f5656a6351409d4b022656abf7de0bd72d5e061a25685f708d9a4" ], "path": "./lib/dbrepo-1.4.4.tar.gz" }, @@ -1414,7 +1414,7 @@ "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" ], - "markers": "python_version >= '3.10'", + "markers": "python_version >= '3.8'", "version": "==2.2.1" }, "werkzeug": { @@ -1940,12 +1940,12 @@ }, "pytest": { "hashes": [ - "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343", - "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977" + "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd", + "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.2.2" + "version": "==8.2.1" }, "python-dateutil": { "hashes": [ @@ -2017,7 +2017,7 @@ "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" ], - "markers": "python_version >= '3.10'", + "markers": "python_version >= '3.8'", "version": "==2.2.1" }, "wrapt": { diff --git a/dbrepo-analyse-service/app.py b/dbrepo-analyse-service/app.py index 0e8a10bf1dccdad1917e85407c53913529b741ba..de1ca37a4d5ac444ddb527a86e041d5868bf1e4b 100644 --- a/dbrepo-analyse-service/app.py +++ b/dbrepo-analyse-service/app.py @@ -19,6 +19,7 @@ from botocore.exceptions import ClientError from clients.keycloak_client import KeycloakClient, User from determine_dt import determine_datatypes from determine_pk import determine_pk +from determine_stats import determine_stats logging.addLevelName(level=logging.NOTSET, levelName='TRACE') logging.basicConfig(level=logging.DEBUG) @@ -57,7 +58,7 @@ basic_auth = HTTPBasicAuth() auth = MultiAuth(token_auth, basic_auth) metrics = PrometheusMetrics(app) -metrics.info("app_info", "Application info", version="1.4.4") +metrics.info("app_info", "Application info", version="__APPVERSION__") app.config["SWAGGER"] = {"openapi": "3.0.1", "title": "Swagger UI", "uiversion": 3} swagger_config = { @@ -78,64 +79,6 @@ swagger_config = { template = { "openapi": "3.0.0", "components": { - "schemas": { - "DataTypesDto": { - "properties": { - "columns": { - "$ref": "#/components/schemas/SuggestedColumnDto" - }, - "line_termination": { - "example": "\r\n", - "type": "string" - }, - "separator": { - "example": ",", - "type": "string" - } - }, - "type": "object" - }, - "ErrorDto": { - "properties": { - "message": { - "example": "Message", - "type": "string" - }, - "success": { - "example": False, - "type": "boolean" - } - }, - "type": "object" - }, - "KeysDto": { - "properties": { - "keys": { - "items": { - "properties": { - "column_name": { - "format": "int64", - "type": "integer" - } - } - }, - "type": "array" - } - }, - "required": [ - "keys" - ], - "type": "object" - }, - "SuggestedColumnDto": { - "properties": { - "column_name": { - "type": "string" - } - }, - "type": "object" - } - }, "securitySchemes": { "bearerAuth": { "type": "http", @@ -153,7 +96,7 @@ template = { "info": { "title": "Database Repository Analyse Service API", "description": "Service that analyses data structures", - "version": "1.4.4", + "version": "__APPVERSION__", "contact": { "name": "Prof. Andreas Rauber", "email": "andreas.rauber@tuwien.ac.at" @@ -237,6 +180,7 @@ def get_user_roles(user: User) -> List[str]: @app.route("/health", methods=["GET"], endpoint="analyse_health") +@swag_from("as-yml/health.yml") def get_health(): res = dumps({"status": "UP", "message": "Application is up and running"}) return Response(res, mimetype="application/json"), 200 @@ -287,3 +231,25 @@ def analyse_keys(): except OSError as e: logging.error(f"Failed to determine primary key: {e}") return ApiError(status='BAD_REQUEST', message=str(e), code='analyse.database.invalid'), 400 + + +@app.route("/api/analyse/database/<database_id>/table/<table_id>/statistics", methods=["GET"], + endpoint="analyse_analyse_table_stat") +@auth.login_required(role=['admin', 'export-query-data', 'export-table-data']) +@metrics.gauge(name='dbrepo_analyse_table_stat', description='Time needed to analyse table statistics') +@swag_from("as-yml/analyse_table_stat.yml") +def analyse_table_stat(database_id: int = None, table_id: int = None): + if database_id is None: + return ApiError(status='BAD_REQUEST', message="Missing path variable 'database_id'", + code='analyse.database.invalid'), 400 + if table_id is None: + return ApiError(status='BAD_REQUEST', message="Missing path variable 'table_id'", + code='analyse.table.invalid'), 400 + + try: + table_stats = determine_stats(database_id=database_id, table_id=table_id) + logging.info(f"Analysed table statistics") + return table_stats.model_dump(), 202 + except OSError: + return ApiError(status='NOT_FOUND', message='Database or table does not exist', + code='analyse.database.missing'), 404 diff --git a/dbrepo-analyse-service/as-yml/analyse_datatypes.yml b/dbrepo-analyse-service/as-yml/analyse_datatypes.yml index ae52198766a9e7842f8320d338791a4f099f26a5..5d30665da832f594a49ecf234205ccd54c1aa32d 100644 --- a/dbrepo-analyse-service/as-yml/analyse_datatypes.yml +++ b/dbrepo-analyse-service/as-yml/analyse_datatypes.yml @@ -57,6 +57,48 @@ responses: application/json: schema: $ref: '#/components/schemas/ErrorDto' -security: - - bearerAuth: [ ] - - basicAuth: [ ] +components: + schemas: + DetermineDataTypesDto: + required: + - filename + - separator + type: object + properties: + enum: + type: boolean + example: false + enum_tol: + type: double + example: 0.01 + filename: + type: string + example: s3-key-from-seaweedfs + separator: + type: string + example: "," + DataTypesDto: + type: object + properties: + columns: + $ref: '#/components/schemas/SuggestedColumnDto' + line_termination: + type: string + example: "\r\n" + separator: + type: string + example: "," + SuggestedColumnDto: + type: object + properties: + column_name: + type: string + ErrorDto: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Message \ No newline at end of file diff --git a/dbrepo-analyse-service/as-yml/analyse_keys.yml b/dbrepo-analyse-service/as-yml/analyse_keys.yml index da4f0bbca04b65b8f4131a6d8ab1a4d43270ad60..a01b396cec7f49fb0960f8025a064ca5fbb74c72 100644 --- a/dbrepo-analyse-service/as-yml/analyse_keys.yml +++ b/dbrepo-analyse-service/as-yml/analyse_keys.yml @@ -45,6 +45,42 @@ responses: application/json: schema: $ref: '#/components/schemas/ErrorDto' -security: - - bearerAuth: [ ] - - basicAuth: [ ] \ No newline at end of file +components: + schemas: + KeysDto: + required: + - keys + type: object + properties: + keys: + type: array + items: + properties: + column_name: + type: integer + format: int64 + DataTypesDto: + type: object + properties: + columns: + $ref: '#/components/schemas/SuggestedColumnDto' + line_termination: + type: string + example: "\r\n" + separator: + type: string + example: "," + SuggestedColumnDto: + type: object + properties: + column_name: + type: string + ErrorDto: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Message \ No newline at end of file diff --git a/dbrepo-analyse-service/as-yml/analyse_table_stat.yml b/dbrepo-analyse-service/as-yml/analyse_table_stat.yml index 8639d4dd9278ddf118f552249021fc60498dd47c..6978daf22904d3449c621f8e253a08908df6a8c8 100644 --- a/dbrepo-analyse-service/as-yml/analyse_table_stat.yml +++ b/dbrepo-analyse-service/as-yml/analyse_table_stat.yml @@ -39,3 +39,50 @@ responses: application/json: schema: $ref: '#/components/schemas/ErrorDto' +components: + schemas: + TableStats: + required: + - columns + type: object + properties: + columns: + type: object + properties: + column_name: + $ref: '#/components/schemas/Stats' + Stats: + type: object + properties: + val_min: + type: float + example: "0.0" + val_max: + type: float + example: "1.0" + mean: + type: float + example: "0.3" + median: + type: float + example: "0.45" + std_dev: + type: float + example: "0.12" + ErrorDto: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Message + securitySchemes: + basicAuth: + type: http + scheme: basic + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT \ No newline at end of file diff --git a/dbrepo-analyse-service/as-yml/health.yml b/dbrepo-analyse-service/as-yml/health.yml new file mode 100644 index 0000000000000000000000000000000000000000..a0f7ebcbacbd06a4dcaf262298456cf5b713cce8 --- /dev/null +++ b/dbrepo-analyse-service/as-yml/health.yml @@ -0,0 +1,18 @@ +tags: + - health-endpoint +summary: "Check if application is running" +description: "This is a simple API which checks if the application is healthy" +consumes: + - "application/json" +produces: + - "application/json" +responses: + 200: + description: "OK" + schema: + type: "object" + properties: + status: + type: "string" + example: "UP" + \ No newline at end of file diff --git a/dbrepo-analyse-service/determine_stats.py b/dbrepo-analyse-service/determine_stats.py new file mode 100644 index 0000000000000000000000000000000000000000..d529ab8c28a5231f658a0081d1aec51c50a015bb --- /dev/null +++ b/dbrepo-analyse-service/determine_stats.py @@ -0,0 +1,28 @@ +import logging + +from flask import current_app + +from pandas import DataFrame, isna +from dbrepo.RestClient import RestClient + +from api.dto import TableStat, ColumnStat + + +def determine_stats(database_id: int, table_id: int) -> TableStat: + client = RestClient(endpoint=current_app.config['GATEWAY_SERVICE_ENDPOINT'], + username=current_app.config['ADMIN_USERNAME'], password=current_app.config['ADMIN_PASSWORD']) + df: DataFrame = client.get_table_data(database_id=database_id, table_id=table_id, page=0, size=1000, df=True) + stats = TableStat(columns=dict()) + for name, dtype in df.dtypes.items(): + # Check if the column has a numeric data type + if dtype.kind in "fi": + val_min = None if isna(df[name].min()) else df[name].min() + val_max = None if isna(df[name].max()) else df[name].max() + mean = None if isna(df[name].mean()) else df[name].mean() + median = None if isna(df[name].median()) else df[name].median() + std_dev = None if isna(df[name].std()) else df[name].std() + stats.columns[str(name)] = ColumnStat(val_min=val_min, val_max=val_max, mean=mean, median=median, + std_dev=std_dev) + logging.debug(f"statistical props of the first 1000 rows: <min={val_min}, max={val_max}, mean={mean}, " + f"median={median}, std_dev={std_dev}>") + return stats diff --git a/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl index 694a6fc02560b3b5d858df0e5a0bd9acf45c8f20..f58e17a58e747e35bbd37f43efe6b460ba31530f 100644 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl and b/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz index f344d01026b92476d80703cbfb7d884cb7822e05..5463f6b170c24fff05d29a434562104553292fea 100644 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz and b/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz differ diff --git a/dbrepo-auth-service/dbrepo-realm.json b/dbrepo-auth-service/dbrepo-realm.json index bd5a5464e7aeadd4c4012e7c0fa7e74efa2b6d04..f5ced37ff24b995b58f2cbb16686269b9ad46056 100644 --- a/dbrepo-auth-service/dbrepo-realm.json +++ b/dbrepo-auth-service/dbrepo-realm.json @@ -126,7 +126,7 @@ "description" : "${default-table-handling}", "composite" : true, "composites" : { - "realm" : [ "modify-table-column-semantics", "list-tables", "update-table-statistic", "find-table", "create-table", "delete-table" ] + "realm" : [ "modify-table-column-semantics", "list-tables", "find-table", "create-table", "delete-table" ] }, "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", @@ -166,14 +166,6 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } - }, { - "id" : "0e12eedf-545d-4d32-ac4d-2821dcb118b8", - "name" : "update-table-statistic", - "description" : "${update-table-statistic}", - "composite" : false, - "clientRole" : false, - "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", - "attributes" : { } }, { "id" : "e63e61a2-d852-4ad3-bfb5-92d9ceafef6a", "name" : "escalated-user-handling", @@ -2118,7 +2110,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper" ] + "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper" ] } }, { "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979", @@ -2127,7 +2119,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper" ] } } ], "org.keycloak.keys.KeyProvider" : [ { @@ -2179,7 +2171,7 @@ "internationalizationEnabled" : false, "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "8b55b559-905f-4f73-b050-0cd68f676a42", + "id" : "fbce9485-c780-438c-bbe9-135352504aa7", "alias" : "Account verification options", "description" : "Method with which to verity the existing account", "providerId" : "basic-flow", @@ -2201,7 +2193,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "293efab0-aa10-44e6-8f5a-dd63d6908d9e", + "id" : "dce6a1a5-7099-4366-a644-79b08fd399fd", "alias" : "Authentication Options", "description" : "Authentication options.", "providerId" : "basic-flow", @@ -2230,7 +2222,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "f3c7659d-9c24-43e7-b94c-8bfb4811084f", + "id" : "ac79c3e5-8aa3-499c-ae23-1656ab67972c", "alias" : "Browser - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2252,7 +2244,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "1d83f267-0342-41c1-9a64-11cc9b8e62fc", + "id" : "ecafaa7c-4a1f-4842-b8cd-6661fea1da33", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2274,7 +2266,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "bb881bf0-e8f5-418e-91ec-09624683ec66", + "id" : "55d29fb3-07a8-47b7-a051-9176e404ab55", "alias" : "First broker login - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2296,7 +2288,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "aea83d83-6c28-4df6-9543-2bf74cc4b78a", + "id" : "23a6b3f9-d7dc-41f0-b9b0-917e64aa62ed", "alias" : "Handle Existing Account", "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId" : "basic-flow", @@ -2318,7 +2310,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "78283326-7419-4cca-a5dd-cf510db7041c", + "id" : "ea03fe83-9a6c-47e0-85e9-94fb006bc504", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -2340,7 +2332,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "c88bb673-7092-4996-8c46-e9b08c94eb8c", + "id" : "c2f4bb71-24a7-42a2-a870-d0485b6430f7", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -2363,7 +2355,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "6632c7a3-8a7f-4f94-a15d-bdce1563f419", + "id" : "08a0c43e-434c-4f9d-97d8-efcc697c0bdb", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -2385,7 +2377,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "3a383f61-8ad4-4815-93a8-d04eefc48791", + "id" : "9df5a633-532d-4da0-99ad-b60bac9a984b", "alias" : "browser", "description" : "browser based authentication", "providerId" : "basic-flow", @@ -2421,7 +2413,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "fc65865d-d3a4-4769-a665-fd49b34d2687", + "id" : "cac0d15d-bba8-4731-a184-5711bfdc38d8", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -2457,7 +2449,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "40077362-bb0b-41c7-a297-1d4c3625b17d", + "id" : "5cb539c9-6124-4883-b058-e4b0062c8ed0", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -2486,7 +2478,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "5b2f7f25-f5dd-4013-800d-6030b79e257e", + "id" : "610d7baf-f915-44e0-8617-8ae6309b1098", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -2501,7 +2493,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "e9da2536-e792-461d-aceb-085f18ca533c", + "id" : "d613df19-1185-4796-b1e9-9716f4b241c9", "alias" : "first broker login", "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "providerId" : "basic-flow", @@ -2524,7 +2516,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "4c17ae53-d99e-4f47-92ef-47accae912fd", + "id" : "7a475371-0966-4dff-9296-28790d5aa227", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -2546,7 +2538,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "da0ed32c-3259-4571-877b-914fa2aa30b3", + "id" : "7d71011c-9828-495a-8fc6-82e88e308d26", "alias" : "http challenge", "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", "providerId" : "basic-flow", @@ -2568,7 +2560,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "476d469b-5c54-42af-a41c-5dbe08412395", + "id" : "0eb1b344-0a43-4ffa-8bf2-98560bd7471f", "alias" : "registration", "description" : "registration flow", "providerId" : "basic-flow", @@ -2584,7 +2576,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "714c4dc0-d7b3-4e12-93bd-59a7c4fbeef2", + "id" : "fd2328ca-38ca-4dc9-b9e5-09790a3512c5", "alias" : "registration form", "description" : "registration form", "providerId" : "form-flow", @@ -2620,7 +2612,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "316122ff-d003-49f7-9a0d-a570489bec9d", + "id" : "770cf19b-4bc2-4161-b156-161dc23eebaa", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -2656,7 +2648,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "5c90488c-9d5c-460d-9deb-9740740c3a9e", + "id" : "ab251c63-6c1b-4d93-9f26-2f5d18c81832", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -2672,13 +2664,13 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "874c7063-05d5-45fb-b919-840798663176", + "id" : "709dcd0e-a60b-4ae5-ac66-d15374b1562c", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "93cf220e-2830-4ccb-9054-b3b87ef75fd4", + "id" : "f80268b2-6944-4acd-b622-426369f8c44d", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" diff --git a/dbrepo-data-db/sidecar/app.py b/dbrepo-data-db/sidecar/app.py index c88966bb00e789e8b102985a5abbdf4ec7034c90..f4342301dfed6a16dc21a60db21c1d0272b07061 100644 --- a/dbrepo-data-db/sidecar/app.py +++ b/dbrepo-data-db/sidecar/app.py @@ -170,6 +170,7 @@ def get_user_roles(user: User) -> List[str]: @app.route("/health", methods=["GET"], endpoint="actuator_health") +@swag_from("ds-yml/health.yml") def health(): logging.debug("endpoint health, body=%s", request) res = dumps({"status": "UP", "message": "Application is up and running"}) diff --git a/dbrepo-data-db/sidecar/ds-yml/import.yml b/dbrepo-data-db/sidecar/ds-yml/import.yml index 87c6777127ffaf36caf42a567140148f09b7ee64..a129e86fa1aa0a0768b718f9115934b8ca7113b1 100644 --- a/dbrepo-data-db/sidecar/ds-yml/import.yml +++ b/dbrepo-data-db/sidecar/ds-yml/import.yml @@ -11,8 +11,8 @@ parameters: description: Name of the object file to import from the Storage Service required: true security: - - bearerAuth: [ ] - - basicAuth: [ ] +- bearerAuth: [] +- basicAuth: [] responses: 202: description: Imported the .csv diff --git a/dbrepo-data-service/Dockerfile b/dbrepo-data-service/Dockerfile index d4016836d91bf88f09ad60279689d9b16b5d9bb8..69edbda3150e0a02b3ce6369052dd189a726d6ea 100644 --- a/dbrepo-data-service/Dockerfile +++ b/dbrepo-data-service/Dockerfile @@ -24,8 +24,6 @@ RUN mvn clean package -DskipTests FROM amazoncorretto:17-alpine3.19 as runtime MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> -RUN apk add --no-cache curl bash jq - WORKDIR /app USER 65534 diff --git a/dbrepo-data-service/metrics.md b/dbrepo-data-service/metrics.md index 425b58ad17e24683a606cf0a4cb9d3123412e4cf..5e0773ad8c40200051ba25a814268208c57e2e26 100644 --- a/dbrepo-data-service/metrics.md +++ b/dbrepo-data-service/metrics.md @@ -6,14 +6,12 @@ | `dbrepo_subset_find` | Find subset | | `dbrepo_subset_list` | Find subsets | | `dbrepo_subset_persist` | Persist subset | -| `dbrepo_table_data_create` | Insert a raw data tuple | +| `dbrepo_table_data_create` | Create table data | | `dbrepo_table_data_delete` | Delete table data | | `dbrepo_table_data_export` | Export table data | | `dbrepo_table_data_history` | Find table history | -| `dbrepo_table_data_import` | Import data from a dataset | +| `dbrepo_table_data_import` | Import dataset | | `dbrepo_table_data_list` | Retrieve table data | -| `dbrepo_table_data_update` | Update a raw data tuple | -| `dbrepo_table_schema_list` | Find table schemas | -| `dbrepo_table_statistic` | Generate table statistic | +| `dbrepo_table_data_update` | Update table data | | `dbrepo_view_data` | Retrieve view data | | `dbrepo_view_schema_list` | Find view schemas | diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 3df58f676f876a8729e6485eef9291717404a242..98ad4d797ce44b3e92a2644562e56118e9c7932b 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -60,7 +60,7 @@ <jackson-datatype.version>2.15.0</jackson-datatype.version> <commons-io.version>2.15.0</commons-io.version> <commons-validator.version>1.8.0</commons-validator.version> - <jacoco.version>0.8.12</jacoco.version> + <jacoco.version>0.8.11</jacoco.version> <jwt.version>4.3.0</jwt.version> <opencsv.version>5.7.1</opencsv.version> <super-csv.version>2.4.0</super-csv.version> @@ -266,6 +266,16 @@ <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.version}</version> + <configuration> + <excludes> + <exclude>at/tuwien/mapper/**/*</exclude> + <exclude>at/tuwien/exception/**/*</exclude> + <exclude>at/tuwien/config/**/*</exclude> + <exclude>at/tuwien/auth/**/*</exclude> + <exclude>at/tuwien/handlers/**/*</exclude> + <exclude>**/DbrepoDataServiceApplication.class</exclude> + </excludes> + </configuration> <executions> <execution> <id>default-prepare-agent</id> diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 4b58c5de3363606e17358de63e35fc8125c555b0..ea7b1b3677cea807fc3892b6835db60f58233b41 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -4,7 +4,6 @@ import at.tuwien.api.database.UpdateDatabaseAccessDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.user.PrivilegedUserDto; -import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.AccessService; @@ -43,8 +42,7 @@ public class AccessEndpoint { @PostMapping("/{userId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Give access to some database", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Give access to some database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Granting access succeeded"), @@ -78,10 +76,10 @@ public class AccessEndpoint { @NotBlank @PathVariable("userId") UUID userId, @Valid @RequestBody UpdateDatabaseAccessDto data) throws NotAllowedException, QueryMalformedException, DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, DatabaseMalformedException, ServiceException { + UserNotFoundException, DatabaseMalformedException { log.debug("endpoint give access to database, databaseId={}, userId={}", databaseId, userId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); - final PrivilegedUserDto user = metadataServiceGateway.getPrivilegedUserById(userId); + final PrivilegedUserDto user = metadataServiceGateway.getUserById(userId); if (database.getAccesses().stream().anyMatch(a -> a.getUser().getId().equals(userId))) { log.error("Failed to create access to user with id {}: already has access", userId); throw new NotAllowedException("Failed to create access to user with id " + userId + ": already has access"); @@ -97,8 +95,7 @@ public class AccessEndpoint { @PutMapping("/{userId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Update access to some database", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Update access to some database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Update access succeeded", @@ -133,11 +130,11 @@ public class AccessEndpoint { @NotBlank @PathVariable("userId") UUID userId, @Valid @RequestBody UpdateDatabaseAccessDto access) throws NotAllowedException, QueryMalformedException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException { log.debug("endpoint modify access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, access.getType()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); - final UserDto user = metadataServiceGateway.getUserById(userId); + final PrivilegedUserDto user = metadataServiceGateway.getUserById(userId); if (database.getAccesses().stream().noneMatch(a -> a.getUser().getId().equals(userId))) { log.error("Failed to update access to user with id {}: no access", userId); throw new NotAllowedException("Failed to update access to user with id " + userId + ": no access"); @@ -153,8 +150,7 @@ public class AccessEndpoint { @DeleteMapping("/{userId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Revoke access to some database", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Revoke access to some database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Revoked access successfully"), @@ -187,10 +183,10 @@ public class AccessEndpoint { public ResponseEntity<?> revoke(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("userId") UUID userId) throws NotAllowedException, QueryMalformedException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException { log.debug("endpoint revoke access to database, databaseId={}, userId={}", databaseId, userId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); - final UserDto user = metadataServiceGateway.getUserById(userId); + final PrivilegedUserDto user = metadataServiceGateway.getUserById(userId); if (database.getAccesses().stream().noneMatch(a -> a.getUser().getId().equals(userId))) { log.error("Failed to delete access to user with id {}: no access", userId); throw new NotAllowedException("Failed to delete access to user with id " + userId + ": no access"); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index bd32093068efc009a835975c9622f7bbe83eb1a5..f69019e7178dd8631723d929747d8654d94881e4 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -54,8 +54,7 @@ public class DatabaseEndpoint { @PostMapping @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Create database", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Create database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Created a database", @@ -85,7 +84,7 @@ public class DatabaseEndpoint { }) public ResponseEntity<DatabaseDto> create(@Valid @RequestBody CreateDatabaseDto data) throws DatabaseUnavailableException, RemoteUnavailableException, ContainerNotFoundException, - DatabaseMalformedException, QueryStoreCreateException, ServiceException { + DatabaseMalformedException, QueryStoreCreateException { log.debug("endpoint create database, data.containerId={}, data.internalName={}, data.username={}", data.getContainerId(), data.getInternalName(), data.getUsername()); final PrivilegedContainerDto container = metadataServiceGateway.getContainerById(data.getContainerId()); @@ -108,8 +107,7 @@ public class DatabaseEndpoint { @PutMapping("/{databaseId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Update user password in database", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Update user password in database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Updated user password in database"), @@ -132,7 +130,7 @@ public class DatabaseEndpoint { public ResponseEntity<Void> update(@NotBlank @PathVariable("databaseId") Long databaseId, @Valid @RequestBody UpdateUserPasswordDto data) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException { log.debug("endpoint update user password in database, databaseId={}, data.username={}", databaseId, data.getUsername()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index 0d4b53b92c9cb32ee588abc917a81b3d222fa8d8..b9a9ae442d8a34340237a9098e79b3a08baa95f8 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -84,7 +84,7 @@ public class SubsetEndpoint { @RequestParam(name = "persisted", required = false) Boolean filterPersisted, Principal principal) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - QueryNotFoundException, NotAllowedException, ServiceException { + QueryNotFoundException, NotAllowedException { log.debug("endpoint find subsets in database, databaseId={}, filterPersisted={}, principal.name={}", databaseId, filterPersisted, principal != null ? principal.getName() : null); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); @@ -149,8 +149,7 @@ public class SubsetEndpoint { Principal principal) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, FormatNotAvailableException, StorageUnavailableException, QueryMalformedException, - SidecarExportException, StorageNotFoundException, NotAllowedException, UserNotFoundException, - ServiceException { + SidecarExportException, StorageNotFoundException, NotAllowedException, UserNotFoundException { String accept = httpServletRequest.getHeader("Accept"); log.debug("endpoint find subset in database, databaseId={}, subsetId={}, accept={}, timestamp={}", databaseId, subsetId, accept, timestamp); @@ -252,7 +251,7 @@ public class SubsetEndpoint { throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, StorageUnavailableException, QueryMalformedException, SidecarExportException, StorageNotFoundException, QueryStoreInsertException, TableMalformedException, PaginationException, - QueryNotSupportedException, NotAllowedException, UserNotFoundException, ServiceException { + QueryNotSupportedException, NotAllowedException, UserNotFoundException { log.debug("endpoint create subset in database, databaseId={}, data.statement={}, principal.name={}, page={}, size={}, timestamp={}", databaseId, data.getStatement(), principal.getName(), page, size, timestamp); /* check */ @@ -324,8 +323,7 @@ public class SubsetEndpoint { @RequestParam(required = false) Long page, @RequestParam(required = false) Long size) throws PaginationException, DatabaseNotFoundException, RemoteUnavailableException, NotAllowedException, QueryNotFoundException, - DatabaseUnavailableException, TableMalformedException, QueryMalformedException, UserNotFoundException, - ServiceException { + DatabaseUnavailableException, TableMalformedException, QueryMalformedException, UserNotFoundException { log.debug("endpoint re-execute query, databaseId={}, subsetId={}, principal.name={} page={}, size={}", databaseId, subsetId, principal != null ? principal.getName() : null, page, size); endpointValidator.validateDataParams(page, size); @@ -410,7 +408,7 @@ public class SubsetEndpoint { @NotNull @Valid @RequestBody QueryPersistDto data, @NotNull Principal principal) throws NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, QueryStorePersistException, - DatabaseUnavailableException, QueryNotFoundException, UserNotFoundException, ServiceException { + DatabaseUnavailableException, QueryNotFoundException, UserNotFoundException { log.debug("endpoint persist query, databaseId={}, queryId={}, data.persist={}, principal.name={}", databaseId, queryId, data.getPersist(), principal.getName()); metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 6856e634ab6776f6db497428cfaaad5aa64394a7..b93ff32264e730c42f9b3c193dfa845d4ec0e4d8 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -12,6 +12,7 @@ import at.tuwien.api.database.table.internal.TableCreateDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; +import at.tuwien.service.AnalyseService; import at.tuwien.service.TableService; import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; @@ -46,21 +47,22 @@ import java.util.List; public class TableEndpoint { private final TableService tableService; + private final AnalyseService analyseService; private final EndpointValidator endpointValidator; private final MetadataServiceGateway metadataServiceGateway; @Autowired - public TableEndpoint(TableService tableService, EndpointValidator endpointValidator, + public TableEndpoint(TableService tableService, AnalyseService analyseService, EndpointValidator endpointValidator, MetadataServiceGateway metadataServiceGateway) { this.tableService = tableService; + this.analyseService = analyseService; this.endpointValidator = endpointValidator; this.metadataServiceGateway = metadataServiceGateway; } @PostMapping @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Create table", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Create table", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Created table", @@ -91,7 +93,7 @@ public class TableEndpoint { public ResponseEntity<TableDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody TableCreateDto data) throws DatabaseNotFoundException, RemoteUnavailableException, TableMalformedException, DatabaseUnavailableException, TableExistsException, - TableNotFoundException, QueryMalformedException, ServiceException { + TableNotFoundException, QueryMalformedException { log.debug("endpoint create table, databaseId={}, data.name={}", databaseId, data.getName()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -105,8 +107,7 @@ public class TableEndpoint { @DeleteMapping("/{tableId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Delete table", security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) + @Operation(summary = "Delete table", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Deleted table", @@ -132,7 +133,7 @@ public class TableEndpoint { public ResponseEntity<Void> delete(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - QueryMalformedException, ServiceException { + QueryMalformedException { log.debug("endpoint delete table, databaseId={}, tableId={}", databaseId, tableId); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); try { @@ -176,7 +177,7 @@ public class TableEndpoint { @RequestParam(required = false) Long page, @RequestParam(required = false) Long size) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, PaginationException, QueryMalformedException, ServiceException { + TableMalformedException, PaginationException, QueryMalformedException { log.debug("endpoint find table data, databaseId={}, tableId={}, timestamp={}, page={}, size={}", databaseId, tableId, timestamp, page, size); endpointValidator.validateDataParams(page, size); @@ -228,12 +229,12 @@ public class TableEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Failed to find table in metadata database or blob in storage service", + description = "Failed to find table in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Failed to establish connection with the metadata service or storage service", + description = "Failed to establish connection with the metadata service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -243,15 +244,15 @@ public class TableEndpoint { @Valid @RequestBody TupleDto data, @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, StorageUnavailableException, - StorageNotFoundException, ServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException { log.debug("endpoint insert raw table data, databaseId={}, tableId={}", databaseId, tableId); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); final DatabaseAccessDto access = metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); try { tableService.createTuple(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + final TableStatisticDto statistics = analyseService.analyseTable(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, statistics); return ResponseEntity.status(HttpStatus.CREATED) .build(); } catch (SQLException e) { @@ -295,7 +296,7 @@ public class TableEndpoint { @Valid @RequestBody TupleUpdateDto data, @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, ServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException { log.debug("endpoint update raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); @@ -303,7 +304,8 @@ public class TableEndpoint { endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); try { tableService.updateTuple(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + final TableStatisticDto statistics = analyseService.analyseTable(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, statistics); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -347,7 +349,7 @@ public class TableEndpoint { @Valid @RequestBody TupleDeleteDto data, @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, ServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException { log.debug("endpoint delete raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); @@ -355,7 +357,8 @@ public class TableEndpoint { endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); try { tableService.deleteTuple(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + final TableStatisticDto statistics = analyseService.analyseTable(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, statistics); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -366,20 +369,13 @@ public class TableEndpoint { @GetMapping("/{tableId}/history") @Observed(name = "dbrepo_table_data_history") - @Operation(summary = "Find table history", - description = "Lists the insert/delete operations performed. Authentication is only required for tables in private databases", - security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) + @Operation(summary = "Find table history", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Found table history", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = TableHistoryDto[].class))}), - @ApiResponse(responseCode = "400", - description = "Invalid pagination request", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "403", description = "Find table history not allowed", content = {@Content( @@ -396,30 +392,19 @@ public class TableEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<List<TableHistoryDto>> getHistory(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId, - @RequestParam(value = "size", required = false) Long size, + public ResponseEntity<List<TableHistoryDto>> getHistory(@NotBlank @PathVariable("databaseId") Long databaseId, + @NotBlank @PathVariable("tableId") Long tableId, Principal principal) throws DatabaseUnavailableException, - RemoteUnavailableException, TableNotFoundException, NotAllowedException, ServiceException, - PaginationException { + RemoteUnavailableException, TableNotFoundException, NotAllowedException { log.debug("endpoint find table history, databaseId={}, tableId={}", databaseId, tableId); - if (size != null && size <= 0) { - log.error("Invalid size: must be > 0"); - throw new PaginationException("Invalid size: must be bigger than zero"); - } else if (size == null) { - log.debug("size not set: default to 100L"); - size = 100L; - } final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); - if (!table.getIsPublic()) { - if (principal == null) { - log.error("Failed to find table history: no authentication found"); - throw new NotAllowedException("Failed to find table history: no authentication found"); - } - metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); + if (!table.getIsPublic() && principal == null) { + log.error("Failed to find table history: no authentication found"); + throw new NotAllowedException("Failed to find table history: no authentication found"); } + metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); try { - final List<TableHistoryDto> dto = tableService.history(table, size); + final List<TableHistoryDto> dto = tableService.history(table); return ResponseEntity.status(HttpStatus.OK) .body(dto); } catch (SQLException e) { @@ -429,9 +414,8 @@ public class TableEndpoint { } @GetMapping - @PreAuthorize("hasAuthority('admin')") - @Observed(name = "dbrepo_table_schema_list") - @Operation(summary = "Find table schemas", hidden = true) + @PreAuthorize("isAuthenticated()") + @Operation(summary = "Find table schemas") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Got table schemas", @@ -466,7 +450,7 @@ public class TableEndpoint { }) public ResponseEntity<List<TableDto>> getSchema(@NotBlank @PathVariable("databaseId") Long databaseId) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - DatabaseMalformedException, TableNotFoundException, QueryMalformedException, ServiceException { + DatabaseMalformedException, TableNotFoundException, QueryMalformedException { log.debug("endpoint inspect table schemas, databaseId={}", databaseId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -513,7 +497,7 @@ public class TableEndpoint { Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, NotAllowedException, StorageUnavailableException, QueryMalformedException, SidecarExportException, - StorageNotFoundException, ServiceException { + StorageNotFoundException { log.debug("endpoint find table history, databaseId={}, tableId={}, timestamp={}", databaseId, tableId, timestamp); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); if (!table.getIsPublic()) { @@ -578,8 +562,7 @@ public class TableEndpoint { @Valid @RequestBody ImportCsvDto data, @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - QueryMalformedException, StorageNotFoundException, SidecarImportException, NotAllowedException, - ServiceException { + QueryMalformedException, StorageNotFoundException, SidecarImportException, NotAllowedException { log.debug("endpoint insert table data, databaseId={}, tableId={}, data.location={}", databaseId, tableId, data.getLocation()); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); final DatabaseAccessDto access = metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); @@ -594,49 +577,11 @@ public class TableEndpoint { } try { tableService.importDataset(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + final TableStatisticDto statistics = analyseService.analyseTable(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, statistics); return ResponseEntity.accepted() .build(); - } catch (SQLException e) { - log.error("Failed to establish connection to database: {}", e.getMessage()); - throw new DatabaseUnavailableException("Failed to establish connection to database", e); - } - } - @GetMapping("/{tableId}/statistic") - @Observed(name = "dbrepo_table_statistic") - @Operation(summary = "Generate table statistic") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "Generated table statistic", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = TableStatisticDto.class))}), - @ApiResponse(responseCode = "400", - description = "Failed to obtain column statistic", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "404", - description = "Failed to find table in metadata database", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "503", - description = "Failed to establish connection with the metadata service", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - }) - public ResponseEntity<TableStatisticDto> statistic(@NotBlank @PathVariable("databaseId") Long databaseId, - @NotBlank @PathVariable("tableId") Long tableId) - throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - ServiceException, TableMalformedException, QueryMalformedException { - log.debug("endpoint generate table statistic, databaseId={}, tableId={}", databaseId, tableId); - final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); - try { - final TableStatisticDto dto = tableService.getStatistics(table); - return ResponseEntity.ok(dto); } catch (SQLException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database", e); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 64eea4ebd0ba058691faad70cafd5d9d7df1fec0..91e5f7390dbe542e39bfa826981dae18574eb647 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -4,6 +4,7 @@ import at.tuwien.api.database.*; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.internal.PrivilegedViewDto; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; @@ -53,9 +54,9 @@ public class ViewEndpoint { } @GetMapping - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("isAuthenticated()") @Observed(name = "dbrepo_view_schema_list") - @Operation(summary = "Find view schemas", hidden = true) + @Operation(summary = "Find view schemas") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Found view schemas", @@ -90,8 +91,7 @@ public class ViewEndpoint { }) public ResponseEntity<List<ViewDto>> getSchema(@NotBlank @PathVariable("databaseId") Long databaseId) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - ViewMalformedException, ViewNotFoundException, DatabaseMalformedException, ViewSchemaException, - ServiceException { + ViewMalformedException, ViewNotFoundException, DatabaseMalformedException, ViewSchemaException { log.debug("endpoint inspect view schemas, databaseId={}", databaseId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -104,8 +104,7 @@ public class ViewEndpoint { @PostMapping @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Create view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}, - hidden = true) + @Operation(summary = "Create view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Created view", @@ -135,7 +134,7 @@ public class ViewEndpoint { }) public ResponseEntity<ViewDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody ViewCreateDto data) throws DatabaseUnavailableException, - DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -149,8 +148,7 @@ public class ViewEndpoint { @DeleteMapping("/{viewId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Delete view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}, - hidden = true) + @Operation(summary = "Delete view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Deleted view"), @@ -178,7 +176,7 @@ public class ViewEndpoint { public ResponseEntity<Void> delete(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("viewId") Long viewId) throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, - ViewMalformedException, ServiceException { + ViewMalformedException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); final PrivilegedViewDto view = metadataServiceGateway.getViewById(databaseId, viewId); try { @@ -234,8 +232,7 @@ public class ViewEndpoint { @NotNull HttpServletRequest request, Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, - QueryMalformedException, ViewMalformedException, PaginationException, NotAllowedException, - ServiceException { + QueryMalformedException, ViewMalformedException, PaginationException, NotAllowedException { log.debug("endpoint get view data, databaseId={}, viewId={}, page={}, size={}, timestamp={}", databaseId, viewId, page, size, timestamp); endpointValidator.validateDataParams(page, size); diff --git a/dbrepo-data-service/rest-service/src/main/resources/application-local.yml b/dbrepo-data-service/rest-service/src/main/resources/application-local.yml index c36b248b7ea2a72bf60d27eeaef910679035e01b..fda4447d0b66d22e95cdb1bd1c2525a9eb5f9a15 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application-local.yml @@ -49,9 +49,9 @@ logging: org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug dbrepo: endpoints: - metadataService: http://localhost - storageService: http://localhost/api/storage - authService: http://localhost/api/auth + gatewayService: http://localhost + storageService: http://localhost:9000 + authService: http://localhost:8080 s3: accessKeyId: seaweedfsadmin secretAccessKey: seaweedfsadmin diff --git a/dbrepo-data-service/rest-service/src/main/resources/application.yml b/dbrepo-data-service/rest-service/src/main/resources/application.yml index 771f95d8d75fe38cc4832bedeeb6a74132d0440e..44daf91e46c603ae27ee7780e4ecc62de90b5339 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml @@ -50,9 +50,9 @@ logging: org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug dbrepo: endpoints: - metadataService: "${METADATA_SERVICE_ENDPOINT:http://gateway-service}" - storageService: "${S3_ENDPOINT:http://gateway-service/api/storage}" - authService: "${AUTH_SERVICE_HOST:http://gateway-service/api/auth}" + gatewayService: "${GATEWAY_SERVICE_ENDPOINT:http://gateway-service}" + storageService: "${S3_ENDPOINT:http://storage-service:9000}" + authService: "${AUTH_SERVICE_HOST:http://auth-service:8080}" s3: accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}" secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}" diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java index 54af799db3fd021475222be7fac444ad83ed4535..43d3b515073e947fcbf474b5d041115a3eb2b3aa 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java @@ -12,7 +12,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; -import java.io.IOException; import java.sql.*; import java.time.Instant; import java.util.*; @@ -78,34 +77,6 @@ public class MariaDbConfig { log.debug("created init database {}", database.getInternalName()); } - public static void grantReadAccess(PrivilegedDatabaseDto database, String username) { - final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); - log.trace("connect to database {}", jdbc); - try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { - connection.prepareStatement("GRANT SELECT ON *.* TO `" + username + "`@`%`;") - .executeUpdate(); - connection.prepareStatement("FLUSH PRIVILEGES;") - .executeUpdate(); - } catch (SQLException e) { - log.error("could not grant read access", e); - } - log.debug("granted read access to user {} in database {}", username, database.getInternalName()); - } - - public static void grantWriteAccess(PrivilegedDatabaseDto database, String username) { - final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); - log.trace("connect to database {}", jdbc); - try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { - connection.prepareStatement("GRANT SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE ON *.* TO `" + username + "`@`%`;") - .executeUpdate(); - connection.prepareStatement("FLUSH PRIVILEGES;") - .executeUpdate(); - } catch (SQLException e) { - log.error("could not grant read access", e); - } - log.debug("granted read access to user {} in database {}", username, database.getInternalName()); - } - public static void dropAllDatabases(PrivilegedContainerDto container) { final String jdbc = "jdbc:mariadb://" + container.getHost() + ":" + container.getPort(); log.trace("connect to database {}", jdbc); @@ -165,43 +136,31 @@ public class MariaDbConfig { } } - public static List<String> getPrivileges(PrivilegedDatabaseDto database, String username) throws SQLException { - final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); + public static String getPrivileges(String hostname, Integer port, String username, String password) + throws Exception { + return getPrivileges(hostname, port, null, username, password); + } + + public static String getPrivileges(String hostname, Integer port, String database, String username, String password) + throws Exception { + final String jdbc = "jdbc:mariadb://" + hostname + ":" + port + (database != null ? "/" + database : ""); log.trace("connect to database {}", jdbc); - try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { + try (Connection connection = DriverManager.getConnection(jdbc, username, password)) { final String query = "SHOW GRANTS FOR `" + username + "`;"; log.trace("prepare statement '{}'", query); final PreparedStatement statement = connection.prepareStatement(query); final ResultSet set = statement.executeQuery(); statement.close(); if (set.next()) { - final Matcher matcher = Pattern.compile("GRANT (.*) ON.*").matcher(set.getString(1)); - if (matcher.find()) { - final List<String> privileges = Arrays.asList(matcher.group(1).split(","));; - log.trace("found privileges: {}", privileges); - return privileges; - } + return set.getString(1); } } - throw new SQLException("Failed to get privileges"); - } - - public static void dropTable(PrivilegedDatabaseDto database, String table) throws SQLException { - final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); - log.trace("connect to database {}", jdbc); - try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { - final String query = "DROP TABLE `" + table + "`;"; - log.trace("prepare statement '{}'", query); - final PreparedStatement statement = connection.prepareStatement(query); - statement.executeUpdate(); - statement.close(); - } - log.debug("dropped table {}", table); + throw new Exception("Failed to get privileges"); } - public static void mockQuery(String hostname, Integer port, String database, String query, String username, String password) + public static void mockQuery(String hostname, String query, String username, String password) throws SQLException { - final String jdbc = "jdbc:mariadb://" + hostname + ":" + port + "/" + database; + final String jdbc = "jdbc:mariadb://" + hostname; log.trace("connect to database {}", jdbc); try (Connection connection = DriverManager.getConnection(jdbc, username, password)) { final PreparedStatement statement = connection.prepareStatement(query); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java index 544f3f0d17d95c6fbb807743a58698f090ee8b37..4598a94b94095d4cf463f286bf10977ee72516ad 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java @@ -41,12 +41,12 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_succeeds() throws UserNotFoundException, NotAllowedException, QueryMalformedException, - DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(metadataServiceGateway.getPrivilegedUserById(USER_4_ID)) + when(metadataServiceGateway.getUserById(USER_4_ID)) .thenReturn(USER_4_PRIVILEGED_DTO); /* test */ @@ -56,12 +56,12 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_alreadyAccess_fails() throws UserNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(metadataServiceGateway.getPrivilegedUserById(USER_1_ID)) + when(metadataServiceGateway.getUserById(USER_1_ID)) .thenReturn(USER_1_PRIVILEGED_DTO); /* test */ @@ -72,8 +72,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -89,18 +88,18 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_userNotFound_fails() throws UserNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(UserNotFoundException.class) .when(metadataServiceGateway) - .getPrivilegedUserById(USER_4_ID); + .getUserById(USER_1_ID); /* test */ assertThrows(UserNotFoundException.class, () -> { - accessEndpoint.create(DATABASE_1_ID, USER_4_ID, UPDATE_DATABASE_ACCESS_READ_DTO); + accessEndpoint.create(DATABASE_1_ID, USER_1_ID, UPDATE_DATABASE_ACCESS_READ_DTO); }); } @@ -117,12 +116,12 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void update_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - NotAllowedException, QueryMalformedException, DatabaseMalformedException, ServiceException { + NotAllowedException, QueryMalformedException, DatabaseMalformedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(metadataServiceGateway.getPrivilegedUserById(USER_1_ID)) + when(metadataServiceGateway.getUserById(USER_1_ID)) .thenReturn(USER_1_PRIVILEGED_DTO); /* test */ @@ -141,8 +140,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void update_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public void update_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -158,7 +156,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void update_userNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, ServiceException { + UserNotFoundException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -176,12 +174,12 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void revoke_succeeds() throws UserNotFoundException, NotAllowedException, QueryMalformedException, - DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(metadataServiceGateway.getPrivilegedUserById(USER_1_ID)) + when(metadataServiceGateway.getUserById(USER_1_ID)) .thenReturn(USER_1_PRIVILEGED_DTO); /* test */ @@ -200,8 +198,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void revoke_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public void revoke_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -217,7 +214,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void revoke_userNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, ServiceException { + UserNotFoundException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java index 21769ff5eb39d5448a0dd05036a6efc7444eb0d2..8ab4d444f1970240e393c4fd0607e83692bed880 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java @@ -58,7 +58,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_succeeds() throws DatabaseUnavailableException, RemoteUnavailableException, - QueryStoreCreateException, ContainerNotFoundException, DatabaseMalformedException, ServiceException { + QueryStoreCreateException, ContainerNotFoundException, DatabaseMalformedException { /* test */ databaseEndpoint.create(DATABASE_1_CREATE_INTERNAL); @@ -67,7 +67,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) public void create_noRole_fails() throws RemoteUnavailableException, ContainerNotFoundException, - SQLException, QueryStoreCreateException, DatabaseMalformedException, ServiceException { + SQLException, QueryStoreCreateException, DatabaseMalformedException { /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) @@ -89,8 +89,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void create_containerNotFound_fails() throws RemoteUnavailableException, ContainerNotFoundException, - ServiceException { + public void create_containerNotFound_fails() throws RemoteUnavailableException, ContainerNotFoundException { /* mock */ doThrow(ContainerNotFoundException.class) @@ -106,7 +105,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_queryStore_fails() throws RemoteUnavailableException, ContainerNotFoundException, SQLException, - DatabaseMalformedException, QueryStoreCreateException, ServiceException { + DatabaseMalformedException, QueryStoreCreateException { /* mock */ doThrow(ContainerNotFoundException.class) @@ -127,7 +126,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void update_succeeds() throws DatabaseUnavailableException, RemoteUnavailableException, - DatabaseMalformedException, DatabaseNotFoundException, ServiceException { + DatabaseMalformedException, DatabaseNotFoundException { /* test */ databaseEndpoint.update(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); @@ -135,7 +134,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) - public void update_noRole_fails() throws RemoteUnavailableException, DatabaseNotFoundException, ServiceException { + public void update_noRole_fails() throws RemoteUnavailableException, DatabaseNotFoundException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -149,8 +148,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void update_databaseNotFound_fails() throws RemoteUnavailableException, DatabaseNotFoundException, - ServiceException { + public void update_databaseNotFound_fails() throws RemoteUnavailableException, DatabaseNotFoundException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -166,7 +164,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void update_password_fails() throws RemoteUnavailableException, DatabaseNotFoundException, SQLException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index 6cdb0c6753488d84be16798636d46d42c139392f..d212bb3064252f2ab2317028224914e96bb85c5f 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -66,7 +66,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findAllById_succeeds() throws DatabaseUnavailableException, NotAllowedException, QueryNotFoundException, - DatabaseNotFoundException, RemoteUnavailableException, SQLException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, SQLException { /* test */ final List<QueryDto> response = generic_findAllById(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO, null); @@ -98,7 +98,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { public void findById_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, SidecarExportException, FormatNotAvailableException, StorageNotFoundException, - SQLException, ServiceException { + SQLException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -113,7 +113,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { public void findById_acceptCsv_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, SidecarExportException, FormatNotAvailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("deadbeef") .resource(new InputStreamResource(InputStream.nullInputStream())) @@ -134,7 +134,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { public void findById_timestamp_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, SidecarExportException, FormatNotAvailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("deadbeef") .resource(new InputStreamResource(InputStream.nullInputStream())) @@ -152,7 +152,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_fails() throws DatabaseNotFoundException, RemoteUnavailableException, ServiceException { + public void findById_fails() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -171,7 +171,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { NotAllowedException, SidecarExportException, QueryNotSupportedException, PaginationException, StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - SQLException, ServiceException { + FormatNotAvailableException, SQLException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -207,7 +207,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { TableMalformedException, NotAllowedException, SidecarExportException, QueryNotSupportedException, PaginationException, StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - SQLException, ServiceException { + FormatNotAvailableException, SQLException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -227,7 +227,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-query"}) public void create_databaseNotFound_fails() throws NotAllowedException, RemoteUnavailableException, - DatabaseNotFoundException, ServiceException { + DatabaseNotFoundException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -260,7 +260,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME, authorities = {"execute-query"}) - public void create_noAccess_fails() throws NotAllowedException, RemoteUnavailableException, ServiceException { + public void create_noAccess_fails() throws NotAllowedException, RemoteUnavailableException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -279,7 +279,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test public void getData_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException, - DatabaseUnavailableException, PaginationException, ServiceException { + DatabaseUnavailableException, PaginationException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -308,7 +308,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test public void getData_onlyHead_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException, - DatabaseUnavailableException, PaginationException, ServiceException { + DatabaseUnavailableException, PaginationException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -332,7 +332,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME) public void getData_private_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException, - QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, ServiceException { + QueryMalformedException, QueryNotFoundException, PaginationException, SQLException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -357,8 +357,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void getData_privateAnonymous_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public void getData_privateAnonymous_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -373,7 +372,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) public void getData_privateNoAccess_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -392,7 +391,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME) public void getData_privateOnlyHead_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException, - QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, ServiceException { + QueryMalformedException, QueryNotFoundException, PaginationException, SQLException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -416,7 +415,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"persist-query"}) public void persist_succeeds() throws NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, QueryStorePersistException, SQLException, UserNotFoundException, QueryNotFoundException, - DatabaseUnavailableException, ServiceException { + DatabaseUnavailableException { final QueryPersistDto request = QueryPersistDto.builder() .persist(true) .build(); @@ -451,7 +450,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"persist-query"}) - public void persist_noAccess_fails() throws NotAllowedException, RemoteUnavailableException, ServiceException { + public void persist_noAccess_fails() throws NotAllowedException, RemoteUnavailableException { final QueryPersistDto request = QueryPersistDto.builder() .persist(true) .build(); @@ -470,7 +469,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"persist-query"}) public void persist_databaseNotFound_fails() throws NotAllowedException, RemoteUnavailableException, - DatabaseNotFoundException, ServiceException { + DatabaseNotFoundException { final QueryPersistDto request = QueryPersistDto.builder() .persist(true) .build(); @@ -490,7 +489,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { protected List<QueryDto> generic_findAllById(Long databaseId, PrivilegedDatabaseDto database, Principal principal) throws DatabaseUnavailableException, NotAllowedException, QueryNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, SQLException, ServiceException { + RemoteUnavailableException, SQLException { /* mock */ if (database != null) { @@ -514,7 +513,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { Principal principal) throws UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, SidecarExportException, RemoteUnavailableException, FormatNotAvailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException { /* mock */ when(queryService.findById(DATABASE_3_PRIVILEGED_DTO, subsetId)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java index 62375e2ab4e397924ce1f6d3a8428111be633478..73760a5a2ab824ff44f550860836c1b79da87bae 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java @@ -7,6 +7,7 @@ import at.tuwien.api.database.table.*; import at.tuwien.endpoints.TableEndpoint; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; +import at.tuwien.service.AnalyseService; import at.tuwien.service.TableService; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; @@ -43,6 +44,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @MockBean private TableService tableService; + @MockBean + private AnalyseService analyseService; + @MockBean private MetadataServiceGateway metadataServiceGateway; @@ -55,7 +59,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_succeeds() throws DatabaseUnavailableException, TableMalformedException, DatabaseNotFoundException, TableExistsException, RemoteUnavailableException, SQLException, - TableNotFoundException, QueryMalformedException, ServiceException { + TableNotFoundException, QueryMalformedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -80,8 +84,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -97,7 +100,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void delete_succeeds() throws RemoteUnavailableException, DatabaseUnavailableException, - TableNotFoundException, QueryMalformedException, SQLException, ServiceException { + TableNotFoundException, QueryMalformedException, SQLException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -123,8 +126,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void delete_tableNotFound_fails() throws RemoteUnavailableException, TableNotFoundException, - ServiceException { + public void delete_tableNotFound_fails() throws RemoteUnavailableException, TableNotFoundException { /* mock */ doThrow(TableNotFoundException.class) @@ -140,7 +142,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, - SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException, ServiceException { + SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID)) @@ -164,8 +166,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void getData_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void getData_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException { /* mock */ doThrow(TableNotFoundException.class) @@ -181,8 +182,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void createTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, StorageUnavailableException, StorageNotFoundException, ServiceException { + TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, SQLException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -198,9 +198,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .createTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); @@ -225,8 +227,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) - public void createTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void createTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -248,7 +249,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -271,8 +272,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void createTuple_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -293,7 +293,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -316,8 +316,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -338,8 +337,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, ServiceException { + TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, SQLException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -358,9 +356,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); @@ -388,8 +388,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) - public void updateTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void updateTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -414,7 +413,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -441,7 +440,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccess_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, ServiceException { + SQLException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -460,9 +459,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); @@ -472,7 +473,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -499,7 +500,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - SQLException, ServiceException { + SQLException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -518,9 +519,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); @@ -530,8 +533,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, ServiceException { + TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, SQLException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -546,9 +548,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); @@ -572,8 +576,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) - public void deleteTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void deleteTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -594,7 +597,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -617,7 +620,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, TableMalformedException, SQLException, QueryMalformedException, - DatabaseUnavailableException, ServiceException { + DatabaseUnavailableException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -632,9 +635,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); @@ -644,7 +649,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -667,7 +672,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - SQLException, ServiceException { + SQLException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -682,9 +687,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); @@ -694,23 +701,22 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - RemoteUnavailableException, SQLException, NotAllowedException, ServiceException, PaginationException { + RemoteUnavailableException, SQLException, NotAllowedException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID)) .thenReturn(TABLE_8_PRIVILEGED_DTO); - when(tableService.history(TABLE_8_PRIVILEGED_DTO, null)) + when(tableService.history(TABLE_8_PRIVILEGED_DTO)) .thenReturn(List.of()); /* test */ - final ResponseEntity<List<TableHistoryDto>> response = tableEndpoint.getHistory(DATABASE_3_ID, TABLE_8_ID, null, null); + final ResponseEntity<List<TableHistoryDto>> response = tableEndpoint.getHistory(DATABASE_3_ID, TABLE_8_ID, null); assertEquals(HttpStatus.OK, response.getStatusCode()); } @Test @WithAnonymousUser - public void getHistory_privateNoRole_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void getHistory_privateNoRole_fails() throws TableNotFoundException, RemoteUnavailableException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -718,14 +724,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.getHistory(DATABASE_1_ID, TABLE_1_ID, null, null); + tableEndpoint.getHistory(DATABASE_1_ID, TABLE_1_ID, null); }); } @Test @WithMockUser(username = USER_4_USERNAME) public void getHistory_privateNoAccess_fails() throws NotAllowedException, RemoteUnavailableException, - TableNotFoundException, ServiceException { + TableNotFoundException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -736,14 +742,13 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.getHistory(DATABASE_1_ID, TABLE_1_ID, null, USER_4_PRINCIPAL); + tableEndpoint.getHistory(DATABASE_1_ID, TABLE_1_ID, USER_4_PRINCIPAL); }); } @Test @WithAnonymousUser - public void getHistory_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void getHistory_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException { /* mock */ doThrow(TableNotFoundException.class) @@ -752,7 +757,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableEndpoint.getHistory(DATABASE_3_ID, TABLE_8_ID, null, null); + tableEndpoint.getHistory(DATABASE_3_ID, TABLE_8_ID, null); }); } @@ -760,7 +765,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithAnonymousUser public void exportData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, NotAllowedException, StorageUnavailableException, QueryMalformedException, SidecarExportException, RemoteUnavailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("deadbeef") .resource(new InputStreamResource(InputStream.nullInputStream())) @@ -781,7 +786,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void exportData_privateNoAccess_fails() throws TableNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -801,7 +806,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void importData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, SidecarImportException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -816,9 +821,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { doNothing() .when(tableService) .importDataset(TABLE_8_PRIVILEGED_DTO, request); + when(analyseService.analyseTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TABLE_8_STATISTIC_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); @@ -842,8 +849,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) - public void importData_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void importData_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -864,7 +870,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -887,7 +893,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void importData_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, SidecarImportException, QueryMalformedException, - StorageNotFoundException, ServiceException { + StorageNotFoundException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -907,7 +913,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -930,7 +936,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, SidecarImportException, QueryMalformedException, - StorageNotFoundException, ServiceException { + StorageNotFoundException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index af4767b0490d69c2d704e8a5243cfced6a61cbe9..de98f501d095dc637b1b21cd667459f65eb08ee8 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -52,7 +52,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, DatabaseUnavailableException, ServiceException { + SQLException, DatabaseUnavailableException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -68,7 +68,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) public void create_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, ServiceException { + SQLException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -84,8 +84,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -101,7 +100,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void delete_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, DatabaseUnavailableException, ViewNotFoundException, ServiceException { + SQLException, DatabaseUnavailableException, ViewNotFoundException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -118,7 +117,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) public void delete_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, ServiceException { + SQLException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -135,8 +134,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void delete_databaseNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException, - ServiceException { + public void delete_databaseNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException { /* mock */ doThrow(ViewNotFoundException.class) @@ -153,7 +151,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ViewMalformedException, SQLException, DatabaseUnavailableException, QueryMalformedException, PaginationException, - NotAllowedException, ServiceException { + NotAllowedException { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) @@ -183,7 +181,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_onlyHead_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ViewMalformedException, SQLException, DatabaseUnavailableException, QueryMalformedException, - PaginationException, NotAllowedException, ServiceException { + PaginationException, NotAllowedException { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) @@ -209,8 +207,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) - public void getData_viewNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException, - ServiceException { + public void getData_viewNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException { /* mock */ doThrow(ViewNotFoundException.class) @@ -226,7 +223,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"view-database-view-data"}) public void getData_privateNoAccess_fails() throws RemoteUnavailableException, ViewNotFoundException, - NotAllowedException, ServiceException { + NotAllowedException { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_3_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java deleted file mode 100644 index 30a4d31cfbb288b58817bc52d803d913fa353421..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java +++ /dev/null @@ -1,151 +0,0 @@ -package at.tuwien.gateway; - -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.*; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class DataDatabaseGatewayUnitTest extends AbstractUnitTest { - - @MockBean - @Qualifier("restTemplate") - private RestTemplate restTemplate; - - @Autowired - private DataDatabaseSidecarGateway dataDatabaseSidecarGateway; - - @BeforeEach - public void beforeEach() { - genesis(); - } - - @Test - public void importFile_succeeds() throws RemoteUnavailableException, StorageNotFoundException, ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.accepted() - .build()); - - /* test */ - dataDatabaseSidecarGateway.importFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - } - - @Test - public void importFile_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - dataDatabaseSidecarGateway.importFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - }); - } - - @Test - public void importFile_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - dataDatabaseSidecarGateway.importFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - }); - } - - @Test - public void importFile_s3_fails() { - - /* mock */ - doThrow(HttpClientErrorException.BadRequest.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class)); - - /* test */ - assertThrows(StorageNotFoundException.class, () -> { - dataDatabaseSidecarGateway.importFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - }); - } - - @Test - public void exportFile_succeeds() throws RemoteUnavailableException, StorageNotFoundException, ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.accepted() - .build()); - - /* test */ - dataDatabaseSidecarGateway.exportFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - } - - @Test - public void exportFile_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - dataDatabaseSidecarGateway.exportFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - }); - } - - @Test - public void exportFile_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - dataDatabaseSidecarGateway.exportFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - }); - } - - @Test - public void exportFile_s3_fails() { - - /* mock */ - doThrow(HttpClientErrorException.BadRequest.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class)); - - /* test */ - assertThrows(StorageNotFoundException.class, () -> { - dataDatabaseSidecarGateway.exportFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java deleted file mode 100644 index 0fd20a8025bc209df9c645f4d2b01329660dbf03..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package at.tuwien.gateway; - -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class InterceptorUnitTest extends AbstractUnitTest { - - @MockBean - @Qualifier("keycloakRestTemplate") - private RestTemplate restTemplate; - - @Autowired - private DataDatabaseSidecarGateway dataDatabaseSidecarGateway; - - @BeforeEach - public void beforeEach() { - genesis(); - } - - @Test - public void intercept_succeeds() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) - .thenReturn(ResponseEntity.ok() - .build()); - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - restTemplate.exchange("https://example.com", HttpMethod.GET, HttpEntity.EMPTY, Void.class); - } -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakSidecarGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakSidecarGatewayUnitTest.java deleted file mode 100644 index 2a02e03466d57116c3c529d5750229e80b015b26..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakSidecarGatewayUnitTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package at.tuwien.gateway; - -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceConnectionException; -import at.tuwien.exception.ServiceException; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class KeycloakSidecarGatewayUnitTest extends AbstractUnitTest { - - @MockBean - @Qualifier("restTemplate") - private RestTemplate restTemplate; - - @Autowired - private KeycloakGateway keycloakGateway; - - @BeforeEach - public void beforeEach() { - genesis(); - } - - @Test - public void obtainUserToken_succeeds() throws ServiceException, RemoteUnavailableException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - final TokenDto response = keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - } - - @Test - public void obtainUserToken_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - }); - } - - @Test - public void obtainUserToken_badRequest_fails() { - - /* mock */ - doThrow(HttpClientErrorException.BadRequest.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); - - /* test */ - assertThrows(ServiceException.class, () -> { - keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - }); - } - - @Test - public void obtainUserToken_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java deleted file mode 100644 index 1ba4978788d7ee5d05d881d397a453086eaed41c..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java +++ /dev/null @@ -1,933 +0,0 @@ -package at.tuwien.gateway; - -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.container.internal.PrivilegedContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.internal.PrivilegedDatabaseDto; -import at.tuwien.api.database.internal.PrivilegedViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.internal.PrivilegedTableDto; -import at.tuwien.api.identifier.IdentifierDto; -import at.tuwien.api.user.PrivilegedUserDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.*; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { - - @MockBean - @Qualifier("restTemplate") - private RestTemplate restTemplate; - - @Autowired - private MetadataServiceGateway metadataServiceGateway; - - @BeforeEach - public void beforeEach() { - genesis(); - } - - @Test - public void getTableById_succeeds() throws TableNotFoundException, RemoteUnavailableException, ServiceException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Type", IMAGE_1_JDBC); - headers.set("X-Host", CONTAINER_1_HOST); - headers.set("X-Port", "" + CONTAINER_1_PORT); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Database", DATABASE_1_INTERNALNAME); - headers.set("X-Sidecar-Host", CONTAINER_1_SIDECAR_HOST); - headers.set("X-Sidecar-Port", "" + CONTAINER_1_SIDECAR_PORT); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .body(TABLE_1_DTO)); - - /* test */ - final PrivilegedTableDto response = metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - assertEquals(IMAGE_1_JDBC, response.getDatabase().getContainer().getImage().getJdbcMethod()); - assertEquals(CONTAINER_1_HOST, response.getDatabase().getContainer().getHost()); - assertEquals(CONTAINER_1_PORT, response.getDatabase().getContainer().getPort()); - assertEquals(CONTAINER_1_PRIVILEGED_USERNAME, response.getDatabase().getContainer().getUsername()); - assertEquals(CONTAINER_1_PRIVILEGED_PASSWORD, response.getDatabase().getContainer().getPassword()); - assertEquals(DATABASE_1_INTERNALNAME, response.getDatabase().getInternalName()); - assertEquals(CONTAINER_1_SIDECAR_HOST, response.getDatabase().getContainer().getSidecarHost()); - assertEquals(CONTAINER_1_SIDECAR_PORT, response.getDatabase().getContainer().getSidecarPort()); - } - - @Test - public void getTableById_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class)); - - /* test */ - assertThrows(TableNotFoundException.class, () -> { - metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - }); - } - - @Test - public void getTableById_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.ServiceUnavailable.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - }); - } - - @Test - public void getTableById_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .body(TABLE_1_DTO)); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - }); - } - - @Test - public void getTableById_headerMissing_fails() { - final List<String> customHeaders = List.of("X-Type", "X-Host", "X-Port", "X-Username", "X-Password", "X-Database", "X-Sidecar-Host", "X-Sidecar-Port"); - - for (int i = 0; i < customHeaders.size(); i++) { - final HttpHeaders headers = new HttpHeaders(); - for (int j = 0; j < i; j++) { - headers.add(customHeaders.get(j), ""); - } - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .body(TABLE_1_DTO)); - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - }); - } - } - - @Test - public void getTableById_emptyBody_fails() { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Type", IMAGE_1_JDBC); - headers.set("X-Host", CONTAINER_1_HOST); - headers.set("X-Port", "" + CONTAINER_1_PORT); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Database", DATABASE_1_INTERNALNAME); - headers.set("X-Sidecar-Host", CONTAINER_1_SIDECAR_HOST); - headers.set("X-Sidecar-Port", "" + CONTAINER_1_SIDECAR_PORT); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - }); - } - - @Test - public void getDatabaseByInternalName_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .body(new PrivilegedDatabaseDto[]{DATABASE_1_PRIVILEGED_DTO})); - - /* test */ - final PrivilegedDatabaseDto response = metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); - assertEquals(response.getId(), response.getId()); - } - - @Test - public void getDatabaseByInternalName_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.ServiceUnavailable.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); - }); - } - - @Test - public void getDatabaseByInternalName_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .body(new PrivilegedDatabaseDto[]{DATABASE_1_PRIVILEGED_DTO})); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); - }); - } - - @Test - public void getDatabaseByInternalName_emptyBody_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); - }); - } - - @Test - public void getDatabaseByInternalName_notFound_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class))) - .thenReturn(ResponseEntity.ok() - .body(new PrivilegedDatabaseDto[]{})); - - /* test */ - assertThrows(DatabaseNotFoundException.class, () -> { - metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); - }); - } - - @Test - public void getDatabaseById_succeeds() throws RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) - .thenReturn(ResponseEntity.ok() - .headers(headers) - .body(DATABASE_1_PRIVILEGED_DTO)); - - /* test */ - final PrivilegedDatabaseDto response = metadataServiceGateway.getDatabaseById(DATABASE_1_ID); - assertEquals(DATABASE_1_ID, response.getId()); - } - - @Test - public void getDatabaseById_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getDatabaseById(DATABASE_1_ID); - }); - } - - @Test - public void getDatabaseById_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class)); - - /* test */ - assertThrows(DatabaseNotFoundException.class, () -> { - metadataServiceGateway.getDatabaseById(DATABASE_1_ID); - }); - } - - @Test - public void getDatabaseById_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getDatabaseById(DATABASE_1_ID); - }); - } - - @Test - public void getDatabaseById_emptyBody_fails() { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getDatabaseById(DATABASE_1_ID); - }); - } - - @Test - public void getDatabaseById_headerMissing_fails() { - final List<String> customHeaders = List.of("X-Username", "X-Password"); - - for (int i = 0; i < customHeaders.size(); i++) { - final HttpHeaders headers = new HttpHeaders(); - for (int j = 0; j < i; j++) { - headers.add(customHeaders.get(j), ""); - } - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .build()); - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getDatabaseById(DATABASE_1_ID); - }); - } - } - - @Test - public void getContainerById_succeeds() throws RemoteUnavailableException, ContainerNotFoundException, ServiceException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) - .thenReturn(ResponseEntity.ok() - .headers(headers) - .body(CONTAINER_1_DTO)); - - /* test */ - final PrivilegedContainerDto response = metadataServiceGateway.getContainerById(CONTAINER_1_ID); - assertEquals(CONTAINER_1_ID, response.getId()); - } - - @Test - public void getContainerById_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getContainerById(CONTAINER_1_ID); - }); - } - - @Test - public void getContainerById_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class)); - - /* test */ - assertThrows(ContainerNotFoundException.class, () -> { - metadataServiceGateway.getContainerById(CONTAINER_1_ID); - }); - } - - @Test - public void getContainerById_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getContainerById(CONTAINER_1_ID); - }); - } - - @Test - public void getContainerById_headerMissing_fails() { - final List<String> customHeaders = List.of("X-Username", "X-Password"); - - for (int i = 0; i < customHeaders.size(); i++) { - final HttpHeaders headers = new HttpHeaders(); - for (int j = 0; j < i; j++) { - headers.add(customHeaders.get(j), ""); - } - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getContainerById(CONTAINER_1_ID); - }); - } - } - - @Test - public void getContainerById_emptyBody_fails() { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getContainerById(CONTAINER_1_ID); - }); - } - - @Test - public void getViewById_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ServiceException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Type", IMAGE_1_JDBC); - headers.set("X-Host", CONTAINER_1_HOST); - headers.set("X-Port", "" + CONTAINER_1_PORT); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Database", DATABASE_1_INTERNALNAME); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) - .thenReturn(ResponseEntity.ok() - .headers(headers) - .body(VIEW_1_DTO)); - - /* test */ - final PrivilegedViewDto response = metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); - assertEquals(VIEW_1_ID, response.getId()); - } - - @Test - public void getViewById_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); - }); - } - - @Test - public void getViewById_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class)); - - /* test */ - assertThrows(ViewNotFoundException.class, () -> { - metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); - }); - } - - @Test - public void getViewById_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); - }); - } - - @Test - public void getViewById_headerMissing_fails() { - final List<String> customHeaders = List.of("X-Type", "X-Host", "X-Port", "X-Username", "X-Password", "X-Database"); - - for (int i = 0; i < customHeaders.size(); i++) { - final HttpHeaders headers = new HttpHeaders(); - for (int j = 0; j < i; j++) { - headers.add(customHeaders.get(j), ""); - } - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); - }); - } - } - - @Test - public void getViewById_emptyBody_fails() { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Type", IMAGE_1_JDBC); - headers.set("X-Host", CONTAINER_1_HOST); - headers.set("X-Port", "" + CONTAINER_1_PORT); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Database", DATABASE_1_INTERNALNAME); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) - .thenReturn(ResponseEntity.ok() - .headers(headers) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); - }); - } - - @Test - public void getUserById_succeeds() throws RemoteUnavailableException, UserNotFoundException, ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.ok() - .body(USER_1_DTO)); - - /* test */ - final UserDto response = metadataServiceGateway.getUserById(USER_1_ID); - assertEquals(USER_1_ID, response.getId()); - } - - @Test - public void getUserById_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getUserById(USER_1_ID); - }); - } - - @Test - public void getUserById_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); - - /* test */ - assertThrows(UserNotFoundException.class, () -> { - metadataServiceGateway.getUserById(USER_1_ID); - }); - } - - @Test - public void getUserById_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getUserById(USER_1_ID); - }); - } - - @Test - public void getUserById_emptyBody_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getUserById(USER_1_ID); - }); - } - - @Test - public void getPrivilegedUserById_succeeds() throws RemoteUnavailableException, UserNotFoundException, - ServiceException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.ok() - .headers(headers) - .body(USER_1_DTO)); - - /* test */ - final PrivilegedUserDto response = metadataServiceGateway.getPrivilegedUserById(USER_1_ID); - assertEquals(USER_1_ID, response.getId()); - assertEquals(CONTAINER_1_PRIVILEGED_USERNAME, response.getUsername()); - assertEquals(CONTAINER_1_PRIVILEGED_PASSWORD, response.getPassword()); - } - - @Test - public void getPrivilegedUserById_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getPrivilegedUserById(USER_1_ID); - }); - } - - @Test - public void getPrivilegedUserById_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); - - /* test */ - assertThrows(UserNotFoundException.class, () -> { - metadataServiceGateway.getPrivilegedUserById(USER_1_ID); - }); - } - - @Test - public void getPrivilegedUserById_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getPrivilegedUserById(USER_1_ID); - }); - } - - @Test - public void getPrivilegedUserById_headerMissing_fails() { - final List<String> customHeaders = List.of("X-Username", "X-Password"); - - for (int i = 0; i < customHeaders.size(); i++) { - final HttpHeaders headers = new HttpHeaders(); - for (int j = 0; j < i; j++) { - headers.add(customHeaders.get(j), ""); - } - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getPrivilegedUserById(USER_1_ID); - }); - } - } - - @Test - public void getPrivilegedUserById_emptyBody_fails() { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) - .thenReturn(ResponseEntity.ok() - .headers(headers) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getPrivilegedUserById(USER_1_ID); - }); - } - - @Test - public void getAccess_succeeds() throws RemoteUnavailableException, NotAllowedException, ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) - .thenReturn(ResponseEntity.ok() - .body(DATABASE_1_USER_1_READ_ACCESS_DTO)); - - /* test */ - final DatabaseAccessDto response = metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); - } - - @Test - public void getAccess_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); - }); - } - - @Test - public void getAccess_forbidden_fails() { - - /* mock */ - doThrow(HttpClientErrorException.Forbidden.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class)); - - /* test */ - assertThrows(NotAllowedException.class, () -> { - metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); - }); - } - - @Test - public void getAccess_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class)); - - /* test */ - assertThrows(NotAllowedException.class, () -> { - metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); - }); - } - - @Test - public void getAccess_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); - }); - } - - @Test - public void getAccess_emptyBody_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); - }); - } - - @Test - public void getIdentifiers_witSubset_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class))) - .thenReturn(ResponseEntity.ok() - .body(new IdentifierDto[]{IDENTIFIER_1_DTO})); - - /* test */ - final List<IdentifierDto> response = metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); - assertEquals(1, response.size()); - } - - @Test - public void getIdentifiers_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, ServiceException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class))) - .thenReturn(ResponseEntity.ok() - .body(new IdentifierDto[]{IDENTIFIER_1_DTO})); - - /* test */ - final List<IdentifierDto> response = metadataServiceGateway.getIdentifiers(DATABASE_1_ID, null); - assertEquals(1, response.size()); - } - - @Test - public void getIdentifiers_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); - }); - } - - @Test - public void getIdentifiers_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class)); - - /* test */ - assertThrows(DatabaseNotFoundException.class, () -> { - metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); - }); - } - - @Test - public void getIdentifiers_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); - }); - } - - @Test - public void getIdentifiers_emptyBody_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); - }); - } - - @Test - public void updateTableStatistics_succeeds() throws RemoteUnavailableException, ServiceException, TableNotFoundException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.accepted() - .build()); - - /* test */ - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); - } - - @Test - public void updateTableStatistics_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); - }); - } - - @Test - public void updateTableStatistics_notFound_fails() { - - /* mock */ - doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class)); - - /* test */ - assertThrows(TableNotFoundException.class, () -> { - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); - }); - } - - @Test - public void updateTableStatistics_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java index dec1fcc0282993ba0a7b527dc4dda7088fc0e4a5..2994e7f0987edbe9e35820556fdf70d7b003b48d 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java @@ -3,7 +3,6 @@ package at.tuwien.listener; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; @@ -62,8 +61,7 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { } @Test - public void onMessage_succeeds(CapturedOutput output) throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + public void onMessage_succeeds(CapturedOutput output) throws TableNotFoundException, RemoteUnavailableException { final Message request = buildMessage("dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID, "{\"id\":4,\"date\":\"2023-10-03\",\"mintemp\":15.0,\"rainfall\":0.2}", new HashMap<>()); /* mock */ @@ -77,8 +75,7 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { @Test @Disabled - public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, RemoteUnavailableException { final Message request = buildMessage("dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID, "{\"id\":4,\"date\":\"2023-10-03\",\"mintemp\":15.0,\"rainfall\":0.2}", new HashMap<>()); /* mock */ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java index ab4a171c8915440055934c904247832ce0cf7549..5c2f61d5b7e42e0d888a15cc25e6884f7b70f353 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java @@ -3,7 +3,6 @@ package at.tuwien.listener; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; @@ -76,7 +75,7 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { @Test public void onMessage_messageMalformed_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException { final Message request = buildMessage("dbrepo.1.1", "{,}", new HashMap<>()); /* mock */ @@ -90,7 +89,7 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { @Test public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException { final Message request = buildMessage("dbrepo.1.1", "{\"id\":1}", new HashMap<>()); /* mock */ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index 803632c078717ef92de0bbedd246734276aa0f9a..a49b264a03c313bfc68fd05c1e9d4e1ffe359b30 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -191,7 +191,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - tableEndpoint.getHistory(DATABASE_1_ID, TABLE_1_ID, null, USER_1_PRINCIPAL); + tableEndpoint.getHistory(DATABASE_1_ID, TABLE_1_ID, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java deleted file mode 100644 index b7b8e0e2630b32c834cc229d043160505496ed63..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.config.MariaDbConfig; -import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.DatabaseMalformedException; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.testcontainers.containers.MariaDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.sql.SQLException; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -@Testcontainers -public class AccessServiceIntegrationTest extends AbstractUnitTest { - - @Autowired - private AccessService accessService; - - @Value("${dbrepo.grant.default.read}") - private String grantDefaultRead; - - @Value("${dbrepo.grant.default.write}") - private String grantDefaultWrite; - - @Container - private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); - - @BeforeEach - public void beforeEach() throws SQLException { - genesis(); - /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); - } - - @Test - public void create_read_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.create(DATABASE_1_PRIVILEGED_DTO, USER_1_PRIVILEGED_DTO, AccessTypeDto.READ); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - for (String privilege : grantDefaultRead.split(",")) { - assertTrue(privileges.stream().anyMatch(p -> p.trim().equals(privilege.trim()))); - } - } - - @Test - public void create_writeOwn_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.create(DATABASE_1_PRIVILEGED_DTO, USER_1_PRIVILEGED_DTO, AccessTypeDto.WRITE_OWN); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - for (String privilege : grantDefaultWrite.split(",")) { - assertTrue(privileges.stream().anyMatch(p -> p.trim().equals(privilege.trim()))); - } - } - - @Test - public void create_writeAll_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.create(DATABASE_1_PRIVILEGED_DTO, USER_1_PRIVILEGED_DTO, AccessTypeDto.WRITE_ALL); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - for (String privilege : grantDefaultWrite.split(",")) { - assertTrue(privileges.stream().anyMatch(p -> p.trim().equals(privilege.trim()))); - } - } - - @Test - public void update_read_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.update(DATABASE_1_PRIVILEGED_DTO, USER_1_DTO, AccessTypeDto.READ); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - for (String privilege : grantDefaultRead.split(",")) { - assertTrue(privileges.stream().anyMatch(p -> p.trim().equals(privilege.trim()))); - } - } - - @Test - public void update_writeOwn_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.update(DATABASE_1_PRIVILEGED_DTO, USER_1_DTO, AccessTypeDto.WRITE_OWN); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - for (String privilege : grantDefaultWrite.split(",")) { - assertTrue(privileges.stream().anyMatch(p -> p.trim().equals(privilege.trim()))); - } - } - - @Test - public void update_writeAll_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.update(DATABASE_1_PRIVILEGED_DTO, USER_1_DTO, AccessTypeDto.WRITE_ALL); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - for (String privilege : grantDefaultWrite.split(",")) { - assertTrue(privileges.stream().anyMatch(p -> p.trim().equals(privilege.trim()))); - } - } - - @Test - public void update_notFound_fails() { - - /* test */ - assertThrows(DatabaseMalformedException.class, () -> { - accessService.update(DATABASE_1_PRIVILEGED_DTO, USER_5_DTO, AccessTypeDto.WRITE_ALL); - }); - } - - @Test - public void delete_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - accessService.delete(DATABASE_1_PRIVILEGED_DTO, USER_1_DTO); - final List<String> privileges = MariaDbConfig.getPrivileges(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - assertEquals(1, privileges.size()); - assertEquals("USAGE", privileges.get(0)); - } - - @Test - public void delete_notFound_fails() { - - /* test */ - assertThrows(DatabaseMalformedException.class, () -> { - accessService.delete(DATABASE_1_PRIVILEGED_DTO, USER_5_DTO); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java deleted file mode 100644 index e53f6ad88f92095ae405d586d39a399e0a6b0304..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.database.internal.PrivilegedDatabaseDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.config.MariaDbConfig; -import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.*; -import at.tuwien.mapper.MariaDbMapper; -import at.tuwien.mapper.MariaDbMapperImpl; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.testcontainers.containers.MariaDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.sql.SQLException; - -import static org.junit.jupiter.api.Assertions.*; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -@Testcontainers -public class DatabaseServiceIntegrationTest extends AbstractUnitTest { - - @Autowired - private DatabaseService databaseService; - - @Container - private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); - - @Autowired - private MariaDbMapper mariaDbMapper; - - @BeforeEach - public void beforeEach() throws SQLException { - genesis(); - /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - } - - @Test - public void create_succeeds() throws SQLException, DatabaseMalformedException { - - /* test */ - final PrivilegedDatabaseDto response = databaseService.create(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_CREATE_INTERNAL); - assertNull(response.getName()); - assertEquals(DATABASE_1_INTERNALNAME, response.getInternalName()); - assertEquals(EXCHANGE_DBREPO_NAME, response.getExchangeName()); - assertNotNull(response.getCreator()); - assertEquals(USER_1_ID, response.getCreator().getId()); - assertNotNull(response.getOwner()); - assertEquals(USER_1_ID, response.getOwner().getId()); - assertNotNull(response.getContact()); - assertEquals(USER_1_ID, response.getContact().getId()); - assertNotNull(response.getContainer()); - assertEquals(CONTAINER_1_ID, response.getContainer().getId()); - } - - @Test - public void create_exists_fails() throws SQLException { - - /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - - /* test */ - assertThrows(DatabaseMalformedException.class, () -> { - databaseService.create(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_CREATE_INTERNAL); - }); - } - - @Test - public void update_succeeds() throws SQLException, DatabaseMalformedException { - final UpdateUserPasswordDto request = UpdateUserPasswordDto.builder() - .username(USER_1_USERNAME) - .password(USER_2_PASSWORD) - .build(); - - /* mock */ - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); - MariaDbConfig.grantWriteAccess(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); - - /* pre-condition */ - MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNALNAME, "CREATE SEQUENCE debug NOCACHE", USER_1_USERNAME, USER_1_PASSWORD); - try { - MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNALNAME, "CREATE SEQUENCE debug NOCACHE", USER_1_USERNAME, USER_2_PASSWORD); - fail(); - } catch (SQLException e) { - /* ignore */ - } - - /* test */ - databaseService.update(DATABASE_1_PRIVILEGED_DTO, request); - MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNALNAME, "CREATE SEQUENCE debug2 NOCACHE", USER_1_USERNAME, USER_2_PASSWORD); - } - - @Test - public void update_notExists_fails() throws SQLException { - final UpdateUserPasswordDto request = UpdateUserPasswordDto.builder() - .username("i_do_not_exist") - .password(USER_1_PASSWORD) - .build(); - - /* mock */ - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); - - /* test */ - assertThrows(DatabaseMalformedException.class, () -> { - databaseService.update(DATABASE_1_PRIVILEGED_DTO, request); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java index 4bfa5b443a19ed6bf7af2c55183fd94fa0366baf..452c88932ca431e0cbee5755f29bb6f7f4a1d889 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java @@ -4,7 +4,6 @@ import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.ContainerNotFoundException; import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.impl.QueueServiceRabbitMqImpl; @@ -51,8 +50,7 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { } @Test - public void insert_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, ServiceException { + public void insert_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException { final Map<String, Object> request = new HashMap<>() {{ put("id", 4L); put("date", "2023-10-03"); @@ -75,8 +73,7 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { } @Test - public void insert_onlyMandatoryFields_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, TableNotFoundException, ServiceException { + public void insert_onlyMandatoryFields_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, TableNotFoundException { final Map<String, Object> request = new HashMap<>() {{ put("id", 5L); put("date", "2023-10-04"); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java index 25dcb0caea1e161e0c6964b5cc121495aed78130..c9efad23f02b5ef280e8d9a55605d94e79a6b2fd 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java @@ -1,19 +1,13 @@ package at.tuwien.service; -import at.tuwien.api.container.image.ImageDateDto; import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; -import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.*; @@ -30,7 +24,6 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import java.sql.SQLException; -import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -69,11 +62,34 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { final List<ColumnDto> columns = response.getColumns(); assertNotNull(columns); assertEquals(5, columns.size()); - assertColumn(columns.get(0), null, null, DATABASE_1_ID, "id", "id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - assertColumn(columns.get(1), null, null, DATABASE_1_ID, "given_name", "given_name", ColumnTypeDto.VARCHAR, 255L, null, false, null, null); - assertColumn(columns.get(2), null, null, DATABASE_1_ID, "middle_name", "middle_name", ColumnTypeDto.VARCHAR, 255L, null, true, null, null); - assertColumn(columns.get(3), null, null, DATABASE_1_ID, "family_name", "family_name", ColumnTypeDto.VARCHAR, 255L, null, false, null, null); - assertColumn(columns.get(4), null, null, DATABASE_1_ID, "age", "age", ColumnTypeDto.INT, 10L, 0L, false, null, null); + final ColumnDto column0 = columns.get(0); + assertEquals("id", column0.getName()); + assertEquals("id", column0.getInternalName()); + assertEquals(ColumnTypeDto.BIGINT, column0.getColumnType()); + assertFalse(column0.getIsNullAllowed()); + final ColumnDto column1 = columns.get(1); + assertEquals("given_name", column1.getName()); + assertEquals("given_name", column1.getInternalName()); + assertEquals(ColumnTypeDto.VARCHAR, column1.getColumnType()); + assertEquals(255, column1.getSize()); + assertFalse(column1.getIsNullAllowed()); + final ColumnDto column2 = columns.get(2); + assertEquals("middle_name", column2.getName()); + assertEquals("middle_name", column2.getInternalName()); + assertEquals(ColumnTypeDto.VARCHAR, column2.getColumnType()); + assertEquals(255, column2.getSize()); + assertTrue(column2.getIsNullAllowed()); + final ColumnDto column3 = columns.get(3); + assertEquals("family_name", column3.getName()); + assertEquals("family_name", column3.getInternalName()); + assertEquals(ColumnTypeDto.VARCHAR, column3.getColumnType()); + assertEquals(255, column3.getSize()); + assertFalse(column3.getIsNullAllowed()); + final ColumnDto column4 = columns.get(4); + assertEquals("age", column4.getName()); + assertEquals("age", column4.getInternalName()); + assertEquals(ColumnTypeDto.INT, column4.getColumnType()); + assertFalse(column4.getIsNullAllowed()); final ConstraintsDto constraints = response.getConstraints(); assertNotNull(constraints); final Set<PrimaryKeyDto> primaryKey = constraints.getPrimaryKey(); @@ -84,210 +100,9 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { final List<UniqueDto> uniques = constraints.getUniques(); assertEquals(1, uniques.size()); assertEquals(2, uniques.get(0).getColumns().size()); - assertEquals("not_in_metadata_db", uniques.get(0).getTable().getName()); assertEquals("not_in_metadata_db", uniques.get(0).getTable().getInternalName()); assertEquals("given_name", uniques.get(0).getColumns().get(0).getInternalName()); assertEquals("family_name", uniques.get(0).getColumns().get(1).getInternalName()); - final List<ForeignKeyDto> foreignKeys = constraints.getForeignKeys(); - assertEquals(0, foreignKeys.size()); - } - - @Test - public void inspectTableFullConstraints_succeeds() throws TableNotFoundException, SQLException, QueryMalformedException { - - /* test */ - final TableDto response = schemaService.inspectTable(DATABASE_1_PRIVILEGED_DTO, "weather_aus"); - assertEquals("weather_aus", response.getInternalName()); - assertEquals("weather_aus", response.getName()); - assertEquals(DATABASE_1_ID, response.getTdbid()); - assertTrue(response.getIsVersioned()); - assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); - assertEquals(DATABASE_1_OWNER, response.getCreatedBy()); - assertNotNull(response.getCreator()); - assertEquals(DATABASE_1_OWNER, response.getCreator().getId()); - assertEquals(USER_1_NAME, response.getCreator().getName()); - assertEquals(USER_1_USERNAME, response.getCreator().getUsername()); - assertEquals(USER_1_FIRSTNAME, response.getCreator().getFirstname()); - assertEquals(USER_1_LASTNAME, response.getCreator().getLastname()); - assertEquals(USER_1_QUALIFIED_NAME, response.getCreator().getQualifiedName()); - assertNotNull(response.getCreator().getAttributes()); - assertEquals(USER_1_AFFILIATION, response.getCreator().getAttributes().getAffiliation()); - assertEquals(USER_1_THEME, response.getCreator().getAttributes().getTheme()); - assertEquals(USER_1_LANGUAGE, response.getCreator().getAttributes().getLanguage()); - assertEquals(USER_1_ORCID_UNCOMPRESSED, response.getCreator().getAttributes().getOrcid()); - assertNull(response.getCreator().getAttributes().getMariadbPassword()); - final List<IdentifierDto> identifiers = response.getIdentifiers(); - assertNotNull(identifiers); - assertEquals(0, identifiers.size()); - final List<ColumnDto> columns = response.getColumns(); - assertNotNull(columns); - assertEquals(5, columns.size()); - assertColumn(columns.get(0), null, null, DATABASE_1_ID, "id", "id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - assertColumn(columns.get(1), null, null, DATABASE_1_ID, "date", "date", ColumnTypeDto.DATE, null, null, false, IMAGE_DATE_1_ID, null); - assertColumn(columns.get(2), null, null, DATABASE_1_ID, "location", "location", ColumnTypeDto.VARCHAR, 255L, null, true, null, "Closest city"); - assertColumn(columns.get(3), null, null, DATABASE_1_ID, "mintemp", "mintemp", ColumnTypeDto.DOUBLE, 22L, null, true, null, null); - assertColumn(columns.get(4), null, null, DATABASE_1_ID, "rainfall", "rainfall", ColumnTypeDto.DOUBLE, 22L, null, true, null, null); - final ConstraintsDto constraints = response.getConstraints(); - final List<PrimaryKeyDto> primaryKey = new LinkedList<>(constraints.getPrimaryKey()); - assertEquals(1, primaryKey.size()); - final PrimaryKeyDto pk0 = primaryKey.get(0); - assertNull(pk0.getId()); - assertNotNull(pk0.getTable()); - assertNull(pk0.getTable().getId()); - assertEquals("weather_aus", pk0.getTable().getName()); - assertEquals("weather_aus", pk0.getTable().getInternalName()); - assertEquals("Weather in Australia", pk0.getTable().getDescription()); - assertNotNull(pk0.getColumn()); - assertNull(pk0.getColumn().getId()); - assertNull(pk0.getColumn().getTableId()); - assertEquals(DATABASE_1_ID, pk0.getColumn().getDatabaseId()); - assertNull(pk0.getColumn().getAlias()); - assertEquals("id", pk0.getColumn().getName()); - assertEquals("id", pk0.getColumn().getInternalName()); - assertEquals(ColumnTypeDto.BIGINT, pk0.getColumn().getColumnType()); - final List<UniqueDto> uniques = constraints.getUniques(); - assertEquals(1, uniques.size()); - final UniqueDto unique0 = uniques.get(0); - assertNotNull(unique0.getTable()); - assertNull(unique0.getTable().getId()); - assertEquals(TABLE_1_INTERNALNAME, unique0.getTable().getName()); - assertEquals(TABLE_1_INTERNALNAME, unique0.getTable().getInternalName()); - assertEquals(TABLE_1_DESCRIPTION, unique0.getTable().getDescription()); - assertTrue(unique0.getTable().getIsVersioned()); - assertNotNull(unique0.getColumns()); - assertEquals(1, unique0.getColumns().size()); - assertNull(unique0.getColumns().get(0).getId()); - assertNull(unique0.getColumns().get(0).getTableId()); - assertEquals("date", unique0.getColumns().get(0).getName()); - assertEquals("date", unique0.getColumns().get(0).getInternalName()); - final List<String> checks = new LinkedList<>(constraints.getChecks()); - assertEquals("`mintemp` > 0", checks.get(0)); - final List<ForeignKeyDto> foreignKeys = constraints.getForeignKeys(); - assertEquals(1, foreignKeys.size()); - final ForeignKeyDto fk0 = foreignKeys.get(0); - assertNotNull(fk0.getName()); - assertNotNull(fk0.getReferences()); - final ForeignKeyReferenceDto fk0ref0 = fk0.getReferences().get(0); - assertNull(fk0ref0.getId()); - assertNotNull(fk0ref0.getColumn()); - assertNotNull(fk0ref0.getReferencedColumn()); - assertNotNull(fk0ref0.getForeignKey()); - assertEquals(DATABASE_1_ID, fk0ref0.getColumn().getDatabaseId()); - assertNull(fk0ref0.getColumn().getId()); - assertNull(fk0ref0.getColumn().getTableId()); - assertEquals("location", fk0ref0.getColumn().getName()); - assertEquals("location", fk0ref0.getColumn().getInternalName()); - assertEquals(DATABASE_1_ID, fk0ref0.getReferencedColumn().getDatabaseId()); - assertNull(fk0ref0.getReferencedColumn().getId()); - assertNull(fk0ref0.getReferencedColumn().getTableId()); - assertEquals("location", fk0ref0.getReferencedColumn().getName()); - assertEquals("location", fk0ref0.getReferencedColumn().getInternalName()); - assertNotNull(fk0.getOnUpdate()); - assertEquals(ReferenceTypeDto.RESTRICT, fk0.getOnUpdate()); - assertNotNull(fk0.getOnDelete()); - assertEquals(ReferenceTypeDto.SET_NULL, fk0.getOnDelete()); - final TableBriefDto fk0table = fk0.getTable(); - assertNull(fk0table.getId()); - assertEquals(DATABASE_1_ID, fk0table.getDatabaseId()); - assertEquals(TABLE_1_INTERNALNAME, fk0table.getName()); - assertEquals(TABLE_1_INTERNALNAME, fk0table.getInternalName()); - assertNotNull(fk0.getOnDelete()); - assertNotNull(fk0.getOnUpdate()); - assertNotNull(fk0.getReferencedTable()); - assertEquals(TABLE_2_INTERNALNAME, fk0.getReferencedTable().getName()); - assertEquals(TABLE_2_INTERNALNAME, fk0.getReferencedTable().getInternalName()); - } - - @Test - public void inspectTable_multipleForeignKeyReferences_succeeds() throws TableNotFoundException, SQLException, QueryMalformedException { - - /* test */ - final TableDto response = schemaService.inspectTable(DATABASE_1_PRIVILEGED_DTO, "complex_foreign_keys"); - final ConstraintsDto constraints = response.getConstraints(); - final List<ForeignKeyDto> foreignKeys = constraints.getForeignKeys(); - assertEquals(1, foreignKeys.size()); - final ForeignKeyDto fk0 = foreignKeys.get(0); - assertNotNull(fk0.getName()); - assertNotNull(fk0.getReferences()); - final ForeignKeyReferenceDto fk0ref0 = fk0.getReferences().get(0); - assertNull(fk0ref0.getId()); - assertNotNull(fk0ref0.getColumn()); - assertNotNull(fk0ref0.getReferencedColumn()); - assertNotNull(fk0ref0.getForeignKey()); - assertEquals(DATABASE_1_ID, fk0ref0.getColumn().getDatabaseId()); - assertNull(fk0ref0.getColumn().getId()); - assertNull(fk0ref0.getColumn().getTableId()); - assertEquals("weather_id", fk0ref0.getColumn().getName()); - assertEquals("weather_id", fk0ref0.getColumn().getInternalName()); - assertEquals(DATABASE_1_ID, fk0ref0.getReferencedColumn().getDatabaseId()); - assertNull(fk0ref0.getReferencedColumn().getId()); - assertNull(fk0ref0.getReferencedColumn().getTableId()); - assertEquals("id", fk0ref0.getReferencedColumn().getName()); - assertEquals("id", fk0ref0.getReferencedColumn().getInternalName()); - final ForeignKeyReferenceDto fk0ref1 = fk0.getReferences().get(1); - assertNull(fk0ref1.getId()); - assertNotNull(fk0ref1.getColumn()); - assertNotNull(fk0ref1.getReferencedColumn()); - assertNotNull(fk0ref1.getForeignKey()); - assertEquals(DATABASE_1_ID, fk0ref1.getColumn().getDatabaseId()); - assertNull(fk0ref1.getColumn().getId()); - assertNull(fk0ref1.getColumn().getTableId()); - assertEquals("other_id", fk0ref1.getColumn().getName()); - assertEquals("other_id", fk0ref1.getColumn().getInternalName()); - assertEquals(DATABASE_1_ID, fk0ref1.getReferencedColumn().getDatabaseId()); - assertNull(fk0ref1.getReferencedColumn().getId()); - assertNull(fk0ref1.getReferencedColumn().getTableId()); - assertEquals("other_id", fk0ref1.getReferencedColumn().getName()); - assertEquals("other_id", fk0ref1.getReferencedColumn().getInternalName()); - final TableBriefDto fk0refT0 = fk0.getTable(); - assertNull(fk0refT0.getId()); - assertEquals(DATABASE_1_ID, fk0refT0.getDatabaseId()); - assertEquals("complex_foreign_keys", fk0refT0.getName()); - assertEquals("complex_foreign_keys", fk0refT0.getInternalName()); - assertNotNull(fk0.getReferencedTable()); - assertEquals("complex_primary_key", fk0.getReferencedTable().getName()); - assertEquals("complex_primary_key", fk0.getReferencedTable().getInternalName()); - assertNotNull(fk0.getOnDelete()); - assertNotNull(fk0.getOnUpdate()); - } - - @Test - public void inspectTable_multiplePrimaryKey_succeeds() throws TableNotFoundException, SQLException, QueryMalformedException { - - /* test */ - final TableDto response = schemaService.inspectTable(DATABASE_1_PRIVILEGED_DTO, "complex_primary_key"); - final ConstraintsDto constraints = response.getConstraints(); - final List<PrimaryKeyDto> primaryKey = new LinkedList<>(constraints.getPrimaryKey()); - assertEquals(2, primaryKey.size()); - final PrimaryKeyDto pk0 = primaryKey.get(0); - assertNull(pk0.getId()); - assertNotNull(pk0.getTable()); - assertNull(pk0.getTable().getId()); - assertEquals("complex_primary_key", pk0.getTable().getName()); - assertEquals("complex_primary_key", pk0.getTable().getInternalName()); - assertNotNull(pk0.getColumn()); - assertNull(pk0.getColumn().getId()); - assertNull(pk0.getColumn().getTableId()); - assertEquals(DATABASE_1_ID, pk0.getColumn().getDatabaseId()); - assertNull(pk0.getColumn().getAlias()); - assertEquals("id", pk0.getColumn().getName()); - assertEquals("id", pk0.getColumn().getInternalName()); - assertEquals(ColumnTypeDto.BIGINT, pk0.getColumn().getColumnType()); - final PrimaryKeyDto pk1 = primaryKey.get(1); - assertNull(pk1.getId()); - assertNotNull(pk1.getTable()); - assertNull(pk1.getTable().getId()); - assertEquals("complex_primary_key", pk1.getTable().getName()); - assertEquals("complex_primary_key", pk1.getTable().getInternalName()); - assertNotNull(pk1.getColumn()); - assertNull(pk1.getColumn().getId()); - assertNull(pk1.getColumn().getTableId()); - assertEquals(DATABASE_1_ID, pk1.getColumn().getDatabaseId()); - assertNull(pk1.getColumn().getAlias()); - assertEquals("other_id", pk1.getColumn().getName()); - assertEquals("other_id", pk1.getColumn().getInternalName()); - assertEquals(ColumnTypeDto.BIGINT, pk1.getColumn().getColumnType()); - } @Test @@ -325,51 +140,4 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { assertEquals(DATABASE_1_ID, column3.getDatabaseId()); } - protected static void assertViewColumn(ViewColumnDto column, Long id, Long databaseId, String name, String internalName, - ColumnTypeDto type, Long size, Long d, Boolean nullAllowed, - ImageDateDto dateFormat, String description) { - log.trace("assert column: {}", internalName); - assertNotNull(column); - assertEquals(id, column.getId()); - assertEquals(databaseId, column.getDatabaseId()); - assertEquals(name, column.getName()); - assertEquals(internalName, column.getInternalName()); - assertEquals(type, column.getColumnType()); - assertEquals(size, column.getSize()); - assertEquals(d, column.getD()); - assertEquals(nullAllowed, column.getIsNullAllowed()); - assertEquals(description, column.getDescription()); - if (dateFormat != null) { - assertNotNull(column.getDateFormat()); - assertEquals(dateFormat.getId(), column.getDateFormat().getId()); - } else { - assertNull(column.getDateFormat()); - } - } - - protected static void assertColumn(ColumnDto column, Long id, Long tableId, Long databaseId, String name, - String internalName, ColumnTypeDto type, Long size, Long d, Boolean nullAllowed, - Long dfid, String description) { - log.trace("assert column: {}", internalName); - assertNotNull(column); - assertEquals(id, column.getId()); - assertEquals(tableId, column.getTableId()); - assertEquals(databaseId, column.getDatabaseId()); - assertNotNull(column.getTable()); - assertEquals(tableId, column.getTable().getId()); - assertEquals(name, column.getName()); - assertEquals(internalName, column.getInternalName()); - assertEquals(type, column.getColumnType()); - assertEquals(size, column.getSize()); - assertEquals(d, column.getD()); - assertEquals(nullAllowed, column.getIsNullAllowed()); - assertEquals(description, column.getDescription()); - if (dfid != null) { - assertNotNull(column.getDateFormat()); - assertEquals(dfid, column.getDateFormat().getId()); - } else { - assertNull(column.getDateFormat()); - } - } - } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java deleted file mode 100644 index 336a2072c58f36762e74ad154f1737647466c7a7..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java +++ /dev/null @@ -1,171 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.ExportResourceDto; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.config.MariaDbConfig; -import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.config.S3Config; -import at.tuwien.exception.DatabaseMalformedException; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.exception.StorageUnavailableException; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.testcontainers.containers.MariaDBContainer; -import org.testcontainers.containers.MinIOContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.CreateBucketRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; - -import java.io.File; -import java.io.InputStream; -import java.sql.SQLException; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -@Testcontainers -public class StorageServiceIntegrationTest extends AbstractUnitTest { - - @Autowired - private StorageService storageService; - - @Autowired - private S3Client s3Client; - - @Autowired - private S3Config s3Config; - - @Container - private static final MinIOContainer minIOContainer = new MinIOContainer("minio/minio:RELEASE.2024-06-06T09-36-42Z"); - - @DynamicPropertySource - static void dynamicProperties(DynamicPropertyRegistry registry) { - registry.add("dbrepo.endpoints.storageService", minIOContainer::getS3URL); - } - - @BeforeEach - public void beforeEach() throws SQLException { - genesis(); - /* s3 */ - if (s3Client.listBuckets().buckets().stream().noneMatch(b -> b.name().equals(s3Config.getS3ImportBucket()))) { - s3Client.createBucket(CreateBucketRequest.builder() - .bucket(s3Config.getS3ImportBucket()) - .build()); - } - if (s3Client.listBuckets().buckets().stream().noneMatch(b -> b.name().equals(s3Config.getS3ExportBucket()))) { - s3Client.createBucket(CreateBucketRequest.builder() - .bucket(s3Config.getS3ExportBucket()) - .build()); - } - } - - @Test - public void getObject_succeeds() throws StorageUnavailableException, StorageNotFoundException { - - /* mock */ - s3Client.putObject(PutObjectRequest.builder() - .key("s3key") - .bucket(s3Config.getS3ImportBucket()) - .build(), RequestBody.fromFile(new File("src/test/resources/csv/weather_aus.csv"))); - - /* test */ - final InputStream response = storageService.getObject(s3Config.getS3ImportBucket(), "s3key"); - assertNotNull(response); - } - - @Test - public void getObject_notFound_fails() { - - /* test */ - assertThrows(StorageNotFoundException.class, () -> { - storageService.getObject(s3Config.getS3ImportBucket(), "i_do_not_exist"); - }); - } - - @Test - public void getObject_bucket_fails() { - - /* test */ - assertThrows(StorageUnavailableException.class, () -> { - storageService.getObject("i_do_not_exist", "s3key"); - }); - } - - @Test - public void getBytes_succeeds() throws StorageUnavailableException, StorageNotFoundException { - - /* mock */ - s3Client.putObject(PutObjectRequest.builder() - .key("s3key") - .bucket(s3Config.getS3ImportBucket()) - .build(), RequestBody.fromFile(new File("src/test/resources/csv/weather_aus.csv"))); - - /* test */ - final byte[] response = storageService.getBytes(s3Config.getS3ImportBucket(), "s3key"); - assertNotNull(response); - } - - @Test - public void getBytes_simple_succeeds() throws StorageUnavailableException, StorageNotFoundException { - - /* mock */ - s3Client.putObject(PutObjectRequest.builder() - .key("s3key") - .bucket(s3Config.getS3ImportBucket()) - .build(), RequestBody.fromFile(new File("src/test/resources/csv/weather_aus.csv"))); - - /* test */ - final byte[] response = storageService.getBytes("s3key"); - assertNotNull(response); - } - - @Test - public void getBytes_notFound_fails() { - - /* test */ - assertThrows(StorageNotFoundException.class, () -> { - storageService.getBytes(s3Config.getS3ImportBucket(), "i_do_not_exist"); - }); - } - - @Test - public void getResource_succeeds() throws StorageUnavailableException, StorageNotFoundException { - - /* mock */ - s3Client.putObject(PutObjectRequest.builder() - .key("s3key") - .bucket(s3Config.getS3ImportBucket()) - .build(), RequestBody.fromFile(new File("src/test/resources/csv/weather_aus.csv"))); - - /* test */ - final ExportResourceDto response = storageService.getResource(s3Config.getS3ImportBucket(), "s3key"); - assertEquals("s3key", response.getFilename()); - assertNotNull(response.getResource()); - } - - @Test - public void getResource_notFound_fails() { - - /* test */ - assertThrows(StorageNotFoundException.class, () -> { - storageService.getBytes(s3Config.getS3ImportBucket(), "i_do_not_exist"); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index aa30bc0580ff3b0aba950a1f1ea495b135280782..f041dc0e7c231ffe22952c2e2303c5c1a1b14b35 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java @@ -57,13 +57,13 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void execute_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException, QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + RemoteUnavailableException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; /* mock */ - when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY)) + when(metadataServiceGateway.getUser(QUERY_1_CREATED_BY)) .thenReturn(QUERY_1_CREATOR); /* test */ @@ -98,7 +98,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void execute_oneResult_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException, QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + RemoteUnavailableException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -106,7 +106,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID)) .thenReturn(List.of(IDENTIFIER_2_DTO)); - when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY)) + when(metadataServiceGateway.getUser(QUERY_1_CREATED_BY)) .thenReturn(QUERY_1_CREATOR); /* test */ @@ -129,13 +129,13 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void execute_oneResultPagination_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException, QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + RemoteUnavailableException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; /* mock */ - when(metadataServiceGateway.getUserById(USER_1_ID)) + when(metadataServiceGateway.getUser(USER_1_ID)) .thenReturn(USER_1_DTO); when(metadataServiceGateway.getIdentifiers(eq(DATABASE_1_ID), anyLong())) .thenReturn(List.of()); @@ -159,7 +159,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void findAll_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + NotAllowedException, RemoteUnavailableException { /* test */ final List<QueryDto> response = findAll_generic(null); @@ -170,7 +170,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void findAll_onlyPersisted_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + NotAllowedException, RemoteUnavailableException { /* test */ final List<QueryDto> response = findAll_generic(true); @@ -180,7 +180,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void findAll_onlyNonPersisted_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + NotAllowedException, RemoteUnavailableException { /* test */ final List<QueryDto> response = findAll_generic(false); @@ -190,15 +190,14 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void findById_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - UserNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { + UserNotFoundException, NotAllowedException, RemoteUnavailableException { /* test */ findById_generic(QUERY_1_ID); } @Test - public void findById_fails() { + public void findById_fails() { /* test */ assertThrows(QueryNotFoundException.class, () -> { @@ -208,11 +207,10 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void persist_succeeds() throws SQLException, InterruptedException, QueryStorePersistException, - QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, - ServiceException, DatabaseNotFoundException { + QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException { /* mock */ - when(metadataServiceGateway.getUserById(QUERY_2_CREATED_BY)) + when(metadataServiceGateway.getUser(QUERY_2_CREATED_BY)) .thenReturn(QUERY_2_CREATOR); /* test */ @@ -224,11 +222,10 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void persist_unPersist_succeeds() throws SQLException, InterruptedException, QueryStorePersistException, - QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, - ServiceException, DatabaseNotFoundException { + QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException { /* mock */ - when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY)) + when(metadataServiceGateway.getUser(QUERY_1_CREATED_BY)) .thenReturn(QUERY_1_CREATOR); /* test */ @@ -238,9 +235,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { assertFalse(response.getIsPersisted()); } - protected void findById_generic(Long queryId) throws InterruptedException, NotAllowedException, - RemoteUnavailableException, SQLException, UserNotFoundException, QueryNotFoundException, ServiceException, - DatabaseNotFoundException { + protected void findById_generic(Long queryId) throws InterruptedException, NotAllowedException, RemoteUnavailableException, + SQLException, UserNotFoundException, QueryNotFoundException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -248,7 +244,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID)) .thenReturn(List.of(IDENTIFIER_2_DTO)); - when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY)) + when(metadataServiceGateway.getUser(QUERY_1_CREATED_BY)) .thenReturn(QUERY_1_CREATOR); MariaDbConfig.insertQueryStore(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, USER_1_ID); @@ -259,8 +255,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } protected List<QueryDto> findAll_generic(Boolean filterPersisted) throws InterruptedException, SQLException, - QueryNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { + QueryNotFoundException, NotAllowedException, RemoteUnavailableException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -268,16 +263,15 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { /* mock */ MariaDbConfig.insertQueryStore(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, USER_1_ID); MariaDbConfig.insertQueryStore(DATABASE_1_PRIVILEGED_DTO, QUERY_2_DTO, USER_1_ID); - when(metadataServiceGateway.getIdentifiers(DATABASE_1_ID, null)) + when(metadataServiceGateway.getIdentifiers(DATABASE_1_ID)) .thenReturn(List.of(IDENTIFIER_2_DTO, IDENTIFIER_5_DTO)); /* test */ return queryService.findAll(DATABASE_1_PRIVILEGED_DTO, filterPersisted); } - protected void persist_generic(Long queryId, List<IdentifierDto> identifiers, Boolean persist) - throws InterruptedException, RemoteUnavailableException, SQLException, QueryStorePersistException, - ServiceException, DatabaseNotFoundException { + protected void persist_generic(Long queryId, List<IdentifierDto> identifiers, Boolean persist) throws InterruptedException, + NotAllowedException, RemoteUnavailableException, SQLException, QueryStorePersistException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index 86a0442ef60a4dc80365c48b8567a15ad04f9e85..25144d827dabaaf1b88fc7ab4914ae2ccc1b3283 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -1,29 +1,20 @@ package at.tuwien.service; -import at.tuwien.ExportResourceDto; -import at.tuwien.api.database.query.ImportCsvDto; -import at.tuwien.api.database.query.QueryResultDto; -import at.tuwien.api.database.table.*; -import at.tuwien.api.database.table.columns.ColumnCreateDto; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.TupleDeleteDto; +import at.tuwien.api.database.table.TupleDto; +import at.tuwien.api.database.table.TupleUpdateDto; import at.tuwien.api.database.table.columns.ColumnDto; -import at.tuwien.api.database.table.columns.ColumnStatisticDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyCreateDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.database.table.internal.TableCreateDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.*; -import at.tuwien.gateway.DataDatabaseSidecarGateway; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; -import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,26 +22,19 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.core.io.InputStreamResource; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.math.BigInteger; import java.sql.SQLException; -import java.time.Instant; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; -import static at.tuwien.service.SchemaServiceIntegrationTest.assertColumn; -import static at.tuwien.service.SchemaServiceIntegrationTest.assertViewColumn; +import static org.junit.Assert.assertEquals; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @Log4j2 @@ -65,12 +49,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @MockBean private MetadataServiceGateway metadataServiceGateway; - @MockBean - private DataDatabaseSidecarGateway dataDatabaseSidecarGateway; - - @MockBean - private StorageService storageService; - @Container private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); @@ -79,14 +57,12 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { genesis(); /* metadata database */ MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); } @Test public void updateTuple_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - ServiceException { + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* modify row based on primary key */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -120,9 +96,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updateTuple_modifyPrimaryKey_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, - QueryMalformedException, ServiceException { + public void updateTuple_modifyPrimaryKey_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* modify row primary key based on primary key */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -157,9 +132,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updateTuple_missingPrimaryKey_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, - QueryMalformedException, ServiceException { + public void updateTuple_missingPrimaryKey_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* modify row based on non-primary key column */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -194,8 +168,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Test public void updateTuple_notInOrder_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - ServiceException { + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* modify row based on non-primary key column */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -230,8 +203,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Test public void createTuple_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* add row with primary key */ final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ @@ -264,8 +236,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Test public void createTuple_notInOrder_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* add row with primary key */ final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ @@ -298,8 +269,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Test public void deleteTuple_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - ServiceException { + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* delete row based on primary key */ final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ @@ -323,9 +293,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void deleteTuple_withoutPrimaryKey_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, - QueryMalformedException, ServiceException { + public void deleteTuple_withoutPrimaryKey_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException { /* remove row based on non-primary key */ final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ @@ -355,392 +324,56 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { /* test */ final List<TableDto> response = tableService.getSchemas(DATABASE_1_PRIVILEGED_DTO); - assertEquals(3, response.size()); final TableDto table0 = response.get(0); - Assertions.assertEquals("complex_foreign_keys", table0.getInternalName()); - Assertions.assertEquals("complex_foreign_keys", table0.getName()); + Assertions.assertEquals("not_in_metadata_db", table0.getInternalName()); + Assertions.assertEquals("not_in_metadata_db", table0.getName()); Assertions.assertEquals(DATABASE_1_ID, table0.getTdbid()); assertTrue(table0.getIsVersioned()); Assertions.assertEquals(DATABASE_1_PUBLIC, table0.getIsPublic()); - final List<ColumnDto> columns0 = table0.getColumns(); - assertNotNull(columns0); - Assertions.assertEquals(3, columns0.size()); - assertColumn(columns0.get(0), null, null, DATABASE_1_ID, "id", "id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - assertColumn(columns0.get(1), null, null, DATABASE_1_ID, "weather_id", "weather_id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - assertColumn(columns0.get(2), null, null, DATABASE_1_ID, "other_id", "other_id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - final ConstraintsDto constraints0 = table0.getConstraints(); - assertNotNull(constraints0); - assertEquals(1, constraints0.getPrimaryKey().size()); - final PrimaryKeyDto pk0 = new LinkedList<>(constraints0.getPrimaryKey()).get(0); - assertNull(pk0.getId()); - assertNull(pk0.getColumn().getId()); - assertEquals("id", pk0.getColumn().getName()); - assertEquals("id", pk0.getColumn().getInternalName()); - assertEquals(1, constraints0.getForeignKeys().size()); - final ForeignKeyDto fk0 = constraints0.getForeignKeys().get(0); - assertNotNull(fk0.getName()); - assertNull(fk0.getTable().getId()); - assertEquals("complex_foreign_keys", fk0.getTable().getName()); - assertEquals("complex_foreign_keys", fk0.getTable().getInternalName()); - assertNull(fk0.getReferencedTable().getId()); - assertEquals("complex_primary_key", fk0.getReferencedTable().getName()); - assertEquals("complex_primary_key", fk0.getReferencedTable().getInternalName()); - assertEquals(2, fk0.getReferences().size()); - final ForeignKeyReferenceDto fk0r0 = fk0.getReferences().get(0); - assertEquals("weather_id", fk0r0.getColumn().getName()); - assertEquals("weather_id", fk0r0.getColumn().getInternalName()); - assertNotNull(fk0r0.getColumn().getName()); - assertNotNull(fk0r0.getForeignKey()); - assertEquals("id", fk0r0.getReferencedColumn().getName()); - assertEquals("id", fk0r0.getReferencedColumn().getInternalName()); - final ForeignKeyReferenceDto fk0r1 = fk0.getReferences().get(1); - assertEquals("other_id", fk0r1.getColumn().getName()); - assertEquals("other_id", fk0r1.getColumn().getInternalName()); - assertNotNull(fk0r1.getColumn().getName()); - assertNotNull(fk0r1.getForeignKey()); - assertEquals("other_id", fk0r1.getReferencedColumn().getName()); - assertEquals("other_id", fk0r1.getReferencedColumn().getInternalName()); - assertEquals(0, constraints0.getChecks().size()); - assertEquals(0, constraints0.getUniques().size()); - /* table 1 */ - final TableDto table1 = response.get(1); - Assertions.assertEquals("complex_primary_key", table1.getInternalName()); - Assertions.assertEquals("complex_primary_key", table1.getName()); - Assertions.assertEquals(DATABASE_1_ID, table1.getTdbid()); - assertTrue(table1.getIsVersioned()); - Assertions.assertEquals(DATABASE_1_PUBLIC, table1.getIsPublic()); - final List<ColumnDto> columns1 = table1.getColumns(); - assertNotNull(columns1); - Assertions.assertEquals(2, columns1.size()); - assertColumn(columns1.get(0), null, null, DATABASE_1_ID, "id", "id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - assertColumn(columns1.get(1), null, null, DATABASE_1_ID, "other_id", "other_id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - final ConstraintsDto constraints1 = table1.getConstraints(); - assertNotNull(constraints1); - assertEquals(2, constraints1.getPrimaryKey().size()); - final PrimaryKeyDto pk10 = new LinkedList<>(constraints1.getPrimaryKey()).get(0); - assertNull(pk10.getId()); - assertNull(pk10.getColumn().getId()); - assertEquals("id", pk10.getColumn().getName()); - assertEquals("id", pk10.getColumn().getInternalName()); - final PrimaryKeyDto pk11 = new LinkedList<>(constraints1.getPrimaryKey()).get(1); - assertNull(pk11.getId()); - assertNull(pk11.getColumn().getId()); - assertEquals("other_id", pk11.getColumn().getName()); - assertEquals("other_id", pk11.getColumn().getInternalName()); - assertEquals(0, constraints1.getForeignKeys().size()); - assertEquals(0, constraints1.getChecks().size()); - assertEquals(0, constraints1.getUniques().size()); - /* table 2 */ - final TableDto table2 = response.get(2); - Assertions.assertEquals("not_in_metadata_db", table2.getInternalName()); - Assertions.assertEquals("not_in_metadata_db", table2.getName()); - Assertions.assertEquals(DATABASE_1_ID, table2.getTdbid()); - assertTrue(table2.getIsVersioned()); - Assertions.assertEquals(DATABASE_1_PUBLIC, table2.getIsPublic()); - final List<ColumnDto> columns2 = table2.getColumns(); - assertNotNull(columns2); - Assertions.assertEquals(5, columns2.size()); - assertColumn(columns2.get(0), null, null, DATABASE_1_ID, "id", "id", ColumnTypeDto.BIGINT, 19L, 0L, false, null, null); - assertColumn(columns2.get(1), null, null, DATABASE_1_ID, "given_name", "given_name", ColumnTypeDto.VARCHAR, 255L, null, false, null, null); - assertColumn(columns2.get(2), null, null, DATABASE_1_ID, "middle_name", "middle_name", ColumnTypeDto.VARCHAR, 255L, null, true, null, null); - assertColumn(columns2.get(3), null, null, DATABASE_1_ID, "family_name", "family_name", ColumnTypeDto.VARCHAR, 255L, null, false, null, null); - assertColumn(columns2.get(4), null, null, DATABASE_1_ID, "age", "age", ColumnTypeDto.INT, 10L, 0L, false, null, null); - final ConstraintsDto constraints2 = table2.getConstraints(); - assertNotNull(constraints2); - final Set<PrimaryKeyDto> primaryKey2 = constraints2.getPrimaryKey(); - Assertions.assertEquals(1, primaryKey2.size()); - final Set<String> checks2 = constraints2.getChecks(); - Assertions.assertEquals(1, checks2.size()); - Assertions.assertEquals(Set.of("`age` > 0 and `age` < 120"), checks2); - final List<UniqueDto> uniques2 = constraints2.getUniques(); - Assertions.assertEquals(1, uniques2.size()); - Assertions.assertEquals(2, uniques2.get(0).getColumns().size()); - Assertions.assertEquals("not_in_metadata_db", uniques2.get(0).getTable().getInternalName()); - Assertions.assertEquals("given_name", uniques2.get(0).getColumns().get(0).getInternalName()); - Assertions.assertEquals("family_name", uniques2.get(0).getColumns().get(1).getInternalName()); - } - - @Test - public void create_succeeds() throws TableNotFoundException, TableMalformedException, SQLException, - QueryMalformedException, TableExistsException { - - /* test */ - final TableDto response = tableService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_CREATE_INTERNAL_DTO); - assertEquals(TABLE_4_NAME, response.getName()); - assertEquals(TABLE_4_INTERNALNAME, response.getInternalName()); - assertEquals(TABLE_4_COLUMNS.size(), response.getColumns().size()); - } - - @Test - public void getStatistics_succeeds() throws TableMalformedException, SQLException, QueryMalformedException { - - /* test */ - final TableStatisticDto response = tableService.getStatistics(TABLE_1_PRIVILEGED_DTO); - assertEquals(TABLE_1_COLUMNS.size(), response.getColumns().size()); - assertEquals(3L, response.getRows()); - assertEquals(Set.of("id", "date", "location", "mintemp", "rainfall"), response.getColumns().keySet()); - final ColumnStatisticDto column0 = response.getColumns().get("id"); - assertEquals(BigDecimal.valueOf(1L), column0.getMin()); - assertEquals(BigDecimal.valueOf(3L), column0.getMax()); - assertNotNull(column0.getMean()); - assertNotNull(column0.getMedian()); - assertNotNull(column0.getStdDev()); - final ColumnStatisticDto column1 = response.getColumns().get("date"); - assertNull(column1.getMin()); - assertNull(column1.getMax()); - assertNull(column1.getMean()); - assertNull(column1.getMedian()); - assertNull(column1.getStdDev()); - final ColumnStatisticDto column2 = response.getColumns().get("location"); - assertNull(column2.getMin()); - assertNull(column2.getMax()); - assertNull(column2.getMean()); - assertNull(column2.getMedian()); - assertNull(column2.getStdDev()); - final ColumnStatisticDto column3 = response.getColumns().get("mintemp"); - assertEquals(BigDecimal.valueOf(7.4), column3.getMin()); - assertEquals(BigDecimal.valueOf(13.4), column3.getMax()); - assertNotNull(column3.getMean()); - assertNotNull(column3.getMedian()); - assertNotNull(column3.getStdDev()); - final ColumnStatisticDto column4 = response.getColumns().get("rainfall"); - assertEquals(BigDecimal.valueOf(0L), column4.getMin()); - assertEquals(BigDecimal.valueOf(0.6), column4.getMax()); - assertNotNull(column4.getMean()); - assertNotNull(column4.getMedian()); - assertNotNull(column4.getStdDev()); - } - - @Test - public void create_malformed_fails() { - final at.tuwien.api.database.table.internal.TableCreateDto request = TableCreateDto.builder() - .needSequence(false) - .name("missing_foreign_key") - .columns(List.of(ColumnCreateDto.builder() - .name("id") - .type(ColumnTypeDto.BIGINT) - .nullAllowed(false) - .build())) - .constraints(ConstraintsCreateDto.builder() - .foreignKeys(List.of(ForeignKeyCreateDto.builder() - .columns(List.of("i_do_not_exist")) - .referencedTable("neither_do_i") - .referencedColumns(List.of("behold")) - .build())) - .build()) - .build(); - - /* test */ - assertThrows(TableMalformedException.class, () -> { - tableService.createTable(DATABASE_1_PRIVILEGED_DTO, request); - }); - } - - @Test - public void create_needSequence_succeeds() throws TableNotFoundException, TableMalformedException, SQLException, - QueryMalformedException, TableExistsException { - - /* mock */ - MariaDbConfig.dropTable(DATABASE_1_PRIVILEGED_DTO, TABLE_1_INTERNALNAME); - - /* test */ - final TableDto response = tableService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_1_CREATE_INTERNAL_DTO); - assertEquals(TABLE_1_NAME, response.getName()); - assertEquals(TABLE_1_INTERNALNAME, response.getInternalName()); - assertEquals(TABLE_1_COLUMNS.size(), response.getColumns().size()); - } - - @Test - public void delete_succeeds() throws SQLException, QueryMalformedException { - - /* test */ - tableService.delete(TABLE_1_PRIVILEGED_DTO); - } - - @Test - public void delete_notFound_fails() throws SQLException { - - /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); - - /* test */ - assertThrows(QueryMalformedException.class, () -> { - tableService.delete(TABLE_5_PRIVILEGED_DTO); - }); - } - - @Test - public void getCount_succeeds() throws SQLException, QueryMalformedException { - - /* test */ - final Long response = tableService.getCount(TABLE_1_PRIVILEGED_DTO, null); - assertEquals(3, response); - } - - @Test - public void getCount_timestamp_succeeds() throws SQLException, QueryMalformedException { - - /* test */ - final Long response = tableService.getCount(TABLE_1_PRIVILEGED_DTO, Instant.ofEpochSecond(0)); - assertEquals(0, response); - } - - @Test - public void getCount_notFound_fails() throws SQLException { - - /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); - - /* test */ - assertThrows(QueryMalformedException.class, () -> { - tableService.getCount(TABLE_5_PRIVILEGED_DTO, null); - }); - } - - @Test - public void getData_succeeds() throws SQLException, TableMalformedException { - - /* test */ - final QueryResultDto response = tableService.getData(TABLE_1_PRIVILEGED_DTO, null, 0L, 10L); - assertEquals(TABLE_1_ID, response.getId()); - final List<Map<String, Integer>> headers = response.getHeaders(); - assertEquals(5, headers.size()); - assertEquals(0, headers.get(0).get("id")); - assertEquals(1, headers.get(1).get("date")); - assertEquals(2, headers.get(2).get("location")); - assertEquals(3, headers.get(3).get("mintemp")); - assertEquals(4, headers.get(4).get("rainfall")); - final List<Map<String, Object>> result = response.getResult(); - assertEquals(Instant.ofEpochSecond(1228089600), result.get(0).get("date")); - assertEquals(0.6, result.get(0).get("rainfall")); - assertEquals("Albury", result.get(0).get("location")); - assertEquals(BigInteger.valueOf(1L), result.get(0).get("id")); - assertEquals(13.4, result.get(0).get("mintemp")); - assertEquals(Instant.ofEpochSecond(1228176000), result.get(1).get("date")); - assertEquals(0.0, result.get(1).get("rainfall")); - assertEquals("Albury", result.get(1).get("location")); - assertEquals(BigInteger.valueOf(2L), result.get(1).get("id")); - assertEquals(7.4, result.get(1).get("mintemp")); - assertEquals(Instant.ofEpochSecond(1228262400), result.get(2).get("date")); - assertEquals(0.0, result.get(2).get("rainfall")); - assertEquals("Albury", result.get(2).get("location")); - assertEquals(BigInteger.valueOf(3L), result.get(2).get("id")); - assertEquals(12.9, result.get(2).get("mintemp")); - } - - @Test - public void getData_notFound_fails() throws SQLException { - - /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); - - /* test */ - assertThrows(TableMalformedException.class, () -> { - tableService.getData(TABLE_5_PRIVILEGED_DTO, null, 0L, 10L); - }); - } - - @Test - public void history_succeeds() throws SQLException, TableNotFoundException { - - /* test */ - final List<TableHistoryDto> response = tableService.history(TABLE_1_PRIVILEGED_DTO, 1000L); - assertEquals(1, response.size()); - final TableHistoryDto history0 = response.get(0); - assertNotNull(history0.getTimestamp()); - assertEquals("INSERT", history0.getEvent()); - assertEquals(3, history0.getTotal()); - } - - @Test - public void history_notFound_fails() throws SQLException { - - /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); - - /* test */ - assertThrows(TableNotFoundException.class, () -> { - tableService.history(TABLE_5_PRIVILEGED_DTO, null); - }); - } - - @Test - public void importDataset_withSeparatorAndQuoteAndNullElement_succeeds() throws SidecarImportException, ServiceException, SQLException, - QueryMalformedException, RemoteUnavailableException, StorageNotFoundException, IOException { - final ImportCsvDto request = ImportCsvDto.builder() - .location("weather_aus.csv") - .separator(';') - .quote('"') - .nullElement("NA") - .build(); - - /* mock */ - final File source = new File("src/test/resources/csv/weather_aus.csv"); - final File target = new File("/tmp/weather_aus.csv"); - log.trace("copy dataset from {} to {}", source.toPath().toAbsolutePath(), target.toPath().toAbsolutePath()); - FileUtils.copyFile(source, target); - doNothing() - .when(dataDatabaseSidecarGateway) - .importFile(anyString(), anyInt(), eq("weather_aus.csv")); - - /* test */ - tableService.importDataset(TABLE_1_PRIVILEGED_DTO, request); - } - - @Test - public void importDataset_malformedData_fails() throws ServiceException, RemoteUnavailableException, StorageNotFoundException, - IOException { - final ImportCsvDto request = ImportCsvDto.builder() - .location("weather_aus.csv") - .separator(';') - .quote('"') - .build(); - - /* mock */ - final File source = new File("src/test/resources/csv/weather_aus.csv"); - final File target = new File("/tmp/weather_aus.csv"); - log.trace("copy dataset from {} to {}", source.toPath().toAbsolutePath(), target.toPath().toAbsolutePath()); - FileUtils.copyFile(source, target); - doNothing() - .when(dataDatabaseSidecarGateway) - .importFile(anyString(), anyInt(), eq("weather_aus.csv")); - - /* test */ - assertThrows(QueryMalformedException.class, () -> { - tableService.importDataset(TABLE_1_PRIVILEGED_DTO, request); - }); - } - - @Test - public void exportDataset_succeeds() throws ServiceException, SQLException, - QueryMalformedException, RemoteUnavailableException, StorageNotFoundException, StorageUnavailableException, - SidecarExportException { - final ExportResourceDto mock = ExportResourceDto.builder() - .filename("weather_aus.csv") - .resource(new InputStreamResource(InputStream.nullInputStream())) - .build(); - - /* mock */ - doNothing() - .when(dataDatabaseSidecarGateway) - .exportFile(anyString(), anyInt(), eq("weather_aus.csv")); - when(storageService.getResource("weather_aus.csv")) - .thenReturn(mock); - - /* test */ - final ExportResourceDto response = tableService.exportDataset(TABLE_1_PRIVILEGED_DTO, null); - } - - @Test - public void exportDataset_malformedData_fails() throws SQLException { - - /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); - - /* test */ - assertThrows(QueryMalformedException.class, () -> { - tableService.exportDataset(TABLE_5_PRIVILEGED_DTO, null); - }); + final List<ColumnDto> columns = table0.getColumns(); + assertNotNull(columns); + Assertions.assertEquals(5, columns.size()); + final ColumnDto column0 = columns.get(0); + Assertions.assertEquals("id", column0.getName()); + Assertions.assertEquals("id", column0.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.BIGINT, column0.getColumnType()); + assertFalse(column0.getIsNullAllowed()); + final ColumnDto column1 = columns.get(1); + Assertions.assertEquals("given_name", column1.getName()); + Assertions.assertEquals("given_name", column1.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.VARCHAR, column1.getColumnType()); + Assertions.assertEquals(255, column1.getSize()); + assertFalse(column1.getIsNullAllowed()); + final ColumnDto column2 = columns.get(2); + Assertions.assertEquals("middle_name", column2.getName()); + Assertions.assertEquals("middle_name", column2.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.VARCHAR, column2.getColumnType()); + Assertions.assertEquals(255, column2.getSize()); + assertTrue(column2.getIsNullAllowed()); + final ColumnDto column3 = columns.get(3); + Assertions.assertEquals("family_name", column3.getName()); + Assertions.assertEquals("family_name", column3.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.VARCHAR, column3.getColumnType()); + Assertions.assertEquals(255, column3.getSize()); + assertFalse(column3.getIsNullAllowed()); + final ColumnDto column4 = columns.get(4); + Assertions.assertEquals("age", column4.getName()); + Assertions.assertEquals("age", column4.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.INT, column4.getColumnType()); + assertFalse(column4.getIsNullAllowed()); + final ConstraintsDto constraints = table0.getConstraints(); + assertNotNull(constraints); + final Set<PrimaryKeyDto> primaryKey = constraints.getPrimaryKey(); + Assertions.assertEquals(1, primaryKey.size()); + final Set<String> checks = constraints.getChecks(); + Assertions.assertEquals(1, checks.size()); + Assertions.assertEquals(Set.of("`age` > 0 and `age` < 120"), checks); + final List<UniqueDto> uniques = constraints.getUniques(); + Assertions.assertEquals(1, uniques.size()); + Assertions.assertEquals(2, uniques.get(0).getColumns().size()); + Assertions.assertEquals("not_in_metadata_db", uniques.get(0).getTable().getInternalName()); + Assertions.assertEquals("given_name", uniques.get(0).getColumns().get(0).getInternalName()); + Assertions.assertEquals("family_name", uniques.get(0).getColumns().get(1).getInternalName()); } } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java index 54df39999b57ed5d5f2ef3d95de387fa732c8420..ba846f37cc1a4dd8de4c2e1927a9c1f2493f29f3 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java @@ -3,6 +3,7 @@ package at.tuwien.service; import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.*; @@ -23,7 +24,6 @@ import java.time.Instant; import java.util.List; import java.util.Map; -import static at.tuwien.service.SchemaServiceIntegrationTest.assertViewColumn; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -58,21 +58,7 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { public void create_succeeds() throws SQLException, ViewMalformedException { /* test */ - final ViewDto response = viewService.create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); - assertEquals(VIEW_1_NAME, response.getName()); - assertEquals(VIEW_1_INTERNAL_NAME, response.getInternalName()); - assertEquals(VIEW_1_QUERY, response.getQuery()); - assertNotNull(response.getQueryHash()); - assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); - final List<ViewColumnDto> columns = response.getColumns(); - assertEquals(VIEW_1_COLUMNS.size(), columns.size()); - ViewColumnDto ref = VIEW_1_COLUMNS_DTO.get(0); - SchemaServiceIntegrationTest.assertViewColumn(columns.get(0), null, ref.getDatabaseId(), ref.getName(), ref.getInternalName(), ref.getColumnType(), ref.getSize(), ref.getD(), ref.getIsNullAllowed(), ref.getDateFormat(), ref.getDescription()); - ref = VIEW_1_COLUMNS_DTO.get(1); - SchemaServiceIntegrationTest.assertViewColumn(columns.get(1), null, ref.getDatabaseId(), ref.getName(), ref.getInternalName(), ref.getColumnType(), ref.getSize(), ref.getD(), ref.getIsNullAllowed(), ref.getDateFormat(), ref.getDescription()); - ref = VIEW_1_COLUMNS_DTO.get(2); - SchemaServiceIntegrationTest.assertViewColumn(columns.get(2), null, ref.getDatabaseId(), ref.getName(), ref.getInternalName(), ref.getColumnType(), ref.getSize(), ref.getD(), ref.getIsNullAllowed(), ref.getDateFormat(), ref.getDescription()); - + viewService.create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); } @Test diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java deleted file mode 100644 index 6ed73e8a01563a6b0b7e950afe5f9bf7c86cfbcf..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package at.tuwien.utils; - -import at.tuwien.api.database.table.columns.ColumnTypeDto; -import org.junit.jupiter.api.Test; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; - -import java.nio.charset.StandardCharsets; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MariaDbUtilTest { - - @Test - public void needValueQuotes_succeeds() { - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.TINYBLOB)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.MEDIUMBLOB)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.LONGBLOB)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.BLOB)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.CHAR)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.VARCHAR)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.ENUM)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.SET)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.TINYTEXT)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.MEDIUMTEXT)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.LONGTEXT)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.TEXT)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.BINARY)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.VARBINARY)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.DATETIME)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.DATE)); - assertTrue(MariaDbUtil.needValueQuotes(ColumnTypeDto.TIMESTAMP)); - assertFalse(MariaDbUtil.needValueQuotes(ColumnTypeDto.INT)); - assertFalse(MariaDbUtil.needValueQuotes(ColumnTypeDto.TINYINT)); - assertFalse(MariaDbUtil.needValueQuotes(ColumnTypeDto.MEDIUMINT)); - assertFalse(MariaDbUtil.needValueQuotes(ColumnTypeDto.DOUBLE)); - assertFalse(MariaDbUtil.needValueQuotes(ColumnTypeDto.DECIMAL)); - assertFalse(MariaDbUtil.needValueQuotes(ColumnTypeDto.BOOL)); - } -} diff --git a/dbrepo-data-service/rest-service/src/test/resources/application.properties b/dbrepo-data-service/rest-service/src/test/resources/application.properties index 07eb7f642bd62128618f3d0b86d04c0ba4743644..ed58329c18d9c4a5bc8f60404fa2c6c99836ddf6 100644 --- a/dbrepo-data-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-data-service/rest-service/src/test/resources/application.properties @@ -25,8 +25,4 @@ logging.level.at.tuwien.=trace spring.rabbitmq.host=localhost spring.rabbitmq.virtual-host=dbrepo spring.rabbitmq.username=guest -spring.rabbitmq.password=guest - -# s3 -dbrepo.s3.accessKeyId=minioadmin -dbrepo.s3.secretAccessKey=minioadmin \ No newline at end of file +spring.rabbitmq.password=guest \ No newline at end of file diff --git a/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql b/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql index 052f23adf8f5772a996d430877c8785d24651305..2eef31b4752b03ed0b1ccad1cc2d93a56e44f1ae 100644 --- a/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql +++ b/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql @@ -13,27 +13,12 @@ CREATE TABLE weather_aus ( id BIGINT NOT NULL PRIMARY KEY, `date` DATE NOT NULL, - location VARCHAR(255) NULL COMMENT 'Closest city', + location VARCHAR(255) NULL, mintemp DOUBLE PRECISION NULL, rainfall DOUBLE PRECISION NULL, - FOREIGN KEY (location) REFERENCES weather_location (location) ON DELETE SET NULL, + FOREIGN KEY (location) REFERENCES weather_location (location), UNIQUE (`date`), CHECK (`mintemp` > 0) -) WITH SYSTEM VERSIONING COMMENT 'Weather in Australia'; - -CREATE TABLE complex_primary_key -( - id BIGINT NOT NULL, - other_id BIGINT NOT NULL, - PRIMARY KEY (id, other_id) -) WITH SYSTEM VERSIONING; - -CREATE TABLE complex_foreign_keys -( - id BIGINT NOT NULL PRIMARY KEY, - weather_id BIGINT NOT NULL, - other_id BIGINT NOT NULL, - FOREIGN KEY (weather_id, other_id) REFERENCES complex_primary_key (id, `other_id`) ) WITH SYSTEM VERSIONING; CREATE TABLE sensor diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java index 805035d42171ba59b997639d26f8104129628a74..6cd55e9ef768e47f3d3463001ba99b5378f5351e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -3,7 +3,6 @@ package at.tuwien.auth; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.api.user.UserDetailsDto; import at.tuwien.config.GatewayConfig; -import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.ServiceConnectionException; import at.tuwien.exception.ServiceException; import at.tuwien.gateway.KeycloakGateway; @@ -54,7 +53,7 @@ public class BasicAuthenticationProvider implements AuthenticationManager { final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - } catch (ServletException | RemoteUnavailableException | ServiceException e) { + } catch (ServletException | ServiceConnectionException | ServiceException e) { throw new BadCredentialsException("Failed to authenticate with authentication service", e); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index b04aff18ce5a49d68c01519a97b3550b14bddc6e..57df3af3a6ad468bdfcef83ef2236f7443f67d68 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -19,8 +19,8 @@ import java.util.List; @Configuration public class GatewayConfig { - @Value("${dbrepo.endpoints.metadataService}") - private String metadataEndpoint; + @Value("${dbrepo.endpoints.gatewayService}") + private String gatewayEndpoint; @Value("${dbrepo.admin.username}") private String adminUsername; @@ -31,8 +31,8 @@ public class GatewayConfig { @Bean public RestTemplate restTemplate() { final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(metadataEndpoint)); - log.debug("add basic authentication for metadata service: username={}, password=(hidden)", adminUsername); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint)); + log.debug("add basic authentication for internal gateway: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), clientHttpRequestInterceptor())); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/AnalyseServiceGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/AnalyseServiceGateway.java new file mode 100644 index 0000000000000000000000000000000000000000..b10f386cd3d9267596620dbde0244311062483e4 --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/AnalyseServiceGateway.java @@ -0,0 +1,10 @@ +package at.tuwien.gateway; + +import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.exception.NotAllowedException; +import at.tuwien.exception.RemoteUnavailableException; +import at.tuwien.exception.TableNotFoundException; + +public interface AnalyseServiceGateway { + TableStatisticDto analyseTable(Long databaseId, Long tableId) throws RemoteUnavailableException, NotAllowedException, TableNotFoundException; +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java index ecac6865f6e4704b915e10016afe8a5b25afaa63..417fe77d7afecece0b48f2382566859e4daf9380 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java @@ -1,11 +1,13 @@ package at.tuwien.gateway; -import at.tuwien.exception.*; +import at.tuwien.exception.SidecarExportException; +import at.tuwien.exception.SidecarImportException; +import at.tuwien.exception.StorageNotFoundException; public interface DataDatabaseSidecarGateway { - void importFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - RemoteUnavailableException, ServiceException; + void importFile(String hostname, Integer port, String filename) throws SidecarImportException, + StorageNotFoundException; void exportFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - ServiceException, RemoteUnavailableException; + SidecarExportException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java index 1058119a25c8b5de2affbc05b72cd9417c7887a7..a05a75a6ff890feba33e1d14f2bd1a9407845861 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java @@ -1,14 +1,11 @@ package at.tuwien.gateway; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.ServiceConnectionException; import at.tuwien.exception.ServiceException; -import javax.naming.ServiceUnavailableException; - public interface KeycloakGateway { - TokenDto obtainUserToken(String username, String password) throws RemoteUnavailableException, ServiceException; + TokenDto obtainUserToken(String username, String password) throws ServiceConnectionException, ServiceException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java index 4c01a40a447954ae666bf7ef9d330b5879b85e59..ad1cb756938d60995f4b2cecda4aef6e5850d42e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java @@ -10,7 +10,6 @@ import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.api.user.PrivilegedUserDto; import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; -import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.UUID; @@ -22,12 +21,21 @@ public interface MetadataServiceGateway { * * @param containerId The container id * @return The container with privileged connection information, if successful. - * @throws ContainerNotFoundException The table was not found in the metadata service. - * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. + * @throws ContainerNotFoundException The container was not found in the metadata service. */ - PrivilegedContainerDto getContainerById(Long containerId) throws RemoteUnavailableException, - ContainerNotFoundException, ServiceException; + PrivilegedContainerDto getContainerById(Long containerId) throws RemoteUnavailableException, ContainerNotFoundException; + + /** + * Get all databases from the metadata service. + * + * @return List of databases, if successful. + * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. + */ + List<PrivilegedDatabaseDto> getDatabases() throws RemoteUnavailableException; + + void updateTableStatistics(Long databaseId, Long tableId, TableStatisticDto data) + throws RemoteUnavailableException; /** * Get a database with given id from the metadata service. @@ -35,11 +43,9 @@ public interface MetadataServiceGateway { * @param id The database id. * @return The database, if successful. * @throws DatabaseNotFoundException The database was not found in the metadata service. - * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. */ - PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException; + PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException; /** * Get a database with given internal name from the metadata service. @@ -47,11 +53,9 @@ public interface MetadataServiceGateway { * @param internalName The internal name. * @return The database, if successful. * @throws DatabaseNotFoundException The database was not found in the metadata service. - * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. */ - PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException, - RemoteUnavailableException, ServiceException; + PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException, RemoteUnavailableException; /** * Get a table with given database id and table id from the metadata service. @@ -60,23 +64,11 @@ public interface MetadataServiceGateway { * @param id The table id. * @return The table, if successful. * @throws TableNotFoundException The table was not found in the metadata service. - * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. */ - PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException, RemoteUnavailableException, - ServiceException; + PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException, RemoteUnavailableException; - /** - * Get a view with given database id and view id from the metadata service. - * @param databaseId The database id. - * @param id The view id. - * @return The view, if successful. - * @throws ViewNotFoundException The view was not found in the metadata service. - * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. - */ - PrivilegedViewDto getViewById(Long databaseId, Long id) throws RemoteUnavailableException, ViewNotFoundException, - ServiceException; + PrivilegedViewDto getViewById(Long databaseId, Long id) throws RemoteUnavailableException, ViewNotFoundException; /** * Get a user with given user id from the metadata service. @@ -85,53 +77,16 @@ public interface MetadataServiceGateway { * @return The user, if successful. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws UserNotFoundException The user was not found in the metadata service. - * @throws ServiceException The remote service returned invalid data. */ - UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, ServiceException; + PrivilegedUserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException; - /** - * Get a user with given user id from the metadata service. - * - * @param userId The user id. - * @return The user, if successful. - * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. - * @throws UserNotFoundException The user was not found in the metadata service. - * @throws ServiceException The remote service returned invalid data. - */ - PrivilegedUserDto getPrivilegedUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, - ServiceException; + DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, NotAllowedException; - /** - * Get database access for a given user and database id from the metadata service. - * @param databaseId The database id. - * @param userId The user id. - * @return The database access, if successful. - * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. - * @throws NotAllowedException The access to this database is denied for the given user. - * @throws ServiceException The remote service returned invalid data. - */ - DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, NotAllowedException, - ServiceException; + List<IdentifierDto> getIdentifiers(Long databaseId, Long subsetId) throws RemoteUnavailableException, + NotAllowedException; - /** - * Get a list of identifiers for a given database id and optional subset id. - * @param databaseId The database id. - * @param subsetId The subset id. Optional. - * @return The list of identifiers. - * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. - * @throws DatabaseNotFoundException The database was not found. - * @throws ServiceException The remote service returned invalid data. - */ - List<IdentifierDto> getIdentifiers(@NotNull Long databaseId, Long subsetId) throws ServiceException, - RemoteUnavailableException, DatabaseNotFoundException; + List<IdentifierDto> getIdentifiers(Long databaseId) throws RemoteUnavailableException, + NotAllowedException; - /** - * Update the table statistics in the metadata service. - * @param databaseId The database id. - * @param tableId The table id. - * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. - * @throws TableNotFoundException The table was not found. - * @throws ServiceException The remote service returned invalid data. - */ - void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, ServiceException, RemoteUnavailableException; + UserDto getUser(UUID userId) throws RemoteUnavailableException, NotAllowedException, UserNotFoundException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/AnalyseServiceGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/AnalyseServiceGatewayImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ff4f769a089c95cba4d9a4ae4fb7ccb818f9f813 --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/AnalyseServiceGatewayImpl.java @@ -0,0 +1,50 @@ +package at.tuwien.gateway.impl; + +import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.exception.*; +import at.tuwien.gateway.AnalyseServiceGateway; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +@Log4j2 +@Service +public class AnalyseServiceGatewayImpl implements AnalyseServiceGateway { + + private final RestTemplate restTemplate; + + @Autowired + public AnalyseServiceGatewayImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @Override + public TableStatisticDto analyseTable(Long databaseId, Long tableId) throws RemoteUnavailableException, + NotAllowedException, TableNotFoundException { + final ResponseEntity<TableStatisticDto> response; + final String url = "/api/analyse/database/" + databaseId + "/table/" + tableId + "/statistics"; + log.trace("mapped url: {}", url); + try { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), TableStatisticDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to analyse table with id {}: {}", tableId, e.getMessage()); + throw new RemoteUnavailableException("Failed to analyse table", e); + } catch (HttpClientErrorException.NotFound e) { + log.error("Failed to analyse table with id {}: not found: {}", tableId, e.getMessage()); + throw new TableNotFoundException("Failed to analyse table: not found", e); + } + if (response.getBody() == null) { + log.error("Failed to analyse table: body is null"); + throw new NotAllowedException("Failed to analyse table: body is null"); + } + return response.getBody(); + } + +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java index b3e7c3bd41545e07b344406d00b29e9daecd0aab..0c1a74dbcf4ba4a702ca70f87d3950cb075b26cb 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java @@ -1,12 +1,13 @@ package at.tuwien.gateway.impl; -import at.tuwien.exception.*; +import at.tuwien.exception.SidecarExportException; +import at.tuwien.exception.SidecarImportException; +import at.tuwien.exception.StorageNotFoundException; import at.tuwien.gateway.DataDatabaseSidecarGateway; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.stereotype.Service; -import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @@ -23,44 +24,38 @@ public class DataDatabaseSidecarGatewayImpl implements DataDatabaseSidecarGatewa } @Override - public void importFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - RemoteUnavailableException, ServiceException { + public void importFile(String hostname, Integer port, String filename) throws SidecarImportException, + StorageNotFoundException { final ResponseEntity<Void> response; final String url = "http://" + hostname + ":" + port + "/sidecar/import/" + filename; log.debug("import file into data database sidecar"); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(null), Void.class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to import dataset with filename: {}: {}", filename, e.getMessage()); - throw new RemoteUnavailableException("Failed to import dataset: " + e.getMessage(), e); - } catch (HttpClientErrorException.BadRequest e) { - log.error("Failed to import dataset with filename: {}: not found: {}", filename, e.getMessage()); - throw new StorageNotFoundException("Failed to import dataset: not found: " + e.getMessage(), e); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to import .csv in data-db sidecar: {}", e.getMessage()); + throw new StorageNotFoundException("Failed to import .csv in data-db sidecar: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { - log.error("Failed to import dataset with filename: {}: service responded unsuccessful: {}", filename, response.getStatusCode()); - throw new ServiceException("Failed to import dataset: service responded unsuccessful: " + response.getStatusCode()); + log.error("Failed to import .csv in data-db sidecar"); + throw new SidecarImportException("Failed to import .csv in data-db sidecar"); } } @Override public void exportFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - RemoteUnavailableException, ServiceException { + SidecarExportException { final ResponseEntity<Void> response; final String url = "http://" + hostname + ":" + port + "/sidecar/export/" + filename; - log.debug("export file from data database sidecar: {}", url); + log.debug("export file into data database sidecar: {}", url); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(null), Void.class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to export dataset with filename: {}: {}", filename, e.getMessage()); - throw new RemoteUnavailableException("Failed to export dataset: " + e.getMessage(), e); - } catch (HttpClientErrorException.BadRequest e) { - log.error("Failed to export dataset with filename: {}: not found: {}", filename, e.getMessage()); - throw new StorageNotFoundException("Failed to export dataset: not found: " + e.getMessage(), e); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to export .csv in data-db sidecar: {}", e.getMessage()); + throw new StorageNotFoundException("Failed to export .csv in data-db sidecar: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { - log.error("Failed to export dataset with filename: {}: service responded unsuccessful: {}", filename, response.getStatusCode()); - throw new ServiceException("Failed to export dataset: service responded unsuccessful: " + response.getStatusCode()); + log.error("Failed to export .csv in data-db sidecar"); + throw new SidecarExportException("Failed to export .csv in data-db sidecar"); } } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index 545e259097951b3ed79d34c73bef72ccd2270b6b..76f3e83cef138b8d64151757e303fd05555a4591 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -2,12 +2,10 @@ package at.tuwien.gateway.impl; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.config.KeycloakConfig; -import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.ServiceConnectionException; import at.tuwien.exception.ServiceException; import at.tuwien.gateway.KeycloakGateway; import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.*; import org.springframework.stereotype.Service; @@ -24,14 +22,37 @@ public class KeycloakGatewayImpl implements KeycloakGateway { private final RestTemplate restTemplate; private final KeycloakConfig keycloakConfig; - @Autowired - public KeycloakGatewayImpl(RestTemplate restTemplate, KeycloakConfig keycloakConfig) { + public KeycloakGatewayImpl(@Qualifier("keycloakRestTemplate") RestTemplate restTemplate, + KeycloakConfig keycloakConfig) { this.restTemplate = restTemplate; this.keycloakConfig = keycloakConfig; } + public TokenDto obtainToken() throws ServiceConnectionException, ServiceException { + final HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); + payload.add("username", keycloakConfig.getKeycloakUsername()); + payload.add("password", keycloakConfig.getKeycloakPassword()); + payload.add("grant_type", "password"); + payload.add("client_id", "admin-cli"); + final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/master/protocol/openid-connect/token"; + log.debug("request admin token from url {}", url); + final ResponseEntity<TokenDto> response; + try { + response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to obtain admin token: {}", e.getMessage()); + throw new ServiceConnectionException("Failed to obtain admin token: " + e.getMessage(), e); + } catch (Exception e) { + log.error("Failed to obtain admin token: remote host answered unexpected: {}", e.getMessage(), e); + throw new ServiceException("Failed to obtain admin token: remote host answered unexpected: " + e.getMessage(), e); + } + return response.getBody(); + } + @Override - public TokenDto obtainUserToken(String username, String password) throws RemoteUnavailableException, ServiceException { + public TokenDto obtainUserToken(String username, String password) throws ServiceConnectionException, ServiceException { final HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); @@ -45,18 +66,15 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.debug("request user token from url {}", url); final ResponseEntity<TokenDto> response; try { - response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); - } catch (HttpServerErrorException e) { + response = new RestTemplate() + .exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { log.error("Failed to obtain user token: {}", e.getMessage()); - throw new RemoteUnavailableException("Failed to obtain user token: " + e.getMessage(), e); + throw new ServiceConnectionException("Failed to obtain user token: " + e.getMessage(), e); } catch (Exception e) { log.error("Failed to obtain user token: unexpected response: {}", e.getMessage(), e); throw new ServiceException("Failed to obtain user token: unexpected response: " + e.getMessage(), e); } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to obtain user token: service responded unsuccessful: {}", response.getStatusCode()); - throw new ServiceException("obtain user token: service responded unsuccessful: " + response.getStatusCode()); - } return response.getBody(); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java index 1fcf3e50ee3df4487eae8492867aa4952413c699..cb3c57b3325e589379f07e4116eb3c6f68d023e5 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java @@ -15,7 +15,6 @@ import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.mapper.MetadataMapper; -import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; @@ -46,29 +45,17 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public PrivilegedContainerDto getContainerById(Long containerId) throws RemoteUnavailableException, - ContainerNotFoundException, ServiceException { + ContainerNotFoundException { final ResponseEntity<ContainerDto> response; try { - response = restTemplate.exchange("/api/container/" + containerId, HttpMethod.GET, HttpEntity.EMPTY, + response = restTemplate.exchange("/api/container/" + containerId, HttpMethod.GET, new HttpEntity<>(null), ContainerDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to find container with id {}: {}", containerId, e.getMessage()); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to find container: {}", e.getMessage()); throw new RemoteUnavailableException("Failed to find container: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to find container with id {}: {}", containerId, e.getMessage()); - throw new ContainerNotFoundException("Failed to find container: " + e.getMessage()); - } - if (response.getStatusCode() != HttpStatus.OK) { - log.error("Failed to find container with id {}: service responded unsuccessful: {}", containerId, response.getStatusCode()); - throw new ServiceException("Failed to find container: service responded unsuccessful: " + response.getStatusCode()); - } - if (!response.getHeaders().keySet().containsAll(List.of("X-Username", "X-Password"))) { - log.error("Failed to find all privileged container headers"); - throw new ServiceException("Failed to find all privileged container headers"); - } - if (response.getBody() == null) { - log.error("Failed to find container with id {}: body is empty", containerId); - throw new ServiceException("Failed to find container with id " + containerId + ": body is empty"); + log.error("Failed to find container: body is null"); + throw new ContainerNotFoundException("Failed to find container: body is null"); } final PrivilegedContainerDto container = metadataMapper.containerDtoToPrivilegedContainerDto(response.getBody()); container.setUsername(response.getHeaders().get("X-Username").get(0)); @@ -77,83 +64,89 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } @Override - public PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + public List<PrivilegedDatabaseDto> getDatabases() throws RemoteUnavailableException { + final ResponseEntity<PrivilegedDatabaseDto[]> response; + try { + response = restTemplate.exchange("/api/database", HttpMethod.GET, new HttpEntity<>(null), + PrivilegedDatabaseDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to find databases: {}", e.getMessage()); + throw new RemoteUnavailableException("Failed to find databases: " + e.getMessage(), e); + } + if (response.getBody() == null) { + log.error("Failed to find databases: body is null"); + throw new RemoteUnavailableException("Failed to find databases: body is null"); + } + return List.of(response.getBody()); + } + + @Override + public void updateTableStatistics(Long databaseId, Long tableId, TableStatisticDto data) + throws RemoteUnavailableException { + final ResponseEntity<Void> response; + try { + response = restTemplate.exchange("/api/database/" + databaseId + "/table/" + tableId, HttpMethod.PUT, + new HttpEntity<>(data), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to update table statistics: {}", e.getMessage()); + throw new RemoteUnavailableException("Failed to update table statistics: " + e.getMessage(), e); + } + if (response.getStatusCode() != HttpStatus.ACCEPTED) { + log.error("Failed to update table statistics: unexpected status code"); + throw new RemoteUnavailableException("Failed to update table statistics: unexpected status code"); + } + } + + @Override + public PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException { final ResponseEntity<PrivilegedDatabaseDto> response; try { - response = restTemplate.exchange("/api/database/" + id, HttpMethod.GET, HttpEntity.EMPTY, + response = restTemplate.exchange("/api/database/" + id, HttpMethod.GET, new HttpEntity<>(null), PrivilegedDatabaseDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { log.error("Failed to find database with id {}: {}", id, e.getMessage()); - throw new RemoteUnavailableException("Failed to find database: " + e.getMessage(), e); + throw new RemoteUnavailableException("Failed to find database with id " + id + ": " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to find database with id {}: body is null", id); - throw new DatabaseNotFoundException("Failed to find database: body is null", e); - } - if (response.getStatusCode() != HttpStatus.OK) { - log.error("Failed to find database with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); - throw new ServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode()); - } - if (!response.getHeaders().keySet().containsAll(List.of("X-Username", "X-Password"))) { - log.error("Failed to find all privileged database headers"); - throw new ServiceException("Failed to find all privileged database headers"); - } - if (response.getBody() == null) { - log.error("Failed to find database with id {}: body is empty", id); - throw new ServiceException("Failed to find database with id " + id + ": body is empty"); + throw new DatabaseNotFoundException("Failed to find database id " + id + ": body is null", e); } final PrivilegedDatabaseDto database = response.getBody(); database.getContainer().setUsername(response.getHeaders().get("X-Username").get(0)); database.getContainer().setPassword(response.getHeaders().get("X-Password").get(0)); - log.debug("found privileged database username={}", database.getContainer().getUsername()); + log.debug("found privileged database username={}, password={}", database.getContainer().getUsername(), + database.getContainer().getPassword().isEmpty() ? "(empty)" : "(hidden)"); return database; } @Override public PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException { final ResponseEntity<PrivilegedDatabaseDto[]> response; try { - response = restTemplate.exchange("/api/database/", HttpMethod.GET, HttpEntity.EMPTY, PrivilegedDatabaseDto[].class); - } catch (ResourceAccessException | HttpServerErrorException e) { + response = restTemplate.exchange("/api/database/", HttpMethod.GET, new HttpEntity<>(null), PrivilegedDatabaseDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { log.error("Failed to find database with internal name {}: {}", internalName, e.getMessage()); - throw new RemoteUnavailableException("Failed to find database: " + e.getMessage(), e); + throw new RemoteUnavailableException("Failed to find database with internal name " + internalName + ": " + e.getMessage(), e); } - if (!response.getStatusCode().equals(HttpStatus.OK) || response.getBody() == null) { - log.error("Failed to find database with internal name {}: service responded unsuccessful: {}", internalName, response.getStatusCode()); - throw new ServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode()); - } - if (response.getBody().length != 1) { - log.error("Failed to find database with internal name {}: body is empty", internalName); - throw new DatabaseNotFoundException("Failed to find database: body is empty"); + if (response.getBody() == null || response.getBody().length != 1) { + log.error("Failed to find database with internal name {}: body is null", internalName); + throw new DatabaseNotFoundException("Failed to find database with internal name " + internalName + ": body is null"); } return response.getBody()[0]; } @Override - public PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + public PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException, RemoteUnavailableException { final ResponseEntity<TableDto> response; try { - response = restTemplate.exchange("/api/database/" + databaseId + "/table/" + id, HttpMethod.GET, HttpEntity.EMPTY, TableDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { + response = restTemplate.exchange("/api/database/" + databaseId + "/table/" + id, HttpMethod.GET, new HttpEntity<>(null), TableDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { log.error("Failed to find table with id {}: {}", id, e.getMessage()); - throw new RemoteUnavailableException("Failed to find table: " + e.getMessage(), e); - } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to find table with id {}: not found: {}", id, e.getMessage()); - throw new TableNotFoundException("Failed to find table: " + e.getMessage()); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to find table with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); - throw new ServiceException("Failed to find table: service responded unsuccessful: " + response.getStatusCode()); - } - if (!response.getHeaders().keySet().containsAll(List.of("X-Type", "X-Host", "X-Port", "X-Username", "X-Password", "X-Database", "X-Sidecar-Host", "X-Sidecar-Port"))) { - log.error("Failed to find all privileged table headers"); - throw new ServiceException("Failed to find all privileged table headers"); + throw new RemoteUnavailableException("Failed to find table with id " + id + ": " + e.getMessage(), e); } if (response.getBody() == null) { - log.error("Failed to find table with id {}: body is empty", id); - throw new ServiceException("Failed to find table with id " + id + ": body is empty"); + log.error("Failed to find table with id {}: body is null", id); + throw new TableNotFoundException("Failed to find table with id " + id + ": body is null"); } final PrivilegedTableDto table = metadataMapper.tableDtoToPrivilegedTableDto(response.getBody()); table.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Type").get(0)); @@ -164,34 +157,24 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { table.getDatabase().setInternalName(response.getHeaders().get("X-Database").get(0)); table.getDatabase().getContainer().setSidecarHost(response.getHeaders().get("X-Sidecar-Host").get(0)); table.getDatabase().getContainer().setSidecarPort(Integer.parseInt(response.getHeaders().get("X-Sidecar-Port").get(0))); - log.debug("found privileged database username={}", table.getDatabase().getContainer().getUsername()); + log.debug("found privileged database username={}, password={}", + table.getDatabase().getContainer().getUsername(), + table.getDatabase().getContainer().getPassword().isEmpty() ? "(empty)" : "(hidden)"); return table; } @Override - public PrivilegedViewDto getViewById(Long databaseId, Long id) throws RemoteUnavailableException, - ViewNotFoundException, ServiceException { + public PrivilegedViewDto getViewById(Long databaseId, Long id) throws RemoteUnavailableException, ViewNotFoundException { final ResponseEntity<ViewDto> response; try { - response = restTemplate.exchange("/api/database/" + databaseId + "/view/" + id, HttpMethod.GET, HttpEntity.EMPTY, ViewDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { + response = restTemplate.exchange("/api/database/" + databaseId + "/view/" + id, HttpMethod.GET, new HttpEntity<>(null), ViewDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { log.error("Failed to find view with id {}: {}", id, e.getMessage()); - throw new RemoteUnavailableException("Failed to find view: " + e.getMessage(), e); - } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to find view with id {}: not found: {}", id, e.getMessage()); - throw new ViewNotFoundException("Failed to find view: " + e.getMessage()); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to find view with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); - throw new ServiceException("Failed to find view: service responded unsuccessful: " + response.getStatusCode()); - } - if (!response.getHeaders().keySet().containsAll(List.of("X-Type", "X-Host", "X-Port", "X-Username", "X-Password", "X-Database"))) { - log.error("Failed to find all privileged view headers"); - throw new ServiceException("Failed to find all privileged view headers"); + throw new RemoteUnavailableException("Failed to find view with id " + id + ": " + e.getMessage(), e); } if (response.getBody() == null) { - log.error("Failed to find view with id {}: body is empty", id); - throw new ServiceException("Failed to find view with id " + id + ": body is empty"); + log.error("Failed to find view with id {}: body is null", id); + throw new ViewNotFoundException("Failed to find view with id " + id + ": body is null"); } final PrivilegedViewDto table = metadataMapper.viewDtoToPrivilegedViewDto(response.getBody()); table.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Type").get(0)); @@ -204,128 +187,101 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } @Override - public UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, - ServiceException { - final ResponseEntity<UserDto> response; + public PrivilegedUserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException { + final ResponseEntity<PrivilegedUserDto> response; try { - response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { + response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, new HttpEntity<>(null), PrivilegedUserDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { log.error("Failed to find user with id {}: {}", userId, e.getMessage()); - throw new RemoteUnavailableException("Failed to find user: " + e.getMessage(), e); - } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to find user with id {}: not found: {}", userId, e.getMessage()); - throw new UserNotFoundException("Failed to find user: " + e.getMessage()); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to find user with id {}: service responded unsuccessful: {}", userId, response.getStatusCode()); - throw new ServiceException("Failed to find user: service responded unsuccessful: " + response.getStatusCode()); + throw new RemoteUnavailableException("Failed to find user with id " + userId + ": " + e.getMessage(), e); } if (response.getBody() == null) { - log.error("Failed to find user with id {}: body is empty", userId); - throw new ServiceException("Failed to find user with id " + userId + ": body is empty"); + log.error("Failed to find user: body is null"); + throw new UserNotFoundException("Failed to find user: body is null"); } return response.getBody(); } @Override - public PrivilegedUserDto getPrivilegedUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, - ServiceException { - final ResponseEntity<UserDto> response; + public DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, + NotAllowedException { + final ResponseEntity<DatabaseAccessDto> response; try { - response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to find user with id {}: {}", userId, e.getMessage()); - throw new RemoteUnavailableException("Failed to find user: " + e.getMessage(), e); + response = restTemplate.exchange("/api/database/" + databaseId + "/access/" + userId, HttpMethod.GET, new HttpEntity<>(null), DatabaseAccessDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to find database access for user with id {}: {}", userId, e.getMessage()); + throw new RemoteUnavailableException("Failed to find database access", e); + } catch (HttpClientErrorException.Forbidden e) { + log.error("Failed to find database access for user with id {}: foreign user: {}", userId, e.getMessage()); + throw new NotAllowedException("Failed to find database access: foreign user", e); } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to find user with id {}: not found: {}", userId, e.getMessage()); - throw new UserNotFoundException("Failed to find user: " + e.getMessage()); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to find user with id {}: service responded unsuccessful: {}", userId, response.getStatusCode()); - throw new ServiceException("Failed to find user: service responded unsuccessful: " + response.getStatusCode()); - } - if (!response.getHeaders().keySet().containsAll(List.of("X-Username", "X-Password"))) { - log.error("Failed to find all privileged user headers"); - throw new ServiceException("Failed to find all privileged user headers"); + log.error("Failed to find database access for user with id {}: missing access: {}", userId, e.getMessage()); + throw new NotAllowedException("Failed to find database access: missing access", e); } if (response.getBody() == null) { - log.error("Failed to find user with id {}: body is empty", userId); - throw new ServiceException("Failed to find user with id " + userId + ": body is empty"); + log.error("Failed to find database access: body is null"); + throw new NotAllowedException("Failed to find database access: body is null"); } - final PrivilegedUserDto user = metadataMapper.userDtoToPrivilegedUserDto(response.getBody()); - user.setUsername(response.getHeaders().get("X-Username").get(0)); - user.setPassword(response.getHeaders().get("X-Password").get(0)); - return user; + return response.getBody(); } @Override - public DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, - NotAllowedException, ServiceException { - final ResponseEntity<DatabaseAccessDto> response; + public List<IdentifierDto> getIdentifiers(Long databaseId, Long subsetId) throws RemoteUnavailableException, + NotAllowedException { + final ResponseEntity<IdentifierDto[]> response; + final String url = "/api/identifier?dbid=" + databaseId + "&qid=" + subsetId; + log.trace("mapped url: {}", url); try { - response = restTemplate.exchange("/api/database/" + databaseId + "/access/" + userId, HttpMethod.GET, HttpEntity.EMPTY, DatabaseAccessDto.class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to find database access for user with id {}: {}", userId, e.getMessage()); - throw new RemoteUnavailableException("Failed to find database access: " + e.getMessage(), e); - } catch (HttpClientErrorException.Forbidden | HttpClientErrorException.NotFound e) { - log.error("Failed to find database access for user with id {}: foreign user: {}", userId, e.getMessage()); - throw new NotAllowedException("Failed to find database access: foreign user: " + e.getMessage(), e); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to find database access for user with id {}: service responded unsuccessful: {}", userId, response.getStatusCode()); - throw new ServiceException("Failed to find database access: service responded unsuccessful: " + response.getStatusCode()); + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), IdentifierDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to find identifiers for database with id {} and subset with id {}: {}", databaseId, subsetId, e.getMessage()); + throw new RemoteUnavailableException("Failed to find identifiers", e); } if (response.getBody() == null) { - log.error("Failed to find database access: body is empty"); - throw new ServiceException("Failed to find database access: body is empty"); + log.error("Failed to find identifiers: body is null"); + throw new NotAllowedException("Failed to find identifiers: body is null"); } - return response.getBody(); + return List.of(response.getBody()); } @Override - public List<IdentifierDto> getIdentifiers(@NotNull Long databaseId, Long subsetId) throws ServiceException, - RemoteUnavailableException, DatabaseNotFoundException { + public List<IdentifierDto> getIdentifiers(Long databaseId) throws RemoteUnavailableException, + NotAllowedException { final ResponseEntity<IdentifierDto[]> response; - final String url = "/api/identifier?dbid=" + databaseId + (subsetId != null ? ("&qid=" + subsetId) : ""); + final String url = "/api/identifier?dbid=" + databaseId; log.trace("mapped url: {}", url); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, IdentifierDto[].class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to find identifiers for database with id {} and subset with id {}: {}", databaseId, subsetId, e.getMessage()); - throw new RemoteUnavailableException("Failed to find identifiers: " + e.getMessage(), e); - } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to find identifiers for database with id {} and subset with id {}: foreign user: {}", databaseId, subsetId, e.getMessage()); - throw new DatabaseNotFoundException("Failed to find identifiers: foreign user: " + e.getMessage(), e); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to find identifiers for database with id {} and subset with id {}: service responded unsuccessful: {}", databaseId, subsetId, response.getStatusCode()); - throw new ServiceException("Failed to find identifiers for database: service responded unsuccessful: " + response.getStatusCode()); + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), IdentifierDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to find identifiers for database with id {}: {}", databaseId, e.getMessage()); + throw new RemoteUnavailableException("Failed to find identifiers", e); } if (response.getBody() == null) { log.error("Failed to find identifiers: body is null"); - throw new ServiceException("Failed to find identifiers: body is null"); + throw new NotAllowedException("Failed to find identifiers: body is null"); } return List.of(response.getBody()); } @Override - public void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, ServiceException, - RemoteUnavailableException { - final ResponseEntity<Void> response; - final String url = "/api/database/" + databaseId + "/table/" + tableId; + public UserDto getUser(UUID userId) throws RemoteUnavailableException, NotAllowedException, UserNotFoundException { + final ResponseEntity<UserDto> response; + final String url = "/api/user/" + userId; + log.trace("mapped url: {}", url); try { - response = restTemplate.exchange(url, HttpMethod.PUT, HttpEntity.EMPTY, Void.class); - } catch (ResourceAccessException | HttpServerErrorException e) { - log.error("Failed to update table statistic for table with id {}: {}", tableId, e.getMessage()); - throw new RemoteUnavailableException("Failed to update table statistic: " + e.getMessage(), e); + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), UserDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to find user with id {}: {}", userId, e.getMessage()); + throw new RemoteUnavailableException("Failed to find user", e); } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to update table statistic for table with id {}: foreign user: {}", tableId, e.getMessage()); - throw new TableNotFoundException("Failed to update table statistic: foreign user: " + e.getMessage(), e); + log.error("Failed to find user with id {}: not found: {}", userId, e.getMessage()); + throw new UserNotFoundException("Failed to find user: not found", e); } - if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { - log.error("Failed to update table statistic for table with id {}: service responded unsuccessful: {}", tableId, response.getStatusCode()); - throw new ServiceException("Failed to update table statistic for database: service responded unsuccessful: " + response.getStatusCode()); + if (response.getBody() == null) { + log.error("Failed to find identifiers: body is null"); + throw new NotAllowedException("Failed to find identifiers: body is null"); } + return response.getBody(); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java index 89b18b3275323545e0defadc3e8b851ada914072..c9e5bda2705d1d6822c1fbffe9fae167a2468858 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java @@ -66,7 +66,7 @@ public class DefaultListener implements MessageListener { log.error("Failed to read object: {}", e.getMessage()); } catch (SQLException | RemoteUnavailableException e) { log.error("Failed to insert tuple: {}", e.getMessage()); - } catch (TableNotFoundException | ServiceException e) { + } catch (TableNotFoundException e) { log.error("Failed to find table: {}", e.getMessage()); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 28204fbe2fa97f8f72e15ed9becc41b6424730f7..e28d05929b51ff1376aaceb2ca39a4ff4b6783f8 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -8,18 +8,16 @@ import at.tuwien.api.database.query.ImportCsvDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.database.table.*; -import at.tuwien.api.database.table.columns.*; +import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.tuwien.api.database.table.columns.ColumnCreateDto; +import at.tuwien.api.database.table.columns.ColumnDto; +import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyBriefDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; -import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; import at.tuwien.config.QueryConfig; import at.tuwien.exception.*; -import at.tuwien.utils.MariaDbUtil; import com.github.dockerjava.zerodep.shaded.org.apache.commons.codec.binary.Hex; import com.google.common.hash.Hashing; import net.sf.jsqlparser.JSQLParserException; @@ -28,8 +26,6 @@ import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.select.*; import org.jetbrains.annotations.NotNull; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import org.mapstruct.Named; import javax.swing.table.TableColumn; @@ -69,45 +65,6 @@ public interface MariaDbMapper { return slug.toLowerCase(Locale.ENGLISH); } - default String databaseSetPasswordQuery(String username, String password) { - final StringBuilder statement = new StringBuilder("ALTER USER `") - .append(username) - .append("`@`%` IDENTIFIED BY '") - .append(password) - .append("';"); - log.trace("mapped set password statement: {}", statement); - return statement.toString(); - } - - default String databaseCreateUserQuery(String username, String password) { - final StringBuilder statement = new StringBuilder("CREATE USER IF NOT EXISTS `") - .append(username) - .append("`@`%` IDENTIFIED BY PASSWORD '") - .append(password) - .append("';"); - log.trace("mapped create user statement: {}", statement); - return statement.toString(); - } - - default String databaseGrantPrivilegesQuery(String username, String grants) { - final StringBuilder statement = new StringBuilder("GRANT ") - .append(grants) - .append(" ON *.* TO `") - .append(username) - .append("`@`%`;"); - log.trace("mapped grant privileges statement: {}", statement); - return statement.toString(); - } - - @Named("createDatabase") - default String databaseCreateDatabaseQuery(String database) { - final StringBuilder statement = new StringBuilder("CREATE DATABASE `") - .append(database) - .append("`"); - log.trace("mapped create database statement: {}", statement); - return statement.toString(); - } - default QueryResultDto resultListToQueryResultDto(List<ColumnDto> columns, ResultSet result) throws SQLException { log.trace("mapping result list to query result, columns.size={}", columns.size()); final List<Map<String, Object>> resultList = new LinkedList<>(); @@ -152,13 +109,13 @@ public interface MariaDbMapper { } default String databaseTablesSelectRawQuery() { - final String statement = "SELECT DISTINCT t.`TABLE_NAME` FROM information_schema.TABLES t WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'SYSTEM VERSIONED' AND t.`TABLE_NAME` != 'qs_queries' ORDER BY t.`TABLE_NAME` ASC"; + final String statement = "SELECT DISTINCT t.`TABLE_NAME` FROM information_schema.TABLES t WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'SYSTEM VERSIONED' AND t.`TABLE_NAME` != 'qs_queries'"; log.trace("mapped select tables statement: {}", statement); return statement; } default String databaseTableSelectRawQuery() { - final String statement = "SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION`, t.`TABLE_COMMENT` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'SYSTEM VERSIONED' AND t.`TABLE_NAME` != 'qs_queries' AND t.`TABLE_NAME` = ?"; + final String statement = "SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'SYSTEM VERSIONED' AND t.`TABLE_NAME` != 'qs_queries' AND t.`TABLE_NAME` = ?"; log.trace("mapped select table statement: {}", statement); return statement; } @@ -176,13 +133,13 @@ public interface MariaDbMapper { } default String databaseTableColumnsSelectRawQuery() { - final String statement = "SELECT `ORDINAL_POSITION`, `COLUMN_DEFAULT`, `IS_NULLABLE`, `DATA_TYPE`, `CHARACTER_MAXIMUM_LENGTH`, `NUMERIC_PRECISION`, `NUMERIC_SCALE`, `COLUMN_TYPE`, `COLUMN_KEY`, `COLUMN_NAME`, IF(`COLUMN_COMMENT`='',NULL,`COLUMN_COMMENT`) AS `COLUMN_COMMENT` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?;"; + final String statement = "SELECT `ORDINAL_POSITION`, `COLUMN_DEFAULT`, `IS_NULLABLE`, `DATA_TYPE`, `CHARACTER_MAXIMUM_LENGTH`, `NUMERIC_PRECISION`, `NUMERIC_SCALE`, `COLUMN_TYPE`, `COLUMN_KEY`, `COLUMN_NAME`, `COLUMN_COMMENT` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?;"; log.trace("mapped select columns statement: {}", statement); return statement; } default String databaseTableConstraintsSelectRawQuery() { - final String statement = "SELECT k.`ORDINAL_POSITION`, c.`CONSTRAINT_TYPE`, k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, k.`REFERENCED_COLUMN_NAME`, r.`DELETE_RULE`, r.`UPDATE_RULE` FROM information_schema.TABLE_CONSTRAINTS c JOIN information_schema.KEY_COLUMN_USAGE k ON c.`TABLE_NAME` = k.`TABLE_NAME` AND c.`CONSTRAINT_NAME` = k.`CONSTRAINT_NAME` LEFT JOIN information_schema.REFERENTIAL_CONSTRAINTS r ON r.`CONSTRAINT_NAME` = k.`CONSTRAINT_NAME` WHERE LOWER(k.`COLUMN_NAME`) != 'row_end' AND c.`TABLE_SCHEMA` = ? AND c.`TABLE_NAME` = ? ORDER BY k.`ORDINAL_POSITION` ASC;"; + final String statement = "SELECT k.`ORDINAL_POSITION`, c.`CONSTRAINT_TYPE`, k.`CONSTRAINT_NAME`, k.`COLUMN_NAME` FROM information_schema.TABLE_CONSTRAINTS c JOIN information_schema.KEY_COLUMN_USAGE k ON c.`TABLE_NAME` = k.`TABLE_NAME` AND c.`CONSTRAINT_NAME` = k.`CONSTRAINT_NAME`WHERE c.`CONSTRAINT_TYPE` = 'UNIQUE' AND LOWER(k.`COLUMN_NAME`) != 'row_end' AND c.`TABLE_SCHEMA` = ? AND c.`TABLE_NAME` = ? ORDER BY k.`ORDINAL_POSITION` ASC;"; log.trace("mapped select table constraints statement: {}", statement); return statement; } @@ -200,9 +157,7 @@ public interface MariaDbMapper { } default String tableCreateDtoToCreateSequenceRawQuery(at.tuwien.api.database.table.internal.TableCreateDto data) { - final String statement = "CREATE SEQUENCE IF NOT EXISTS `" + tableCreateDtoToSequenceName(data) + "` NOCACHE"; - log.trace("mapped create sequence statement: {}", statement); - return statement; + return "CREATE SEQUENCE IF NOT EXISTS `" + tableCreateDtoToSequenceName(data) + "` NOCACHE"; } default String filterToGetQueriesRawQuery(Boolean filterPersisted) { @@ -257,31 +212,6 @@ public interface MariaDbMapper { return ""; } - default String tableColumnStatisticsSelectRawQuery(List<ColumnDto> data, String table) { - final StringBuilder statement = new StringBuilder(); - final int[] idx = new int[]{0}; - data.stream() - .filter(column -> MariaDbUtil.numericDataTypes.contains(column.getColumnType())) - .forEach(column -> statement.append(idx[0]++ > 0 ? " UNION " : "") - .append("SELECT '") - .append(column.getInternalName()) - .append("' as name, MIN(`") - .append(column.getInternalName()) - .append("`) as min, MAX(`") - .append(column.getInternalName()) - .append("`) as max, MEDIAN(`") - .append(column.getInternalName()) - .append("`) OVER () as median, AVG(`") - .append(column.getInternalName()) - .append("`) as mean, STDDEV(`") - .append(column.getInternalName()) - .append("`) as std_dev FROM ") - .append(table)); - statement.append(";"); - log.trace("mapped select column statistic statement: {}", statement); - return statement.toString(); - } - default String tableCreateDtoToCreateTableRawQuery(at.tuwien.api.database.table.internal.TableCreateDto data) { final StringBuilder stringBuilder = new StringBuilder("CREATE TABLE `") .append(nameToInternalName(data.getName())) @@ -308,25 +238,22 @@ public interface MariaDbMapper { } /* create primary key index */ + stringBuilder.append(", PRIMARY KEY (") + .append(String.join(",", data.getConstraints() + .getPrimaryKey() + .stream() + .map(c -> { + final Optional<ColumnCreateDto> optional = data.getColumns() + .stream() + .filter(cc -> cc.getName().equals(c)) + .findFirst(); + log.trace("lookup {} in columns: {}", c, data.getColumns().stream().map(ColumnCreateDto::getName).toList()); + return "`" + nameToInternalName(c) + "`" + columnCreateDtoToPrimaryKeyLengthSpecification(optional.get()); + }) + .toArray(String[]::new))) + .append(")"); if (data.getConstraints() != null) { log.trace("constraints are {}", data.getConstraints()); - if (data.getConstraints().getPrimaryKey() != null && !data.getConstraints().getPrimaryKey().isEmpty()) { - /* create primary key index */ - stringBuilder.append(", PRIMARY KEY (") - .append(String.join(",", data.getConstraints() - .getPrimaryKey() - .stream() - .map(c -> { - final Optional<ColumnCreateDto> optional = data.getColumns() - .stream() - .filter(cc -> cc.getName().equals(c)) - .findFirst(); - log.trace("lookup {} in columns: {}", c, data.getColumns().stream().map(ColumnCreateDto::getName).toList()); - return "`" + nameToInternalName(c) + "`" + columnCreateDtoToPrimaryKeyLengthSpecification(optional.get()); - }) - .toArray(String[]::new))) - .append(")"); - } if (data.getConstraints().getUniques() != null) { /* create unique indices */ data.getConstraints().getUniques() @@ -362,16 +289,15 @@ public interface MariaDbMapper { .append(ck) .append(")")); } + if (data.getDescription() != null && !data.getDescription().isBlank()) { + /* create table comments */ + stringBuilder.append(" COMMENT \"") + .append(data.getDescription()) + .append("\""); + } } - stringBuilder.append(") WITH SYSTEM VERSIONING"); - if (data.getDescription() != null && !data.getDescription().isBlank()) { - /* create table comments */ - stringBuilder.append(" COMMENT \"") - .append(data.getDescription()) - .append("\""); - } - stringBuilder.append(";"); - log.trace("mapped create table statement: {}", stringBuilder); + stringBuilder.append(") WITH SYSTEM VERSIONING;"); + log.trace("mapped create table query: {}", stringBuilder); return stringBuilder.toString(); } @@ -405,23 +331,6 @@ public interface MariaDbMapper { return data.getLong(1); } - default TableStatisticDto resultSetToTableStatistic(ResultSet data) throws SQLException { - final TableStatisticDto statistic = TableStatisticDto.builder() - .columns(new LinkedHashMap<>()) - .build(); - while (data.next()) { - final ColumnStatisticDto columnStatistic = ColumnStatisticDto.builder() - .min(data.getBigDecimal(2)) - .max(data.getBigDecimal(3)) - .median(data.getBigDecimal(4)) - .mean(data.getBigDecimal(5)) - .stdDev(data.getBigDecimal(6)) - .build(); - statistic.getColumns().put(data.getString(1), columnStatistic); - } - return statistic; - } - /** * Selects the dataset page from a table/view. * @@ -479,9 +388,8 @@ public interface MariaDbMapper { return statement.toString(); } - @Named("dropTableQuery") default String dropTableRawQuery(String tableName) { - return "DROP TABLE `" + tableName + "`;"; + return "DROP TABLE IF EXISTS `" + tableName + "`;"; } default String tupleToRawInsertQuery(PrivilegedTableDto table, TupleDto data) throws TableMalformedException { @@ -493,17 +401,18 @@ public interface MariaDbMapper { final StringBuilder statement = new StringBuilder("INSERT INTO `") .append(table.getInternalName()) .append("` (") - .append(data.getData() - .keySet() + .append(table.getColumns() .stream() - .map(o -> "`" + o + "`") + .filter(column -> !column.getAutoGenerated()) + .map(column -> "`" + column.getInternalName() + "`") .collect(Collectors.joining(","))) - .append(") VALUES (") - .append(data.getData() - .keySet() - .stream() - .map(o -> "?") - .collect(Collectors.joining(","))); + .append(") VALUES ("); + final int[] idx = new int[]{1, 0}; + table.getColumns() + .stream() + .filter(c -> !c.getAutoGenerated()) + .forEach(c -> statement.append(idx[1]++ > 0 ? "," : "") + .append("?")); statement.append(");"); for (int i = 0; i < table.getColumns().size(); i++) { final ColumnDto column = table.getColumns() @@ -623,7 +532,6 @@ public interface MariaDbMapper { .tdbid(database.getId()) .queueName("dbrepo") .routingKey("dbrepo") - .description(resultSet.getString(10)) .columns(new LinkedList<>()) .identifiers(new LinkedList<>()) .creator(database.getOwner()) @@ -644,16 +552,10 @@ public interface MariaDbMapper { return table; } - ForeignKeyBriefDto foreignKeyDtoToForeignKeyBriefDto(ForeignKeyDto data); - default TableDto resultSetToConstraint(ResultSet resultSet, TableDto table) throws SQLException { final String type = resultSet.getString(2); final String name = resultSet.getString(3); final String columnName = resultSet.getString(4); - final String referencedTable = resultSet.getString(5); - final String referencedColumnName = resultSet.getString(6); - final ReferenceTypeDto deleteRule = resultSet.getString(7) != null ? ReferenceTypeDto.fromType(resultSet.getString(7)) : null; - final ReferenceTypeDto updateRule = resultSet.getString(8) != null ? ReferenceTypeDto.fromType(resultSet.getString(8)) : null; final Optional<ColumnDto> optional = table.getColumns().stream() .filter(c -> c.getInternalName().equals(columnName)) .findFirst(); @@ -662,7 +564,7 @@ public interface MariaDbMapper { throw new IllegalArgumentException("Failed to find table column"); } final ColumnDto column = optional.get(); - if (type.equals("FOREIGN KEY") || type.equals("UNIQUE")) { + if (type.equals("UNIQUE")) { final Optional<UniqueDto> optional2 = table.getConstraints().getUniques().stream().filter(u -> u.getName().equals(name)).findFirst(); if (optional2.isPresent()) { optional2.get() @@ -670,66 +572,17 @@ public interface MariaDbMapper { .add(column); return table; } - if (type.equals("UNIQUE")) { - table.getConstraints() - .getUniques() - .add(UniqueDto.builder() - .name(name) - .columns(new LinkedList<>(List.of(column))) - .build()); - return table; - } - final Optional<ForeignKeyDto> optional1 = table.getConstraints() - .getForeignKeys() - .stream() - .filter(fk -> fk.getName().equals(name)) - .findFirst(); - final ForeignKeyReferenceDto foreignKeyReference = ForeignKeyReferenceDto.builder() - .column(ColumnBriefDto.builder() - .name(columnName) - .internalName(columnName) - .databaseId(table.getTdbid()) - .build()) - .referencedColumn(ColumnBriefDto.builder() - .name(referencedColumnName) - .internalName(referencedColumnName) - .databaseId(table.getTdbid()) - .build()) - .build(); - if (optional1.isPresent()) { - foreignKeyReference.setForeignKey(foreignKeyDtoToForeignKeyBriefDto(optional1.get())); - optional1.get() - .getReferences() - .add(foreignKeyReference); - log.debug("found foreign key: create part ({}) referencing table {} ({})", columnName, referencedTable, referencedColumnName); - return table; - } - final ForeignKeyDto foreignKey = ForeignKeyDto.builder() - .name(name) - .table(tableDtoToTableBriefDto(table)) - .referencedTable(TableBriefDto.builder() - .name(referencedTable) - .internalName(referencedTable) - .databaseId(table.getTdbid()) - .build()) - .references(new LinkedList<>(List.of(foreignKeyReference))) - .onDelete(deleteRule) - .onUpdate(updateRule) - .build(); - foreignKey.getReferences() - .forEach(ref -> ref.setForeignKey(foreignKeyDtoToForeignKeyBriefDto(foreignKey))); table.getConstraints() - .getForeignKeys() - .add(foreignKey); - log.debug("create foreign key: add part ({}) referencing table {} ({})", columnName, referencedTable, referencedColumnName); + .getUniques() + .add(UniqueDto.builder() + .name(name) + .columns(new LinkedList<>(List.of(column))) + .build()); return table; } return table; } - @Mappings({ - @Mapping(target = "databaseId", source = "tdbid") - }) TableBriefDto tableDtoToTableBriefDto(TableDto data); ColumnBriefDto columnDtoToColumnBriefDto(ColumnDto data); @@ -815,7 +668,6 @@ public interface MariaDbMapper { } view.getColumns() .add(column); - log.trace("parsed view {}.{} column: {}", view.getDatabase().getInternalName(), view.getInternalName(), column.getInternalName()); return view; } @@ -868,12 +720,15 @@ public interface MariaDbMapper { statement.append("@") .append(column.getInternalName()); if (column.getDateFormat() != null) { + log.trace("import column has date format, need to format it differently"); /* reformat dates */ columnToDateSet(data, column, set); } else if (column.getColumnType().equals(ColumnTypeDto.BOOL)) { + log.trace("import column has boolean format, need to format it differently"); /* reformat booleans */ columnToBoolSet(data, column, set); } else { + log.trace("import column has text format"); /* reformat others */ columnToTextSet(data, column, set); } @@ -882,7 +737,6 @@ public interface MariaDbMapper { statement.append(")") .append(set.length() != 0 ? (" SET " + set) : "") .append(";"); - log.trace("mapped insert statement: {}", statement); return statement.toString(); } @@ -967,7 +821,7 @@ public interface MariaDbMapper { log.error("Failed to find table column {}", key); throw new IllegalArgumentException("Failed to find table column"); } - if (optional.get().getAutoGenerated()) { + if (optional.get().getAutoGenerated() || value == null) { return; } statement.append(idx[0]++ == 0 ? "" : ", ") @@ -986,7 +840,7 @@ public interface MariaDbMapper { log.error("Failed to find table column {}", key); throw new IllegalArgumentException("Failed to find table column"); } - if (optional.get().getAutoGenerated()) { + if (optional.get().getAutoGenerated() || value == null) { return; } statement.append(jdx[0]++ == 0 ? "" : ", ") @@ -998,12 +852,13 @@ public interface MariaDbMapper { } default void columnToDateSet(ImportCsvDto data, ColumnDto column, StringBuilder set) { - log.trace("import column has date format, need to format it: {}", column.getDateFormat().getUnixFormat()); + log.trace("mapping column to date set"); set.append(!set.isEmpty() ? ", " : "") .append("`") .append(column.getInternalName()) .append("` = STR_TO_DATE("); if (data.getNullElement() != null) { + log.trace("import has null element present"); set.append("IF(STRCMP(@") .append(column.getInternalName()) .append(",'") @@ -1027,11 +882,13 @@ public interface MariaDbMapper { } default void columnToBoolSet(ImportCsvDto data, ColumnDto column, StringBuilder set) { + log.trace("mapping column to bool set, data={}, column={}, set=(generated)", data, column); set.append(!set.isEmpty() ? ", " : "") .append("`") .append(column.getInternalName()) .append("` = "); if (data.getNullElement() != null) { + log.trace("import has null element present"); set.append("IF(!STRCMP(@") .append(column.getInternalName()) .append(",'") @@ -1045,7 +902,9 @@ public interface MariaDbMapper { } default void columnToBoolSet2(ImportCsvDto data, ColumnDto column, StringBuilder set) { + log.trace("mapping column to inner bool set, data={}, column={}, set=(generated)", data, column); if (data.getTrueElement() != null) { + log.trace("import has true element present"); set.append("IF(!STRCMP(@") .append(column.getInternalName()) .append(",'") @@ -1070,6 +929,7 @@ public interface MariaDbMapper { return; } if (data.getFalseElement() != null) { + log.trace("import has false element present"); set.append("IF(!STRCMP(@") .append(column.getInternalName()) .append(",'") @@ -1098,11 +958,13 @@ public interface MariaDbMapper { } default void columnToTextSet(ImportCsvDto data, ColumnDto column, StringBuilder set) { + log.trace("mapping column to text set"); set.append(!set.isEmpty() ? ", " : "") .append("`") .append(column.getInternalName()) .append("` = "); if (data.getNullElement() != null) { + log.trace("import has null element present"); set.append("IF(STRCMP(@") .append(column.getInternalName()) .append(",'") @@ -1117,11 +979,11 @@ public interface MariaDbMapper { } default void prepareStatementWithColumnTypeObject(PreparedStatement statement, ColumnTypeDto columnType, int idx, - String columnName, Object value) throws SQLException { + Object value) throws SQLException { switch (columnType) { case BLOB, TINYBLOB, MEDIUMBLOB, LONGBLOB: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.BLOB); break; } @@ -1130,26 +992,26 @@ public interface MariaDbMapper { try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { ois.writeObject(value); statement.setBlob(idx, new ByteArrayInputStream(boas.toByteArray())); - log.trace("prepare statement idx {} = {} blob", idx, columnName); + log.trace("prepare statement idx {} blob", idx); } } catch (IOException e) { - log.error("Failed to set blob/tinyblob/mediumblob/longblob: {}", e.getMessage()); + log.error("Failed to set blob: {}", e.getMessage()); throw new SQLException("Failed to set blob: " + e.getMessage(), e); } break; case TEXT, CHAR, VARCHAR, TINYTEXT, MEDIUMTEXT, LONGTEXT, ENUM, SET: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.VARCHAR); break; } - log.trace("prepare statement idx {} = {} text/char/varchar/tinytext/mediumtext/longtext/enum/set: {}", idx, columnName, value); + log.trace("prepare statement idx {} string: {}", idx, value); statement.setString(idx, String.valueOf(value)); break; case DATE: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.DATE); break; } @@ -1158,114 +1020,113 @@ public interface MariaDbMapper { break; case BIGINT: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.BIGINT); break; } - log.trace("prepare statement idx {} bigint: {}", idx, value); + log.trace("prepare statement idx {} long: {}", idx, value); statement.setLong(idx, Long.parseLong(String.valueOf(value))); break; case INT, MEDIUMINT: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.INTEGER); break; } - log.trace("prepare statement idx {} = {} int/mediumint: {}", idx, columnName, value); + log.trace("prepare statement idx {} long: {}", idx, value); statement.setLong(idx, Long.parseLong(String.valueOf(value))); break; case TINYINT: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.TINYINT); break; } - log.trace("prepare statement idx {} = {} tinyint: {}", idx, columnName, value); + log.trace("prepare statement idx {} long: {}", idx, value); statement.setLong(idx, Long.parseLong(String.valueOf(value))); break; case SMALLINT: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.SMALLINT); break; } - log.trace("prepare statement idx {} = {} smallint: {}", idx, columnName, value); + log.trace("prepare statement idx {} long: {}", idx, value); statement.setLong(idx, Long.parseLong(String.valueOf(value))); break; case DECIMAL: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.DECIMAL); break; } - log.trace("prepare statement idx {} = {} decimal: {}", idx, columnName, value); statement.setDouble(idx, Double.parseDouble(String.valueOf(value))); break; case FLOAT: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.FLOAT); break; } - log.trace("prepare statement idx {} = {} float: {}", idx, columnName, value); + log.trace("prepare statement idx {} double: {}", idx, value); statement.setDouble(idx, Double.parseDouble(String.valueOf(value))); break; case DOUBLE: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.DOUBLE); break; } - log.trace("prepare statement idx {} = {} double: {}", idx, columnName, value); + log.trace("prepare statement idx {} double: {}", idx, value); statement.setDouble(idx, Double.parseDouble(String.valueOf(value))); break; case BINARY, VARBINARY, BIT: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.DECIMAL); break; } - log.trace("prepare statement idx {} = {} binary/varbinary/bit", idx, columnName); statement.setBinaryStream(idx, (InputStream) value); + log.trace("prepare statement idx {} binary stream", idx); break; case BOOL: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.BOOLEAN); break; } - log.trace("prepare statement idx {} = {} bool: {}", idx, columnName, value); + log.trace("prepare statement idx {} bool: {}", idx, value); statement.setBoolean(idx, Boolean.parseBoolean(String.valueOf(value))); break; case TIMESTAMP, DATETIME: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.TIMESTAMP); break; } - log.trace("prepare statement idx {} timestamp/datetime: {}", idx, value); statement.setTimestamp(idx, Timestamp.valueOf(String.valueOf(value))); + log.trace("prepare statement idx {} timestamp: {}", idx, value); break; case TIME: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.TIME); break; } - log.trace("prepare statement idx {} = {} time: {}", idx, columnName, value); statement.setTime(idx, Time.valueOf(String.valueOf(value))); + log.trace("prepare statement idx {} time: {}", idx, value); break; case YEAR: if (value == null) { - log.trace("idx {} = {} is null, prepare with null value", idx, columnName); + log.trace("idx {} is null, prepare with null value", idx); statement.setNull(idx, Types.TIME); break; } - log.trace("prepare statement idx {} = {} year: {}", idx, columnName, value); + log.trace("prepare statement idx {} string: {}", idx, value); statement.setString(idx, String.valueOf(value)); break; default: - log.error("Failed to map column type {} at idx {} = {} for value {}", columnType, idx, columnName, value); + log.error("Failed to map column type {} at index {} for value {}", columnType, idx, value); throw new IllegalArgumentException("Failed to map column type " + columnType); } } @@ -1452,7 +1313,7 @@ public interface MariaDbMapper { } default boolean columnMatches(ColumnDto column, String tableOrView) { - if (column.getTable() != null && column.getTable().getInternalName().equals(tableOrView)) { + if (column.getTable().getInternalName().equals(tableOrView)) { log.trace("table '{}' found in column table", tableOrView); return true; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java index 4cde78c7d913108bdf9d3d0d1b13c541ca44724d..67633ba1757897a4a0f5619670e7990d9cd1559a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -12,8 +12,6 @@ import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; -import at.tuwien.api.user.PrivilegedUserDto; -import at.tuwien.api.user.UserDto; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; @@ -45,6 +43,4 @@ public interface MetadataMapper { ContainerDto privilegedContainerDtoToContainerDto(PrivilegedContainerDto data); - PrivilegedUserDto userDtoToPrivilegedUserDto(UserDto data); - } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java index a6d57dc8b6f27300c1ec960e2ea7f5ad3939ff52..ac86984f393e7e4a8db89f35524ed1cd98989447 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java @@ -3,42 +3,17 @@ package at.tuwien.service; import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.user.PrivilegedUserDto; -import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; import java.sql.SQLException; public interface AccessService { - - /** - * Create a user with access to a given database. - * @param database The database. - * @param user The user. - * @param access The access type. - * @throws SQLException The connection to the database could not be established. - * @throws DatabaseMalformedException The database schema is malformed. - */ void create(PrivilegedDatabaseDto database, PrivilegedUserDto user, AccessTypeDto access) throws SQLException, DatabaseMalformedException; - /** - * Update access to a given database for a given user. - * @param database The database. - * @param user The user. - * @param access The access type. - * @throws SQLException The connection to the database could not be established. - * @throws DatabaseMalformedException The database schema is malformed. - */ - void update(PrivilegedDatabaseDto database, UserDto user, AccessTypeDto access) throws SQLException, + void update(PrivilegedDatabaseDto database, PrivilegedUserDto user, AccessTypeDto access) throws SQLException, DatabaseMalformedException; - /** - * Revoke access to a given database for a given user. - * @param database The database. - * @param user The user. - * @throws SQLException The connection to the database could not be established. - * @throws DatabaseMalformedException The database schema is malformed. - */ - void delete(PrivilegedDatabaseDto database, UserDto user) throws SQLException, + void delete(PrivilegedDatabaseDto database, PrivilegedUserDto user) throws SQLException, DatabaseMalformedException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/AnalyseService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/AnalyseService.java new file mode 100644 index 0000000000000000000000000000000000000000..eb1c047b0560a238ad5dfa77f0eed32e5db6af2e --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/AnalyseService.java @@ -0,0 +1,11 @@ +package at.tuwien.service; + +import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.exception.NotAllowedException; +import at.tuwien.exception.RemoteUnavailableException; +import at.tuwien.exception.TableNotFoundException; + +public interface AnalyseService { + TableStatisticDto analyseTable(Long databaseId, Long tableId) throws TableNotFoundException, + NotAllowedException, RemoteUnavailableException; +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java index 271b2abb82918027053a357c648a1d2ac1926278..6c99910e67067502070d307fc55cb22b905b377e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java @@ -11,24 +11,9 @@ import java.sql.SQLException; public interface DatabaseService { - /** - * Creates a database in the given container. - * @param container The container. - * @param data The database metadata. - * @return The created database, if successful. - * @throws SQLException The connection to the database could not be established. - * @throws DatabaseMalformedException The database schema is malformed. - */ PrivilegedDatabaseDto create(PrivilegedContainerDto container, CreateDatabaseDto data) throws SQLException, DatabaseMalformedException; - /** - * Updates a user's password in a given database. - * @param database The database. - * @param data The user-password tuple. - * @throws SQLException The connection to the database could not be established. - * @throws DatabaseMalformedException The database schema is malformed. - */ void update(PrivilegedDatabaseDto database, UpdateUserPasswordDto data) throws SQLException, DatabaseMalformedException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java index 7c2575b9cc348724f801dfd7e67d322b5ddd2070..9c9bc25a71c33ac388feffbf79d195fa12933ab9 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java @@ -28,7 +28,7 @@ public interface SubsetService { QueryResultDto execute(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId, Long page, Long size, SortTypeDto sortDirection, String sortColumn) - throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException; + throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException, UserNotFoundException, NotAllowedException, RemoteUnavailableException; QueryResultDto reExecute(PrivilegedDatabaseDto database, QueryDto query, Long page, Long size, SortTypeDto sortDirection, String sortColumn) throws TableMalformedException, @@ -45,11 +45,11 @@ public interface SubsetService { * @return The list of queries. */ List<QueryDto> findAll(PrivilegedDatabaseDto database, Boolean filterPersisted) throws SQLException, - QueryNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException; + QueryNotFoundException, NotAllowedException, RemoteUnavailableException; ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp, String filename) throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException; + StorageUnavailableException; Long executeCountNonPersistent(PrivilegedDatabaseDto database, String statement, Instant timestamp) throws SQLException, QueryMalformedException, TableMalformedException; @@ -62,7 +62,7 @@ public interface SubsetService { * @return The query. * @throws QueryNotFoundException The query store did not return a query */ - QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException, NotAllowedException, RemoteUnavailableException, UserNotFoundException, ServiceException, DatabaseNotFoundException; + QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException, NotAllowedException, RemoteUnavailableException, UserNotFoundException; /** * Inserts a query and metadata to the query store of a given database id. diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java index fb045b4a19217d968fdf27e4753c2596bc0f9431..b8d2f393902545b1931a6927bc318cb606be92f6 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java @@ -15,110 +15,40 @@ import java.util.List; public interface TableService { - /** - * Get table schemas from the information_schema in the data database. - * @param database The data database privileged object. - * @return List of tables, if successful. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws TableNotFoundException The table could not be inspected in the data database. - * @throws QueryMalformedException The inspection query is malformed. - * @throws DatabaseMalformedException The database inspection was unsuccessful, likely due to a bug in the mapping. - */ - List<TableDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, TableNotFoundException, - QueryMalformedException, DatabaseMalformedException; - - /** - * Generate table statistic for a given table. Only numerical columns are calculated. - * @param table The table. - * @return The table statistic, if successful. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws TableMalformedException The table statistic generation was unsuccessful, likely due to a bug in the mapping. - * @throws QueryMalformedException The inspection query is malformed. - */ - TableStatisticDto getStatistics(PrivilegedTableDto table) throws SQLException, TableMalformedException, - QueryMalformedException; + List<TableDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, TableNotFoundException, QueryMalformedException, DatabaseMalformedException; - /** - * Finds a table with given data database and table name. - * @param database The data database. - * @param tableName The table name. - * @return The table, if successful. - * @throws TableNotFoundException The table could not be inspected in the data database. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws QueryMalformedException The inspection query is malformed. - */ - TableDto find(PrivilegedDatabaseDto database, String tableName) throws TableNotFoundException, SQLException, - QueryMalformedException; + TableDto find(PrivilegedDatabaseDto database, String tableName) throws TableNotFoundException, SQLException, QueryMalformedException; - /** - * Creates a table in given data database with table definition. - * @param database The data database privileged object. - * @param data The table definition. - * @return The created table, if successful. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws TableNotFoundException The table could not be inspected in the data database. - * @throws TableExistsException The table name already exists in the information_schema. - * @throws TableNotFoundException The table could not be inspected in the data database. - * @throws QueryMalformedException The create/inspection query is malformed. - */ TableDto createTable(PrivilegedDatabaseDto database, TableCreateDto data) throws SQLException, TableMalformedException, TableExistsException, TableNotFoundException, QueryMalformedException; - /** - * Drops a table in given table object. - * @param table The table object. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws QueryMalformedException The drop table query is malformed. - */ void delete(PrivilegedTableDto table) throws SQLException, QueryMalformedException; - /** - * Obtains data from a table with given table object at timestamp, loaded as page number and length size. - * @param table The table object. - * @param timestamp The timestamp. - * @param page The page number. - * @param size The page size/length. - * @return The data. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws TableMalformedException The table schema is malformed, likely due to a bug in the application. - */ - QueryResultDto getData(PrivilegedTableDto table, Instant timestamp, Long page, Long size) throws SQLException, - TableMalformedException; - - /** - * Obtains the table history for a given table object. - * @param table The table object. - * @param size The maximum size. - * @return The table history. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws TableNotFoundException The table could not be found in the data database. - */ - List<TableHistoryDto> history(PrivilegedTableDto table, Long size) throws SQLException, TableNotFoundException; - - /** - * Obtains the table data tuples count at time. - * @param table The table object. - * @param timestamp The timestamp. - * @return Number of tuples, if successful. - * @throws SQLException Failed to parse SQL query, contains invalid syntax. - * @throws QueryMalformedException The count query is malformed, likely due to a bug in the application. - */ + QueryResultDto getData(PrivilegedTableDto table, Instant timestamp, Long page, + Long size) throws SQLException, TableMalformedException; + + List<TableHistoryDto> history(PrivilegedTableDto table) throws SQLException, + TableNotFoundException; + Long getCount(PrivilegedTableDto table, Instant timestamp) throws SQLException, QueryMalformedException; - void importDataset(PrivilegedTableDto table, ImportCsvDto data) throws SidecarImportException, - StorageNotFoundException, SQLException, QueryMalformedException, ServiceException, RemoteUnavailableException; + void importTuple(PrivilegedTableDto table, TupleDto data) + throws TableMalformedException, StorageUnavailableException, StorageNotFoundException, SQLException, QueryMalformedException; + + void importDataset(PrivilegedTableDto table, ImportCsvDto data) + throws SidecarImportException, StorageNotFoundException, SQLException, QueryMalformedException; void deleteTuple(PrivilegedTableDto table, TupleDeleteDto data) throws SQLException, TableMalformedException, QueryMalformedException; void createTuple(PrivilegedTableDto table, TupleDto data) throws SQLException, - QueryMalformedException, TableMalformedException, StorageUnavailableException, StorageNotFoundException; + QueryMalformedException, TableMalformedException; void updateTuple(PrivilegedTableDto table, TupleUpdateDto data) throws SQLException, QueryMalformedException, TableMalformedException; ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) throws SQLException, SidecarExportException, StorageNotFoundException, StorageUnavailableException, - QueryMalformedException, ServiceException, RemoteUnavailableException; + QueryMalformedException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java index 3455c320cd10c2e488220843db8ac3d644ef902d..4dcd96ed535971d7b32507f998535544b0a27317 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -58,5 +58,5 @@ public interface ViewService { ExportResourceDto exportDataset(PrivilegedDatabaseDto database, ViewDto view, Instant timestamp) throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException; + StorageUnavailableException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java index 8c52e020103db210744884e1f5973f67a8e44861..96ded2b074d9aa626e289bcecd418274faa31cc3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java @@ -3,13 +3,10 @@ package at.tuwien.service.impl; import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.user.PrivilegedUserDto; -import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; -import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.AccessService; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -26,13 +23,6 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce @Value("${dbrepo.grant.default.write}") private String grantDefaultWrite; - private MariaDbMapper mariaDbMapper; - - @Autowired - public AccessServiceMariaDbImpl(MariaDbMapper mariaDbMapper) { - this.mariaDbMapper = mariaDbMapper; - } - @Override public void create(PrivilegedDatabaseDto database, PrivilegedUserDto user, AccessTypeDto access) throws SQLException, DatabaseMalformedException { @@ -40,11 +30,11 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce final Connection connection = dataSource.getConnection(); try { /* create user if not exists */ - connection.prepareStatement(mariaDbMapper.databaseCreateUserQuery(user.getUsername(), user.getPassword())) + connection.prepareStatement("CREATE USER IF NOT EXISTS `" + user.getUsername() + "`@`%` IDENTIFIED BY PASSWORD '" + user.getPassword() + "';") .execute(); /* grant access */ final String grants = access != AccessTypeDto.READ ? grantDefaultWrite : grantDefaultRead; - connection.prepareStatement(mariaDbMapper.databaseGrantPrivilegesQuery(user.getUsername(), grants)) + connection.prepareStatement("GRANT " + grants + " ON *.* TO `" + user.getUsername() + "`@`%`;") .execute(); /* grant query store */ connection.prepareStatement("GRANT EXECUTE ON PROCEDURE `store_query` TO `" + user.getUsername() + "`@`%`;") @@ -64,14 +54,15 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce } @Override - public void update(PrivilegedDatabaseDto database, UserDto user, AccessTypeDto access) + public void update(PrivilegedDatabaseDto database, PrivilegedUserDto user, AccessTypeDto access) throws DatabaseMalformedException, SQLException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); try { /* grant access */ - final String grants = access != AccessTypeDto.READ ? grantDefaultWrite : grantDefaultRead; - connection.prepareStatement(mariaDbMapper.databaseGrantPrivilegesQuery(user.getUsername(), grants)) + connection.prepareStatement("GRANT SELECT" + + (access != AccessTypeDto.READ ? "CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE" : "") + + " ON *.* TO `" + user.getUsername() + "`@`%`;") .execute(); /* apply access rights */ connection.prepareStatement("FLUSH PRIVILEGES;"); @@ -87,7 +78,7 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce } @Override - public void delete(PrivilegedDatabaseDto database, UserDto user) throws DatabaseMalformedException, + public void delete(PrivilegedDatabaseDto database, PrivilegedUserDto user) throws DatabaseMalformedException, SQLException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AnalyseServiceImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AnalyseServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..7b722597c533b39fad6615e5d6fc486ea57235f0 --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AnalyseServiceImpl.java @@ -0,0 +1,30 @@ +package at.tuwien.service.impl; + +import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.exception.NotAllowedException; +import at.tuwien.exception.RemoteUnavailableException; +import at.tuwien.exception.TableNotFoundException; +import at.tuwien.gateway.AnalyseServiceGateway; +import at.tuwien.service.AnalyseService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Log4j2 +@Service +public class AnalyseServiceImpl implements AnalyseService { + + private final AnalyseServiceGateway analyseServiceGateway; + + @Autowired + public AnalyseServiceImpl(AnalyseServiceGateway analyseServiceGateway) { + this.analyseServiceGateway = analyseServiceGateway; + } + + @Override + public TableStatisticDto analyseTable(Long databaseId, Long tableId) throws TableNotFoundException, + NotAllowedException, RemoteUnavailableException { + return analyseServiceGateway.analyseTable(databaseId, tableId); + } + +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java index 2d91dcb8f4612e6cca1ba77f1a73aa4670c5ecbe..7bd233371e5b42ea8085c58ca5cae06b03af4aa7 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java @@ -1,20 +1,27 @@ package at.tuwien.service.impl; import at.tuwien.api.container.internal.PrivilegedContainerDto; +import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.user.UserDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.config.RabbitConfig; import at.tuwien.exception.*; import at.tuwien.mapper.MariaDbMapper; +import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.DatabaseService; +import at.tuwien.service.SchemaService; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; @Log4j2 @@ -22,12 +29,10 @@ import java.sql.SQLException; public class DatabaseServiceMariaDbImpl extends HibernateConnector implements DatabaseService { private final RabbitConfig rabbitConfig; - private final MariaDbMapper mariaDbMapper; @Autowired - public DatabaseServiceMariaDbImpl(RabbitConfig rabbitConfig, MariaDbMapper mariaDbMapper) { + public DatabaseServiceMariaDbImpl(RabbitConfig rabbitConfig) { this.rabbitConfig = rabbitConfig; - this.mariaDbMapper = mariaDbMapper; } @Override @@ -37,7 +42,7 @@ public class DatabaseServiceMariaDbImpl extends HibernateConnector implements Da final Connection connection = dataSource.getConnection(); try { /* create database if not exists */ - connection.prepareStatement(mariaDbMapper.databaseCreateDatabaseQuery(data.getInternalName())) + connection.prepareStatement("CREATE DATABASE IF NOT EXISTS `" + data.getInternalName() + "`;") .execute(); connection.commit(); } catch (SQLException e) { @@ -71,7 +76,7 @@ public class DatabaseServiceMariaDbImpl extends HibernateConnector implements Da final Connection connection = dataSource.getConnection(); try { /* update user password */ - connection.prepareStatement(mariaDbMapper.databaseSetPasswordQuery(data.getUsername(), data.getPassword())) + connection.prepareStatement("SET PASSWORD FOR `" + data.getUsername() + "`@`%` = '" + data.getPassword() + "';") .execute(); connection.commit(); } catch (SQLException e) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java index 537c4878a4f44a1b47e39278b3233f03448cf439..c2c53c7830730ce548ea9d16afb66ef4f9bfba22 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java @@ -100,7 +100,6 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche } } table.setTdbid(database.getId()); - database.getCreator().getAttributes().setMariadbPassword(null); table.setCreator(database.getCreator()); table.setCreatedBy(database.getCreator().getId()); final TableDto tmpTable = table; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java index d298f2fada278f1eba060b030fbcc1040324adc1..57d7472dde490ae39143ca04fd255454e7c3b724 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java @@ -84,8 +84,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs public QueryResultDto execute(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId, Long page, Long size, SortTypeDto sortDirection, String sortColumn) throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException, - UserNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { + UserNotFoundException, NotAllowedException, RemoteUnavailableException { final Long queryId = storeQuery(database, statement, timestamp, userId); final QueryDto query = findById(database, queryId); return reExecute(database, query, page, size, sortDirection, sortColumn); @@ -116,8 +115,8 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public List<QueryDto> findAll(PrivilegedDatabaseDto database, Boolean filterPersisted) throws SQLException, - QueryNotFoundException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { - final List<IdentifierDto> identifiers = metadataServiceGateway.getIdentifiers(database.getId(), null); + QueryNotFoundException, NotAllowedException, RemoteUnavailableException { + final List<IdentifierDto> identifiers = metadataServiceGateway.getIdentifiers(database.getId()); final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); try { @@ -149,7 +148,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp, String filename) throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException { + StorageUnavailableException { final String filePath = s3Config.getS3FilePath() + "/" + filename; final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); @@ -204,7 +203,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException, - RemoteUnavailableException, UserNotFoundException, ServiceException, DatabaseNotFoundException { + NotAllowedException, RemoteUnavailableException, UserNotFoundException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); try { @@ -216,7 +215,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs } final QueryDto query = mariaDbMapper.resultSetToQueryDto(resultSet); query.setIdentifiers(metadataServiceGateway.getIdentifiers(database.getId(), queryId)); - final UserDto creator = metadataServiceGateway.getUserById(query.getCreatedBy()); + final UserDto creator = metadataServiceGateway.getUser(query.getCreatedBy()); log.debug("retrieved creator from metadata service: creator.id={}, creator.username={}", creator.getId(), creator.getUsername()); query.setCreator(creator); query.setDatabaseId(database.getId()); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java index 55e96c516185699e6c17e8e58ed43de1637da1bf..92e369e0afd2d0d24509ab3691cc32d40702de55 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java @@ -6,7 +6,6 @@ import at.tuwien.api.database.query.ImportCsvDto; import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.database.table.*; import at.tuwien.api.database.table.columns.ColumnDto; -import at.tuwien.api.database.table.columns.ColumnStatisticDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; import at.tuwien.api.database.table.internal.TableCreateDto; @@ -17,7 +16,6 @@ import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.SchemaService; import at.tuwien.service.StorageService; import at.tuwien.service.TableService; -import at.tuwien.utils.MariaDbUtil; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; @@ -81,33 +79,6 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table return tables; } - @Override - public TableStatisticDto getStatistics(PrivilegedTableDto table) throws SQLException, TableMalformedException, - QueryMalformedException { - final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); - final Connection connection = dataSource.getConnection(); - final TableStatisticDto statistic; - try { - /* obtain statistic */ - final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.tableColumnStatisticsSelectRawQuery(table.getColumns(), table.getInternalName())) - .executeQuery(); - statistic = mariaDbMapper.resultSetToTableStatistic(resultSet); - statistic.setRows(getCount(table, null)); - } catch (SQLException e) { - connection.rollback(); - log.error("Failed to obtain column statistics: {}", e.getMessage()); - throw new TableMalformedException("Failed to obtain column statistics: " + e.getMessage(), e); - } finally { - dataSource.close(); - } - table.getColumns() - .stream() - .filter(column -> !MariaDbUtil.numericDataTypes.contains(column.getColumnType())) - .forEach(column -> statistic.getColumns().put(column.getInternalName(), new ColumnStatisticDto())); - log.info("Obtained column statistics for table: {}", table.getInternalName()); - return statistic; - } - @Override public TableDto find(PrivilegedDatabaseDto database, String tableName) throws TableNotFoundException, SQLException, QueryMalformedException { @@ -143,9 +114,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table dataSource.close(); } log.info("Created table with name {}", tableName); - final TableDto table = find(database, tableName); - table.setName(data.getName()); - return table; + return find(database, tableName); } @Override @@ -160,12 +129,12 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table connection.commit(); } catch (SQLException e) { connection.rollback(); - log.error("Failed to delete table: {}", e.getMessage()); - throw new QueryMalformedException("Failed to delete table: " + e.getMessage(), e); + log.error("Failed to delete table and history view: {}", e.getMessage()); + throw new QueryMalformedException("Failed to delete table and history view: " + e.getMessage(), e); } finally { dataSource.close(); } - log.info("Deleted table with name {}", tableName); + log.info("Deleted table and history view with name {}", tableName); } @Override @@ -176,9 +145,9 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table final QueryResultDto queryResult; try { /* find table data */ - final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectDatasetRawQuery( - table.getDatabase().getInternalName(), table.getInternalName(), table.getColumns(), - timestamp, size, page)) + final ResultSet resultSet = connection.prepareStatement( + mariaDbMapper.selectDatasetRawQuery(table.getDatabase().getInternalName(), table.getInternalName(), + table.getColumns(), timestamp, size, page)) .executeQuery(); connection.commit(); queryResult = mariaDbMapper.resultListToQueryResultDto(table.getColumns(), resultSet); @@ -190,12 +159,11 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table dataSource.close(); } log.info("Find data from table {}.{}", table.getDatabase().getInternalName(), table.getInternalName()); - queryResult.setId(table.getId()); return queryResult; } @Override - public List<TableHistoryDto> history(PrivilegedTableDto table, Long size) throws SQLException, + public List<TableHistoryDto> history(PrivilegedTableDto table) throws SQLException, TableNotFoundException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); final Connection connection = dataSource.getConnection(); @@ -203,7 +171,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table try { /* find table data */ final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectHistoryRawQuery( - table.getDatabase().getInternalName(), table.getInternalName(), size)) + table.getDatabase().getInternalName(), table.getInternalName(), 100L)) .executeQuery(); history = mariaDbMapper.resultSetToTableHistory(resultSet); connection.commit(); @@ -242,9 +210,48 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table return queryResult; } + @Override + public void importTuple(PrivilegedTableDto table, TupleDto data) + throws TableMalformedException, StorageUnavailableException, StorageNotFoundException, SQLException, QueryMalformedException { + /* for each LOB-like data-column, retrieve the bytes and replace the value */ + for (String key : data.getData().keySet()) { + final boolean found = table.getColumns() + .stream() + .filter(c -> List.of(ColumnTypeDto.BLOB, ColumnTypeDto.LONGBLOB, ColumnTypeDto.TINYBLOB, ColumnTypeDto.MEDIUMBLOB).contains(c.getColumnType())) + .anyMatch(c -> c.getInternalName().equals(key)); + if (!found || data.getData().get(key) == null) { + continue; + } + final byte[] blob = storageService.getBytes(String.valueOf(data.getData().get(key))); + log.debug("replaced S3 storage key {} with blob", key); + data.getData().replace(key, blob); + } + final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); + final Connection connection = dataSource.getConnection(); + try { + /* import tuple */ + final int[] idx = new int[]{1}; + final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawInsertQuery(table, data)); + for (String column : data.getData().keySet()) { + mariaDbMapper.prepareStatementWithColumnTypeObject(statement, + getColumnType(table.getColumns(), column), idx[0], data.getData().get(column)); + idx[0]++; + } + statement.execute(); + connection.commit(); + } catch (SQLException e) { + connection.rollback(); + log.error("Failed to import tuple: {}", e.getMessage()); + throw new QueryMalformedException("Failed to import tuple: " + e.getMessage(), e); + } finally { + dataSource.close(); + } + log.info("Imported tuple into table: {}.{}", table.getDatabase().getInternalName(), table.getInternalName()); + } + @Override public void importDataset(PrivilegedTableDto table, ImportCsvDto data) - throws StorageNotFoundException, SQLException, QueryMalformedException, ServiceException, RemoteUnavailableException { + throws SidecarImportException, StorageNotFoundException, SQLException, QueryMalformedException { /* import .csv from blob storage to sidecar */ dataDatabaseSidecarGateway.importFile(table.getDatabase().getContainer().getSidecarHost(), table.getDatabase().getContainer().getSidecarPort(), data.getLocation()); /* import .csv from sidecar to database */ @@ -279,7 +286,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawDeleteQuery(table, data)); for (String column : data.getKeys().keySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, - getColumnType(table.getColumns(), column), idx[0], column, data.getKeys().get(column)); + getColumnType(table.getColumns(), column), idx[0], data.getKeys().get(column)); idx[0]++; } statement.executeUpdate(); @@ -296,22 +303,8 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table @Override public void createTuple(PrivilegedTableDto table, TupleDto data) throws SQLException, - QueryMalformedException, TableMalformedException, StorageUnavailableException, StorageNotFoundException { + QueryMalformedException, TableMalformedException { log.trace("create tuple: {}", data); - /* for each LOB-like data-column, retrieve the bytes and replace the value */ - for (String key : data.getData().keySet()) { - final boolean found = table.getColumns() - .stream() - .filter(c -> List.of(ColumnTypeDto.BLOB, ColumnTypeDto.LONGBLOB, ColumnTypeDto.TINYBLOB, ColumnTypeDto.MEDIUMBLOB).contains(c.getColumnType())) - .anyMatch(c -> c.getInternalName().equals(key)); - if (!found || data.getData().get(key) == null) { - continue; - } - final byte[] blob = storageService.getBytes(String.valueOf(data.getData().get(key))); - log.debug("replaced S3 storage key {} with blob", key); - data.getData() - .replace(key, blob); - } /* prepare the statement */ final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); final Connection connection = dataSource.getConnection(); @@ -321,7 +314,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawCreateQuery(table, data)); for (Map.Entry<String, Object> entry : data.getData().entrySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, - getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getKey(), entry.getValue()); + getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getValue()); idx[0]++; } statement.executeUpdate(); @@ -349,13 +342,13 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table /* set data */ for (Map.Entry<String, Object> entry : data.getData().entrySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, - getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getKey(), entry.getValue()); + getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getValue()); idx[0]++; } /* set key(s) */ for (Map.Entry<String, Object> entry : data.getKeys().entrySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, - getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getKey(), entry.getValue()); + getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getValue()); idx[0]++; } statement.executeUpdate(); @@ -382,9 +375,9 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table } @Override - public ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) throws SQLException, - StorageNotFoundException, StorageUnavailableException, QueryMalformedException, ServiceException, - RemoteUnavailableException { + public ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) + throws SQLException, SidecarExportException, StorageNotFoundException, StorageUnavailableException, + QueryMalformedException { final String fileName = RandomStringUtils.randomAlphabetic(40) + ".csv"; final String filePath = s3Config.getS3FilePath() + "/" + fileName; final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java index c85f5bfbdba9ffbe83d512a37f3f5cdebf5e4c1d..b28e2a1dc4f0e4530b8a4a9235b7cdc4819ee0fe 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java @@ -16,14 +16,12 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.SchemaService; import at.tuwien.service.StorageService; import at.tuwien.service.ViewService; -import com.google.common.hash.Hashing; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -98,11 +96,7 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe final Connection connection = dataSource.getConnection(); ViewDto view = ViewDto.builder() .name(data.getName()) - .internalName(mariaDbMapper.nameToInternalName(data.getName())) - .query(data.getQuery()) - .queryHash(Hashing.sha256() - .hashString(data.getQuery(), StandardCharsets.UTF_8) - .toString()) + .internalName(data.getName()) .isPublic(database.getIsPublic()) .creator(database.getOwner()) .createdBy(database.getOwner().getId()) @@ -114,12 +108,12 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe .build(); try { /* create view if not exists */ - connection.prepareStatement(mariaDbMapper.viewCreateRawQuery(view.getInternalName(), data.getQuery())) + connection.prepareStatement(mariaDbMapper.viewCreateRawQuery(data.getName(), data.getQuery())) .execute(); /* select view columns */ final PreparedStatement statement2 = connection.prepareStatement(mariaDbMapper.databaseTableColumnsSelectRawQuery()); statement2.setString(1, database.getInternalName()); - statement2.setString(2, view.getInternalName()); + statement2.setString(2, data.getName()); final ResultSet resultSet2 = statement2.executeQuery(); while (resultSet2.next()) { view = mariaDbMapper.resultSetToTable(resultSet2, view, queryConfig); @@ -211,8 +205,8 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe @Override public ExportResourceDto exportDataset(PrivilegedDatabaseDto database, ViewDto view, Instant timestamp) - throws SQLException, QueryMalformedException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException { + throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, + StorageUnavailableException { final String fileName = RandomStringUtils.randomAlphabetic(40) + ".csv"; final String filePath = s3Config.getS3FilePath() + "/" + fileName; final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java b/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java index a917be6d46899c62e3e166ad0610950c9463bbca..17847c15c6e6fd33b1ba0d77dff3b17ed10d58ca 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java @@ -9,36 +9,16 @@ public class MariaDbUtil { /** * https://mariadb.com/kb/en/string-data-types/ */ - final static List<ColumnTypeDto> stringDataTypes = List.of( - ColumnTypeDto.BINARY, - ColumnTypeDto.VARBINARY, - ColumnTypeDto.TINYBLOB, - ColumnTypeDto.MEDIUMBLOB, - ColumnTypeDto.LONGBLOB, + final static List<ColumnTypeDto> stringDataTypes = List.of(ColumnTypeDto.BINARY, ColumnTypeDto.BLOB, ColumnTypeDto.CHAR, - ColumnTypeDto.VARCHAR, ColumnTypeDto.ENUM, - ColumnTypeDto.SET, - ColumnTypeDto.TINYTEXT, - ColumnTypeDto.MEDIUMTEXT, + ColumnTypeDto.MEDIUMBLOB, + ColumnTypeDto.LONGBLOB, ColumnTypeDto.LONGTEXT, - ColumnTypeDto.TEXT); - - /** - * https://mariadb.com/kb/en/numeric-data-type-overview/ - */ - final public static List<ColumnTypeDto> numericDataTypes = List.of( - ColumnTypeDto.TINYINT, - ColumnTypeDto.BOOL, - ColumnTypeDto.SMALLINT, - ColumnTypeDto.MEDIUMINT, - ColumnTypeDto.INT, - ColumnTypeDto.BIGINT, - ColumnTypeDto.DECIMAL, - ColumnTypeDto.FLOAT, - ColumnTypeDto.DOUBLE, - ColumnTypeDto.BIT); + ColumnTypeDto.TEXT, + ColumnTypeDto.TINYTEXT, + ColumnTypeDto.SET); /** * https://mariadb.com/kb/en/date-and-time-data-types/ diff --git a/dbrepo-gateway-service/dbrepo.conf b/dbrepo-gateway-service/dbrepo.conf index f9c0001cebfbba5bbb842984377fb01197617d96..4ea19528f17b17f24761b3fcefd8584faa10239c 100644 --- a/dbrepo-gateway-service/dbrepo.conf +++ b/dbrepo-gateway-service/dbrepo.conf @@ -101,7 +101,7 @@ server { proxy_read_timeout 90; } - location ~ /api/database/([0-9]+)/table/([0-9]+)/(data|history|export|statistic) { + location ~ /api/database/([0-9]+)/table/([0-9]+)/(data|history|export) { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/dbrepo-metadata-service/Dockerfile b/dbrepo-metadata-service/Dockerfile index 75fe485c16073094c202a476cd55ddf5c6fb84e7..5fd1138f24bcf19cd3bd3ad665d154a4d662c8c7 100644 --- a/dbrepo-metadata-service/Dockerfile +++ b/dbrepo-metadata-service/Dockerfile @@ -30,8 +30,6 @@ RUN mvn clean install -DskipTests FROM amazoncorretto:17-alpine3.19 as runtime MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> -RUN apk add --no-cache curl bash jq - WORKDIR /app USER 65534 diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java index 337a61a637ea03437f74462c3b1c245e6943999d..35edfc6d8410c2eedbad2c9118fcad494cd01f73 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java @@ -76,10 +76,6 @@ public class ViewColumnDto { private UnitDto unit; - @Size(max = 2048) - @Schema(example = "Column comment") - private String description; - @NotNull @JsonProperty("is_public") @Schema(example = "true") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java index 11f99f48eb7cf29d06a03b7ab8b8fb6930769672..aa566a495c6ea05a5a1d1259f0577ccf37cf1d0c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java @@ -33,6 +33,7 @@ public class TableBriefDto { @Schema(example = "Air Quality") private String name; + @NotBlank @Schema(example = "Air Quality in Austria") private String description; @@ -48,4 +49,9 @@ public class TableBriefDto { @NotNull private UserBriefDto owner; + + @ToString.Exclude + @JsonIgnore + @NotNull + private List<ColumnBriefDto> columns; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java index 8d41bcc7ff79ba6a51ea1caabad2fd52686cd4a5..bcf744c0b382e2fc1191a53753bf52009e15d545 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java @@ -1,7 +1,6 @@ package at.tuwien.api.database.table; import at.tuwien.api.database.table.columns.ColumnStatisticDto; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; @@ -17,10 +16,6 @@ import java.util.Map; @ToString public class TableStatisticDto { - @NotNull - @JsonProperty("rows") - private Long rows; - @NotNull private Map<String, ColumnStatisticDto> columns; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java index 37aa493020845255694d4d0fb0ac5cc7900803f2..78fb7fb84e5f0f8f171a97cafe63e68f32c47e35 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java @@ -46,12 +46,6 @@ public class ColumnCreateDto { @Schema(example = "true") private Boolean nullAllowed; - @JsonProperty("concept_uri") - private String conceptUri; - - @JsonProperty("unit_uri") - private String unitUri; - @Schema(description = "date format id") private Long dfid; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java index 026d5d89b7dbb77a6bf4cd94b60448f8a73bc424..740b2184e72d5f8df4dba6a32cc852f134e58723 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java @@ -117,7 +117,7 @@ public class ColumnDto { private UnitDto unit; @Size(max = 2048) - @Schema(example = "Column comment") + @Schema(example = "Formatted as YYYY-MM-dd") private String description; @ToString.Exclude diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyBriefDto.java deleted file mode 100644 index 58a4d5b2453f617297673891f4a879fb02409f10..0000000000000000000000000000000000000000 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyBriefDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package at.tuwien.api.database.table.constraints.foreign; - -import lombok.*; -import lombok.extern.jackson.Jacksonized; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Jacksonized -@ToString -public class ForeignKeyBriefDto { - - private Long id; -} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java index 1644c95cdcf488425f5ee6fb795bdac432169d6f..9fe7c683827f86a95977b9af2d728254dff9974a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java @@ -1,6 +1,5 @@ package at.tuwien.api.database.table.constraints.foreign; -import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import com.fasterxml.jackson.annotation.JsonProperty; @@ -29,12 +28,12 @@ public class ForeignKeyDto { @NotNull @ToString.Exclude - private TableBriefDto table; + private TableDto table; @NotNull @ToString.Exclude @JsonProperty("referenced_table") - private TableBriefDto referencedTable; + private TableDto referencedTable; @JsonProperty("on_update") private ReferenceTypeDto onUpdate; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java index 111903d9265517e4b532c46a84983843619f0835..fb978671bc9a2b8d9f647b5c537762977c628229 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java @@ -1,6 +1,6 @@ package at.tuwien.api.database.table.constraints.foreign; -import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.tuwien.api.database.table.columns.ColumnDto; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; import lombok.*; @@ -19,14 +19,14 @@ public class ForeignKeyReferenceDto { @NotNull @JsonProperty("foreign_key") - private ForeignKeyBriefDto foreignKey; + private ForeignKeyDto foreignKey; @NotNull @ToString.Exclude - private ColumnBriefDto column; + private ColumnDto column; @NotNull @ToString.Exclude @JsonProperty("referenced_column") - private ColumnBriefDto referencedColumn; + private ColumnDto referencedColumn; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java index 239b95e7e916a01e596e78e41154d0fdae6e9bf8..ebd2d5688764c85dffa273a88bb05d42ad8a9f28 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java @@ -27,17 +27,6 @@ public enum ReferenceTypeDto { this.type = type; } - public static ReferenceTypeDto fromType(String type) { - return switch (type) { - case "RESTRICT" -> ReferenceTypeDto.RESTRICT; - case "CASCADE" -> ReferenceTypeDto.CASCADE; - case "SET NULL" -> ReferenceTypeDto.SET_NULL; - case "NO ACTION" -> ReferenceTypeDto.NO_ACTION; - case "SET DEFAULT" -> ReferenceTypeDto.SET_DEFAULT; - default -> null; - }; - } - @Override public String toString() { return this.type; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java index 568e16e4749c810ef8eae67872d4b2be9e29ddf3..b315c7e81daf711103ab063ca2b4d9a8b438c1a9 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java @@ -23,9 +23,6 @@ import java.util.List; @EntityListeners(AuditingEntityListener.class) @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "mdb_images", uniqueConstraints = @UniqueConstraint(columnNames = {"name", "version"})) -@NamedQueries({ - @NamedQuery(name = "ContainerImage.findAll", query = "select i from ContainerImage i order by i.id asc") -}) public class ContainerImage { @Id diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index 563373645070c416f257ec69b25354e1d00111c5..464cf28ed983e940a7d96736c4fe7807f55a11aa 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -45,7 +45,7 @@ <commons-io.version>2.15.0</commons-io.version> <commons-validator.version>1.8.0</commons-validator.version> <guava.version>33.0.0-jre</guava.version> - <jacoco.version>0.8.12</jacoco.version> + <jacoco.version>0.8.11</jacoco.version> <jwt.version>4.3.0</jwt.version> <c3p0.version>0.9.5.5</c3p0.version> <c3p0-hibernate.version>6.2.2.Final</c3p0-hibernate.version> @@ -279,6 +279,23 @@ <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.version}</version> + <configuration> + <excludes> + <exclude>at/tuwien/utils/**/*</exclude> + <exclude>at/tuwien/seeder/**/*</exclude> + <exclude>at/tuwien/mapper/**/*</exclude> + <exclude>at/tuwien/handlers/**/*</exclude> + <exclude>at/tuwien/exception/**/*</exclude> + <exclude>at/tuwien/converters/**/*</exclude> + <exclude>at/tuwien/utils/**/*</exclude> + <exclude>at/tuwien/config/**/*</exclude> + <exclude>at/tuwien/auth/**/*</exclude> + <exclude>at/tuwien/gateway/impl/ApiTemplateInterceptorImpl.class</exclude> + <exclude>**/testcontainers.properties</exclude> + <exclude>**/HibernateConnector.class</exclude> + <exclude>**/DbrepoMetadataServiceApplication.class</exclude> + </excludes> + </configuration> <executions> <execution> <id>default-prepare-agent</id> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index 1cb8f6d3949704cb18f635f1d90af0829d7c95e6..1a41226977ab90f778a3e07e61ac126a83279fc8 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -19,10 +19,8 @@ import at.tuwien.api.database.table.columns.concepts.UnitDto; import at.tuwien.api.database.table.columns.concepts.UnitSaveDto; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyBriefDto; import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; -import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.api.datacite.doi.*; @@ -90,8 +88,6 @@ public interface MetadataMapper { BannerMessageBriefDto bannerMessageToBannerMessageBriefDto(BannerMessage data); - ViewColumn viewColumnDtoToViewColumn(ViewColumnDto data); - BannerMessage bannerMessageCreateDtoToBannerMessage(BannerMessageCreateDto data); BannerMessageType bannerMessageTypeDtoToBannerMessageType(BannerMessageTypeDto data); @@ -462,7 +458,9 @@ public interface MetadataMapper { TableColumnConcept conceptSaveDtoToTableColumnConcept(ConceptSaveDto data); @Mappings({ - @Mapping(target = "databaseId", source = "tdbid"), + @Mapping(source = "id", target = "id"), + @Mapping(target = "name", expression = "java(data.getName())"), + @Mapping(target = "internalName", expression = "java(data.getInternalName())") }) TableBriefDto tableToTableBriefDto(Table data); @@ -482,12 +480,14 @@ public interface MetadataMapper { @Mappings({ @Mapping(target = "table.owner", ignore = true), + @Mapping(target = "table.creator", ignore = true), + @Mapping(target = "table.constraints", ignore = true), @Mapping(target = "referencedTable.owner", ignore = true), + @Mapping(target = "referencedTable.creator", ignore = true), + @Mapping(target = "referencedTable.constraints", ignore = true), }) ForeignKeyDto foreignKeyToForeignKeyDto(ForeignKey data); - ForeignKeyBriefDto foreignKeyDtoToForeignKeyBriefDto(ForeignKeyDto data); - default ConstraintsDto constraintsToConstraintsDto(Constraints data) { if (data == null) { return null; @@ -539,20 +539,6 @@ public interface MetadataMapper { pk.getColumn().setTableId(data.getId()); pk.getColumn().setDatabaseId(data.getDatabase().getId()); }); - for (ForeignKeyDto fk : table.getConstraints().getForeignKeys()) { - for (ForeignKeyReferenceDto ref : fk.getReferences()) { - ref.setForeignKey(foreignKeyDtoToForeignKeyBriefDto(fk)); - ref.getColumn().setTableId(table.getId()); - ref.getColumn().setDatabaseId(table.getTdbid()); - final Optional<TableColumn> optional = data.getDatabase().getTables().stream().map(Table::getColumns).flatMap(List::stream).filter(c -> c.getId().equals(ref.getReferencedColumn().getId())).findFirst(); - if (optional.isEmpty()) { - log.error("Failed to find foreign key referenced column {}.{} in columns: {}", table.getInternalName(), ref.getReferencedColumn().getInternalName(), data.getDatabase().getTables().stream().map(Table::getColumns).flatMap(List::stream).toList()); - throw new IllegalArgumentException("Failed to find foreign key referenced column"); - } - ref.getReferencedColumn().setTableId(optional.get().getTable().getId()); - ref.getReferencedColumn().setDatabaseId(optional.get().getTable().getTdbid()); - } - } table.getConstraints() .getUniques() .forEach(uk -> { @@ -599,12 +585,11 @@ public interface MetadataMapper { Table tableDtoToTable(TableDto data); @Mappings({ - @Mapping(target = "table.owner", ignore = true) + @Mapping(target = "table.owner", ignore = true), + @Mapping(target = "table.columns", ignore = true) }) PrimaryKeyDto primaryKeyToPrimaryKeyDto(PrimaryKey data); - ReferenceType referenceTypeDtoToReferenceType(ReferenceTypeDto data); - /* keep */ default Constraints constraintsCreateDtoToConstraints(ConstraintsCreateDto data, Database database, Table table) { final int[] idx = new int[]{0, 0}; @@ -632,39 +617,40 @@ public interface MetadataMapper { log.error("Failed to find foreign key referenced table {} in tables: {}", fk.getReferencedTable(), database.getTables().stream().map(Table::getInternalName).toList()); throw new IllegalArgumentException("Failed to find foreign key referenced table"); } - final List<ForeignKeyReference> references = new LinkedList<>(); - for (int i = 0; i < fk.getColumns().size(); i++) { - final int k = i; - final Optional<TableColumn> column = table.getColumns() - .stream() - .filter(cc -> cc.getInternalName().equals(fk.getColumns().get(k))) - .findFirst(); - if (column.isEmpty()) { - log.error("Failed to find foreign key column {}.{} in columns: {}", table.getInternalName(), fk.getColumns().get(k), optional.get().getColumns().stream().map(TableColumn::getInternalName).toList()); - throw new IllegalArgumentException("Failed to find foreign key column"); - } - final Optional<TableColumn> referencedColumn = optional.get() - .getColumns() - .stream() - .filter(cc -> cc.getInternalName().equals(fk.getReferencedColumns().get(k))) - .findFirst(); - if (referencedColumn.isEmpty()) { - log.error("Failed to find foreign key referenced column {} in referenced columns: {}", fk.getReferencedColumns().get(k), database.getTables().stream().filter(t -> t.getInternalName().equals(fk.getReferencedTable())).map(Table::getColumns).flatMap(List::stream).map(TableColumn::getInternalName).toList()); - throw new IllegalArgumentException("Failed to find foreign key referenced column"); - } - references.add(ForeignKeyReference.builder() - .column(column.get()) - .referencedColumn(referencedColumn.get()) - .foreignKey(null) // set at the end - .build()); - } return ForeignKey.builder() .name("fk_" + table.getInternalName() + "_" + idx[1]++) - .table(table) .referencedTable(optional.get()) - .references(references) - .onDelete(referenceTypeDtoToReferenceType(fk.getOnDelete())) - .onUpdate(referenceTypeDtoToReferenceType(fk.getOnUpdate())) + .references(fk.getReferencedColumns() + .stream() + .map(c -> { + final Optional<TableColumn> column = table.getColumns() + .stream() + .filter(cc -> cc.getInternalName().equals(c)) + .findFirst(); + if (column.isEmpty()) { + log.error("Failed to find foreign key column {} in columns: {}", c, table.getColumns().stream().map(TableColumn::getInternalName).toList()); + throw new IllegalArgumentException("Failed to find foreign key column"); + } + final Optional<TableColumn> referencedColumn = database.getTables() + .stream() + .filter(t -> t.getInternalName().equals(fk.getReferencedTable())) + .map(Table::getColumns) + .flatMap(List::stream) + .filter(cc -> cc.getInternalName().equals(c)) + .findFirst(); + if (referencedColumn.isEmpty()) { + log.error("Failed to find foreign key referenced column {} in referenced columns: {}", c, database.getTables().stream().filter(t -> t.getInternalName().equals(fk.getReferencedTable())).map(Table::getColumns).flatMap(List::stream).map(TableColumn::getInternalName).toList()); + throw new IllegalArgumentException("Failed to find foreign key referenced column"); + } + return ForeignKeyReference.builder() + .column(column.get()) + .referencedColumn(referencedColumn.get()) + .foreignKey(null) // set later + .build(); + }) + .toList()) + .onDelete(ReferenceType.CASCADE) + .onUpdate(ReferenceType.CASCADE) .build(); }) .toList()) @@ -805,12 +791,6 @@ public interface MetadataMapper { }) ViewDto viewToViewDto(View data); - @Mappings({ - @Mapping(target = "databaseId", source = "view.vdbid"), - @Mapping(target = "isPublic", source = "view.isPublic") - }) - ViewColumnDto viewColumnToViewColumnDto(ViewColumn data); - ViewBriefDto viewToViewBriefDto(View data); @Mappings({ diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java index 593a4727180d55b4bc0cb1971c0aecf49313f8cb..d2262f37d69bd8dc2ad5c504236e839d2ff7c523 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java @@ -4,14 +4,11 @@ import at.tuwien.entities.container.image.ContainerImage; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import java.util.List; import java.util.Optional; @Repository public interface ImageRepository extends JpaRepository<ContainerImage, Long> { - List<ContainerImage> findAll(); - Optional<ContainerImage> findByNameAndVersion(String name, String version); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index c87b4039c1425c6b15a7665c8def80125fa46be6..97f7207f0b9bd489b9ede20d0496b2fd84742505 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -4,6 +4,7 @@ import at.tuwien.api.amqp.QueueDto; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.TableStatisticDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; @@ -61,7 +62,7 @@ public class TableEndpoint { private final EndpointValidator endpointValidator; @Autowired - public TableEndpoint(UserService userService, TableService tableService, RabbitConfig rabbitMqConfig, + public TableEndpoint(UserService userService, TableService tableService, RabbitConfig rabbitMqConfig, EntityService entityService, BrokerService messageQueueService, MetadataMapper metadataMapper, DatabaseService databaseService, EndpointValidator endpointValidator) { this.userService = userService; @@ -155,19 +156,19 @@ public class TableEndpoint { @PutMapping("/{tableId}") @Transactional - @PreAuthorize("hasAuthority('update-table-statistic') or hasAuthority('admin')") + @PreAuthorize("hasAuthority('admin')") @Observed(name = "dbrepo_statistic_table_update") @Operation(summary = "Update table statistics", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Updated table statistics successfully"), - @ApiResponse(responseCode = "404", - description = "Failed to find database/table in metadata database", + @ApiResponse(responseCode = "400", + description = "Payload malformed", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "400", - description = "Failed to map column statistic to known columns", + @ApiResponse(responseCode = "404", + description = "Failed to find database/table in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -183,12 +184,14 @@ public class TableEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> updateStatistic(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId) - throws TableNotFoundException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, MalformedException, ServiceException, ServiceConnectionException { - log.debug("endpoint update table statistics, databaseId={}, tableId={}", databaseId, tableId); + @NotNull @PathVariable("tableId") Long tableId, + @NotNull @Valid @RequestBody TableStatisticDto data) + throws MalformedException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException { + log.debug("endpoint update table statistics, databaseId={}, tableId={}, data.columns.size={}", databaseId, + tableId, data.getColumns().size()); final Table table = tableService.findById(databaseId, tableId); - tableService.updateStatistics(table); + tableService.updateStatistics(table, data); return ResponseEntity.accepted() .build(); } @@ -341,7 +344,7 @@ public class TableEndpoint { @NotNull Principal principal) throws NotAllowedException, MalformedException, ServiceException, ServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, TableNotFoundException, TableExistsException, SearchServiceException, - SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { + SearchServiceConnectionException { log.debug("endpoint create table, databaseId={}, data.name={}", databaseId, data.getName()); final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyAccess(database, principal, true); diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml index 3312af7c5af638096be77f207d0b6524ea9d0dab..6f69d7737cb69c1aab6d3af2b8f3bf0082e6c4ee 100644 --- a/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml @@ -62,12 +62,11 @@ dbrepo: username: admin password: admin endpoints: - searchService: http://localhost - analyseService: http://localhost + searchService: http://localhost:4000 dataService: http://localhost:9093 brokerService: http://localhost/admin/broker - authService: http://localhost/api/auth - storageService: http://localhost/api/storage + authService: http://localhost:8080 + storageService: http://storage-service:9000 pid: base: http://localhost/pid/ jwt: diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml index ca7cec2ea5045c077bc58c4817546aff8d0d1f75..326e628b2cf096c8fb8cd2c969ee1219d825dadd 100644 --- a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml @@ -51,7 +51,7 @@ logging: dbrepo: repository-name: "${REPOSITORY_NAME:Database Repository}" base-url: "${BASE_URL:http://localhost}" - admin-email: "${ADMIN_EMAIL:noreply@example.com}" + admin-email: "${ADMIN_MAIL:noreply@example.com}" deleted-record: "${DELETED_RECORD:persistent}" granularity: "${GRANULARITY:YYYY-MM-DDThh:mm:ssZ}" exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}" @@ -66,12 +66,11 @@ dbrepo: username: "${ADMIN_USERNAME:admin}" password: "${ADMIN_PASSWORD:admin}" endpoints: - searchService: "${SEARCH_SERVICE_ENDPOINT:http://gateway-service}" - analyseService: "${ANALYSE_SERVICE_ENDPOINT:http://gateway-service}" + searchService: "${SEARCH_SERVICE_ENDPOINT:http://search-service:8080}" dataService: "${DATA_SERVICE_ENDPOINT:http://data-service:8080}" brokerService: "${BROKER_SERVICE_ENDPOINT:http://gateway-service/admin/broker}" - authService: "${AUTH_SERVICE_ENDPOINT:http://gateway-service/api/auth}" - storageService: "${S3_ENDPOINT:http://gateway-service/api/storage}" + authService: "${AUTH_SERVICE_ENDPOINT:http://auth-service:8080}" + storageService: "${S3_ENDPOINT:http://storage-service:9000}" pid: base: "${PID_BASE:http://localhost/pid/}" jwt: diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index e5e5097edeedebed520ce7156af79b6e3f88bd3b..6bc0b98692a24b29f30d04c1dc4784e89c027cb0 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -897,7 +897,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { Principal principal, User user, DatabaseAccess access) throws MalformedException, NotAllowedException, ServiceException, ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, TableNotFoundException, - TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { + TableExistsException, SearchServiceException, SearchServiceConnectionException { /* mock */ if (principal != null) { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java index 28ab4ccb41133b237c033adbf77c85e9dcf7bb3f..e253d4f764d73a3aa8890ea9ade0b59cddc46a50 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java @@ -152,7 +152,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { } @Test - public void customDatabaseToDatabaseDto_succeeds() { + public void databaseToDatabaseDto_succeeds() { /* test */ final DatabaseDto response = metadataMapper.customDatabaseToDatabaseDto(DATABASE_1); @@ -289,11 +289,6 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { final ForeignKeyReferenceDto table1fkr = table1fk.getReferences().get(0); assertEquals(1L, table1fkr.getId()); assertEquals(TABLE_2_COLUMNS_DTO.get(2).getId(), table1fkr.getColumn().getId()); - assertEquals(TABLE_2_COLUMNS_DTO.get(2).getTable().getId(), table1fkr.getColumn().getTableId()); - assertEquals(TABLE_2_COLUMNS_DTO.get(2).getDatabaseId(), table1fkr.getColumn().getDatabaseId()); - assertEquals(TABLE_1_COLUMNS_DTO.get(0).getDatabaseId(), table1fkr.getReferencedColumn().getId()); - assertEquals(TABLE_1_COLUMNS_DTO.get(0).getDatabaseId(), table1fkr.getReferencedColumn().getTableId()); - assertEquals(TABLE_1_COLUMNS_DTO.get(0).getDatabaseId(), table1fkr.getReferencedColumn().getDatabaseId()); assertEquals(1, table1.getConstraints().getPrimaryKey().size()); final PrimaryKeyDto table1pk = new ArrayList<>(table1.getConstraints().getPrimaryKey()).get(0); assertEquals(2L, table1pk.getId()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index 44b924f39613f1dbf0dfe951164d6210a6c3d51d..76678a1fe376b77926d1929b5888a649e2c9d512 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -538,7 +538,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID); + tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID, TableStatisticDto.builder().build()); } catch (Exception e) { /* ignore */ } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java index 24536a9ca56a9686e13905a46d7326d4863fa6c7..91b64ef93c52e38a83a42fb4d39cd0c966f2ce67 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest +@Disabled("CI/CD") @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) public class TableServicePersistenceTest extends AbstractUnitTest { @@ -78,7 +79,7 @@ public class TableServicePersistenceTest extends AbstractUnitTest { @Test @Transactional public void create_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, - UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { + UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException { final TableCreateDto request = TableCreateDto.builder() .name("New Table") .description("A wonderful table") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index c16a4191f90cdf1a3228bad5879a40f375abe409..6dfcb5187ec6237929d5c158ddcd6f21900f7356 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -119,8 +119,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { @Test public void createTable_succeeds() throws ServiceException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, - SearchServiceConnectionException, MalformedException, OntologyNotFoundException, - SemanticEntityNotFoundException { + SearchServiceConnectionException, MalformedException { /* mock */ when(userService.findByUsername(USER_1_USERNAME)) @@ -141,8 +140,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { @Test public void createTable_nonStandardColumnNames_succeeds() throws ServiceException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, - SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, - SemanticEntityNotFoundException { + SearchServiceException, SearchServiceConnectionException, MalformedException { final TableCreateDto request = TableCreateDto.builder() .name("New Table") .description("A wonderful table") @@ -242,8 +240,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { @Test public void create_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, - SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, - SemanticEntityNotFoundException { + SearchServiceException, SearchServiceConnectionException { /* mock */ when(userService.findByUsername(USER_1_USERNAME)) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java index fc83d3a650b5642bbe0e8cdc252e95ef59c9dcf5..f686a1c23a15b4728395ee3ca0c0ec0353071a45 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java @@ -1,10 +1,7 @@ package at.tuwien.service; -import at.tuwien.entities.database.Database; import at.tuwien.entities.database.View; import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; import at.tuwien.repository.ContainerRepository; import at.tuwien.repository.DatabaseRepository; import at.tuwien.repository.LicenseRepository; @@ -17,16 +14,12 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @@ -50,12 +43,6 @@ public class ViewServicePersistenceTest extends AbstractUnitTest { @Autowired private ViewService viewService; - @MockBean - private DataServiceGateway dataServiceGateway; - - @MockBean - private SearchServiceGateway searchServiceGateway; - @BeforeEach public void beforeEach() { genesis(); @@ -78,19 +65,4 @@ public class ViewServicePersistenceTest extends AbstractUnitTest { assertEquals(VIEW_1_COLUMNS.size(), response.getColumns().size()); } - @Test - public void delete_succeeds() throws SearchServiceException, ServiceException, ServiceConnectionException, - DatabaseNotFoundException, SearchServiceConnectionException, ViewNotFoundException { - - /* mock */ - doNothing() - .when(dataServiceGateway) - .deleteView(DATABASE_1_ID, VIEW_1_ID); - when(searchServiceGateway.update(any(Database.class))) - .thenReturn(DATABASE_1_DTO); - - /* test */ - viewService.delete(VIEW_1); - } - } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index c64fc52282af3dc8fb3f6bc075ad080e5f162f0c..d0029e9458d26144a0921ab3008f202bd01e4c63 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -30,9 +30,6 @@ public class GatewayConfig { @Value("${dbrepo.endpoints.dataService}") private String dataEndpoint; - @Value("${dbrepo.endpoints.analyseService}") - private String analyseEndpoint; - @Value("${dbrepo.endpoints.searchService}") private String searchEndpoint; @@ -57,7 +54,6 @@ public class GatewayConfig { public RestTemplate brokerRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(brokerEndpoint)); - log.debug("add basic authentication for broker service: username={}, password=(hidden)", brokerUsername); restTemplate.getInterceptors() .addAll(List.of(new BasicAuthenticationInterceptor(brokerUsername, brokerPassword), clientHttpRequestInterceptor())); @@ -68,18 +64,7 @@ public class GatewayConfig { public RestTemplate dataServiceRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(dataEndpoint)); - log.debug("add basic authentication for data service: username={}, password=(hidden)", adminUsername); - restTemplate.getInterceptors() - .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), - clientHttpRequestInterceptor())); - return restTemplate; - } - - @Bean("analyseServiceRestTemplate") - public RestTemplate analyseServiceRestTemplate() { - final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(analyseEndpoint)); - log.debug("add basic authentication for analyse service: username={}, password=(hidden)", adminUsername); + log.debug("add basic authentication for internal data service: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), clientHttpRequestInterceptor())); @@ -90,7 +75,7 @@ public class GatewayConfig { public RestTemplate searchServiceRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(searchEndpoint)); - log.debug("add basic authentication for search service: username={}, password=(hidden)", adminUsername); + log.debug("add basic authentication for internal search service: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), clientHttpRequestInterceptor())); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java index 9edb9f388da8ef481f2ec1b18522f8bc4695b954..d8ba8a490fc41d3bff8234a1d2ea6e0fd9c42951 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java @@ -9,7 +9,6 @@ import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableStatisticDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.exception.*; @@ -42,6 +41,4 @@ public interface DataServiceGateway { List<TableDto> getTableSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; List<ViewDto> getViewSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; - - TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, TableNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java index b86780f5c43401f7a206be3125f54d593ac641ac..8ab7c8a7309d319949f3abde033534e5fb76f5a7 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java @@ -2,6 +2,7 @@ package at.tuwien.gateway.impl; import at.tuwien.api.amqp.*; import at.tuwien.api.user.ExchangeUpdatePermissionsDto; +import at.tuwien.config.GatewayConfig; import at.tuwien.config.RabbitConfig; import at.tuwien.exception.*; import at.tuwien.gateway.BrokerServiceGateway; @@ -20,12 +21,15 @@ import org.springframework.web.client.RestTemplate; public class BrokerServiceGatewayImpl implements BrokerServiceGateway { private final RestTemplate restTemplate; + private final GatewayConfig gatewayConfig; private final RabbitConfig rabbitConfig; @Autowired - public BrokerServiceGatewayImpl(@Qualifier("brokerRestTemplate") RestTemplate restTemplate, + public BrokerServiceGatewayImpl(GatewayConfig gatewayConfig, + @Qualifier("brokerRestTemplate") RestTemplate restTemplate, RabbitConfig rabbitMqConfig) { this.restTemplate = restTemplate; + this.gatewayConfig = gatewayConfig; this.rabbitConfig = rabbitMqConfig; } @@ -33,6 +37,7 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { public void grantTopicPermission(String username, ExchangeUpdatePermissionsDto data) throws ServiceConnectionException, ServiceException { final String url = "/api/topic-permissions/" + rabbitConfig.getVirtualHost() + "/" + username; + log.debug("grant topic permission in url {}{}", gatewayConfig.getBrokerEndpoint(), url); final ResponseEntity<Void> response; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); @@ -52,6 +57,7 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { @Override public void grantVirtualHostPermission(String username, GrantVirtualHostPermissionsDto data) throws ServiceConnectionException, ServiceException { final String url = "/api/permissions/" + rabbitConfig.getVirtualHost() + "/" + username; + log.debug("grant virtual host permissions in url {}{}", gatewayConfig.getBrokerEndpoint(), url); final ResponseEntity<Void> response; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); @@ -71,6 +77,7 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { @Override public void grantExchangePermission(String username, GrantExchangePermissionsDto data) throws ServiceConnectionException, ServiceException { final String url = "/api/topic-permissions/" + rabbitConfig.getVirtualHost() + "/" + username; + log.debug("grant topic permissions in url {}{}", gatewayConfig.getBrokerEndpoint(), url); final ResponseEntity<Void> response; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); @@ -92,6 +99,8 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { final String url = "/api/queues/" + rabbitConfig.getVirtualHost() + "/" + name; final HttpHeaders headers = new HttpHeaders(); headers.set("Accept", "application/json"); + log.trace("gateway broker find queue, virtual host={}, queue={}", rabbitConfig.getVirtualHost(), name); + log.debug("find queue from url {}{}", gatewayConfig.getBrokerEndpoint(), url); final ResponseEntity<QueueDto> response; try { response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), QueueDto.class); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java index 6c09d6d50067be958efc69cfbc28fa866cfec803..a278fc60b97ecfa0bc58aa771965ddf6b60f8f91 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java @@ -6,7 +6,6 @@ import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableStatisticDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; @@ -16,6 +15,7 @@ import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import java.util.Arrays; @@ -37,10 +37,12 @@ public class DataServiceGatewayImpl implements DataServiceGateway { throws ServiceConnectionException, ServiceException, DatabaseNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/access/" + userId; + log.debug("create access in data service"); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(UpdateDatabaseAccessDto.builder().type(access).build()), Void.class); - } catch (HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to create access: {}", e.getMessage()); throw new ServiceConnectionException("Failed to create access: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -61,10 +63,12 @@ public class DataServiceGatewayImpl implements DataServiceGateway { throws ServiceConnectionException, ServiceException, AccessNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/access/" + userId; + log.debug("update access in data service"); try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(UpdateDatabaseAccessDto.builder().type(access).build()), Void.class); - } catch (HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to update access: {}", e.getMessage()); throw new ServiceConnectionException("Failed to update access: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -85,9 +89,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { AccessNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/access/" + userId; + log.debug("delete access in data service"); try { - response = restTemplate.exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to delete access: {}", e.getMessage()); throw new ServiceConnectionException("Failed to delete access: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -107,9 +113,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { public DatabaseDto createDatabase(CreateDatabaseDto data) throws ServiceConnectionException, ServiceException { final ResponseEntity<DatabaseDto> response; final String url = "/api/database"; + log.debug("create database in data service"); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), DatabaseDto.class); - } catch (HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to create database: {}", e.getMessage()); throw new ServiceConnectionException("Failed to create database: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { @@ -128,9 +136,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { ServiceException, DatabaseNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId; + log.debug("update database in data service"); try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); - } catch (HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to update user password in database: {}", e.getMessage()); throw new ServiceConnectionException("Failed to update user password in database: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -151,9 +161,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { DatabaseNotFoundException, TableExistsException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/table"; + log.debug("create table in data service"); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), Void.class); - } catch (HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to create table: {}", e.getMessage()); throw new ServiceConnectionException("Failed to create table: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -177,9 +189,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { TableNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/table/" + tableId; + log.debug("delete table in data service"); try { - response = restTemplate.exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to delete table: {}", e.getMessage()); throw new ServiceConnectionException("Failed to delete table: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -199,9 +213,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { public ViewDto createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException { final ResponseEntity<ViewDto> response; final String url = "/api/database/" + databaseId + "/view"; + log.debug("create view in data service"); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), ViewDto.class); - } catch (HttpServerErrorException e) { + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to create view: {}", e.getMessage()); throw new ServiceConnectionException("Failed to create view: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { @@ -224,9 +240,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { ViewNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/view/" + viewId; + log.debug("delete view in data service"); try { - response = restTemplate.exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to delete view: {}", e.getMessage()); throw new ServiceConnectionException("Failed to delete view: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -247,9 +265,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { QueryNotFoundException { final ResponseEntity<QueryDto> response; final String url = "/api/database/" + databaseId + "/subset/" + queryId; + log.debug("get query in data service"); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, QueryDto.class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), QueryDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to find query: {}", e.getMessage()); throw new ServiceConnectionException("Failed to find query", e); } catch (HttpClientErrorException.NotFound e) { @@ -274,9 +294,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { ServiceException, QueryNotFoundException { final ResponseEntity<ExportResourceDto> response; final String url = "/api/database/" + databaseId + "/subset/" + queryId; + log.debug("export query in data service"); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ExportResourceDto.class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), ExportResourceDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to export query: {}", e.getMessage()); throw new ServiceConnectionException("Failed to export query: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -297,9 +319,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { public List<TableDto> getTableSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException { final ResponseEntity<TableDto[]> response; final String url = "/api/database/" + databaseId + "/table"; + log.debug("retrieve table schema metadata in data service"); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, TableDto[].class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), TableDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to get table schemas: {}", e.getMessage()); throw new ServiceConnectionException("Failed to get table schemas: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -327,8 +351,9 @@ public class DataServiceGatewayImpl implements DataServiceGateway { final ResponseEntity<ViewDto[]> response; final String url = "/api/database/" + databaseId + "/view"; try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ViewDto[].class); - } catch (HttpServerErrorException e) { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), ViewDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { log.error("Failed to get view schemas: {}", e.getMessage()); throw new ServiceConnectionException("Failed to get view schemas: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { @@ -351,31 +376,4 @@ public class DataServiceGatewayImpl implements DataServiceGateway { return views; } - @Override - public TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, TableNotFoundException { - final ResponseEntity<TableStatisticDto> response; - final String url = "/api/database/" + databaseId + "/table/" + tableId + "/statistic"; - try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, TableStatisticDto.class); - } catch (HttpServerErrorException e) { - log.error("Failed to analyse table statistic: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to analyse table statistic: " + e.getMessage(), e); - } catch (HttpClientErrorException.NotFound e) { - log.error("Failed to analyse table statistic: not found: {}", e.getMessage()); - throw new TableNotFoundException("Failed to analyse table statistic: not found: " + e.getMessage(), e); - } catch (HttpClientErrorException.Unauthorized e) { - log.error("Failed to analyse table statistic: {}", e.getMessage()); - throw new ServiceException("Failed to analyse table statistic: " + e.getMessage(), e); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to analyse table statistic: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to analyse table statistic: wrong http code: " + response.getStatusCode()); - } - if (response.getBody() == null) { - log.error("Failed to analyse table statistic: empty body: {}", response.getStatusCode()); - throw new ServiceException("Failed to analyse table statistic: empty body: " + response.getStatusCode()); - } - return response.getBody(); - } - } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java index deba8360f21d2ac982c00dd959617f4c49f7059e..49a2a1423ccae657f03f490c5a43cc3b7c057274 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java @@ -1,6 +1,7 @@ package at.tuwien.gateway.impl; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.entities.database.Database; import at.tuwien.exception.*; import at.tuwien.gateway.SearchServiceGateway; @@ -15,6 +16,9 @@ import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import java.util.LinkedList; +import java.util.List; + @Log4j2 @Service public class SearchServiceGatewayImpl implements SearchServiceGateway { @@ -36,6 +40,7 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { headers.set("Accept", "application/json"); headers.set("Content-Type", "application/json"); final String url = "/api/search/database/" + database.getId(); + log.debug("update database in search service"); try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>( metadataMapper.customDatabaseToDatabaseDto(database), headers), DatabaseDto.class); @@ -48,7 +53,7 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { throw new DatabaseNotFoundException("Failed to update database: not found", e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { log.error("Failed to update database: malformed payload: {}", e.getMessage()); - throw new SearchServiceException("Failed to update database: malformed payload: " + e.getMessage(), e); + throw new SearchServiceException("Failed to update database: malformed payload", e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to update database: response code is not 202"); @@ -61,6 +66,7 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { public void delete(Long databaseId) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException { final ResponseEntity<Void> response; final String url = "/api/search/database/" + databaseId; + log.trace("delete to url {}", url); try { response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null), Void.class); } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java index 94fa1e0c890637d62e3faa20382c0fb668d8904a..88e90908f8bf225cfb973c44b46551bd16435ea6 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java @@ -7,8 +7,6 @@ import java.util.List; public interface ConceptService { - TableColumnConcept create(TableColumnConcept concept); - /** * Finds all table column concepts in the metadata database. * diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java index 0eb228ccd5d0a284b3c94e5735cff525ff86dfe1..22d0f1781b6f045599302b14d8344652bc077256 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java @@ -44,7 +44,7 @@ public interface TableService { */ Table createTable(Database database, TableCreateDto createDto, Principal principal) throws TableNotFoundException, ServiceException, ServiceConnectionException, UserNotFoundException, - DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException; + DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException; /** * Deletes a table from the database in the metadata database and data database. @@ -58,5 +58,8 @@ public interface TableService { TableColumn findColumnById(Table table, Long columnId) throws MalformedException; - void updateStatistics(Table table) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, ServiceException, ServiceConnectionException; + TableColumn findColumnByName(Table table, String name) throws MalformedException; + + @Transactional + void updateStatistics(Table table, TableStatisticDto data) throws MalformedException, SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java index 93824eeb62b94ca5191526b5cb8c576acc9ed433..c45d78c48c2bc68a700d44876f157cd8f1282803 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java @@ -2,14 +2,11 @@ package at.tuwien.service; import at.tuwien.entities.database.table.columns.TableColumnUnit; import at.tuwien.exception.UnitNotFoundException; -import org.springframework.transaction.annotation.Transactional; import java.util.List; public interface UnitService { - TableColumnUnit create(TableColumnUnit unit); - /** * Finds all table column units in the metadata database. * diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java index d19a3be73beab67d160e09dc892f2a0c46faaee1..f2346ec34064b0a1b0ef44b6ca3790c6330b3c7f 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -33,8 +33,7 @@ public interface ViewService { * * @param view The view. */ - void delete(View view) throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, - ViewNotFoundException, SearchServiceException, SearchServiceConnectionException; + void delete(View view) throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException; /** * Creates a view in the container with given id and database with id with the given query. diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java index 647d4fe198abc4b4ab4caf3836ab552bb521ce2c..8dd0b76a844dde64ff395eff8dcd8fe808ffef75 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java @@ -23,12 +23,6 @@ public class ConceptServiceImpl implements ConceptService { this.conceptRepository = conceptRepository; } - @Override - @Transactional - public TableColumnConcept create(TableColumnConcept concept) { - return conceptRepository.save(concept); - } - @Override @Transactional(readOnly = true) public List<TableColumnConcept> findAll() { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java index 16d23d7af1d31c4bbefa50c607f6ad42b23eac8e..c4a8187b5255cfea46ec0ebb19b80977014afa46 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java @@ -6,7 +6,6 @@ import at.tuwien.api.database.DatabaseModifyVisibilityDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.entities.container.Container; @@ -41,7 +40,7 @@ public class DatabaseServiceImpl implements DatabaseService { @Autowired public DatabaseServiceImpl(MetadataMapper metadataMapper, ContainerService containerService, - DatabaseRepository databaseRepository, DataServiceGateway dataServiceGateway, + DatabaseRepository databaseRepository, DataServiceGateway dataServiceGateway, SearchServiceGateway searchServiceGateway) { this.metadataMapper = metadataMapper; this.containerService = containerService; @@ -223,7 +222,7 @@ public class DatabaseServiceImpl implements DatabaseService { fk.setTable(tableEntity); }); /* map primary key constraint */ - for (PrimaryKey key : tableEntity.getConstraints().getPrimaryKey()) { + for (PrimaryKeyDto key : table.getConstraints().getPrimaryKey()) { final Optional<TableColumn> optional = tableEntity.getColumns() .stream() .filter(c -> c.getInternalName().equals(key.getColumn().getInternalName())) @@ -232,8 +231,12 @@ public class DatabaseServiceImpl implements DatabaseService { log.error("Failed to find primary key column {} in table {}.{}", key.getColumn().getInternalName(), database.getInternalName(), table.getInternalName()); throw new MalformedException("Failed to find primary key column: " + key.getColumn().getInternalName()); } - key.setTable(tableEntity); - key.setColumn(optional.get()); + tableEntity.getConstraints() + .getPrimaryKey() + .add(PrimaryKey.builder() + .table(tableEntity) + .column(optional.get()) + .build()); } database.getTables() .add(tableEntity); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index e8fecdf300095d9d936a6bdf1a9269b141952bcd..bf5ca0a98f13d2233f5fd6b2a896348f9955d732 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -36,6 +36,7 @@ public class TableServiceImpl implements TableService { private final UserService userService; private final UnitService unitService; + private final SparqlMapper ontologyMapper; private final RabbitConfig rabbitConfig; private final EntityService entityService; private final ConceptService conceptService; @@ -46,12 +47,14 @@ public class TableServiceImpl implements TableService { private final SearchServiceGateway searchServiceGateway; @Autowired - public TableServiceImpl(UserService userService, UnitService unitService, RabbitConfig rabbitConfig, - EntityService entityService, ConceptService conceptService, MetadataMapper metadataMapper, - DatabaseService databaseService, DataServiceGateway dataServiceGateway, - DatabaseRepository databaseRepository, SearchServiceGateway searchServiceGateway) { + public TableServiceImpl(UserService userService, UnitService unitService, SparqlMapper ontologyMapper, + RabbitConfig rabbitConfig, EntityService entityService, ConceptService conceptService, + MetadataMapper metadataMapper, DatabaseService databaseService, + DataServiceGateway dataServiceGateway, DatabaseRepository databaseRepository, + SearchServiceGateway searchServiceGateway) { this.userService = userService; this.unitService = unitService; + this.ontologyMapper = ontologyMapper; this.rabbitConfig = rabbitConfig; this.entityService = entityService; this.conceptService = conceptService; @@ -98,7 +101,7 @@ public class TableServiceImpl implements TableService { @Transactional public Table createTable(Database database, TableCreateDto data, Principal principal) throws ServiceException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, - TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException { + TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException { final User owner = userService.findByUsername(principal.getName()); /* check */ if (data.getConstraints().getPrimaryKey().isEmpty()) { @@ -131,59 +134,36 @@ public class TableServiceImpl implements TableService { .creator(owner) .ownedBy(owner.getId()) .owner(owner) - .numRows(0L) - .dataLength(0L) .identifiers(new LinkedList<>()) .columns(new LinkedList<>()) .build(); try { /* set the ordinal position for the columns */ - final int[] idx = new int[]{0}; - for (int i = 0; i < data.getColumns().size(); i++) { - final ColumnCreateDto c = data.getColumns().get(i); - final TableColumn column = metadataMapper.columnCreateDtoToTableColumn(c, database.getContainer().getImage()); - column.setOrdinalPosition(idx[0]++); - column.setTable(table); - if (data.isNeedSequence() && column.getName().equals("id")) { - column.setAutoGenerated(true); - } - if (c.getUnitUri() != null) { - log.trace("column {} has assigned unit uri: {}", column.getInternalName(), c.getUnitUri()); - TableColumnUnit unit; - try { - unit = unitService.find(c.getUnitUri()); - } catch (UnitNotFoundException e) { - unit = unitService.create(metadataMapper.entityDtoToTableColumnUnit(entityService.findOneByUri(c.getUnitUri()))); - } - column.setUnit(unit); - } - if (c.getConceptUri() != null) { - log.trace("column {} has assigned concept uri: {}", column.getInternalName(), c.getConceptUri()); - TableColumnConcept concept; - try { - concept = conceptService.find(c.getConceptUri()); - } catch (ConceptNotFoundException e) { - concept = conceptService.create(metadataMapper.entityDtoToTableColumnConcept(entityService.findOneByUri(c.getConceptUri()))); - } - column.setConcept(concept); - } - if (List.of(TableColumnType.TIME, TableColumnType.TIMESTAMP, TableColumnType.DATE, TableColumnType.DATETIME).contains(column.getColumnType())) { - final Optional<ContainerImageDate> optional = database.getContainer() - .getImage() - .getDateFormats() + table.getColumns() + .addAll(data.getColumns() .stream() - .filter(df -> df.getId().equals(c.getDfid())) - .findFirst(); - if (optional.isEmpty()) { - log.error("Failed to find date format with id {} in metadata database", c.getDfid()); - throw new IllegalArgumentException("Failed to find date format in metadata database"); - } - column.setDateFormat(optional.get()); - log.debug("column is of temporal type: added date format with id {}", column.getDateFormat().getId()); - } - table.getColumns() - .add(column); - } + .map(c -> { + final TableColumn column = metadataMapper.columnCreateDtoToTableColumn(c, database.getContainer().getImage()); + if (data.isNeedSequence() && column.getName().equals("id")) { + column.setAutoGenerated(true); + } + if (List.of(TableColumnType.TIME, TableColumnType.TIMESTAMP, TableColumnType.DATE, TableColumnType.DATETIME).contains(column.getColumnType())) { + final Optional<ContainerImageDate> optional = database.getContainer() + .getImage() + .getDateFormats() + .stream() + .filter(df -> df.getId().equals(c.getDfid())) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find date format with id {} in metadata database", c.getDfid()); + throw new IllegalArgumentException("Failed to find date format in metadata database"); + } + column.setDateFormat(optional.get()); + log.debug("column is of temporal type: added date format with id {}", column.getDateFormat().getId()); + } + return column; + }) + .toList()); /* set constraints */ table.setConstraints(metadataMapper.constraintsCreateDtoToConstraints(data.getConstraints(), database, table)); } catch (IllegalArgumentException e) { @@ -196,8 +176,13 @@ public class TableServiceImpl implements TableService { throw new MalformedException("Failed to create table: some unique constraint(s) reference non-existing table columns"); } } - database.getTables() - .add(table); + int[] idx = {0}; + table.getColumns() + .forEach(column -> { + column.setTable(table); + column.setOrdinalPosition(idx[0]++); + }); + database.getTables().add(table); /* create in data service */ dataServiceGateway.createTable(database.getId(), data); /* update in metadata database */ @@ -285,35 +270,51 @@ public class TableServiceImpl implements TableService { return optional.get(); } + @Override + @Transactional(readOnly = true) + public TableColumn findColumnByName(Table table, String name) throws MalformedException { + final Optional<TableColumn> optional = table.getColumns() + .stream() + .filter(c -> c.getInternalName().equals(name)) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find column with name {} in table with name {}", name, table.getInternalName()); + throw new MalformedException("Failed to find column in metadata database"); + } + return optional.get(); + } + @Override @Transactional - public void updateStatistics(Table table) throws SearchServiceException, - DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, - ServiceException, ServiceConnectionException { - final TableStatisticDto statistic = dataServiceGateway.getTableStatistics(table.getTdbid(), table.getId()); - table.setNumRows(statistic.getRows()); - for (Map.Entry<String, ColumnStatisticDto> entry : statistic.getColumns().entrySet()) { - final Optional<TableColumn> optional = table.getColumns().stream().filter(c -> c.getInternalName().equals(entry.getKey())).findFirst(); - if (optional.isEmpty()) { - log.error("Failed to assign table column statistic: column {} does not exist in table {}.{}", entry.getKey(), table.getDatabase().getInternalName(), table.getInternalName()); - throw new MalformedException("Failed to assign table column statistic: column does not exist"); - } - final TableColumn column = optional.get(); - final ColumnStatisticDto columnStatistic = statistic.getColumns().get(entry.getKey()); - column.setMean(columnStatistic.getMean()); - column.setMedian(columnStatistic.getMedian()); - column.setMin(columnStatistic.getMin()); - column.setMax(columnStatistic.getMax()); - column.setStdDev(columnStatistic.getStdDev()); + public void updateStatistics(Table table, TableStatisticDto data) throws MalformedException, SearchServiceException, + DatabaseNotFoundException, SearchServiceConnectionException { + final List<String> notFound = data.getColumns() + .keySet() + .stream() + .filter(key -> table.getColumns().stream().noneMatch(c -> c.getInternalName().equals(key))) + .toList(); + if (!notFound.isEmpty()) { + log.error("Failed to update statistics: column(s) not found: {}", notFound); + throw new MalformedException("Failed to update statistics: column(s) not found"); } + table.getColumns() + .forEach(column -> { + if (!data.getColumns().containsKey(column.getInternalName())) { + return; + } + final ColumnStatisticDto statistic = data.getColumns().get(column.getInternalName()); + column.setMean(statistic.getMean()); + column.setMedian(statistic.getMedian()); + column.setMin(statistic.getMin()); + column.setMax(statistic.getMax()); + }); /* update in metadata database */ final Database database = table.getDatabase(); database.getTables() .set(database.getTables().indexOf(table), table); - databaseRepository.save(database); /* update in open search service */ searchServiceGateway.update(database); - log.info("Updated statistics of table with id: {}", table.getId()); + log.info("Updated table statistics"); } } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java index 03270abcd597683a39e106a1bb12325719a9dde0..c0bcf19f2881cd3cbf01803a5fd7bbaa9becbfc9 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java @@ -23,12 +23,6 @@ public class UnitServiceImpl implements UnitService { this.unitRepository = unitRepository; } - @Override - @Transactional - public TableColumnUnit create(TableColumnUnit unit) { - return unitRepository.save(unit); - } - @Override @Transactional(readOnly = true) public List<TableColumnUnit> findAll() { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java index a91e03284403b63453f129467f6ce7adaf7c0f90..f9d888b5a0bd4117ce56ca2d5be81d8b9751a8c7 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java @@ -105,13 +105,7 @@ public class ViewServiceImpl implements ViewService { .build(); /* create in data service */ data.setName(view.getInternalName()); - final ViewDto rawView = dataServiceGateway.createView(database.getId(), data); - view.setColumns(rawView.getColumns() - .stream() - .map(metadataMapper::viewColumnDtoToViewColumn) - .toList()); - view.getColumns() - .forEach(column -> column.setView(view)); + final ViewDto dto = dataServiceGateway.createView(database.getId(), data); database.getViews() .add(view); database = databaseRepository.save(database); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index cf32bf4f005830c3aff5ff22b13dea03df26bb3e..3ba5fc9e360d907f68b9fa2a44974e87a8af8054 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -28,7 +28,6 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); TABLE_1_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); - VIEW_1_DTO.setDatabase(DATABASE_1_DTO); DATABASE_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))); DATABASE_1.setTables(new LinkedList<>(List.of(TABLE_1, TABLE_2, TABLE_3, TABLE_4))); DATABASE_1.setViews(new LinkedList<>(List.of(VIEW_1, VIEW_2, VIEW_3))); @@ -42,7 +41,6 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_2_CONSTRAINTS.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_2_CONSTRAINTS.getForeignKeys().get(0)); TABLE_2.setConstraints(TABLE_2_CONSTRAINTS); TABLE_2_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_2_COLUMNS_DTO)); - TABLE_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); TABLE_2_DTO.setColumns(TABLE_2_COLUMNS_DTO); TABLE_2_DTO.setConstraints(TABLE_2_CONSTRAINTS_DTO); TABLE_3.setDatabase(DATABASE_1); @@ -78,8 +76,6 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_5.setDatabase(DATABASE_2); TABLE_5.setColumns(new LinkedList<>(TABLE_5_COLUMNS)); TABLE_5.setConstraints(TABLE_5_CONSTRAINTS); - TABLE_5_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_5_COLUMNS_DTO)); - TABLE_5_PRIVILEGED_DTO.setDatabase(DATABASE_2_PRIVILEGED_DTO); TABLE_5_DTO.setColumns(TABLE_5_COLUMNS_DTO); TABLE_5_DTO.setConstraints(TABLE_5_CONSTRAINTS_DTO); TABLE_6.setDatabase(DATABASE_2); @@ -92,8 +88,8 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_7_CONSTRAINTS.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(1)); TABLE_7_DTO.setColumns(TABLE_7_COLUMNS_DTO); TABLE_7_DTO.setConstraints(TABLE_7_CONSTRAINTS_DTO); - TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_0_DTO); - TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_1_DTO); + TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0)); + TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1)); VIEW_4.setDatabase(DATABASE_2); IDENTIFIER_5.setDatabase(DATABASE_2); /* DATABASE 3 */ diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index fa47be8af84496f5fcbd96fb9c485a9fffdc3ceb..b78619575639f23815785dfb9d50f844b595c455 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -22,7 +22,10 @@ import at.tuwien.api.database.table.columns.*; import at.tuwien.api.database.table.columns.concepts.*; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.*; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyCreateDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; +import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; @@ -186,8 +189,7 @@ public abstract class BaseTest { public final static String[] ESCALATED_QUERY_HANDLING = new String[]{"escalated-query-handling"}; public final static String[] DEFAULT_TABLE_HANDLING = new String[]{"default-table-handling", - "list-tables", "create-table", "modify-table-column-semantics", "find-table", "delete-table", - "update-table-statistic"}; + "list-tables", "create-table", "modify-table-column-semantics", "find-table", "delete-table"}; public final static String[] ESCALATED_TABLE_HANDLING = new String[]{"escalated-table-handling", "delete-foreign-table"}; @@ -1241,7 +1243,6 @@ public abstract class BaseTest { .containerId(CONTAINER_1_ID) .username(USER_1_USERNAME) .password(USER_1_PASSWORD) - .userId(USER_1_ID) .privilegedUsername(CONTAINER_1_PRIVILEGED_USERNAME) .privilegedPassword(CONTAINER_1_PRIVILEGED_PASSWORD) .build(); @@ -1509,7 +1510,7 @@ public abstract class BaseTest { public final static String TABLE_1_INTERNALNAME = "weather_aus"; public final static Boolean TABLE_1_VERSIONED = true; public final static Boolean TABLE_1_PROCESSED_CONSTRAINTS = true; - public final static String TABLE_1_DESCRIPTION = "Weather in Australia"; + public final static String TABLE_1_DESCRIPTION = "Weather in the world"; public final static String TABLE_1_QUEUE_NAME = TABLE_1_INTERNALNAME; public final static String TABLE_1_ROUTING_KEY = "dbrepo\\." + DATABASE_1_ID + "\\." + TABLE_1_ID; public final static Long TABLE_1_DATABASE_ID = DATABASE_1_ID; @@ -1591,8 +1592,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_1_COLUMNS_DTO = List.of(ColumnDto.builder() .id(1L) .table(TABLE_1_DTO) - .tableId(TABLE_1_ID) - .databaseId(DATABASE_1_ID) .name("id") .internalName("id") .ordinalPosition(0) @@ -1605,8 +1604,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(2L) .table(TABLE_1_DTO) - .tableId(TABLE_1_ID) - .databaseId(DATABASE_1_ID) .name("Date") .internalName("date") .ordinalPosition(1) @@ -1620,8 +1617,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(3L) .table(TABLE_1_DTO) - .tableId(TABLE_1_ID) - .databaseId(DATABASE_1_ID) .name("Location") .internalName("location") .ordinalPosition(2) @@ -1635,8 +1630,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(4L) .table(TABLE_1_DTO) - .tableId(TABLE_1_ID) - .databaseId(DATABASE_1_ID) .name("MinTemp") .internalName("mintemp") .ordinalPosition(3) @@ -1651,8 +1644,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(5L) .table(TABLE_1_DTO) - .tableId(TABLE_1_ID) - .databaseId(DATABASE_1_ID) .name("Rainfall") .internalName("rainfall") .ordinalPosition(4) @@ -1673,6 +1664,7 @@ public abstract class BaseTest { .isVersioned(TABLE_1_VERSIONED) .description(TABLE_1_DESCRIPTION) .name(TABLE_1_NAME) + .columns(new LinkedList<>() /* TABLE_1_COLUMNS */) .owner(USER_1_BRIEF_DTO) .build(); @@ -1764,6 +1756,7 @@ public abstract class BaseTest { .isVersioned(TABLE_2_VERSIONED) .description(TABLE_2_DESCRIPTION) .name(TABLE_2_NAME) + .columns(new LinkedList<>() /* TABLE_2_COLUMNS */) .owner(USER_2_BRIEF_DTO) .build(); @@ -1832,6 +1825,7 @@ public abstract class BaseTest { .isVersioned(TABLE_3_VERSIONED) .description(TABLE_3_DESCRIPTION) .name(TABLE_3_NAME) + .columns(new LinkedList<>() /* TABLE_3_COLUMNS */) .owner(USER_3_BRIEF_DTO) .build(); @@ -1874,10 +1868,6 @@ public abstract class BaseTest { public final static String TABLE_5_ROUTING_KEY = "dbrepo\\." + DATABASE_2_ID + "\\." + TABLE_5_ID; public final static Instant TABLE_5_CREATED = Instant.ofEpochSecond(1677400067L) /* 2023-02-26 08:27:47 (UTC) */; public final static Instant TABLE_5_LAST_MODIFIED = Instant.ofEpochSecond(1677400067L) /* 2023-02-26 08:27:47 (UTC) */; - public final static Long TABLE_5_AVG_ROW_LENGTH = 1080L; - public final static Long TABLE_5_NUM_ROWS = 101L; - public final static Long TABLE_5_DATA_LENGTH = 15200L; - public final static Long TABLE_5_MAX_DATA_LENGTH = Long.MAX_VALUE; public final static Table TABLE_5 = Table.builder() .id(TABLE_5_ID) @@ -1912,35 +1902,13 @@ public abstract class BaseTest { .owner(USER_1_DTO) .build(); - public final static PrivilegedTableDto TABLE_5_PRIVILEGED_DTO = PrivilegedTableDto.builder() - .id(TABLE_5_ID) - .tdbid(DATABASE_2_ID) - .database(null) /* DATABASE_2_PRIVILEGED_DTO */ - .created(TABLE_5_CREATED) - .internalName(TABLE_5_INTERNALNAME) - .isVersioned(TABLE_5_VERSIONED) - .description(TABLE_5_DESCRIPTION) - .name(TABLE_5_NAME) - .queueName(TABLE_5_QUEUE_NAME) - .routingKey(TABLE_5_ROUTING_KEY) - .identifiers(new LinkedList<>()) - .columns(new LinkedList<>() /* TABLE_5_COLUMNS_DTO */) - .constraints(null) /* TABLE_5_CONSTRAINTS_DTO */ - .createdBy(USER_5_ID) - .owner(USER_5_DTO) - .isPublic(DATABASE_2_PUBLIC) - .avgRowLength(TABLE_5_AVG_ROW_LENGTH) - .numRows(TABLE_5_NUM_ROWS) - .dataLength(TABLE_5_DATA_LENGTH) - .maxDataLength(TABLE_5_MAX_DATA_LENGTH) - .build(); - public final static TableBriefDto TABLE_5_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_5_ID) .internalName(TABLE_5_INTERNALNAME) .isVersioned(TABLE_5_VERSIONED) .description(TABLE_5_DESCRIPTION) .name(TABLE_5_NAME) + .columns(new LinkedList<>() /* TABLE_5_COLUMNS_DTO */) .owner(USER_1_BRIEF_DTO) .build(); @@ -1996,6 +1964,7 @@ public abstract class BaseTest { .isVersioned(TABLE_6_VERSIONED) .description(TABLE_6_DESCRIPTION) .name(TABLE_6_NAME) + .columns(new LinkedList<>()) /* TABLE_6_COLUMNS_DTO */ .owner(USER_1_BRIEF_DTO) .build(); @@ -2051,6 +2020,7 @@ public abstract class BaseTest { .isVersioned(TABLE_7_VERSIONED) .description(TABLE_7_DESCRIPTION) .name(TABLE_7_NAME) + .columns(new LinkedList<>()) /* TABLE_7_COLUMNS_DTO */ .owner(USER_1_BRIEF_DTO) .build(); @@ -2118,6 +2088,7 @@ public abstract class BaseTest { .internalName(TABLE_4_INTERNALNAME) .description(TABLE_4_DESCRIPTION) .name(TABLE_4_NAME) + .columns(new LinkedList<>() /* TABLE_4_COLUMNS */) .isVersioned(TABLE_4_VERSIONED) .owner(USER_1_BRIEF_DTO) .build(); @@ -2261,6 +2232,7 @@ public abstract class BaseTest { .description(TABLE_8_DESCRIPTION) .isVersioned(TABLE_8_VERSIONED) .name(TABLE_8_NAME) + .columns(new LinkedList<>()) /* TABLE_8_COLUMNS_DTO */ .owner(USER_1_BRIEF_DTO) .build(); @@ -2776,6 +2748,8 @@ public abstract class BaseTest { .columnType(TableColumnType.BIGINT) .isNullAllowed(false) .autoGenerated(false) + .enums(null) + .sets(null) .build(), TableColumn.builder() .id(2L) @@ -2787,6 +2761,8 @@ public abstract class BaseTest { .dateFormat(IMAGE_DATE_1) .isNullAllowed(true) .autoGenerated(false) + .enums(null) + .sets(null) .build(), TableColumn.builder() .id(3L) @@ -2798,6 +2774,8 @@ public abstract class BaseTest { .size(255L) .isNullAllowed(true) .autoGenerated(false) + .enums(null) + .sets(null) .build(), TableColumn.builder() .id(4L) @@ -2810,6 +2788,8 @@ public abstract class BaseTest { .d(0L) .isNullAllowed(true) .autoGenerated(false) + .enums(null) + .sets(null) .build(), TableColumn.builder() .id(5L) @@ -2824,69 +2804,10 @@ public abstract class BaseTest { .unit(UNIT_1) .isNullAllowed(true) .autoGenerated(false) - .build()); - - public final static List<ColumnCreateDto> TABLE_1_COLUMNS_CREATE_DTO = List.of(ColumnCreateDto.builder() - .name("id") - .type(ColumnTypeDto.BIGINT) - .nullAllowed(false) .enums(null) .sets(null) - .build(), - ColumnCreateDto.builder() - .name("Date") - .type(ColumnTypeDto.DATE) - .nullAllowed(true) - .dfid(IMAGE_DATE_1_ID) - .build(), - ColumnCreateDto.builder() - .name("Location") - .type(ColumnTypeDto.VARCHAR) - .size(255L) - .nullAllowed(true) - .dfid(IMAGE_DATE_1_ID) - .build(), - ColumnCreateDto.builder() - .name("MinTemp") - .type(ColumnTypeDto.DECIMAL) - .size(10L) - .d(0L) - .nullAllowed(true) - .dfid(IMAGE_DATE_1_ID) - .build(), - ColumnCreateDto.builder() - .name("Rainfall") - .type(ColumnTypeDto.DECIMAL) - .size(10L) - .d(0L) - .nullAllowed(true) - .dfid(IMAGE_DATE_1_ID) - .conceptUri(CONCEPT_1_URI) - .unitUri(UNIT_1_URI) .build()); - public final static ConstraintsCreateDto TABLE_1_CONSTRAINTS_CREATE_DTO = ConstraintsCreateDto.builder() - .checks(new LinkedHashSet<>()) - .primaryKey(new LinkedHashSet<>(List.of("id"))) - .foreignKeys(new LinkedList<>()) - .uniques(List.of(List.of("date"))) - .build(); - - public final static TableCreateDto TABLE_1_CREATE_DTO = TableCreateDto.builder() - .name(TABLE_1_NAME) - .description(TABLE_1_DESCRIPTION) - .columns(TABLE_1_COLUMNS_CREATE_DTO) - .constraints(TABLE_1_CONSTRAINTS_CREATE_DTO) - .build(); - - public final static at.tuwien.api.database.table.internal.TableCreateDto TABLE_1_CREATE_INTERNAL_DTO = at.tuwien.api.database.table.internal.TableCreateDto.builder() - .name(TABLE_1_NAME) - .description(TABLE_1_DESCRIPTION) - .columns(TABLE_1_COLUMNS_CREATE_DTO) - .constraints(TABLE_1_CONSTRAINTS_CREATE_DTO) - .needSequence(true) - .build(); - public final static List<TableColumn> TABLE_2_COLUMNS = List.of(TableColumn.builder() .id(6L) .ordinalPosition(0) @@ -2939,18 +2860,9 @@ public abstract class BaseTest { .columnType(ColumnTypeDto.VARCHAR) .build(); - public final static ColumnBriefDto TABLE_2_COLUMNS_BRIEF_2_DTO = ColumnBriefDto.builder() - .id(8L) - .name("lng") - .internalName("lng") - .columnType(ColumnTypeDto.DECIMAL) - .build(); - public final static List<ColumnDto> TABLE_2_COLUMNS_DTO = List.of(ColumnDto.builder() .id(6L) .table(TABLE_2_DTO) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) .name("location") .internalName("location") .ordinalPosition(0) @@ -2964,13 +2876,12 @@ public abstract class BaseTest { ColumnDto.builder() .id(7L) .table(TABLE_2_DTO) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) .name("lat") .internalName("lat") .ordinalPosition(1) - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) .isNullAllowed(true) .autoGenerated(false) .enums(null) @@ -2979,13 +2890,12 @@ public abstract class BaseTest { ColumnDto.builder() .id(8L) .table(TABLE_2_DTO) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) .name("lng") .internalName("lng") .ordinalPosition(2) - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) .isNullAllowed(true) .autoGenerated(false) .enums(null) @@ -3455,7 +3365,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_3_COLUMNS_DTO = List.of(ColumnDto.builder() .id(9L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(true) .columnType(ColumnTypeDto.BIGINT) @@ -3469,7 +3378,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(10L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3483,7 +3391,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(11L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3497,7 +3404,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(12L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.DATE) @@ -3511,7 +3417,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(13L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3525,7 +3430,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(14L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3539,7 +3443,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(15L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3553,7 +3456,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(16L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3567,7 +3469,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(17L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3581,7 +3482,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(18L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3595,7 +3495,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(19L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.DATE) @@ -3609,7 +3508,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(20L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3623,7 +3521,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(21L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3637,7 +3534,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(22L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3651,7 +3547,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(23L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3665,7 +3560,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(24L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3679,7 +3573,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(25L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3693,7 +3586,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(26L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3707,7 +3599,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(27L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3721,7 +3612,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(28L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.DATE) @@ -3735,7 +3625,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(29L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3749,7 +3638,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(30L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3763,7 +3651,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(31L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3777,7 +3664,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(32L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3791,7 +3677,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(33L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3805,7 +3690,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(34L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3819,7 +3703,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(35L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3833,7 +3716,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(36L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3847,7 +3729,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(37L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3861,7 +3742,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(38L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3875,7 +3755,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(39L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3889,7 +3768,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(40L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3903,7 +3781,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(41L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3917,7 +3794,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(42L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -3931,7 +3807,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(43L) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .autoGenerated(false) .columnType(ColumnTypeDto.INT) @@ -4164,7 +4039,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_5_COLUMNS_DTO = List.of(ColumnDto.builder() .id(45L) .ordinalPosition(0) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("id") .internalName("id") @@ -4175,7 +4049,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(46L) .ordinalPosition(1) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Animal Name") .internalName("animal_name") @@ -4186,7 +4059,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(47L) .ordinalPosition(2) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Hair") .internalName("hair") @@ -4197,7 +4069,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(48L) .ordinalPosition(3) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Feathers") .internalName("feathers") @@ -4208,7 +4079,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(49L) .ordinalPosition(4) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Bread") .internalName("bread") @@ -4219,7 +4089,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(50L) .ordinalPosition(5) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Eggs") .internalName("eggs") @@ -4230,7 +4099,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(51L) .ordinalPosition(6) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Milk") .internalName("milk") @@ -4241,7 +4109,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(52L) .ordinalPosition(7) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Water") .internalName("water") @@ -4252,7 +4119,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(53L) .ordinalPosition(8) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Airborne") .internalName("airborne") @@ -4263,7 +4129,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(54L) .ordinalPosition(9) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Waterborne") .internalName("waterborne") @@ -4274,7 +4139,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(55L) .ordinalPosition(10) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Aquantic") .internalName("aquantic") @@ -4285,7 +4149,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(56L) .ordinalPosition(11) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Predator") .internalName("predator") @@ -4296,7 +4159,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(57L) .ordinalPosition(12) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Backbone") .internalName("backbone") @@ -4307,7 +4169,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(58L) .ordinalPosition(13) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Breathes") .internalName("breathes") @@ -4318,7 +4179,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(59L) .ordinalPosition(14) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Venomous") .internalName("venomous") @@ -4329,7 +4189,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(60L) .ordinalPosition(15) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Fin") .internalName("fin") @@ -4340,7 +4199,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(61L) .ordinalPosition(16) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Legs") .internalName("legs") @@ -4351,7 +4209,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(62L) .ordinalPosition(17) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Tail") .internalName("tail") @@ -4362,7 +4219,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(63L) .ordinalPosition(18) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Domestic") .internalName("domestic") @@ -4373,7 +4229,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(64L) .ordinalPosition(19) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Catsize") .internalName("catsize") @@ -4384,7 +4239,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(64L) .ordinalPosition(20) - .tableId(TABLE_5_ID) .table(TABLE_5_DTO) .name("Class Type") .internalName("class_type") @@ -4602,7 +4456,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_6_COLUMNS_DTO = List.of(ColumnDto.builder() .id(66L) .ordinalPosition(0) - .tableId(TABLE_6_ID) .table(TABLE_6_DTO) .name("id") .internalName("id") @@ -4613,7 +4466,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(67L) .ordinalPosition(1) - .tableId(TABLE_6_ID) .table(TABLE_6_DTO) .name("firstname") .internalName("firstname") @@ -4624,7 +4476,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(68L) .ordinalPosition(2) - .tableId(TABLE_6_ID) .table(TABLE_6_DTO) .name("lastname") .internalName("lastname") @@ -4635,7 +4486,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(69L) .ordinalPosition(3) - .tableId(TABLE_6_ID) .table(TABLE_6_DTO) .name("birth") .internalName("birth") @@ -4646,7 +4496,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(70L) .ordinalPosition(4) - .tableId(TABLE_6_ID) .table(TABLE_6_DTO) .name("reminder") .internalName("reminder") @@ -4658,7 +4507,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(71L) .ordinalPosition(5) - .tableId(TABLE_6_ID) .table(TABLE_6_DTO) .name("ref_id") .internalName("ref_id") @@ -4712,13 +4560,6 @@ public abstract class BaseTest { .columnType(ColumnTypeDto.BIGINT) .build(); - public final static ColumnBriefDto TABLE_7_COLUMNS_BRIEF_1_DTO = ColumnBriefDto.builder() - .id(27L) - .name("zoo_id") - .internalName("zoo_id") - .columnType(ColumnTypeDto.BIGINT) - .build(); - public final static List<TableColumn> TABLE_7_COLUMNS = List.of(TableColumn.builder() .id(26L) .ordinalPosition(0) @@ -4743,7 +4584,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_7_COLUMNS_DTO = List.of(ColumnDto.builder() .id(26L) .ordinalPosition(0) - .tableId(TABLE_7_ID) .table(TABLE_7_DTO) .name("name_id") .internalName("name_id") @@ -4754,7 +4594,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(27L) .ordinalPosition(1) - .tableId(TABLE_7_ID) .table(TABLE_7_DTO) .name("zoo_id") .internalName("zoo_id") @@ -4776,7 +4615,6 @@ public abstract class BaseTest { public final static List<ViewColumnDto> VIEW_1_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(1L) - .databaseId(DATABASE_1_ID) .name("location") .internalName("location") .ordinalPosition(0) @@ -4787,23 +4625,23 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(2L) - .databaseId(DATABASE_1_ID) .name("lat") .internalName("lat") .ordinalPosition(1) - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) .isNullAllowed(true) .autoGenerated(false) .build(), ViewColumnDto.builder() .id(3L) - .databaseId(DATABASE_1_ID) .name("lng") .internalName("lng") .ordinalPosition(2) - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) .isNullAllowed(true) .autoGenerated(false) .build() @@ -4900,7 +4738,6 @@ public abstract class BaseTest { .query(VIEW_1_QUERY) .queryHash(VIEW_1_QUERY_HASH) .columns(VIEW_1_COLUMNS_DTO) - .database(null) .build(); public final static PrivilegedViewDto VIEW_1_PRIVILEGED_DTO = PrivilegedViewDto.builder() @@ -7575,17 +7412,16 @@ public abstract class BaseTest { public final static ConstraintsDto TABLE_2_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>(List.of("`mintemp` > 0"))) .foreignKeys(new LinkedList<>(List.of(ForeignKeyDto.builder() - .id(1L) .name("fk_location") .onDelete(ReferenceTypeDto.NO_ACTION) .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() .id(1L) - .column(TABLE_2_COLUMNS_BRIEF_2_DTO) - .referencedColumn(TABLE_1_COLUMNS_BRIEF_0_DTO) + .column(TABLE_2_COLUMNS_DTO.get(2)) + .referencedColumn(TABLE_1_COLUMNS_DTO.get(0)) .foreignKey(null) // set later .build()))) - .table(TABLE_1_BRIEF_DTO) - .referencedTable(TABLE_2_BRIEF_DTO) + .table(TABLE_1_DTO) + .referencedTable(TABLE_2_DTO) .onUpdate(ReferenceTypeDto.NO_ACTION) .build()))) .uniques(new LinkedList<>(List.of(UniqueDto.builder() @@ -7725,48 +7561,34 @@ public abstract class BaseTest { .build()))) .build(); - public final static ForeignKeyDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_0_DTO = ForeignKeyDto.builder() - .id(2L) - .name("fk_name_id") - .onDelete(ReferenceTypeDto.NO_ACTION) - .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() - .id(2L) - .column(TABLE_6_COLUMNS_BRIEF_0_DTO) - .referencedColumn(TABLE_7_COLUMNS_BRIEF_0_DTO) - .foreignKey(null) // set later - .build()))) - .table(TABLE_7_BRIEF_DTO) - .referencedTable(TABLE_6_BRIEF_DTO) - .onUpdate(ReferenceTypeDto.NO_ACTION) - .build(); - - public final static ForeignKeyBriefDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_0_DTO = ForeignKeyBriefDto.builder() - .id(2L) - .build(); - - public final static ForeignKeyDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_1_DTO = ForeignKeyDto.builder() - .id(3L) - .name("fk_zoo_id") - .onDelete(ReferenceTypeDto.NO_ACTION) - .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() - .id(3L) - .column(TABLE_5_COLUMNS_BRIEF_0_DTO) - .referencedColumn(TABLE_7_COLUMNS_BRIEF_1_DTO) - .foreignKey(null) // set later - .build()))) - .table(TABLE_7_BRIEF_DTO) - .referencedTable(TABLE_5_BRIEF_DTO) - .onUpdate(ReferenceTypeDto.NO_ACTION) - .build(); - - public final static ForeignKeyBriefDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_1_DTO = ForeignKeyBriefDto.builder() - .id(3L) - .build(); - public final static ConstraintsDto TABLE_7_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) - .foreignKeys(new LinkedList<>(List.of(TABLE_7_CONSTRAINTS_FOREIGN_KEY_0_DTO, - TABLE_7_CONSTRAINTS_FOREIGN_KEY_1_DTO))) + .foreignKeys(new LinkedList<>(List.of(ForeignKeyDto.builder() + .name("fk_name_id") + .onDelete(ReferenceTypeDto.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() + .id(2L) + .column(TABLE_6_COLUMNS_DTO.get(0)) + .referencedColumn(TABLE_7_COLUMNS_DTO.get(0)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_7_DTO) + .referencedTable(TABLE_6_DTO) + .onUpdate(ReferenceTypeDto.NO_ACTION) + .build(), + ForeignKeyDto.builder() + .name("fk_zoo_id") + .onDelete(ReferenceTypeDto.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() + .id(3L) + .column(TABLE_5_COLUMNS_DTO.get(0)) + .referencedColumn(TABLE_7_COLUMNS_DTO.get(1)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_7_DTO) + .referencedTable(TABLE_5_DTO) + .onUpdate(ReferenceTypeDto.NO_ACTION) + .build()))) .uniques(new LinkedList<>()) .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() .table(TABLE_7_BRIEF_DTO) diff --git a/dbrepo-search-service/Dockerfile b/dbrepo-search-service/Dockerfile index 875a9f28bdce23969ac1687e3a2af6fd8b6d0ccf..dfa23dfe8ce0a2b79694be158cdf93d3a2801114 100644 --- a/dbrepo-search-service/Dockerfile +++ b/dbrepo-search-service/Dockerfile @@ -1,7 +1,7 @@ FROM python:3.11-alpine MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> -RUN apk add --no-cache curl bash jq +RUN apk add bash curl WORKDIR /home/alpine diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index a0b551b34afeaa080332b83e6ece463440df3676..c85c4145f461295fa388802c1e6564c8c15c74f7 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -302,45 +302,45 @@ }, "cryptography": { "hashes": [ - "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad", - "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583", - "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b", - "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c", - "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1", - "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648", - "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949", - "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba", - "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c", - "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9", - "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d", - "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c", - "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e", - "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2", - "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d", - "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7", - "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70", - "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2", - "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7", - "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14", - "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe", - "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e", - "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71", - "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961", - "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7", - "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c", - "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28", - "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842", - "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902", - "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801", - "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a", - "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e" + "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55", + "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785", + "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b", + "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886", + "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82", + "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1", + "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda", + "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f", + "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68", + "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60", + "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7", + "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd", + "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582", + "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc", + "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858", + "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b", + "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2", + "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678", + "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13", + "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4", + "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8", + "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604", + "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477", + "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e", + "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a", + "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9", + "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14", + "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda", + "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da", + "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562", + "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2", + "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9" ], "markers": "python_version >= '3.7'", - "version": "==42.0.8" + "version": "==42.0.7" }, "dbrepo": { "hashes": [ - "sha256:2bdb48c70b4c99b5044fbfc12aa653c1e9281ca8913a433cc08a1e14cb4bd2ef" + "sha256:110db9e4e70f5656a6351409d4b022656abf7de0bd72d5e061a25685f708d9a4" ], "path": "./lib/dbrepo-1.4.4.tar.gz" }, @@ -1042,12 +1042,12 @@ }, "pytest": { "hashes": [ - "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343", - "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977" + "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd", + "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.2.2" + "version": "==8.2.1" }, "python-dateutil": { "hashes": [ @@ -1654,12 +1654,12 @@ }, "pytest": { "hashes": [ - "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343", - "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977" + "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd", + "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.2.2" + "version": "==8.2.1" } } } diff --git a/dbrepo-search-service/app.py b/dbrepo-search-service/app.py index 5d3c816ffd35b6e923ffa91644d8c08db7a58723..844c01709f5b92b00a1daa2922be65ba81f106bb 100644 --- a/dbrepo-search-service/app.py +++ b/dbrepo-search-service/app.py @@ -62,7 +62,8 @@ swagger_config = { { "endpoint": "api-search", "route": "/api-search.json", - "rule_filter": lambda rule: rule.endpoint.startswith('search'), + "rule_filter": lambda rule: rule.endpoint.startswith('actuator') or rule.endpoint.startswith( + 'search') or rule.endpoint.startswith('database'), "model_filter": lambda tag: True, # all in } ], @@ -74,79 +75,6 @@ swagger_config = { template = { "openapi": "3.0.0", "components": { - "schemas": { - "IndexDto": { - "required": ["results", "type"], - "properties": { - "results": { - "type": "array", - "items": { - "type": "object", - } - }, - "type": { - "type": "string", - "description": "Same as the requested type", - "enum": ["database", "table", "view", "column", "user", "identifier", "concept", "unit"] - } - } - }, - "IndexFieldsDto": { - "required": ["results"], - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IndexFieldDto" - } - } - } - }, - "IndexFieldDto": { - "required": ["attr_name", "attr_friendly_name", "type"], - "type": "object", - "properties": { - "attr_name": { - "type": "string", - "example": "name" - }, - "attr_friendly_name": { - "type": "string", - "example": "Name" - }, - "type": { - "type": "string", - "example": "string", - "description": "OpenSearch data types." - } - } - }, - "SearchResultDto": { - "required": ["results"], - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "type": "object" - } - } - } - }, - "SearchRequestDto": { - "required": ["search_term", "field_value_pairs"], - "type": "object", - "properties": { - "search_term": { - "type": "string" - }, - "field_value_pairs": { - "type": "object" - } - } - } - }, "securitySchemes": { "bearerAuth": { "type": "http", @@ -164,7 +92,7 @@ template = { "info": { "title": "Database Repository Search Service API", "description": "Service that searches the search database", - "version": "1.4.4", + "version": "__APPVERSION__", "contact": { "name": "Prof. Andreas Rauber", "email": "andreas.rauber@tuwien.ac.at" @@ -176,7 +104,7 @@ template = { }, "externalDocs": { "description": "Sourcecode Documentation", - "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.4.4/" + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/__APPVERSION__/" }, "servers": [ { @@ -283,6 +211,7 @@ def general_filter(index, results): @app.route("/health", methods=["GET"], endpoint="actuator_health") +@swag_from("os-yml/health.yml") def health(): return dict({"status": "UP"}), 200 @@ -427,12 +356,14 @@ def post_general_search(type): return dict({'results': response, 'type': type}), 200 -@app.route("/api/search/database/<int:database_id>", methods=["PUT"], endpoint="search_put_database") +@app.route("/api/search/database/<int:database_id>", methods=["PUT"], endpoint="database_put_database") @metrics.gauge(name='dbrepo_search_update_database', description='Time needed to update a database in the search database') @auth.login_required(role=['admin']) +@swag_from("os-yml/update_database.yml") def update_database(database_id: int) -> Database | ApiError: logging.debug(f"updating database with id: {database_id}") + logging.debug(f"====> {request.json}") try: payload: Database = Database.model_validate(request.json) except ValidationError as e: @@ -455,6 +386,7 @@ def update_database(database_id: int) -> Database | ApiError: @metrics.gauge(name='dbrepo_search_delete_database', description='Time needed to delete a database in the search database') @auth.login_required(role=['admin']) +@swag_from("os-yml/delete_database.yml") def delete_database(database_id: int): try: OpenSearchClient().delete_database(database_id) diff --git a/dbrepo-search-service/init/database.json b/dbrepo-search-service/init/database.json index d87d33b5e29abae3ffbb9beab8bad45a00d0ff56..4e5200c06a3ea304499a5e21ffaa7fdf9b7734d8 100644 --- a/dbrepo-search-service/init/database.json +++ b/dbrepo-search-service/init/database.json @@ -2,123 +2,38 @@ "aliases": {}, "mappings": { "properties": { - "accesses": { - "properties": { - "created": { - "type": "date" - }, - "type": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "user": { - "properties": { - "attributes": { - "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - } - } - }, "contact": { + "type": "object", "properties": { - "attributes": { - "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } + "firstname": { + "type": "keyword" }, "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "lastname": { + "type": "keyword" + }, + "name": { + "type": "keyword" }, "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, "container": { + "type": "object", "properties": { "created": { - "type": "date" + "type": "date", + "format": "strict_date_optional_time" }, "host": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "id": { "type": "long" @@ -128,7 +43,8 @@ "date_formats": { "properties": { "created_at": { - "type": "date" + "type": "date", + "format": "strict_date_optional_time" }, "database_format": { "type": "text", @@ -168,15 +84,6 @@ } } }, - "driver_class": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, "id": { "type": "long" }, @@ -198,15 +105,6 @@ } } }, - "registry": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, "version": { "type": "text", "fields": { @@ -219,406 +117,505 @@ } }, "internal_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "port": { - "type": "long" + "type": "integer" }, "sidecar_host": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "sidecar_port": { - "type": "long" + "type": "integer" }, "ui_host": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "ui_port": { - "type": "long" + "type": "integer" } } }, "created": { - "type": "date" + "type": "date", + "format": "strict_date_optional_time" }, - "creator": { - "properties": { - "attributes": { - "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } + "description": { + "type": "text" }, "exchange_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "exchange_type": { + "type": "keyword" }, "id": { - "type": "long" + "type": "keyword" }, "identifiers": { + "type": "object", "properties": { "created": { - "type": "date" + "type": "date", + "format": "strict_date_optional_time" }, "creator": { + "type": "object", "properties": { + "firstname": { + "type": "keyword" + }, "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "lastname": { + "type": "keyword" + }, + "name": { + "type": "keyword" }, "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, "creators": { + "type": "object", "properties": { + "affiliation": { + "type": "keyword" + }, + "affiliation_identifier": { + "type": "keyword" + }, + "affiliation_identifier_scheme": { + "type": "keyword" + }, + "affiliation_identifier_scheme_uri": { + "type": "keyword" + }, "creator_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" + }, + "firstname": { + "type": "text" }, "id": { - "type": "long" + "type": "keyword" + }, + "lastname": { + "type": "text" }, "name_identifier": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name_identifier_scheme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name_identifier_scheme_uri": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name_type": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, "database_id": { - "type": "long" + "type": "keyword" }, "descriptions": { + "type": "object", "properties": { "description": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, "id": { - "type": "long" + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "doi": { + "type": "keyword" + }, + "execution": { + "type": "date", + "format": "strict_date_optional_time" + }, + "funders": { + "type": "object", + "properties": { + "award_number": { + "type": "keyword" + }, + "award_title": { + "type": "keyword" + }, + "funder_identifier": { + "type": "keyword" + }, + "funder_identifier_type": { + "type": "keyword" + }, + "funder_name": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "scheme_uri": { + "type": "keyword" } } }, "id": { - "type": "long" + "type": "keyword" }, - "last_modified": { - "type": "date" + "language": { + "type": "keyword" }, "licenses": { + "type": "object", "properties": { - "description": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, "identifier": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "uri": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, "publication_day": { - "type": "long" + "type": "integer" }, "publication_month": { - "type": "long" + "type": "integer" }, "publication_year": { - "type": "long" + "type": "integer" }, "publisher": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, "query": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, - "query_normalized": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "query_hash": { + "type": "text" }, - "status": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "query_id": { + "type": "keyword" + }, + "query_normalized": { + "type": "text" + }, + "related_identifiers": { + "type": "object", + "properties": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, + "id": { + "type": "keyword" + }, + "relation": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "result_hash": { + "type": "text" + }, + "result_number": { + "type": "long" + }, + "status": { + "type": "keyword" + }, + "table_id": { + "type": "keyword" }, "titles": { + "type": "object", "properties": { "id": { - "type": "long" + "type": "keyword" + }, + "language": { + "type": "keyword" }, "title": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "type": { + "type": "keyword" } } }, "type": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "view_id": { - "type": "long" - } - } - }, - "image": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "type": "keyword" } } }, "internal_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "is_public": { "type": "boolean" }, "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "type": "keyword" + }, + "owner": { + "type": "object", + "properties": { + "firstname": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "lastname": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "qualified_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" } } }, - "owner": { + "subsets": { + "type": "object", "properties": { - "attributes": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, + "creators": { + "type": "object", "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "affiliation": { + "type": "keyword" + }, + "affiliation_identifier": { + "type": "keyword" + }, + "affiliation_identifier_scheme": { + "type": "keyword" + }, + "affiliation_identifier_scheme_uri": { + "type": "keyword" + }, + "creator_name": { + "type": "text" + }, + "firstname": { + "type": "text" + }, + "id": { + "type": "keyword" + }, + "lastname": { + "type": "text" + }, + "name_identifier": { + "type": "keyword" + }, + "name_identifier_scheme": { + "type": "keyword" + }, + "name_identifier_scheme_uri": { + "type": "keyword" + }, + "name_type": { + "type": "keyword" + } + } + }, + "database_id": { + "type": "keyword" + }, + "descriptions": { + "type": "object", + "properties": { + "description": { + "type": "text" + }, + "id": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "doi": { + "type": "keyword" + }, + "execution": { + "type": "date", + "format": "strict_date_optional_time" + }, + "funders": { + "type": "object", + "properties": { + "award_number": { + "type": "keyword" + }, + "award_title": { + "type": "keyword" + }, + "funder_identifier": { + "type": "keyword" + }, + "funder_identifier_type": { + "type": "keyword" + }, + "funder_name": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "scheme_uri": { + "type": "keyword" } } }, "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "licenses": { + "type": "object", + "properties": { + "identifier": { + "type": "keyword" + }, + "uri": { + "type": "keyword" } } }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "publication_day": { + "type": "integer" + }, + "publication_month": { + "type": "integer" + }, + "publication_year": { + "type": "integer" + }, + "publisher": { + "type": "text" + }, + "query": { + "type": "text" + }, + "query_hash": { + "type": "text" + }, + "query_id": { + "type": "keyword" + }, + "query_normalized": { + "type": "text" + }, + "related_identifiers": { + "type": "object", + "properties": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, + "id": { + "type": "keyword" + }, + "relation": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "value": { + "type": "keyword" } } }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "result_hash": { + "type": "text" + }, + "result_number": { + "type": "long" + }, + "status": { + "type": "keyword" + }, + "table_id": { + "type": "keyword" + }, + "titles": { + "type": "object", + "properties": { + "id": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "type": { + "type": "keyword" } } + }, + "type": { + "type": "keyword" + }, + "view_id": { + "type": "keyword" } } }, "tables": { + "type": "object", "properties": { + "avg_row_length": { + "type": "long" + }, "columns": { "properties": { "auto_generated": { @@ -633,43 +630,30 @@ } } }, - "d": { - "type": "long" - }, - "database_id": { - "type": "long" - }, - "date_format": { + "concept": { + "type": "object", "properties": { - "created_at": { - "type": "date" - }, - "database_format": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "has_time": { - "type": "boolean" + "created": { + "type": "date", + "format": "strict_date_optional_time" }, "id": { "type": "long" }, - "unix_format": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "uri": { + "type": "keyword" } } }, + "database_id": { + "type": "long" + }, + "data_length": { + "type": "long" + }, + "description": { + "type": "text" + }, "id": { "type": "long" }, @@ -688,9 +672,6 @@ "is_public": { "type": "boolean" }, - "mean": { - "type": "float" - }, "name": { "type": "text", "fields": { @@ -700,74 +681,115 @@ } } }, - "size": { + "num_rows": { + "type": "long" + }, + "max_data_length": { "type": "long" }, + "mean": { + "type": "double" + }, + "median": { + "type": "double" + }, "std_dev": { - "type": "float" + "type": "double" + }, + "size": { + "type": "long" }, "table_id": { "type": "long" + }, + "unit": { + "type": "object", + "properties": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, + "id": { + "type": "long" + }, + "uri": { + "type": "keyword" + } + } + }, + "val_min": { + "type": "double" + }, + "val_max": { + "type": "double" } } }, "constraints": { + "type": "object", "properties": { - "primary_key": { + "foreign_keys": { + "type": "object", "properties": { - "column": { - "properties": { - "database_id": { - "type": "long" - }, - "id": { - "type": "long" - }, - "table_id": { - "type": "long" - } - } + "name": { + "type": "keyword" }, - "id": { - "type": "long" + "columns": { + "type": "keyword" }, - "table": { - "properties": { - "database_id": { - "type": "long" - }, - "id": { - "type": "long" - } - } + "referenced_table": { + "type": "keyword" + }, + "referenced_columns": { + "type": "keyword" + }, + "on_delete": { + "type": "keyword" + }, + "on_update": { + "type": "keyword" } } }, "uniques": { + "type": "object", "properties": { - "columns": { + "id": { + "type": "keyword" + } + } + }, + "checks": { + "type": "keyword" + }, + "primary_key": { + "type": "object", + "properties": { + "id": { + "type": "keyword" + }, + "table": { + "type": "object", "properties": { - "database_id": { - "type": "long" - }, "id": { - "type": "long" + "type": "keyword" }, - "table_id": { - "type": "long" + "database_id": { + "type": "keyword" } } }, - "id": { - "type": "long" - }, - "table": { + "column": { + "type": "object", "properties": { - "database_id": { - "type": "long" - }, "id": { - "type": "long" + "type": "keyword" + }, + "table_id": { + "type": "keyword" + }, + "database_id": { + "type": "keyword" } } } @@ -776,518 +798,483 @@ } }, "created": { - "type": "date" - }, - "created_by": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "date", + "format": "strict_date_optional_time" }, - "creator": { - "properties": { - "attributes": { - "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } + "database_id": { + "type": "keyword" }, "data_length": { "type": "long" }, - "database_id": { - "type": "long" - }, "description": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, "id": { - "type": "long" - }, - "internal_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "is_public": { - "type": "boolean" + "type": "keyword" }, - "is_versioned": { - "type": "boolean" - }, - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "num_rows": { - "type": "long" - }, - "owner": { + "identifiers": { + "type": "object", "properties": { - "attributes": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, + "creators": { + "type": "object", "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "affiliation": { + "type": "keyword" + }, + "affiliation_identifier": { + "type": "keyword" + }, + "affiliation_identifier_scheme": { + "type": "keyword" + }, + "affiliation_identifier_scheme_uri": { + "type": "keyword" + }, + "creator_name": { + "type": "text" + }, + "firstname": { + "type": "text" + }, + "id": { + "type": "keyword" + }, + "lastname": { + "type": "text" + }, + "name_identifier": { + "type": "keyword" + }, + "name_identifier_scheme": { + "type": "keyword" + }, + "name_identifier_scheme_uri": { + "type": "keyword" + }, + "name_type": { + "type": "keyword" } } }, - "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "database_id": { + "type": "keyword" }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "descriptions": { + "type": "object", + "properties": { + "description": { + "type": "text" + }, + "id": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "type": { + "type": "keyword" } } }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "doi": { + "type": "keyword" + }, + "execution": { + "type": "date", + "format": "strict_date_optional_time" + }, + "funders": { + "type": "object", + "properties": { + "award_number": { + "type": "keyword" + }, + "award_title": { + "type": "keyword" + }, + "funder_identifier": { + "type": "keyword" + }, + "funder_identifier_type": { + "type": "keyword" + }, + "funder_name": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "scheme_uri": { + "type": "keyword" } } - } - } - }, - "queue_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "routing_key": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "views": { - "properties": { - "columns": { - "properties": { - "auto_generated": { - "type": "boolean" }, - "column_type": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "id": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "licenses": { + "type": "object", + "properties": { + "identifier": { + "type": "keyword" + }, + "uri": { + "type": "keyword" } } }, - "database_id": { - "type": "long" + "publication_day": { + "type": "integer" + }, + "publication_month": { + "type": "integer" + }, + "publication_year": { + "type": "integer" }, - "date_format": { + "publisher": { + "type": "text" + }, + "query": { + "type": "text" + }, + "query_hash": { + "type": "text" + }, + "query_id": { + "type": "keyword" + }, + "query_normalized": { + "type": "text" + }, + "related_identifiers": { + "type": "object", "properties": { - "created_at": { - "type": "date" + "created": { + "type": "date", + "format": "strict_date_optional_time" }, - "database_format": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "id": { + "type": "keyword" }, - "has_time": { - "type": "boolean" + "relation": { + "type": "keyword" }, - "id": { - "type": "long" + "type": { + "type": "keyword" }, - "unix_format": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "value": { + "type": "keyword" } } }, - "id": { - "type": "long" + "result_hash": { + "type": "text" }, - "internal_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "result_number": { + "type": "long" }, - "is_null_allowed": { - "type": "boolean" + "status": { + "type": "keyword" }, - "is_public": { - "type": "boolean" + "table_id": { + "type": "keyword" }, - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "titles": { + "type": "object", + "properties": { + "id": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "type": { + "type": "keyword" } } + }, + "type": { + "type": "keyword" + }, + "view_id": { + "type": "keyword" } } }, - "created": { - "type": "date" + "internal_name": { + "type": "keyword" }, - "creator": { + "is_public": { + "type": "boolean" + }, + "is_versioned": { + "type": "boolean" + }, + "name": { + "type": "keyword" + }, + "num_rows": { + "type": "long" + }, + "max_data_length": { + "type": "long" + }, + "owner": { + "type": "object", "properties": { - "attributes": { - "properties": { - "theme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } + "firstname": { + "type": "keyword" }, "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "lastname": { + "type": "keyword" + }, + "name": { + "type": "keyword" }, "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, + "queue_name": { + "type": "keyword" + }, + "queue_type": { + "type": "keyword" + }, + "routing_key": { + "type": "keyword" + } + } + }, + "views": { + "type": "object", + "properties": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, "database_id": { - "type": "long" + "type": "keyword" }, "id": { - "type": "long" + "type": "keyword" }, "identifiers": { + "type": "object", "properties": { "created": { - "type": "date" + "type": "date", + "format": "strict_date_optional_time" }, - "creator": { + "creators": { + "type": "object", "properties": { - "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "affiliation": { + "type": "keyword" }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "affiliation_identifier": { + "type": "keyword" + }, + "affiliation_identifier_scheme": { + "type": "keyword" + }, + "affiliation_identifier_scheme_uri": { + "type": "keyword" }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "creators": { - "properties": { "creator_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" + }, + "firstname": { + "type": "text" }, "id": { - "type": "long" + "type": "keyword" + }, + "lastname": { + "type": "text" }, "name_identifier": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name_identifier_scheme": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name_identifier_scheme_uri": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "name_type": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, "database_id": { - "type": "long" + "type": "keyword" }, "descriptions": { + "type": "object", "properties": { "description": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, "id": { - "type": "long" + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "doi": { + "type": "keyword" + }, + "execution": { + "type": "date", + "format": "strict_date_optional_time" + }, + "funders": { + "type": "object", + "properties": { + "award_number": { + "type": "keyword" + }, + "award_title": { + "type": "keyword" + }, + "funder_identifier": { + "type": "keyword" + }, + "funder_identifier_type": { + "type": "keyword" + }, + "funder_name": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "scheme_uri": { + "type": "keyword" } } }, "id": { - "type": "long" + "type": "keyword" }, - "last_modified": { - "type": "date" + "language": { + "type": "keyword" }, "licenses": { + "type": "object", "properties": { - "description": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, "identifier": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "uri": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } }, "publication_day": { - "type": "long" + "type": "integer" }, "publication_month": { - "type": "long" + "type": "integer" }, "publication_year": { - "type": "long" + "type": "integer" }, "publisher": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, "query": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" + }, + "query_hash": { + "type": "text" + }, + "query_id": { + "type": "keyword" }, "query_normalized": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 + "type": "text" + }, + "related_identifiers": { + "type": "object", + "properties": { + "created": { + "type": "date", + "format": "strict_date_optional_time" + }, + "id": { + "type": "keyword" + }, + "relation": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "value": { + "type": "keyword" } } }, + "result_hash": { + "type": "text" + }, + "result_number": { + "type": "long" + }, "status": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "table_id": { + "type": "keyword" }, "titles": { + "type": "object", "properties": { "id": { - "type": "long" + "type": "keyword" + }, + "language": { + "type": "keyword" }, "title": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" + }, + "type": { + "type": "keyword" } } }, "type": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "view_id": { - "type": "long" + "type": "keyword" } } }, @@ -1295,46 +1282,19 @@ "type": "boolean" }, "internal_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "is_public": { "type": "boolean" }, - "last_modified": { - "type": "date" - }, "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" }, "query": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "text" }, "query_hash": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } + "type": "keyword" } } } diff --git a/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl index 694a6fc02560b3b5d858df0e5a0bd9acf45c8f20..f58e17a58e747e35bbd37f43efe6b460ba31530f 100644 Binary files a/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl and b/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl differ diff --git a/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz b/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz index f344d01026b92476d80703cbfb7d884cb7822e05..5463f6b170c24fff05d29a434562104553292fea 100644 Binary files a/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz and b/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz differ diff --git a/dbrepo-search-service/os-yml/get_fields.yml b/dbrepo-search-service/os-yml/get_fields.yml index bf7f48764327969d3665c9dce8f5bed74779f6eb..6ff4c879741babf74f6a72d403b564d9e0acb1ce 100644 --- a/dbrepo-search-service/os-yml/get_fields.yml +++ b/dbrepo-search-service/os-yml/get_fields.yml @@ -16,6 +16,22 @@ responses: content: application/json: schema: - $ref: '#/components/schemas/IndexFieldsDto' + type: object + properties: + results: + type: array + items: + type: object + properties: + attr_name: + type: "string" + example: "name" + attr_friendly_name: + type: "string" + example: "Name" + type: + type: "string" + example: "string" + description: OpenSearch data types. "404": description: Invalid type. diff --git a/dbrepo-search-service/os-yml/get_fuzzy_search.yml b/dbrepo-search-service/os-yml/get_fuzzy_search.yml index bc54419eb9735fe731fb12a5e911070ebc29f80e..3dbd5d19d5c0d46d7ec904bdc0a0ac5e08f6d2d9 100644 --- a/dbrepo-search-service/os-yml/get_fuzzy_search.yml +++ b/dbrepo-search-service/os-yml/get_fuzzy_search.yml @@ -8,17 +8,25 @@ consumes: produces: - application/json parameters: - - name: q - in: query + - in: query required: true schema: - type: string + type: "string" + properties: + q: + type: "string" + example: "air quality" responses: 200: description: OK, contains the elements formatted as an array of JSON arrays content: application/json: schema: - $ref: '#/components/schemas/SearchResultDto' + type: object + properties: + results: + type: array + items: + type: object 415: description: Wrong accept type diff --git a/dbrepo-search-service/os-yml/get_index.yml b/dbrepo-search-service/os-yml/get_index.yml index fe4941810c66d97d6f26752dfa61f08e98d98e3f..48fc4ca286288ba94f0de1b9030d2c0eae49ed9f 100644 --- a/dbrepo-search-service/os-yml/get_index.yml +++ b/dbrepo-search-service/os-yml/get_index.yml @@ -38,4 +38,13 @@ responses: content: application/json: schema: - $ref: '#/components/schemas/IndexDto' + type: object + properties: + results: + type: array + items: + type: object + type: + type: string + enum: [ database, table, view, column, user, identifier, concept, unit ] + description: "Same as the requested type" diff --git a/dbrepo-search-service/os-yml/health.yml b/dbrepo-search-service/os-yml/health.yml new file mode 100644 index 0000000000000000000000000000000000000000..a4b273a2bf739abc5385a1ba1bce5c0ebafef1aa --- /dev/null +++ b/dbrepo-search-service/os-yml/health.yml @@ -0,0 +1,24 @@ +summary: Return a healthcheck +description: | + Return UP if the instance is ready to serve connections. +consumes: + - application/json +produces: + - application/json +parameters: [] +definitions: + Health: + type: object + properties: + status: + type: string + description: UP +responses: + 200: + description: OK, service is up and running + schema: + $ref: "#/definitions/Column" + 404: + description: Service is not yet ready +tags: + - actuator \ No newline at end of file diff --git a/dbrepo-search-service/os-yml/post_general_search.yml b/dbrepo-search-service/os-yml/post_general_search.yml index cbff09b7fc686af87ee9f2086e34c2b85ea0df54..33cbea636730a13b518434284178bd8d21b2711b 100644 --- a/dbrepo-search-service/os-yml/post_general_search.yml +++ b/dbrepo-search-service/os-yml/post_general_search.yml @@ -27,7 +27,13 @@ parameters: name: "body" required: true schema: - $ref: '#/components/schemas/SearchRequestDto' + type: "object" + properties: + search_term: + type: "string" + example: "air quality" + field_value_pairs: + type: "object" responses: 200: description: OK, contains the elements formatted as an array of JSON arrays diff --git a/dbrepo-search-service/os-yml/update_database.yml b/dbrepo-search-service/os-yml/update_database.yml index e9cd0d56f967a62144dba4af10edea38b055a11c..f1f2911d3e87258c714fd0bdcce9dd49c6b0faea 100644 --- a/dbrepo-search-service/os-yml/update_database.yml +++ b/dbrepo-search-service/os-yml/update_database.yml @@ -12,7 +12,14 @@ parameters: name: "body" required: true schema: - $ref: '#/components/schemas/DatabaseDto' + type: "object" + properties: + name: + type: "string" + example: "Air Quality" + internal_name: + type: "string" + example: "air_quality_abcd" security: - bearerAuth: [ ] - basicAuth: [ ] diff --git a/dbrepo-ui/components/table/TableHistory.vue b/dbrepo-ui/components/dialogs/TimeTravel.vue similarity index 86% rename from dbrepo-ui/components/table/TableHistory.vue rename to dbrepo-ui/components/dialogs/TimeTravel.vue index dd3dad66e2961b59f5591a586150e88fa2c00ff6..12f4228503c61b61561e367986a3ef34521e6a14 100644 --- a/dbrepo-ui/components/table/TableHistory.vue +++ b/dbrepo-ui/components/dialogs/TimeTravel.vue @@ -54,7 +54,7 @@ <script> import { Bar } from 'vue-chartjs' import { format } from 'date-fns' -import { useCacheStore } from '~/stores/cache.js' +import { useCacheStore } from '@/stores/cache' import { Chart as ChartJS, Title, Tooltip, BarElement, CategoryScale, LinearScale, LogarithmicScale } from 'chart.js' ChartJS.register(Title, Tooltip, BarElement, CategoryScale, LinearScale, LogarithmicScale) @@ -153,19 +153,23 @@ export default { this.datetime = this.chartData.labels[idx] console.debug('date time', this.datetime, 'idx', idx) }, - loadHistory () { - this.loading = true - const tableService = useTableService() - tableService.history(this.table.database_id, this.table.id) - .then((history) => { - this.loading = false - this.history = history - }) - .catch(({message}) => { - const toast = useToastInstance() - toast.error(message) - this.loading = false - }) + async loadHistory () { + try { + this.loading = true + const tableService = useTableService() + this.history = await tableService.history(this.table.database_id, this.table.id) + // this.chartData.labels = history.map(d => format(new Date(d.timestamp), 'dd.MM.yyyy HH:mm:ss')) + // this.chartData.datasets = [{ + // // backgroundColor: 'red', + // data: history.map(d => d.total) + // }] + this.totalChanges = history.length + console.debug('history', this.chartData) + } catch (err) { + this.error = true + console.error('failed to load table history', err) + } + this.loading = false } } } diff --git a/dbrepo-ui/components/subset/Results.vue b/dbrepo-ui/components/subset/Results.vue index ed6f7448334ae631d400e354832947e9d095c0fa..9f0cb366a7a6dfef9198a35ce971f5ec247fc7ae 100644 --- a/dbrepo-ui/components/subset/Results.vue +++ b/dbrepo-ui/components/subset/Results.vue @@ -19,6 +19,12 @@ export default { type: String, default: () => 'query' /* query or view */ }, + view: { + type: Object, + default: () => { + return {} + } + }, loading: { type: Boolean, default: () => { @@ -52,6 +58,15 @@ export default { if (this.result.headers.length !== 0) { return this.result.headers } + if (this.type === 'view' && this.view && this.view.columns) { + return this.view.columns.map((c) => { + return { + title: c.alias ? c.alias : c.internal_name, + value: c.alias ? c.alias : c.internal_name, + sortable: false + } + }) + } return [] } }, diff --git a/dbrepo-ui/components/table/TableSchema.vue b/dbrepo-ui/components/table/TableSchema.vue index 1cc172858c9302b43dd1bbad5ea311fc5898dbd2..07485c8690b54ba47fdae0ad75e7eeb4f8b5dd0a 100644 --- a/dbrepo-ui/components/table/TableSchema.vue +++ b/dbrepo-ui/components/table/TableSchema.vue @@ -1,19 +1,15 @@ <template> <div> + <v-alert + v-if="needsSequence" + class="mb-6" + border="start" + :text="$t('validation.schema.primary-key')" + color="info" /> <v-form ref="form" v-model="valid" :disabled="disabled"> - <v-row> - <v-col md="8"> - <v-alert - v-if="needsSequence" - class="mb-6" - border="start" - :text="$t('validation.schema.primary-key')" - color="info" /> - </v-col> - </v-row> <v-row v-for="(c, idx) in columns" :key="`r-${idx}`" diff --git a/dbrepo-ui/components/view/ViewToolbar.vue b/dbrepo-ui/components/view/ViewToolbar.vue index 21125764983e9f7f79bf8dd6ec5f522a3bff7d49..e6cb5e09db3df478b70edc0c189cef179b109c65 100644 --- a/dbrepo-ui/components/view/ViewToolbar.vue +++ b/dbrepo-ui/components/view/ViewToolbar.vue @@ -1,43 +1,44 @@ <template> - <v-toolbar flat> - <v-btn - class="mr-2" - size="small" - icon="mdi-arrow-left" - :to="`/database/${$route.params.database_id}/view`" /> - <v-toolbar-title - v-if="view" - :text="title" /> - <v-spacer /> - <v-btn - v-if="canDeleteView" - prepend-icon="mdi-delete" - class="mr-2" - variant="flat" - color="error" - :text="$vuetify.display.lgAndUp ? $t('navigation.delete') : ''" - :loading="loadingDelete" - @click="deleteView" /> - <v-btn - v-if="canCreatePid" - prepend-icon="mdi-content-save-outline" - variant="flat" - color="primary" - :text="($vuetify.display.lgAndUp ? $t('toolbars.view.pid.xl') + ' ' : '') + $t('toolbars.view.pid.permanent')" - :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/persist`" /> - <template v-slot:extension> - <v-tabs - v-model="tab" - color="primary"> - <v-tab - :text="$t('navigation.info')" - :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/info`" /> - <v-tab - :text="$t('navigation.data')" - :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/data`" /> - </v-tabs> - </template> - </v-toolbar> + <div v-if="view"> + <v-toolbar flat> + <v-btn + class="mr-2" + size="small" + icon="mdi-arrow-left" + :to="`/database/${$route.params.database_id}/view`" /> + <v-toolbar-title + :text="title" /> + <v-spacer /> + <v-btn + v-if="canDeleteView" + prepend-icon="mdi-delete" + class="mr-2" + variant="flat" + color="error" + :text="$vuetify.display.lgAndUp ? $t('navigation.delete') : ''" + :loading="loadingDelete" + @click="deleteView" /> + <v-btn + v-if="canCreatePid" + prepend-icon="mdi-content-save-outline" + variant="flat" + color="primary" + :text="($vuetify.display.lgAndUp ? $t('toolbars.view.pid.xl') + ' ' : '') + $t('toolbars.view.pid.permanent')" + :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/persist`" /> + <template v-slot:extension> + <v-tabs + v-model="tab" + color="primary"> + <v-tab + :text="$t('navigation.info')" + :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/info`" /> + <v-tab + :text="$t('navigation.data')" + :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/data`" /> + </v-tabs> + </template> + </v-toolbar> + </div> </template> <script> @@ -127,9 +128,9 @@ export default { this.cacheStore.reloadDatabase() this.$router.push(`/database/${this.$route.params.database_id}/view`) }) - .catch(({code, message}) => { + .catch(({code}) => { const toast = useToastInstance() - toast.error(this.$t(code) + ": " + message) + toast.error(this.$t(code)) }) .finally(() => { this.loadingDelete = false diff --git a/dbrepo-ui/composables/table-service.ts b/dbrepo-ui/composables/table-service.ts index 96be0537d07b3990ab638acafc724442ae5f7735..393c540f83739ec59ede4c8a6a9bb278f6fd25d4 100644 --- a/dbrepo-ui/composables/table-service.ts +++ b/dbrepo-ui/composables/table-service.ts @@ -69,7 +69,6 @@ export const useTableService = (): any => { async function getData(databaseId: number, tableId: number, page: number, size: number, timestamp: Date): Promise<QueryResultDto> { const axios = useAxiosInstance() - console.debug('====>', mapFilter(timestamp, page, size)) console.debug('get data for table with id', tableId, 'in database with id', databaseId); return new Promise<QueryResultDto>((resolve, reject) => { axios.get<QueryResultDto>(`/api/database/${databaseId}/table/${tableId}/data`, { params: mapFilter(timestamp, page, size), timeout: 30_000 }) @@ -192,7 +191,7 @@ export const useTableService = (): any => { const axios = useAxiosInstance() console.debug('suggest semantic entities for table column with id', columnId, 'of table with id', tableId, 'of database with id', databaseId) return new Promise<TableColumnEntityDto[]>((resolve, reject) => { - axios.get<TableColumnEntityDto[]>(`/api/database/${databaseId}/table/${tableId}/column/${columnId}/suggest`, {timeout: 10000}) + axios.get<TableColumnEntityDto[]>(`/api/semantic/database/${databaseId}/table/${tableId}/column/${columnId}`, {timeout: 10000}) .then((response) => { console.info('Suggested semantic entities for table column with id', columnId, 'of table with id', tableId, 'of database with id', databaseId) resolve(response.data) @@ -249,10 +248,10 @@ export const useTableService = (): any => { } function mapFilter(timestamp: Date | null, page: number | null, size: number | null) { - if (timestamp === null) { + if (!timestamp) { return {page, size} } - if (page === null || size === null) { + if (!page || !size) { return {timestamp} } return {timestamp, page, size} diff --git a/dbrepo-ui/locales/de-AT.json b/dbrepo-ui/locales/de-AT.json index bf84b689328bfc34624217596e6e269db1c2eb3a..2e713bd365e175035cde2f569e4c24564fd0baf3 100644 --- a/dbrepo-ui/locales/de-AT.json +++ b/dbrepo-ui/locales/de-AT.json @@ -88,12 +88,12 @@ }, "publication-year": { "label": "Erscheinungsjahr", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "titles": { "title": { "label": "Titel", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "type": { "label": "Typ", @@ -116,15 +116,15 @@ "subtitle": "Haben Sie bereits einen DOI für diesen Datensatz?", "label": "Geben Sie hier Ihren bestehenden DOI an", "hint": "Ein DOI ermöglicht die einfache und eindeutige Zitierung Ihres Uploads. ", - "mint": "Nach dem Speichern wird ein PID erstellt" + "mint": "Nach dem Speichern wird ein PID erstellt." }, "doi": { - "mint": "Nach dem Speichern wird ein DOI erstellt" + "mint": "Nach dem Speichern wird ein DOI erstellt." }, "descriptions": { "description": { "label": "Beschreibung", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "type": { "label": "Typ", @@ -146,14 +146,14 @@ "title": "Veröffentlichungsinformationen", "subtitle": "Der Name der Entität, die die Ressource hält, archiviert, veröffentlicht, druckt, verteilt, freigibt, herausgibt oder produziert. ", "label": "Herausgeber", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "related-identifiers": { "title": "Verwandter Bezeichner", "subtitle": "Bezeichner verwandter Ressourcen. ", "identifier": { "label": "Kennung", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "type": { "label": "Typ", @@ -179,7 +179,7 @@ }, "language": { "title": "Sprache", - "subtitle": "Die primäre Sprache des Datensatzes", + "subtitle": "Die primäre Sprache des Datensatzes.", "language": { "label": "Sprache", "hint": "" @@ -187,14 +187,14 @@ }, "funders": { "title": "Finanzierungsreferenz", - "subtitle": "Informationen zur finanziellen Unterstützung (Finanzierung) für den zu registrierenden Datensatz", + "subtitle": "Informationen zur finanziellen Unterstützung (Finanzierung) für den zu registrierenden Datensatz.", "identifier": { "label": "Kennung des Geldgebers", - "hint": "Verwenden Sie eine Namenskennung, ausgedrückt als URL von ORCID*, ROR*, DOI*, ISNI, GND (Schemata mit * unterstützen den automatischen Metadatenabruf)" + "hint": "Verwenden Sie eine Namenskennung, ausgedrückt als URL von ORCID*, ROR*, DOI*, ISNI, GND (Schemata mit * unterstützen den automatischen Metadatenabruf)." }, "name": { "label": "Name des Geldgebers", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "award-number": { "label": "Auszeichnungsnummer", @@ -212,10 +212,10 @@ } }, "creators": { - "subtitle": "Die wichtigsten Forscher, die an der Erstellung der Daten beteiligt waren, in der Reihenfolge ihrer Priorität", + "subtitle": "Die wichtigsten Forscher, die an der Erstellung der Daten beteiligt waren, in der Reihenfolge ihrer Priorität.", "identifier": { "label": "Namensbezeichner", - "hint": "Verwenden Sie eine Namenskennung, ausgedrückt als URL von ORCID*, ROR*, DOI*, ISNI, GND (Schemata mit * unterstützen den automatischen Metadatenabruf)" + "hint": "Verwenden Sie eine Namenskennung, ausgedrückt als URL von ORCID*, ROR*, DOI*, ISNI, GND (Schemata mit * unterstützen den automatischen Metadatenabruf)." }, "insert": { "text": "Füge mich ein" @@ -239,11 +239,11 @@ }, "name": { "label": "Name", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "affiliation-identifier": { "label": "Zugehörigkeitskennung", - "hint": "Verwenden Sie eine Zugehörigkeitskennung, ausgedrückt als URL von ORCID*, ROR*, DOI*, ISNI, GND (Schemata mit * unterstützen den automatischen Metadatenabruf)" + "hint": "Verwenden Sie eine Zugehörigkeitskennung, ausgedrückt als URL von ORCID*, ROR*, DOI*, ISNI, GND (Schemata mit * unterstützen den automatischen Metadatenabruf)." }, "affiliation": { "label": "Zugehörigkeitsname", @@ -253,7 +253,7 @@ }, "summary": { "title": "Zusammenfassung", - "subtitle": "Details zur Kennung, die zur Identifizierung dieses Datensatzes erstellt wird", + "subtitle": "Details zur Kennung, die zur Identifizierung dieses Datensatzes erstellt wird.", "record": "Der Bezeichner beschreibt", "publisher": "Herausgeber", "license": "Lizenz", @@ -287,8 +287,8 @@ "secure": "sicher", "insecure": "unsicher", "permissions": { - "write": "Sie können in diese Tabelle schreiben", - "read": "Sie können den gesamten Inhalt dieser Tabelle lesen" + "write": "Sie können in diese Tabelle schreiben.", + "read": "Sie können den gesamten Inhalt dieser Tabelle lesen." } }, "protocol": { @@ -330,7 +330,7 @@ }, "generated": { "label": "Vorschau des Tabellennamens", - "hint": "Schreibgeschützt" + "hint": "Schreibgeschützt." }, "description": { "label": "Beschreibung", @@ -385,7 +385,7 @@ "summary": { "title": "Zusammenfassung", "prefix": "Importiert", - "suffix": "Zeilen aus dem Datensatz" + "suffix": "Zeilen aus dem Datensatz." }, "analyse": { "text": "Hochladen und analysieren" @@ -398,7 +398,7 @@ }, "name": { "label": "Tabellenname", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "description": { "label": "Tabellenbeschreibung", @@ -406,23 +406,22 @@ }, "summary": { "prefix": "Tabelle mit Namen erstellt", - "suffix": "und importierter Datensatz erfolgreich" + "suffix": "und importierter Datensatz erfolgreich." } }, "drop": { "title": "Tabelle Löschen", "warning": { "prefix": "Diese Aktion kann nicht rückgängig gemacht werden! ", - "suffix": "unten, wenn Sie es wirklich mit allen gespeicherten Daten löschen möchten" + "suffix": "unten, wenn Sie es wirklich mit allen gespeicherten Daten löschen möchten." }, "name": { "label": "Tabellenname", - "hint": "Erforderlich" + "hint": "Erforderlich." } }, "schema": { "title": "System Versioniert", - "subtitle": "Tabellenbeschränkungen", "bullet": "●", "assign": "Zuordnen", "remove": { @@ -454,14 +453,14 @@ }, "name": { "label": "Name", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "add": { "text": "Spalte hinzufügen" }, "type": { "label": "Typ", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "size": { "label": "Größe" @@ -497,23 +496,23 @@ }, "summary": { "title": "Zusammenfassung", - "text": "Tabelle mit internem Namen erfolgreich erstellt" + "text": "Tabelle mit internem Namen erfolgreich erstellt:" } }, "semantics": { - "title": "Semantische Instanz für Tabellenspalte zuweisen", - "subtitle": "Semantische Instanzen helfen Maschinen dabei, den richtigen Kontext Ihres Datensatzes zu ermitteln", + "title": "Semantische Instanz für Tabellenspalte zuweisen:", + "subtitle": "Semantische Instanzen helfen Maschinen dabei, den richtigen Kontext Ihres Datensatzes zu ermitteln.", "recommended": "Empfohlene semantische Instanzen", "bullet": "●", "info": "Die folgenden Ontologien fragen automatisch die Felder rdfs:label ab und speichern sie für diese Spalte. ", "uri": { "label": "Semantischer Instanz-URI", - "hint": "Dieser URI kann automatisch aufgelöst werden" + "hint": "Dieser URI kann automatisch aufgelöst werden." } }, "versioning": { "title": "Geschichte", - "subtitle": "Wählen Sie einen Zeitstempel aus, um die Daten für diese bestimmte Tageszeit anzuzeigen", + "subtitle": "Wählen Sie einen Zeitstempel aus, um die Daten für diese bestimmte Tageszeit anzuzeigen.", "chart": { "title": "Datenereignisse", "ylabel": "# Veranstaltungen", @@ -528,22 +527,22 @@ }, "data": { "auto": { - "hint": "Der Wert wird automatisch durch eine Sequenz generiert" + "hint": "Der Wert wird automatisch durch eine Sequenz generiert." }, "primary-key": { - "hint": "Der Wert ist ein Primärschlüssel" + "hint": "Der Wert ist ein Primärschlüssel." }, "format": { - "hint": "Der Wert muss folgendes Format haben" + "hint": "Der Wert muss folgendes Format haben:" }, "required": { "hint": "Erforderlich. " }, "float": { - "max": "max", - "min": "Mindest", - "before": "Ziffer(n) vor dem Punkt", - "after": "Ziffer(n) nach dem Punkt" + "max": "max.", + "min": "Mindest.", + "before": "Ziffer(n) vor dem Punkt.", + "after": "Ziffer(n) nach dem Punkt." } } } @@ -583,7 +582,7 @@ "subpages": { "access": { "title": "Datenbankzugriff", - "subtitle": "Übersicht über Benutzer mit ihrem Zugriff auf die Datenbank", + "subtitle": "Übersicht über Benutzer mit ihrem Zugriff auf die Datenbank.", "read": "Sie können alle Inhalte lesen", "write-own": "Sie können eigene Tabellen schreiben und alle Inhalte lesen", "write-all": "Sie können eigene Tabellen schreiben und alle Inhalte lesen", @@ -603,7 +602,7 @@ }, "create": { "title": "Datenbank erstellen", - "subtitle": "Wählen Sie einen aussagekräftigen Datenbanknamen und eine Datenbank-Engine", + "subtitle": "Wählen Sie einen aussagekräftigen Datenbanknamen und eine Datenbank-Engine.", "name": { "label": "Name", "hint": "Erforderlich. ", @@ -611,7 +610,7 @@ }, "engine": { "label": "Motor", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "submit": { "text": "Erstellen" @@ -637,7 +636,7 @@ }, "settings": { "title": "Einstellungen", - "subtitle": "Das Bild wird in einem Feld mit den maximalen Abmessungen 200x200 Pixel angezeigt", + "subtitle": "Das Bild wird in einem Feld mit den maximalen Abmessungen 200x200 Pixel angezeigt.", "image": { "label": "Teaser-Bild", "hint": "max. " @@ -650,16 +649,16 @@ }, "scheme": { "title": "Schema", - "subtitle": "Aktualisiert die Metadaten im Datenbankschema, um systemversionierte Tabellen und Ansichten in der Benutzeroberfläche anzuzeigen", + "subtitle": "Aktualisiert die Metadaten im Datenbankschema, um systemversionierte Tabellen und Ansichten in der Benutzeroberfläche anzuzeigen.", "submit": { "text": "Aktualisieren" } }, "ownership": { "title": "Eigentum", - "subtitle": "Benutzer, der Eigentümer dieser Datenbank ist", + "subtitle": "Benutzer, der Eigentümer dieser Datenbank ist.", "label": "Datenbankbesitzer", - "hint": "Erforderlich", + "hint": "Erforderlich.", "submit": { "text": "Überweisen" } @@ -669,7 +668,7 @@ "subtitle": "Private Datenbanken verbergen die Daten, während Metadaten weiterhin sichtbar sind. ", "visibility": { "label": "Datenbanksichtbarkeit", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "submit": { "text": "Ändern" @@ -682,19 +681,19 @@ "name": "Melden Sie sich an", "email": { "label": "E-Mail-Adresse", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "username": { "label": "Nutzername", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "password": { "label": "Passwort", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "confirm": { "label": "Bestätige das Passwort", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "submit": { "label": "Einreichen" @@ -704,11 +703,11 @@ "name": "Anmeldung", "username": { "label": "Nutzername", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "password": { "label": "Passwort", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "submit": { "label": "Einreichen" @@ -721,7 +720,7 @@ "subpages": { "info": { "title": "Information", - "subtitle": "Allgemeine Benutzermetadaten", + "subtitle": "Allgemeine Benutzermetadaten.", "id": { "label": "ID" }, @@ -755,7 +754,7 @@ }, "theme": { "title": "Theme", - "subtitle": "Aktualisieren Sie das Benutzerdesign, wenn Sie angemeldet sind", + "subtitle": "Aktualisieren Sie das Benutzerdesign, wenn Sie angemeldet sind.", "label": "Thema", "dark": "Dunkel", "dark-contrast": "Dunkel – hoher Kontrast", @@ -771,14 +770,14 @@ "subpages": { "authentication": { "title": "Benutzer-Passwort", - "subtitle": "Aktualisieren Sie das Benutzerkennwort, das für die Basisauthentifizierung bei allen Schnittstellen verwendet wird", + "subtitle": "Aktualisieren Sie das Benutzerkennwort, das für die Basisauthentifizierung bei allen Schnittstellen verwendet wird.", "password": { "label": "Passwort", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "confirm": { "label": "Bestätige das Passwort", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "submit": { "text": "Aktualisieren" @@ -787,7 +786,7 @@ "developer": { "token": { "title": "Token-Informationen", - "subtitle": "Sehen Sie sich Ihre Token-Geheimnisse zu Debugging-Zwecken an", + "subtitle": "Sehen Sie sich Ihre Token-Geheimnisse zu Debugging-Zwecken an.", "expiry": "Läuft ab", "access": { "label": "Zugangstoken" @@ -806,11 +805,11 @@ "title": "Wartungsmeldung", "type": { "label": "Typ", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "message": { "label": "Nachricht", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "start": { "label": "Zeitstempel starten" @@ -841,9 +840,6 @@ "info": "Info", "data": "Daten" }, - "name": { - "title": "Name" - }, "query": { "title": "Abfrage" }, @@ -861,19 +857,19 @@ "title": "Ansicht erstellen", "name": { "label": "Name", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "table": { "label": "Datentabelle", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "columns": { "label": "Datenspalten", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "visibility": { "label": "Datensichtbarkeit", - "warn": "Nur Personen mit mindestens Leserechten können die Daten einsehen", + "warn": "Nur Personen mit mindestens Leserechten können die Daten einsehen.", "hint": "Erforderlich. " } } @@ -891,7 +887,7 @@ "title": "Abfrage" }, "query-hash": { - "prefix": "sha256", + "prefix": "sha256:", "title": "Abfrage-Hash" }, "executed": { @@ -910,14 +906,14 @@ "subpages": { "create": { "title": "Teilmenge erstellen", - "generated": "Die folgende Abfrage wird ausgeführt (schreibgeschützt)", - "subtitle": "Die folgende Abfrage wird ausgeführt", + "generated": "Die folgende Abfrage wird ausgeführt (schreibgeschützt):", + "subtitle": "Die folgende Abfrage wird ausgeführt:", "simple": { "text": "Einfach" }, "expert": { "text": "Experte", - "warn": "Von der Verwendung von Kommentaren, Aggregationsfunktionen und den folgenden Vorgängen wird abgeraten" + "warn": "Von der Verwendung von Kommentaren, Aggregationsfunktionen und den folgenden Vorgängen wird abgeraten:" }, "name": { "label": "" @@ -926,15 +922,15 @@ "text": "Filter hinzufügen", "column": { "label": "Spalte", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "operator": { "label": "Operator", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "value": { "label": "Wert", - "hint": "Erforderlich" + "hint": "Erforderlich." }, "remove": { "text": "Entfernen" @@ -977,7 +973,7 @@ "hint": "" }, "publication-range": { - "hint": "Geben Sie Ihren benutzerdefinierten Veröffentlichungsjahrbereich an" + "hint": "Geben Sie Ihren benutzerdefinierten Veröffentlichungsjahrbereich an." }, "start-year": { "label": "Startjahr", @@ -988,7 +984,7 @@ "hint": "" }, "concept-unit": { - "hint": "Wenn Sie ein KONZEPT und eine EINHEIT auswählen, können Sie unabhängig von der Maßeinheit spaltenübergreifend suchen" + "hint": "Wenn Sie ein KONZEPT und eine EINHEIT auswählen, können Sie unabhängig von der Maßeinheit spaltenübergreifend suchen." }, "concept": { "label": "Konzept", @@ -1031,216 +1027,216 @@ }, "error": { "access": { - "missing": "Der Zugriff in der Metadatendatenbank konnte nicht gefunden werden" + "missing": "Der Zugriff in der Metadatendatenbank konnte nicht gefunden werden." }, "axios": { - "connection": "Es konnte keine Verbindung hergestellt werden", - "timeout": "Zeitüberschreitung der Verbindung" + "connection": "Es konnte keine Verbindung hergestellt werden.", + "timeout": "Zeitüberschreitung der Verbindung." }, "concept": { - "missing": "Das Konzept konnte in der Metadatendatenbank nicht gefunden werden" + "missing": "Das Konzept konnte in der Metadatendatenbank nicht gefunden werden." }, "container": { - "exists": "Der Container ist bereits in der Metadatendatenbank vorhanden", - "missing": "Der Container konnte in der Metadatendatenbank nicht gefunden werden" + "exists": "Der Container ist bereits in der Metadatendatenbank vorhanden.", + "missing": "Der Container konnte in der Metadatendatenbank nicht gefunden werden." }, "data": { - "invalid": "Die Kommunikation mit dem Datendienst ist fehlgeschlagen", - "connection": "Es konnte keine Verbindung zum Datendienst hergestellt werden", - "value": "Spaltenwert konnte nicht festgelegt werden", - "drift": "Die Uhr Ihres Browsers ist nicht mit UTC synchronisiert und scheint um Folgendes eingestellt zu sein" + "invalid": "Die Kommunikation mit dem Datendienst ist fehlgeschlagen.", + "connection": "Es konnte keine Verbindung zum Datendienst hergestellt werden.", + "value": "Spaltenwert konnte nicht festgelegt werden:", + "drift": "Die Uhr Ihres Browsers ist nicht mit UTC synchronisiert und scheint um Folgendes eingestellt zu sein:" }, "database": { - "connection": "Es konnte keine Verbindung zur Datenbank hergestellt werden", - "invalid": "Aktion in der Datenbank konnte nicht ausgeführt werden", + "connection": "Es konnte keine Verbindung zur Datenbank hergestellt werden.", + "invalid": "Aktion in der Datenbank konnte nicht ausgeführt werden.", "querystore": "Die Abfrage konnte nicht in den Abfragespeicher eingefügt werden", - "missing": "Die Datenbank konnte nicht in der Metadatendatenbank gefunden werden", - "create": "Es konnte keine Verbindung zum Metadatendienst hergestellt werden" + "missing": "Die Datenbank konnte nicht in der Metadatendatenbank gefunden werden.", + "create": "Es konnte keine Verbindung zum Metadatendienst hergestellt werden." }, "doi": { - "missing": "DOI konnte in der Metadatendatenbank nicht gefunden werden" + "missing": "DOI konnte in der Metadatendatenbank nicht gefunden werden." }, "exchange": { - "missing": "Im Broker-Service konnte keine Börse gefunden werden" + "missing": "Im Broker-Service konnte keine Börse gefunden werden." }, "semantic": { - "filter": "Die semantische Entität konnte im Metadatendienst nicht gefiltert werden", - "missing": "Die semantische Entität konnte im Metadatendienst nicht gefunden werden" + "filter": "Die semantische Entität konnte im Metadatendienst nicht gefiltert werden.", + "missing": "Die semantische Entität konnte im Metadatendienst nicht gefunden werden." }, "storage": { - "missing": "Datensatz im Speicherdienst konnte nicht gefunden werden", - "invalid": "Es konnte keine Verbindung zum Speicherdienst hergestellt werden" + "missing": "Datensatz im Speicherdienst konnte nicht gefunden werden.", + "invalid": "Es konnte keine Verbindung zum Speicherdienst hergestellt werden." }, "identifier": { - "format": "Die Kennung konnte im Metadatendienst nicht in das angeforderte Format umgewandelt werden", - "missing": "Die Kennung konnte in der Metadatendatenbank nicht gefunden werden", - "unsupported": "Es konnten keine Metadaten von einem nicht unterstützten Metadatenanbieter gefunden werden", + "format": "Die Kennung konnte im Metadatendienst nicht in das angeforderte Format umgewandelt werden.", + "missing": "Die Kennung konnte in der Metadatendatenbank nicht gefunden werden.", + "unsupported": "Es konnten keine Metadaten von einem nicht unterstützten Metadatenanbieter gefunden werden.", "form": "Bitte geben Sie im Formular alle erforderlichen Werte ein" }, "image": { - "exists": "Das Bild ist bereits in der Metadatendatenbank vorhanden", - "missing": "Das Bild konnte nicht in der Metadatendatenbank gefunden werden", - "invalid": "Bildmetadaten sind fehlerhaft" + "exists": "Das Bild ist bereits in der Metadatendatenbank vorhanden.", + "missing": "Das Bild konnte nicht in der Metadatendatenbank gefunden werden.", + "invalid": "Bildmetadaten sind fehlerhaft." }, "license": { - "missing": "Die Lizenz konnte in der Metadatendatenbank nicht gefunden werden" + "missing": "Die Lizenz konnte in der Metadatendatenbank nicht gefunden werden." }, "request": { - "invalid": "Die Anforderungsnutzlast wurde vom Metadatendienst abgelehnt", - "forbidden": "Anfrage ist unzulässig, Rollen oder Authentifizierung fehlen", - "pagination": "Die Anfrage enthält ungültige Paginierungsinformationen", - "sort": "Die Anfrage enthält ungültige Sortierinformationen" + "invalid": "Die Anforderungsnutzlast wurde vom Metadatendienst abgelehnt.", + "forbidden": "Anfrage ist unzulässig, Rollen oder Authentifizierung fehlen.", + "pagination": "Die Anfrage enthält ungültige Paginierungsinformationen.", + "sort": "Die Anfrage enthält ungültige Sortierinformationen." }, "message": { - "missing": "Die Nachricht konnte in der Metadatendatenbank nicht gefunden werden" + "missing": "Die Nachricht konnte in der Metadatendatenbank nicht gefunden werden." }, "ontology": { - "missing": "Die Ontologie konnte in der Metadatendatenbank nicht gefunden werden" + "missing": "Die Ontologie konnte in der Metadatendatenbank nicht gefunden werden." }, "orcid": { - "missing": "ORCID konnte im Metadatenanbieter nicht gefunden werden" + "missing": "ORCID konnte im Metadatenanbieter nicht gefunden werden." }, "query": { - "missing": "Die Abfrage konnte im Datendienst nicht gefunden werden", - "invalid": "Die Abfrage ist ungültig", - "type.exists": "Abfrage konnte nicht erstellt werden: kein solcher Spaltentyp", - "type.build": "Abfrage konnte nicht erstellt werden: Derzeit gibt es keine Abfrageerstellungsunterstützung für den Spaltentyp", - "column.exists": "Abfrage konnte nicht erstellt werden: In den Datenspalten fehlt die Spalte mit dem Namen" + "missing": "Die Abfrage konnte im Datendienst nicht gefunden werden.", + "invalid": "Die Abfrage ist ungültig (enthält beispielsweise verbotene Schlüsselwörter).", + "type.exists": "Abfrage konnte nicht erstellt werden: kein solcher Spaltentyp:", + "type.build": "Abfrage konnte nicht erstellt werden: Derzeit gibt es keine Abfrageerstellungsunterstützung für den Spaltentyp:", + "column.exists": "Abfrage konnte nicht erstellt werden: In den Datenspalten fehlt die Spalte mit dem Namen:" }, "store": { - "invalid": "Der Abfragespeicher in der Datenbank konnte nicht erstellt werden", - "clean": "Der Abfragespeicher in der Datenbank konnte nicht durchsucht werden", - "insert": "Die Abfrage konnte nicht in den Abfragespeicher der Datenbank eingefügt werden", - "persist": "Die Abfrage konnte nicht im Abfragespeicher der Datenbank gespeichert werden" + "invalid": "Der Abfragespeicher in der Datenbank konnte nicht erstellt werden.", + "clean": "Der Abfragespeicher in der Datenbank konnte nicht durchsucht werden.", + "insert": "Die Abfrage konnte nicht in den Abfragespeicher der Datenbank eingefügt werden.", + "persist": "Die Abfrage konnte nicht im Abfragespeicher der Datenbank gespeichert werden." }, "metadata": { - "privileged": "Das Abrufen privilegierter Metadaten im Datendienst ist fehlgeschlagen", - "connection": "Es konnte keine Verbindung zum Metadatendienst hergestellt werden", - "invalid": "Es konnten keine Authentifizierungsmetadaten im Datendienst abgerufen werden" + "privileged": "Das Abrufen privilegierter Metadaten im Datendienst ist fehlgeschlagen.", + "connection": "Es konnte keine Verbindung zum Metadatendienst hergestellt werden.", + "invalid": "Es konnten keine Authentifizierungsmetadaten im Datendienst abgerufen werden." }, "sidecar": { - "export": "Der Datensatz konnte nicht in den Datenbank-Sidecar exportiert werden", - "import": "Der Datensatz konnte nicht aus dem Datenbank-Sidecar importiert werden" + "export": "Der Datensatz konnte nicht in den Datenbank-Sidecar exportiert werden.", + "import": "Der Datensatz konnte nicht aus dem Datenbank-Sidecar importiert werden." }, "queue": { - "missing": "Die Warteschlange im Broker-Dienst konnte nicht gefunden werden" + "missing": "Die Warteschlange im Broker-Dienst konnte nicht gefunden werden." }, "ror": { - "missing": "ROR konnte im Metadatenanbieter nicht gefunden werden" + "missing": "ROR konnte im Metadatenanbieter nicht gefunden werden." }, "import": { - "dataset": "Der Datensatz konnte nicht importiert werden" + "dataset": "Der Datensatz konnte nicht importiert werden." }, "upload": { - "dataset": "Der Datensatz konnte nicht hochgeladen werden" + "dataset": "Der Datensatz konnte nicht hochgeladen werden." }, "schema": { - "id": "Die Spalte „id“ muss ein Primärschlüssel sein", - "view": "Ansichtsschema konnte nicht zugeordnet werden", - "table": "Tabellenschema konnte nicht zugeordnet werden" + "id": "Die Spalte „id“ muss ein Primärschlüssel sein.", + "view": "Ansichtsschema konnte nicht zugeordnet werden.", + "table": "Tabellenschema konnte nicht zugeordnet werden." }, "user": { - "exists": "Benutzer mit Benutzername ist in der Authentifizierungsdatenbank vorhanden", - "missing": "Benutzer konnte in der Authentifizierungsdatenbank nicht gefunden werden", - "credentials": "Ungültige Benutzername und Passwort Kombination", - "email-exists": "Das Konto mit dieser E-Mail-Adresse existiert bereits", - "setup": "Bitte ändern Sie Ihr Passwort" + "exists": "Benutzer mit Benutzername ist in der Authentifizierungsdatenbank vorhanden.", + "missing": "Benutzer konnte in der Authentifizierungsdatenbank nicht gefunden werden.", + "credentials": "Ungültige Benutzername und Passwort Kombination.", + "email-exists": "Das Konto mit dieser E-Mail-Adresse existiert bereits.", + "setup": "Bitte ändern Sie Ihr Passwort." }, "search": { - "connection": "Es konnte keine Verbindung zum Suchdienst hergestellt werden", - "invalid": "Ungültige Suchanfrage" + "connection": "Es konnte keine Verbindung zum Suchdienst hergestellt werden.", + "invalid": "Ungültige Suchanfrage." }, "semantics": { - "timeout": "Semantikvorschlag fehlgeschlagen: Zeitüberschreitung bei der Anfrage", - "uri": "Der semantische URI ist fehlerhaft" + "timeout": "Semantikvorschlag fehlgeschlagen: Zeitüberschreitung bei der Anfrage.", + "uri": "Der semantische URI ist fehlerhaft." }, "subset": { - "format": "Die Teilmenge konnte nicht dem angeforderten Format zugeordnet werden" + "format": "Die Teilmenge konnte nicht dem angeforderten Format zugeordnet werden." }, "pagination": { - "malformed": "Ungültige Paginierungsanforderung" + "malformed": "Ungültige Paginierungsanforderung." }, "table": { - "missing": "Die Tabelle konnte in der Metadatendatenbank nicht gefunden werden", - "exists": "Die Tabelle mit diesem Namen existiert bereits", - "invalid": "Die Spalten im Datendienst konnten nicht analysiert werden", - "malformed": "Eintrag konnte nicht eingefügt werden", - "create": "Tabelle konnte nicht erstellt werden", - "connection": "Das Laden der Tabellendaten ist fehlgeschlagen, da die Datenbank nicht erreichbar ist" + "missing": "Die Tabelle konnte in der Metadatendatenbank nicht gefunden werden.", + "exists": "Die Tabelle mit diesem Namen existiert bereits.", + "invalid": "Die Spalten im Datendienst konnten nicht analysiert werden.", + "malformed": "Eintrag konnte nicht eingefügt werden:", + "create": "Tabelle konnte nicht erstellt werden:", + "connection": "Das Laden der Tabellendaten ist fehlgeschlagen, da die Datenbank nicht erreichbar ist." }, "unit": { - "missing": "Die semantische Einheit konnte in der Metadatendatenbank nicht gefunden werden" + "missing": "Die semantische Einheit konnte in der Metadatendatenbank nicht gefunden werden." }, "view": { - "create": "Ansicht konnte nicht erstellt werden", - "missing": "Die Ansicht konnte in der Metadatendatenbank nicht gefunden werden", - "invalid": "Die Ansichtsabfrage konnte den Spalten im Datendienst nicht zugeordnet werden" + "create": "Ansicht konnte nicht erstellt werden:", + "missing": "Die Ansicht konnte in der Metadatendatenbank nicht gefunden werden.", + "invalid": "Die Ansichtsabfrage konnte den Spalten im Datendienst nicht zugeordnet werden." } }, "success": { - "signup": "Konto erfolgreich erstellt", + "signup": "Konto erfolgreich erstellt.", "clipboard": { - "user": "Benutzer-ID erfolgreich kopiert" + "user": "Benutzer-ID erfolgreich kopiert." }, "query": { "build": "Abfrage konnte nicht erstellt werden: Spalte nicht gefunden", "fatal": "Abfragen mit diesem Schema können derzeit nicht über die Benutzeroberfläche erstellt werden" }, "import": { - "dataset": "Datensatz erfolgreich importiert" + "dataset": "Datensatz erfolgreich importiert." }, "upload": { - "dataset": "Datensatz erfolgreich hochgeladen", - "blob": "Datei erfolgreich hochgeladen" + "dataset": "Datensatz erfolgreich hochgeladen.", + "blob": "Datei erfolgreich hochgeladen." }, "analyse": { - "dataset": "Datensatz erfolgreich analysiert" + "dataset": "Datensatz erfolgreich analysiert." }, "access": { - "created": "Zugriff erfolgreich bereitgestellt", - "modified": "Zugriff erfolgreich geändert", - "revoked": "Zugriff erfolgreich widerrufen" + "created": "Zugriff erfolgreich bereitgestellt.", + "modified": "Zugriff erfolgreich geändert.", + "revoked": "Zugriff erfolgreich widerrufen." }, "data": { - "add": "Dateneingabe erfolgreich hinzugefügt", - "update": "Dateneingabe erfolgreich aktualisiert" + "add": "Dateneingabe erfolgreich hinzugefügt.", + "update": "Dateneingabe erfolgreich aktualisiert." }, "table": { - "created": "Tabelle erfolgreich erstellt", - "semantics": "Semantische Instanz erfolgreich zugewiesen" + "created": "Tabelle erfolgreich erstellt.", + "semantics": "Semantische Instanz erfolgreich zugewiesen." }, "schema": { - "tables": "Die Metadaten der Datenbanktabellen wurden erfolgreich aktualisiert", - "views": "Metadaten der Datenbankansichten wurden erfolgreich aktualisiert" + "tables": "Die Metadaten der Datenbanktabellen wurden erfolgreich aktualisiert.", + "views": "Metadaten der Datenbankansichten wurden erfolgreich aktualisiert." }, "database": { - "upload": "Datenbankbild erfolgreich hochgeladen", - "transfer": "Der Datenbankeigentümer wurde erfolgreich übertragen", - "visibility": "Die Datenbanksichtbarkeit wurde erfolgreich aktualisiert", + "upload": "Datenbankbild erfolgreich hochgeladen.", + "transfer": "Der Datenbankeigentümer wurde erfolgreich übertragen.", + "visibility": "Die Datenbanksichtbarkeit wurde erfolgreich aktualisiert.", "image": { - "update": "Datenbankbild erfolgreich aktualisiert", - "remove": "Datenbankbild erfolgreich entfernt" + "update": "Datenbankbild erfolgreich aktualisiert.", + "remove": "Datenbankbild erfolgreich entfernt." } }, "pid": { - "saved": "Kennung erfolgreich gespeichert", - "created": "Kennung erfolgreich erstellt", - "published": "Identifikator erfolgreich veröffentlicht", - "updated": "Kennung erfolgreich aktualisiert", - "deleted": "Kennung erfolgreich gelöscht" + "saved": "Kennung erfolgreich gespeichert.", + "created": "Kennung erfolgreich erstellt.", + "published": "Identifikator erfolgreich veröffentlicht.", + "updated": "Kennung erfolgreich aktualisiert.", + "deleted": "Kennung erfolgreich gelöscht." }, "user": { - "info": "Benutzerinformationen erfolgreich aktualisiert", - "theme": "Benutzerthema erfolgreich aktualisiert", - "password": "Benutzerkennwort erfolgreich aktualisiert", - "login": "Erfolgreich angemeldet" + "info": "Benutzerinformationen erfolgreich aktualisiert.", + "theme": "Benutzerthema erfolgreich aktualisiert.", + "password": "Benutzerkennwort erfolgreich aktualisiert.", + "login": "Erfolgreich angemeldet." }, "view": { - "create": "Ansicht erfolgreich erstellt", - "delete": "Ansicht erfolgreich gelöscht" + "create": "Ansicht erfolgreich erstellt.", + "delete": "Ansicht erfolgreich gelöscht." }, "subset": { - "create": "Teilmenge erfolgreich erstellt" + "create": "Teilmenge erfolgreich erstellt." } }, "toolbars": { @@ -1252,7 +1248,7 @@ "semantic": { "register": { "title": "Registrieren Sie die Ontologie", - "subtitle": "Registrieren Sie einen neuen Ontologie-Endpunkt" + "subtitle": "Registrieren Sie einen neuen Ontologie-Endpunkt." }, "ontologies": { "title": "Ontologien", @@ -1270,7 +1266,6 @@ "public": "Öffentlich", "private": "Privat", "current": "Aktuelle Daten", - "history": "Historische Daten", "create": { "text": "Datenbank" }, @@ -1334,7 +1329,7 @@ }, "search": { "fuzzy": { - "placeholder": "Suchen .." + "placeholder": "Suchen ..." }, "result": "Ergebnis", "results": "Ergebnisse" @@ -1376,7 +1371,7 @@ "tuple": "Eintrag", "download": "Herunterladen", "version": "Geschichte", - "subtitle": "Stellen Sie Daten bereit, die direkt in den Datensatz eingefügt werden sollen" + "subtitle": "Stellen Sie Daten bereit, die direkt in den Datensatz eingefügt werden sollen." } } }, @@ -1391,7 +1386,7 @@ "month": "Ungültiger Monat", "schema": { "id": "Die Spalte muss als Primärschlüssel deklariert werden", - "primary-key": "Wir erstellen eine Spalte mit dem Namen „id“ mit einer automatisch ansteigenden Sequenz, die bei 1 beginnt. Bitte geben Sie eine Spalte mit Primärschlüssel an, wenn Sie dieses Verhalten nicht wünschen" + "primary-key": "Wir erstellen eine Spalte mit dem Namen „id“ mit einer automatisch ansteigenden Sequenz, die bei 1 beginnt. Bitte geben Sie eine Spalte mit Primärschlüssel an, wenn Sie dieses Verhalten nicht wünschen." }, "uri": { "pattern": "Ungültiger URI", diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 54d7a64a7adf6c8db89b95b7ee9e4e54a7691940..71d8c09051fe8fad476fa1b11fb23d612755e884 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -88,12 +88,12 @@ }, "publication-year": { "label": "Publication Year", - "hint": "Required" + "hint": "Required." }, "titles": { "title": { "label": "Title", - "hint": "Required" + "hint": "Required." }, "type": { "label": "Type", @@ -103,7 +103,7 @@ "label": "Language", "hint": "" }, - "subtitle": "A name or title by which a resource is known. May be the title of a dataset", + "subtitle": "A name or title by which a resource is known. May be the title of a dataset.", "remove": { "text": "Remove" }, @@ -116,15 +116,15 @@ "subtitle": "Do you already have a DOI for this dataset?", "label": "Provide your existing DOI here", "hint": "A DOI allows your upload to be easily and unambiguously cited. Example: 10.1234/foo.bar", - "mint": "A PID will be minted after saving" + "mint": "A PID will be minted after saving." }, "doi": { - "mint": "A DOI will be created after saving" + "mint": "A DOI will be created after saving." }, "descriptions": { "description": { "label": "Description", - "hint": "Required" + "hint": "Required." }, "type": { "label": "Type", @@ -134,7 +134,7 @@ "label": "Language", "hint": "" }, - "subtitle": "All additional information. May be used for technical information or detailed information associated with a dataset", + "subtitle": "All additional information. May be used for technical information or detailed information associated with a dataset.", "remove": { "text": "Remove" }, @@ -144,16 +144,16 @@ }, "publisher": { "title": "Publication Information", - "subtitle": "The name of the entity that holds, archives, publishes, prints, distributes, releases, issues, or produces the resource. This property will be used to formulate the citation, so consider the prominence of the role", + "subtitle": "The name of the entity that holds, archives, publishes, prints, distributes, releases, issues, or produces the resource. This property will be used to formulate the citation, so consider the prominence of the role.", "label": "Publisher", - "hint": "Required" + "hint": "Required." }, "related-identifiers": { "title": "Related Identifier", - "subtitle": "Identifiers of related resources. These must be globally unique identifiers", + "subtitle": "Identifiers of related resources. These must be globally unique identifiers.", "identifier": { "label": "Identifier", - "hint": "Required" + "hint": "Required." }, "type": { "label": "Type", @@ -172,14 +172,14 @@ }, "licenses": { "title": "License", - "subtitle": "Identifiers of related resources. These must be globally unique identifiers", + "subtitle": "Identifiers of related resources. These must be globally unique identifiers.", "license": { "label": "License" } }, "language": { "title": "Language", - "subtitle": "The primary language of the dataset", + "subtitle": "The primary language of the dataset.", "language": { "label": "Language", "hint": "" @@ -187,14 +187,14 @@ }, "funders": { "title": "Funding Reference", - "subtitle": "Information about financial support (funding) for the dataset being registered", + "subtitle": "Information about financial support (funding) for the dataset being registered.", "identifier": { "label": "Funder Identifier", "hint": "Use a name identifier expressed as URL from ORCID*, ROR*, DOI*, ISNI, GND (schemes with * support automatic metadata retrieval)" }, "name": { "label": "Funder Name", - "hint": "Required" + "hint": "Required." }, "award-number": { "label": "Award Number", @@ -212,7 +212,7 @@ } }, "creators": { - "subtitle": "The main researchers involved in producing the data, in priority order", + "subtitle": "The main researchers involved in producing the data, in priority order.", "identifier": { "label": "Name Identifier", "hint": "Use a name identifier expressed as URL from ORCID*, ROR*, DOI*, ISNI, GND (schemes with * support automatic metadata retrieval)" @@ -239,7 +239,7 @@ }, "name": { "label": "Name", - "hint": "Required" + "hint": "Required." }, "affiliation-identifier": { "label": "Affiliation Identifier", @@ -253,7 +253,7 @@ }, "summary": { "title": "Summary", - "subtitle": "Details of the identifier that will be created to identify this record", + "subtitle": "Details of the identifier that will be created to identify this record.", "record": "The identifier describes", "publisher": "Publisher", "license": "License", @@ -287,8 +287,8 @@ "secure": "secure", "insecure": "insecure", "permissions": { - "write": "You can write to this table", - "read": "You can read all contents of this table" + "write": "You can write to this table.", + "read": "You can read all contents of this table." } }, "protocol": { @@ -322,32 +322,32 @@ }, "dataset": { "title": "Dataset Structure", - "warn": "The dataset schema does not match the target table schema. You can still force the import but it is not recommended" + "warn": "The dataset schema does not match the target table schema. You can still force the import but it is not recommended." }, "name": { "label": "Name", - "hint": "Required. Maximum length is 64 characters" + "hint": "Required. Maximum length is 64 characters." }, "generated": { "label": "Preview Table Name", - "hint": "Readonly" + "hint": "Readonly." }, "description": { "label": "Description", - "hint": "Optional. Short and concise description of the data" + "hint": "Optional. Short and concise description of the data." }, "separator": { "label": "Column Separator", - "hint": "Optional. Character that separates the columns", + "hint": "Optional. Character that separates the columns.", "warn": { "prefix": "We analysed your .csv/.tsv dataset and found that the separator you provided", "middle": "is not correct, the separator", - "suffix": "is more likely to be correct. It is advised to change the separator above" + "suffix": "is more likely to be correct. It is advised to change the separator above." } }, "skip": { "label": "Skip Rows", - "hint": "Optional. Number of rows to skip, e.g. when the first one contains header and no data" + "hint": "Optional. Number of rows to skip, e.g. when the first one contains header and no data." }, "quote": { "label": "Quote Encoding", @@ -355,11 +355,11 @@ }, "terminator": { "label": "Line Termination Encoding", - "hint": "Optional. Character that terminates the newlines", + "hint": "Optional. Character that terminates the newlines.", "warn": { "prefix": "We analysed your .csv/.tsv dataset and found that the line termination encoding you provided", "middle": "is not correct, the line termination encoding", - "suffix": "is more likely to be correct. It is advised to change the line termination encoding above" + "suffix": "is more likely to be correct. It is advised to change the line termination encoding above." } }, "null": { @@ -368,16 +368,16 @@ }, "true": { "label": "True Encoding", - "hint": "Optional. Character sequence that represents boolean true, e.g. 1, true, yes" + "hint": "Optional. Character sequence that represents boolean true, e.g. 1, true, yes." }, "false": { "label": "False Encoding", - "hint": "Optional. Character sequence that represents boolean false, e.g. 0, false, no" + "hint": "Optional. Character sequence that represents boolean false, e.g. 0, false, no." }, "file": { "title": "Dataset Upload", "label": "Dataset File", - "hint": "Required. Needs to be in .csv/.tsv file format" + "hint": "Required. Needs to be in .csv/.tsv file format." }, "preview": { "title": "Preview" @@ -385,7 +385,7 @@ "summary": { "title": "Summary", "prefix": "Imported", - "suffix": "rows from dataset" + "suffix": "rows from dataset." }, "analyse": { "text": "Upload & Analyse" @@ -398,7 +398,7 @@ }, "name": { "label": "Table Name", - "hint": "Required" + "hint": "Required." }, "description": { "label": "Table Description", @@ -406,23 +406,22 @@ }, "summary": { "prefix": "Created table with name", - "suffix": "and imported dataset successfully" + "suffix": "and imported dataset successfully." } }, "drop": { "title": "Drop table", "warning": { "prefix": "This action cannot be undone! Type the table name", - "suffix": "below if you really want to drop it with all stored data" + "suffix": "below if you really want to drop it with all stored data." }, "name": { "label": "Table Name", - "hint": "Required" + "hint": "Required." } }, "schema": { "title": "System Versioned", - "subtitle": "Table Constraints", "bullet": "●", "assign": "Assign", "remove": { @@ -454,14 +453,14 @@ }, "name": { "label": "Name", - "hint": "Required" + "hint": "Required." }, "add": { "text": "Add Column" }, "type": { "label": "Type", - "hint": "Required" + "hint": "Required." }, "size": { "label": "Size" @@ -497,23 +496,23 @@ }, "summary": { "title": "Summary", - "text": "Successfully created table with internal name" + "text": "Successfully created table with internal name:" } }, "semantics": { - "title": "Assign semantic instance for table column", - "subtitle": "Semantic instances help machines to get the proper context of your dataset", + "title": "Assign semantic instance for table column:", + "subtitle": "Semantic instances help machines to get the proper context of your dataset.", "recommended": "Recommended semantic instances", "bullet": "●", - "info": "The following ontologies automatically will query the fields rdfs:label and store it for this column. You can still use other URIs that are not matching these ontologies, the URI will be displayed instead", + "info": "The following ontologies automatically will query the fields rdfs:label and store it for this column. You can still use other URIs that are not matching these ontologies, the URI will be displayed instead.", "uri": { "label": "Semantic Instance URI", - "hint": "This URI can be automatically resolved" + "hint": "This URI can be automatically resolved." } }, "versioning": { "title": "History", - "subtitle": "Select a timestamp to view the data for this specific time of day", + "subtitle": "Select a timestamp to view the data for this specific time of day.", "chart": { "title": "Data Events", "ylabel": "# Events", @@ -528,22 +527,22 @@ }, "data": { "auto": { - "hint": "Value is automatically generated by a sequence" + "hint": "Value is automatically generated by a sequence." }, "primary-key": { - "hint": "Value is a primary key" + "hint": "Value is a primary key." }, "format": { - "hint": "Value must be in format" + "hint": "Value must be in format:" }, "required": { "hint": "Required. " }, "float": { - "max": "max", - "min": "min", - "before": "digit(s) before the dot", - "after": "digit(s) after the dot" + "max": "max.", + "min": "min.", + "before": "digit(s) before the dot.", + "after": "digit(s) after the dot." } } } @@ -583,7 +582,7 @@ "subpages": { "access": { "title": "Database Access", - "subtitle": "Overview on users with their access to the database", + "subtitle": "Overview on users with their access to the database.", "read": "You can read all contents", "write-own": "You can write own tables and read all contents", "write-all": "You can write own tables and read all contents", @@ -603,7 +602,7 @@ }, "create": { "title": "Create Database", - "subtitle": "Choose an expressive database name and select a database engine", + "subtitle": "Choose an expressive database name and select a database engine.", "name": { "label": "Name", "hint": "Required. The internal database name will be lowercase alphanumeric, others will be replaced with _", @@ -611,7 +610,7 @@ }, "engine": { "label": "Engine", - "hint": "Required" + "hint": "Required." }, "submit": { "text": "Create" @@ -637,7 +636,7 @@ }, "settings": { "title": "Settings", - "subtitle": "The image will be displayed in a box with maximum dimensions 200x200 pixels", + "subtitle": "The image will be displayed in a box with maximum dimensions 200x200 pixels.", "image": { "label": "Teaser Image", "hint": "max. 1MB file size" @@ -650,26 +649,26 @@ }, "scheme": { "title": "Schema", - "subtitle": "Update the metadata on the database schema to display system-versioned tables and views in the UI", + "subtitle": "Update the metadata on the database schema to display system-versioned tables and views in the UI.", "submit": { "text": "Refresh" } }, "ownership": { "title": "Ownership", - "subtitle": "User who has ownership over this database", + "subtitle": "User who has ownership over this database.", "label": "Database Owner", - "hint": "Required", + "hint": "Required.", "submit": { "text": "Transfer" } }, "visibility": { "title": "Visibility", - "subtitle": "Private databases hide the data while metadata is still visible. Public databases are fully transparent", + "subtitle": "Private databases hide the data while metadata is still visible. Public databases are fully transparent.", "visibility": { "label": "Database Visibility", - "hint": "Required" + "hint": "Required." }, "submit": { "text": "Modify" @@ -682,19 +681,19 @@ "name": "Signup", "email": { "label": "E-Mail Address", - "hint": "Required" + "hint": "Required." }, "username": { "label": "Username", - "hint": "Required" + "hint": "Required." }, "password": { "label": "Password", - "hint": "Required" + "hint": "Required." }, "confirm": { "label": "Confirm Password", - "hint": "Required" + "hint": "Required." }, "submit": { "label": "Submit" @@ -704,11 +703,11 @@ "name": "Login", "username": { "label": "Username", - "hint": "Required" + "hint": "Required." }, "password": { "label": "Password", - "hint": "Required" + "hint": "Required." }, "submit": { "label": "Submit" @@ -721,7 +720,7 @@ "subpages": { "info": { "title": "Information", - "subtitle": "General user metadata", + "subtitle": "General user metadata.", "id": { "label": "ID" }, @@ -755,7 +754,7 @@ }, "theme": { "title": "Theme", - "subtitle": "Update the user theme when logged in", + "subtitle": "Update the user theme when logged in.", "label": "Theme", "dark": "Dark", "dark-contrast": "Dark - High Contrast", @@ -771,14 +770,14 @@ "subpages": { "authentication": { "title": "User Password", - "subtitle": "Update the user password used for basic authentication with all interfaces", + "subtitle": "Update the user password used for basic authentication with all interfaces.", "password": { "label": "Password", - "hint": "Required" + "hint": "Required." }, "confirm": { "label": "Confirm Password", - "hint": "Required" + "hint": "Required." }, "submit": { "text": "Update" @@ -787,7 +786,7 @@ "developer": { "token": { "title": "Token Information", - "subtitle": "View your token secrets for debugging purposes", + "subtitle": "View your token secrets for debugging purposes.", "expiry": "Expires", "access": { "label": "Access Token" @@ -806,11 +805,11 @@ "title": "Maintenance Message", "type": { "label": "Type", - "hint": "Required" + "hint": "Required." }, "message": { "label": "Message", - "hint": "Required" + "hint": "Required." }, "start": { "label": "Start Timestamp" @@ -841,11 +840,8 @@ "info": "Info", "data": "Data" }, - "name": { - "title": "Name" - }, "query": { - "title": "Statement" + "title": "Query" }, "creator": { "title": "Creator" @@ -861,20 +857,20 @@ "title": "Create View", "name": { "label": "Name", - "hint": "Required" + "hint": "Required." }, "table": { "label": "Data Table", - "hint": "Required" + "hint": "Required." }, "columns": { "label": "Data Columns", - "hint": "Required" + "hint": "Required." }, "visibility": { "label": "Data Visibility", - "warn": "Only people with at least read access can view the data", - "hint": "Required. When private, the view metadata will still be public but the data will only be visible to people with at least read access to this database" + "warn": "Only people with at least read access can view the data.", + "hint": "Required. When private, the view metadata will still be public but the data will only be visible to people with at least read access to this database." } } } @@ -891,7 +887,7 @@ "title": "Query" }, "query-hash": { - "prefix": "sha256", + "prefix": "sha256:", "title": "Query Hash" }, "executed": { @@ -910,14 +906,14 @@ "subpages": { "create": { "title": "Create Subset", - "generated": "The following query will be executed (readonly)", - "subtitle": "The following query will be executed", + "generated": "The following query will be executed (readonly):", + "subtitle": "The following query will be executed:", "simple": { "text": "Simple" }, "expert": { "text": "Expert", - "warn": "It is not recommended to use comments, aggregation functions and the following operations" + "warn": "It is not recommended to use comments, aggregation functions and the following operations:" }, "name": { "label": "" @@ -926,15 +922,15 @@ "text": "Add Filter", "column": { "label": "Column", - "hint": "Required" + "hint": "Required." }, "operator": { "label": "Operator", - "hint": "Required" + "hint": "Required." }, "value": { "label": "Value", - "hint": "Required" + "hint": "Required." }, "remove": { "text": "Remove" @@ -977,7 +973,7 @@ "hint": "" }, "publication-range": { - "hint": "Specify your custom publication year range" + "hint": "Specify your custom publication year range." }, "start-year": { "label": "Start Year", @@ -988,7 +984,7 @@ "hint": "" }, "concept-unit": { - "hint": "If you select a CONCEPT and UNIT, you can search across columns regardless of their unit of measurement" + "hint": "If you select a CONCEPT and UNIT, you can search across columns regardless of their unit of measurement." }, "concept": { "label": "Concept", @@ -1031,216 +1027,216 @@ }, "error": { "access": { - "missing": "Failed to find access in metadata database" + "missing": "Failed to find access in metadata database." }, "axios": { - "connection": "Failed to establish connection", - "timeout": "Connection timed out" + "connection": "Failed to establish connection.", + "timeout": "Connection timed out." }, "concept": { - "missing": "Failed to find concept in metadata database" + "missing": "Failed to find concept in metadata database." }, "container": { - "exists": "Container already exists in metadata database", - "missing": "Failed to find container in metadata database" + "exists": "Container already exists in metadata database.", + "missing": "Failed to find container in metadata database." }, "data": { - "invalid": "Failed to communicate with data service", - "connection": "Failed to establish connection to data service", - "value": "Failed to set column value", - "drift": "Your browser clock is not synchronized with UTC and seems to be off by" + "invalid": "Failed to communicate with data service.", + "connection": "Failed to establish connection to data service.", + "value": "Failed to set column value:", + "drift": "Your browser clock is not synchronized with UTC and seems to be off by:" }, "database": { - "connection": "Failed to establis connection to the database", - "invalid": "Failed to perform action in database", + "connection": "Failed to establis connection to the database.", + "invalid": "Failed to perform action in database.", "querystore": "Failed to insert query into query store", - "missing": "Failed to find database in metadata database", - "create": "Failed to establish connection with metadata service" + "missing": "Failed to find database in metadata database.", + "create": "Failed to establish connection with metadata service." }, "doi": { - "missing": "Failed to find DOI in metadata database" + "missing": "Failed to find DOI in metadata database." }, "exchange": { - "missing": "Failed to find exchange in broker service" + "missing": "Failed to find exchange in broker service." }, "semantic": { - "filter": "Failed to filter semantic entity in metadata service", - "missing": "Failed to find semantic entity in metadata service" + "filter": "Failed to filter semantic entity in metadata service.", + "missing": "Failed to find semantic entity in metadata service." }, "storage": { - "missing": "Failed to find dataset in storage service", - "invalid": "Failed to establish connection with storage service" + "missing": "Failed to find dataset in storage service.", + "invalid": "Failed to establish connection with storage service." }, "identifier": { - "format": "Failed to transform identifier into the requested format in metadata service", - "missing": "Failed to find identifier in metadata database", - "unsupported": "Failed to find metadata from unsupported metadata provider", + "format": "Failed to transform identifier into the requested format in metadata service.", + "missing": "Failed to find identifier in metadata database.", + "unsupported": "Failed to find metadata from unsupported metadata provider.", "form": "Please provide all required values in the form" }, "image": { - "exists": "Image already exists in metadata database", - "missing": "Failed to find image in metadata database", - "invalid": "Image metadata is malformed" + "exists": "Image already exists in metadata database.", + "missing": "Failed to find image in metadata database.", + "invalid": "Image metadata is malformed." }, "license": { - "missing": "Failed to find license in metadata database" + "missing": "Failed to find license in metadata database." }, "request": { - "invalid": "Request payload was rejected by the metadata service", - "forbidden": "Request is forbidden, roles or authentication missing", - "pagination": "Request contains invalid pagination information", - "sort": "Request contains invalid sort information" + "invalid": "Request payload was rejected by the metadata service.", + "forbidden": "Request is forbidden, roles or authentication missing.", + "pagination": "Request contains invalid pagination information.", + "sort": "Request contains invalid sort information." }, "message": { - "missing": "Failed to find message in metadata database" + "missing": "Failed to find message in metadata database." }, "ontology": { - "missing": "Failed to find ontology in metadata database" + "missing": "Failed to find ontology in metadata database." }, "orcid": { - "missing": "Failed to find ORCID in metadata provider" + "missing": "Failed to find ORCID in metadata provider." }, "query": { - "missing": "Failed to find query in data service", - "invalid": "Query is invalid", - "type.exists": "Failed to build query: no such column type", - "type.build": "Failed to build query: currently no query build support for column type", - "column.exists": "Failed to build query: data columns are missing column with name" + "missing": "Failed to find query in data service.", + "invalid": "Query is invalid (e.g. contains forbidden keywords).", + "type.exists": "Failed to build query: no such column type:", + "type.build": "Failed to build query: currently no query build support for column type:", + "column.exists": "Failed to build query: data columns are missing column with name:" }, "store": { - "invalid": "Failed to create query store in the database", - "clean": "Failed to sweep query store in the database", - "insert": "Failed to insert query into database query store", - "persist": "Failed to persist query in the database query store" + "invalid": "Failed to create query store in the database.", + "clean": "Failed to sweep query store in the database.", + "insert": "Failed to insert query into database query store.", + "persist": "Failed to persist query in the database query store." }, "metadata": { - "privileged": "Failed to fetch privileged metadata in the data service", - "connection": "Failed to establish connection to the metadata service", - "invalid": "Failed to obtain authentication metadata in the data service" + "privileged": "Failed to fetch privileged metadata in the data service.", + "connection": "Failed to establish connection to the metadata service.", + "invalid": "Failed to obtain authentication metadata in the data service." }, "sidecar": { - "export": "Failed to export dataset to the database sidecar", - "import": "Failed to import dataset from the database sidecar" + "export": "Failed to export dataset to the database sidecar.", + "import": "Failed to import dataset from the database sidecar." }, "queue": { - "missing": "Failed to find queue in broker service" + "missing": "Failed to find queue in broker service." }, "ror": { - "missing": "Failed to find ROR in metadata provider" + "missing": "Failed to find ROR in metadata provider." }, "import": { - "dataset": "Failed to import dataset" + "dataset": "Failed to import dataset." }, "upload": { - "dataset": "Failed to upload dataset" + "dataset": "Failed to upload dataset." }, "schema": { - "id": "Column \"id\" must be a primary key", - "view": "Failed to map view schema", - "table": "Failed to map table schema" + "id": "Column \"id\" must be a primary key.", + "view": "Failed to map view schema.", + "table": "Failed to map table schema." }, "user": { - "exists": "User with username exists in auth database", - "missing": "Failed to find user in auth database", - "credentials": "Invalid username/password combination", - "email-exists": "Account with this e-mail exists already", - "setup": "Please change your password" + "exists": "User with username exists in auth database.", + "missing": "Failed to find user in auth database.", + "credentials": "Invalid username/password combination.", + "email-exists": "Account with this e-mail exists already.", + "setup": "Please change your password." }, "search": { - "connection": "Failed to establish connection to the search service", - "invalid": "Malformed search request" + "connection": "Failed to establish connection to the search service.", + "invalid": "Malformed search request." }, "semantics": { - "timeout": "Failed to suggest semantics: request timed out", - "uri": "Semantic URI is malformed" + "timeout": "Failed to suggest semantics: request timed out.", + "uri": "Semantic URI is malformed." }, "subset": { - "format": "Failed to map subset into requested format" + "format": "Failed to map subset into requested format." }, "pagination": { - "malformed": "Invalid pagination request" + "malformed": "Invalid pagination request." }, "table": { - "missing": "Failed to find table in metadata database", - "exists": "Table with this name exists already", - "invalid": "Failed to parse columns in the data service", - "malformed": "Failed to insert entry", - "create": "Failed to create table", - "connection": "Failed to load table data because database is not reachable" + "missing": "Failed to find table in metadata database.", + "exists": "Table with this name exists already.", + "invalid": "Failed to parse columns in the data service.", + "malformed": "Failed to insert entry:", + "create": "Failed to create table:", + "connection": "Failed to load table data because database is not reachable." }, "unit": { - "missing": "Failed to find semantic unit in metadata database" + "missing": "Failed to find semantic unit in metadata database." }, "view": { - "create": "Failed to create view", - "missing": "Failed to find view in metadata database", - "invalid": "Failed to map view query to columns in data service" + "create": "Failed to create view:", + "missing": "Failed to find view in metadata database.", + "invalid": "Failed to map view query to columns in data service." } }, "success": { - "signup": "Successfully created account", + "signup": "Successfully created account.", "clipboard": { - "user": "Successfully copied user id" + "user": "Successfully copied user id." }, "query": { "build": "Failed to build query: column not found", "fatal": "Query with this schema is not buildable through the UI at the moment" }, "import": { - "dataset": "Successfully imported dataset" + "dataset": "Successfully imported dataset." }, "upload": { - "dataset": "Successfully uploaded dataset", - "blob": "Successfully uploaded file" + "dataset": "Successfully uploaded dataset.", + "blob": "Successfully uploaded file." }, "analyse": { - "dataset": "Successfully analysed dataset" + "dataset": "Successfully analysed dataset." }, "access": { - "created": "Successfully provisioned access", - "modified": "Successfully modified access", - "revoked": "Successfully revoked access" + "created": "Successfully provisioned access.", + "modified": "Successfully modified access.", + "revoked": "Successfully revoked access." }, "data": { - "add": "Successfully added data entry", - "update": "Successfully updated data entry" + "add": "Successfully added data entry.", + "update": "Successfully updated data entry." }, "table": { - "created": "Successfully created table", - "semantics": "Successfully assigned semantic instance" + "created": "Successfully created table.", + "semantics": "Successfully assigned semantic instance." }, "schema": { - "tables": "Successfully refreshed database tables metadata", - "views": "Successfully refreshed database views metadata" + "tables": "Successfully refreshed database tables metadata.", + "views": "Successfully refreshed database views metadata." }, "database": { - "upload": "Successfully uploaded database image", - "transfer": "Successfully transferred the database owner", - "visibility": "Successfully updated the database visibility", + "upload": "Successfully uploaded database image.", + "transfer": "Successfully transferred the database owner.", + "visibility": "Successfully updated the database visibility.", "image": { - "update": "Successfully updated database image", - "remove": "Successfully removed database image" + "update": "Successfully updated database image.", + "remove": "Successfully removed database image." } }, "pid": { - "saved": "Successfully saved identifier", - "created": "Successfully created identifier", - "published": "Successfully published identifier", - "updated": "Successfully updated identifier", - "deleted": "Successfully deleted identifier" + "saved": "Successfully saved identifier.", + "created": "Successfully created identifier.", + "published": "Successfully published identifier.", + "updated": "Successfully updated identifier.", + "deleted": "Successfully deleted identifier." }, "user": { - "info": "Successfully updated user information", - "theme": "Successfully updated user theme", - "password": "Successfully updated user password", - "login": "Successfully logged in" + "info": "Successfully updated user information.", + "theme": "Successfully updated user theme.", + "password": "Successfully updated user password.", + "login": "Successfully logged in." }, "view": { - "create": "Successfully created view", - "delete": "Successfully deleted view" + "create": "Successfully created view.", + "delete": "Successfully deleted view." }, "subset": { - "create": "Successfully created subset" + "create": "Successfully created subset." } }, "toolbars": { @@ -1252,7 +1248,7 @@ "semantic": { "register": { "title": "Register Ontology", - "subtitle": "Register a new ontology endpoint" + "subtitle": "Register a new ontology endpoint." }, "ontologies": { "title": "Ontologies", @@ -1270,7 +1266,6 @@ "public": "Public", "private": "Private", "current": "Current Data", - "history": "Historic Data", "create": { "text": "Database" }, @@ -1334,7 +1329,7 @@ }, "search": { "fuzzy": { - "placeholder": "Search .." + "placeholder": "Search ..." }, "result": "Result", "results": "Results" @@ -1376,7 +1371,7 @@ "tuple": "Entry", "download": "Download", "version": "History", - "subtitle": "Provide data to be directly inserted into the dataset" + "subtitle": "Provide data to be directly inserted into the dataset." } } }, @@ -1391,7 +1386,7 @@ "month": "Invalid month", "schema": { "id": "Column needs to be declared as primary key", - "primary-key": "We create a column named id with a auto-increasing sequence starting at 1. Please specify a column with primary key if you don't want this behavior" + "primary-key": "We create a column named id with a auto-increasing sequence starting at 1. Please specify a column with primary key if you don't want this behavior." }, "uri": { "pattern": "Invalid URI", diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue index 27191e2a606f838a78956854b18352f93c503e9c..3c90c1485819bbd03e267e556e853cbf2c6b0f65 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue @@ -88,7 +88,7 @@ v-model="pickVersionDialog" max-width="640" @close="closeVersion"> - <TableHistory + <TimeTravel ref="timeTravel" @close="pickVersion" /> </v-dialog> @@ -117,7 +117,7 @@ </template> <script> -import TableHistory from '@/components/table/TableHistory.vue' +import TimeTravel from '@/components/dialogs/TimeTravel.vue' import TimeDrift from '@/components/TimeDrift.vue' import TableToolbar from '@/components/table/TableToolbar.vue' import {formatTimestampUTC, formatDateUTC, formatTimestamp} from '@/utils' @@ -130,7 +130,7 @@ export default { components: { BlobDownload, EditTuple, - TableHistory, + TimeTravel, TableToolbar, TimeDrift }, @@ -404,7 +404,7 @@ export default { return } try { - this.headers = [] + this.headers = [{ value: 'selection', title: '', sortable: false }] this.table.columns.map((c) => { return { value: c.internal_name, @@ -448,9 +448,9 @@ export default { }) this.loadingData = false }) - .catch(({code, message}) => { + .catch(({code}) => { const toast = useToastInstance() - toast.error(this.$t(code) + ": " + message) + toast.error(this.$t(code)) this.error = true this.loadingData = false }) @@ -463,9 +463,9 @@ export default { this.total = count this.loadingCount = false }) - .catch(({code, message}) => { + .catch(({code}) => { const toast = useToastInstance() - toast.error(this.$t(code) + ": " + message) + toast.error(this.$t(code)) this.loadingCount = false }) }, diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue index 3a821a730b50c6292f603b67c8b666add18aaa08..0509cc0c2c0dd3edfb711c39fcda15daf5d6993f 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue @@ -78,7 +78,7 @@ variant="flat" rounded="0" tile - :title="$t('pages.table.subpages.schema.subtitle')"> + :title="$t('pages.table.subpages.schema.title')"> <v-card-text> <v-container> <ul> @@ -87,7 +87,12 @@ (<i v-text="primaryKeysColumns" />) </li> <li v-for="(foreignKey, i) in table.constraints.foreign_keys" :key="`fk-${i}`"> - <strong>FOREIGN KEY</strong> <span v-text="foreignKey.name" /> (<i v-text="foreignKeyColumns(foreignKey)" />) <strong>REFERENCES</strong> <a :href="`/database/${database.id}/table/${foreignKey.referenced_table.id}/schema`" v-text="foreignKeyReferencedTable(foreignKey)" /> (<i v-text="foreignKeyReferencedColumns(foreignKey)" />) + <strong>FOREIGN KEY</strong> + <span v-text="foreignKey.name" /> + (<i v-text="foreignKeyColumns(foreignKey)" />) + <strong>REFERENCES</strong> + <a :href="`/database/${database.id}/table/${foreignKey.referenced_table.id}/schema`" v-text="foreignKeyReferencedTable(foreignKey)" /> + (<i v-text="foreignKeyReferencedColumns(foreignKey)" />) </li> <li v-for="(uniqueConstraint, i) in table.constraints.uniques" :key="`uk-${i}`"> <strong>UNIQUE INDEX</strong> @@ -257,7 +262,7 @@ export default { if (!foreignKey) { return null } - return foreignKey.references.map(r => r.column.internal_name).join(',') + return foreignKey.columns.map(c => c.internal_name).join(',') }, foreignKeyReferencedTable (foreignKey) { if (!foreignKey) { @@ -269,7 +274,7 @@ export default { if (!foreignKey) { return null } - return foreignKey.references.map(r => r.referenced_column.internal_name).join(',') + return foreignKey.referenced_columns.map(c => c.internal_name).join(',') }, uniqueColumns (uniqueConstraint) { if (!uniqueConstraint) { diff --git a/dbrepo-ui/pages/database/[database_id]/table/create.vue b/dbrepo-ui/pages/database/[database_id]/table/create.vue index 52af4ad304db37b7884c746447a1f0629fd0fa8e..34c87d163d5e571b0eaa1f08f161e7d15953db75 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/create.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/create.vue @@ -113,7 +113,7 @@ <v-container v-if="table"> <v-row dense> - <v-col md="8"> + <v-col> <v-alert border="start" color="success" diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue index 03464f5dbba66d89312f7b1c4a55332c79af161a..783ad566378a9b91acee508ee93e81489a107074 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue @@ -1,7 +1,6 @@ <template> - <div> - <ViewToolbar - v-if="view" /> + <div v-if="view"> + <ViewToolbar /> <v-toolbar color="secondary" :title="$t('toolbars.database.current')" @@ -20,6 +19,7 @@ id="query-results" ref="queryResults" type="view" + :view="view" class="mt-0 mb-0" /> </v-card> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> @@ -76,12 +76,15 @@ export default { } }, mounted () { + if (!this.view) { + return + } this.reload() }, methods: { reload () { - this.$refs.queryResults.reExecute(Number(this.$route.params.view_id)) - this.$refs.queryResults.reExecuteCount(Number(this.$route.params.view_id)) + this.$refs.queryResults.reExecute(this.view.id) + this.$refs.queryResults.reExecuteCount(this.view.id) } } } diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue index 3ec97f2bdaec1109edc16f1bedf0ee22b07a1f52..44211b6eacebb09a27e72b1236742f984ebde666 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue @@ -1,10 +1,10 @@ <template> - <div> + <div + v-if="view"> <ViewToolbar /> <v-window v-model="tab"> - <v-window-item - v-if="view"> + <v-window-item> <v-card variant="flat"> <Summary v-if="hasIdentifier" @@ -25,10 +25,6 @@ <v-list v-if="view" dense> - <v-list-item - :title="$t('pages.view.name.title')"> - {{ view.internal_name }} - </v-list-item> <v-list-item :title="$t('pages.view.query.title')"> <pre>{{ view.query }}</pre> diff --git a/.docker/docker-compose.yml b/docker-compose.prod.yml similarity index 92% rename from .docker/docker-compose.yml rename to docker-compose.prod.yml index d51b00551a3a6af30bbb7d454f6fea00c17e7d65..3f24092344e371430730a450bbda9218b0d19144 100644 --- a/.docker/docker-compose.yml +++ b/docker-compose.prod.yml @@ -14,7 +14,7 @@ services: restart: "no" container_name: dbrepo-metadata-db hostname: metadata-db - image: docker.io/dbrepo/metadata-db:1.4.4 + image: docker.io/dbrepo/metadata-db:latest volumes: - metadata-db-data:/bitnami/mariadb - ./dist/2_setup-data.sql:/docker-entrypoint-initdb.d/2_setup-data.sql @@ -76,7 +76,7 @@ services: restart: "no" container_name: dbrepo-auth-service hostname: auth-service - image: docker.io/dbrepo/auth-service:1.4.4 + image: docker.io/dbrepo/auth-service:latest healthcheck: test: curl -sSL 'http://0.0.0.0:8080/realms/dbrepo' | grep "dbrepo" || exit 1 interval: 10s @@ -98,19 +98,18 @@ services: restart: "no" container_name: dbrepo-metadata-service hostname: metadata-service - image: docker.io/dbrepo/metadata-service:1.4.4 + image: docker.io/dbrepo/metadata-service:latest volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: - ADMIN_EMAIL: "${ADMIN_EMAIL:-noreply@localhost}" + ADMIN_MAIL: "${ADMIN_MAIL:-noreply@localhost}" ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" - ANALYSE_SERVICE_ENDPOINT: "${ANALYSE_SERVICE_ENDPOINT:-http://gateway-service}" AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-fda} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-fda} AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} - AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://gateway-service/api/auth} + AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} BASE_URL: "${BASE_URL:-http://localhost}" BROKER_EXCHANGE_NAME: ${BROKER_EXCHANGE_NAME:-dbrepo} BROKER_QUEUE_NAME: ${BROKER_QUEUE_NAME:-dbrepo} @@ -122,9 +121,10 @@ services: BROKER_VIRTUALHOST: "${BROKER_VIRTUALHOST:-dbrepo}" DATA_SERVICE_ENDPOINT: ${DATA_SERVICE_ENDPOINT:-http://data-service:8080} DELETED_RECORD: "${DELETED_RECORD:-persistent}" + GATEWAY_SERVICE_ENDPOINT: ${GATEWAY_SERVICE_ENDPOINT:-http://gateway-service} GRANULARITY: "${GRANULARITY:-YYYY-MM-DDThh:mm:ssZ}" JWT_PUBKEY: "${JWT_PUBKEY:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" - LOG_LEVEL: "${LOG_LEVEL:-info}" + LOG_LEVEL: ${LOG_LEVEL:-info} METADATA_DB: "${METADATA_DB:-dbrepo}" METADATA_HOST: "${METADATA_HOST:-metadata-db}" METADATA_JDBC_EXTRA_ARGS: "${METADATA_JDBC_EXTRA_ARGS:-}" @@ -132,9 +132,9 @@ services: METADATA_PASSWORD: "${METADATA_PASSWORD:-dbrepo}" PID_BASE: ${PID_BASE:-http://localhost/pid/} REPOSITORY_NAME: "${REPOSITORY_NAME:-Database Repository}" - SEARCH_SERVICE_ENDPOINT: "${SEARCH_SERVICE_ENDPOINT:-http://gateway-service}" + SEARCH_SERVICE_ENDPOINT: "${SEARCH_SERVICE_ENDPOINT:-http://search-service:8080}" S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}" - S3_ENDPOINT: "${S3_ENDPOINT:-http://gateway-service/api/storage}" + S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}" S3_EXPORT_BUCKET: "${S3_EXPORT_BUCKET:-dbrepo-download}" S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" @@ -160,7 +160,7 @@ services: restart: "no" container_name: dbrepo-analyse-service hostname: analyse-service - image: docker.io/dbrepo/analyse-service:1.4.4 + image: docker.io/dbrepo/analyse-service:latest environment: ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" @@ -211,7 +211,7 @@ services: restart: "no" container_name: dbrepo-search-db hostname: search-db - image: docker.io/dbrepo/search-db:1.4.4 + image: docker.io/dbrepo/search-db:latest healthcheck: test: curl -sSL localhost:9200/_plugins/_security/health | jq .status | grep UP interval: 10s @@ -235,7 +235,7 @@ services: restart: "no" container_name: dbrepo-search-service hostname: search-service - image: docker.io/dbrepo/search-service:1.4.4 + image: docker.io/dbrepo/search-service:latest environment: ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" @@ -253,12 +253,11 @@ services: restart: "no" container_name: dbrepo-data-db-sidecar hostname: data-db-sidecar - image: docker.io/dbrepo/data-db-sidecar:1.4.4 + image: docker.io/dbrepo/data-db-sidecar:latest environment: S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}" S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}" S3_EXPORT_BUCKET: "${S3_EXPORT_BUCKET:-dbrepo-download}" - S3_FILE_PATH: "${S3_FILE_PATH:-/tmp}" S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" volumes: @@ -275,7 +274,7 @@ services: restart: "no" container_name: dbrepo-ui hostname: ui - image: docker.io/dbrepo/ui:1.4.4 + image: docker.io/dbrepo/ui:latest depends_on: dbrepo-search-service: condition: service_started @@ -319,7 +318,7 @@ services: restart: "no" container_name: dbrepo-search-service-init hostname: search-service-init - image: docker.io/dbrepo/search-service-init:1.4.4 + image: docker.io/dbrepo/search-service-init:latest environment: GATEWAY_SERVICE_ENDPOINT: ${GATEWAY_SERVICE_ENDPOINT:-http://gateway-service} OPENSEARCH_HOST: ${OPENSEARCH_HOST:-search-db} @@ -354,7 +353,7 @@ services: restart: "no" container_name: dbrepo-storage-service-init hostname: storage-service-init - image: docker.io/dbrepo/storage-service-init:1.4.4 + image: docker.io/dbrepo/storage-service-init:latest environment: SEAWEEDFS_ENDPOINT: "${STORAGE_SEAWEEDFS_ENDPOINT:-storage-service:9333}" depends_on: @@ -391,7 +390,7 @@ services: restart: "no" container_name: dbrepo-data-service hostname: data-service - image: docker.io/dbrepo/data-service:1.4.4 + image: docker.io/dbrepo/data-service:latest volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: @@ -412,7 +411,7 @@ services: BROKER_VIRTUALHOST: "${BROKER_VIRTUALHOST:-dbrepo}" CONNECTION_TIMEOUT: ${CONNECTION_TIMEOUT:-60000} EXCHANGE_NAME: ${EXCHANGE_NAME:-dbrepo} - METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://gateway-service} + GATEWAY_SERVICE_ENDPOINT: ${GATEWAY_SERVICE_ENDPOINT:-http://gateway-service} GRANT_DEFAULT_READ: "${GRANT_DEFAULT_READ:-SELECT}" GRANT_DEFAULT_WRITE: "${GRANT_DEFAULT_WRITE:-SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE}" JWT_PUBKEY: "${JWT_PUBKEY:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" @@ -422,12 +421,7 @@ services: QUEUE_NAME: ${QUEUE_NAME:-dbrepo} REQUEUE_REJECTED: ${REQUEUE_REJECTED:-false} ROUTING_KEY: "${ROUTING_KEY:-dbrepo.#}" - S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}" - S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}" - S3_EXPORT_BUCKET: "${S3_EXPORT_BUCKET:-dbrepo-download}" - S3_FILE_PATH: "${S3_FILE_PATH:-/tmp}" - S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" - S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" + STORAGE_SERVICE_ENDPOINT: ${BROKER_SERVICE_ENDPOINT:-http://storage-service:9000} healthcheck: test: wget -qO- localhost:8080/actuator/health/readiness | grep -q "UP" || exit 1 interval: 10s diff --git a/docker-compose.yml b/docker-compose.yml index 415c754090cad7fea2799123465f5421a04cc827..da0d6a27ea28a19be313f36be686d43116df87d8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -115,15 +115,14 @@ services: volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: - ADMIN_EMAIL: "${ADMIN_EMAIL:-noreply@localhost}" + ADMIN_MAIL: "${ADMIN_MAIL:-noreply@localhost}" ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" - ANALYSE_SERVICE_ENDPOINT: "${ANALYSE_SERVICE_ENDPOINT:-http://gateway-service}" AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-fda} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-fda} AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} - AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://gateway-service/api/auth} + AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} BASE_URL: "${BASE_URL:-http://localhost}" BROKER_EXCHANGE_NAME: ${BROKER_EXCHANGE_NAME:-dbrepo} BROKER_QUEUE_NAME: ${BROKER_QUEUE_NAME:-dbrepo} @@ -135,8 +134,10 @@ services: BROKER_VIRTUALHOST: "${BROKER_VIRTUALHOST:-dbrepo}" DATA_SERVICE_ENDPOINT: ${DATA_SERVICE_ENDPOINT:-http://data-service:8080} DELETED_RECORD: "${DELETED_RECORD:-persistent}" + GATEWAY_SERVICE_ENDPOINT: ${GATEWAY_SERVICE_ENDPOINT:-http://gateway-service} GRANULARITY: "${GRANULARITY:-YYYY-MM-DDThh:mm:ssZ}" JWT_PUBKEY: "${JWT_PUBKEY:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" +# LOG_LEVEL: ${LOG_LEVEL:-info} LOG_LEVEL: trace METADATA_DB: "${METADATA_DB:-dbrepo}" METADATA_HOST: "${METADATA_HOST:-metadata-db}" @@ -145,7 +146,7 @@ services: METADATA_PASSWORD: "${METADATA_PASSWORD:-dbrepo}" PID_BASE: ${PID_BASE:-http://localhost/pid/} REPOSITORY_NAME: "${REPOSITORY_NAME:-Database Repository}" - SEARCH_SERVICE_ENDPOINT: "${SEARCH_SERVICE_ENDPOINT:-http://gateway-service}" + SEARCH_SERVICE_ENDPOINT: "${SEARCH_SERVICE_ENDPOINT:-http://search-service:8080}" S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}" S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}" S3_EXPORT_BUCKET: "${S3_EXPORT_BUCKET:-dbrepo-download}" @@ -153,7 +154,7 @@ services: S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" SPARQL_CONNECTION_TIMEOUT: "${SPARQL_CONNECTION_TIMEOUT:-10000}" healthcheck: - test: curl -sSL localhost:8080/actuator/health/liveness | grep 'UP' || exit 1 + test: wget -qO- localhost:8080/actuator/health/readiness | grep -q "UP" || exit 1 interval: 10s timeout: 5s retries: 12 @@ -398,8 +399,6 @@ services: volumes: - ./dbrepo-storage-service/s3_config.json:/app/s3_config.json - storage-service-data:/data - ports: - - "9000:9000" healthcheck: test: echo "cluster.check" | weed shell | grep "checking master.*ok" || exit 1 interval: 10s @@ -478,11 +477,11 @@ services: BROKER_VIRTUALHOST: "${BROKER_VIRTUALHOST:-dbrepo}" CONNECTION_TIMEOUT: ${CONNECTION_TIMEOUT:-60000} EXCHANGE_NAME: ${EXCHANGE_NAME:-dbrepo} - METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://gateway-service} + GATEWAY_SERVICE_ENDPOINT: ${GATEWAY_SERVICE_ENDPOINT:-http://gateway-service} GRANT_DEFAULT_READ: "${GRANT_DEFAULT_READ:-SELECT}" GRANT_DEFAULT_WRITE: "${GRANT_DEFAULT_WRITE:-SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE}" JWT_PUBKEY: "${JWT_PUBKEY:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" - LOG_LEVEL: ${LOG_LEVEL:-trace} + LOG_LEVEL: ${LOG_LEVEL:-info} MIN_CONCURRENT_CONSUMERS: ${MIN_CONCURRENT_CONSUMERS:-1} MAX_CONCURRENT_CONSUMERS: ${MAX_CONCURRENT_CONSUMERS:-5} QUEUE_NAME: ${QUEUE_NAME:-dbrepo} @@ -495,7 +494,7 @@ services: S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" healthcheck: - test: curl -sSL localhost:8080/actuator/health/liveness | grep 'UP' || exit 1 + test: wget -qO- localhost:8080/actuator/health/readiness | grep -q "UP" || exit 1 interval: 10s timeout: 5s retries: 12 diff --git a/helm/dbrepo/artifacthub-repo.yml b/helm/artifacthub-repo.yml similarity index 100% rename from helm/dbrepo/artifacthub-repo.yml rename to helm/artifacthub-repo.yml diff --git a/helm/dbrepo/.helmignore b/helm/dbrepo/.helmignore index b9029e8dea3ccab2aabc5c3a8d9226e9bb9ac827..62d87df84fcf8a1c6cdd3918d35280bfbd07f336 100644 --- a/helm/dbrepo/.helmignore +++ b/helm/dbrepo/.helmignore @@ -14,7 +14,6 @@ hack/ .svn/ # Generated build/ -artifacthub-repo.yml # Common backup files *.swp *.bak diff --git a/helm/dbrepo/Makefile b/helm/dbrepo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b89c9b4decd70764a400405af0ff4ccf69b66e61 --- /dev/null +++ b/helm/dbrepo/Makefile @@ -0,0 +1,8 @@ +.PHONY: all +all: + +.PHONY: build +build: ## Generate Helm values schema JSON + #helm package --sign --key 'Martin Weise' . --keyring ~/.gnupg/mweise.gpg --destination ./build + helm schema -input ./values.yaml + readme-generator-for-helm --readme README.md --values values.yaml diff --git a/helm/dbrepo/README.md b/helm/dbrepo/README.md index 01f699d9e1841eef85f4889248eef4c83bf4d49c..f7c43ba5dbd6f123cb701d9928415fda931e01de 100644 --- a/helm/dbrepo/README.md +++ b/helm/dbrepo/README.md @@ -145,7 +145,6 @@ The command removes all the Kubernetes components associated with the chart and | Name | Description | Value | | ----------------------------- | ----------------------------------------------------- | ------------------------------- | | `analyseservice.enabled` | Enable the Broker Service. | `true` | -| `analyseservice.endpoint` | The url of the endpoint. | `http://analyse-service` | | `analyseservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | | `analyseservice.replicaCount` | The number of replicas. | `2` | @@ -154,7 +153,6 @@ The command removes all the Kubernetes components associated with the chart and | Name | Description | Value | | ------------------------------------------ | --------------------------------------------------------------------- | ------------------------------- | | `metadataservice.enabled` | Enable the Metadata Service. | `true` | -| `metadataservice.endpoint` | The Metadata Service endpoint. | `http://metadata-service` | | `metadataservice.admin.email` | The OAI-PMH exposed admin e-mail. | `noreply@example.com` | | `metadataservice.deletedRecord` | The OAI-PMH exposed delete policy. | `permanent` | | `metadataservice.repositoryName` | The OAI-PMH exposed repository name. | `Database Repository` | diff --git a/helm/dbrepo/templates/data-secret.yaml b/helm/dbrepo/templates/data-secret.yaml index 7797626672d1976564fcc8404f8f7651a4054120..b5307a23d95df9abcf06868646ddc8ac85c80e70 100644 --- a/helm/dbrepo/templates/data-secret.yaml +++ b/helm/dbrepo/templates/data-secret.yaml @@ -31,7 +31,6 @@ stringData: DEFAULT_TIMESTAMP_FORMAT_ID: "{{ .Values.dataservice.default.timestamp }}" JWT_PUBKEY: "{{ .Values.authservice.jwt.pubkey }}" LOG_LEVEL: "{{ ternary "debug" "info" .Values.dataservice.image.debug }}" - METADATA_SERVICE_ENDPOINT: "{{ .Values.metadataservice.endpoint }}" MIN_CONCURRENT_CONSUMERS: "{{ .Values.dataservice.consumerConcurrentMin }}" MAX_CONCURRENT_CONSUMERS: "{{ .Values.dataservice.consumerConcurrentMax }}" REQUEUE_REJECTED: "{{ .Values.dataservice.requeueRejected }}" diff --git a/helm/dbrepo/templates/metadata-configmap.yaml b/helm/dbrepo/templates/metadata-configmap.yaml index 4bb2eb136b557c0a44f3a9fb77d8d6a023ab67ea..88c761643a70da48cd6032f3225ceb5459543052 100644 --- a/helm/dbrepo/templates/metadata-configmap.yaml +++ b/helm/dbrepo/templates/metadata-configmap.yaml @@ -13,10 +13,11 @@ data: BEGIN; INSERT INTO `mdb_containers` (name, internal_name, image_id, host, port, sidecar_host, sidecar_port, privileged_username, privileged_password) VALUES ('MariaDB Galera 11.1.3', 'mariadb_11_1_3', 1, 'data-db', 3306, 'data-db', 80, 'root', 'dbrepo'); + INSERT INTO `mdb_banner_messages` (type, message) + VALUES ('INFO', 'You are currently working on our test environment. Any data upload to this system may be deleted.'); COMMIT; 01-setup-schema.sql: | BEGIN; - CREATE TABLE IF NOT EXISTS `mdb_users` ( id character varying(36) NOT NULL, @@ -137,13 +138,13 @@ data: CREATE TABLE IF NOT EXISTS `mdb_tables` ( - ID bigint NOT NULL AUTO_INCREMENT, - tDBID bigint NOT NULL, - tName VARCHAR(64) NOT NULL, - internal_name VARCHAR(64) NOT NULL, - queue_name VARCHAR(255) NOT NULL, - routing_key VARCHAR(255), - tDescription VARCHAR(2048), + ID bigint NOT NULL AUTO_INCREMENT, + tDBID bigint NOT NULL, + internal_name character varying(255) NOT NULL, + queue_name character varying(255) NOT NULL, + routing_key character varying(255), + tName VARCHAR(50), + tDescription TEXT, num_rows BIGINT, data_length BIGINT, max_data_length BIGINT, @@ -155,13 +156,12 @@ data: element_true VARCHAR(50), element_false VARCHAR(50), Version TEXT, - created timestamp NOT NULL DEFAULT NOW(), - versioned boolean not null default true, - created_by character varying(36) NOT NULL, - owned_by character varying(36) NOT NULL, + created timestamp NOT NULL DEFAULT NOW(), + versioned boolean not null default true, + created_by character varying(36) NOT NULL, + owned_by character varying(36) NOT NULL, last_modified timestamp, PRIMARY KEY (ID), - UNIQUE (tDBID, internal_name), FOREIGN KEY (tDBID) REFERENCES mdb_databases (id), FOREIGN KEY (created_by) REFERENCES mdb_users (id), FOREIGN KEY (owned_by) REFERENCES mdb_users (id) @@ -169,26 +169,25 @@ data: CREATE TABLE IF NOT EXISTS `mdb_columns` ( - ID BIGINT NOT NULL AUTO_INCREMENT, - tID BIGINT NOT NULL, + ID BIGINT NOT NULL AUTO_INCREMENT, + tID BIGINT NOT NULL, dfID BIGINT, - cName VARCHAR(64), - internal_name VARCHAR(64) NOT NULL, + cName VARCHAR(100), + internal_name VARCHAR(100) NOT NULL, Datatype ENUM ('CHAR','VARCHAR','BINARY','VARBINARY','TINYBLOB','TINYTEXT','TEXT','BLOB','MEDIUMTEXT','MEDIUMBLOB','LONGTEXT','LONGBLOB','ENUM','SET','BIT','TINYINT','BOOL','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL','DATE','DATETIME','TIMESTAMP','TIME','YEAR'), - length BIGINT NULL, - ordinal_position INTEGER NOT NULL, - index_length BIGINT NULL, - description VARCHAR(2048), + length BIGINT NULL, + ordinal_position INTEGER NOT NULL, + index_length BIGINT NULL, size BIGINT, d BIGINT, - auto_generated BOOLEAN DEFAULT false, - is_null_allowed BOOLEAN NOT NULL DEFAULT true, - val_min NUMERIC NULL, - val_max NUMERIC NULL, - mean NUMERIC NULL, - median NUMERIC NULL, - std_dev Numeric NULL, - created timestamp NOT NULL DEFAULT NOW(), + auto_generated BOOLEAN DEFAULT false, + is_null_allowed BOOLEAN NOT NULL DEFAULT true, + val_min NUMERIC NULL, + val_max NUMERIC NULL, + mean NUMERIC NULL, + median NUMERIC NULL, + std_dev Numeric NULL, + created timestamp NOT NULL DEFAULT NOW(), last_modified timestamp, FOREIGN KEY (tID) REFERENCES mdb_tables (ID) ON DELETE CASCADE, PRIMARY KEY (ID) @@ -345,8 +344,8 @@ data: ( id bigint NOT NULL AUTO_INCREMENT, vdbid bigint NOT NULL, - vName VARCHAR(64) NOT NULL, - internal_name VARCHAR(64) NOT NULL, + vName VARCHAR(255) NOT NULL, + internal_name VARCHAR(255) NOT NULL, Query TEXT NOT NULL, query_hash VARCHAR(255) NOT NULL, Public BOOLEAN NOT NULL, @@ -388,19 +387,14 @@ data: CREATE TABLE IF NOT EXISTS `mdb_view_columns` ( - id BIGINT NOT NULL AUTO_INCREMENT, - view_id BIGINT NOT NULL, - dfID BIGINT, - name VARCHAR(64), - internal_name VARCHAR(64) NOT NULL, - column_type ENUM ('CHAR','VARCHAR','BINARY','VARBINARY','TINYBLOB','TINYTEXT','TEXT','BLOB','MEDIUMTEXT','MEDIUMBLOB','LONGTEXT','LONGBLOB','ENUM','SET','BIT','TINYINT','BOOL','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL','DATE','DATETIME','TIMESTAMP','TIME','YEAR'), - ordinal_position INTEGER NOT NULL, - size BIGINT, - d BIGINT, - auto_generated BOOLEAN DEFAULT false, - is_null_allowed BOOLEAN NOT NULL DEFAULT true, + id BIGINT NOT NULL AUTO_INCREMENT, + cid BIGINT NOT NULL, + vid BIGINT NOT NULL, + alias VARCHAR(100), + ordinal_position INTEGER, PRIMARY KEY (id), - FOREIGN KEY (view_id) REFERENCES mdb_view (id) + FOREIGN KEY (vid) REFERENCES mdb_view (id), + FOREIGN KEY (cid) REFERENCES mdb_columns (ID) ) WITH SYSTEM VERSIONING; CREATE TABLE IF NOT EXISTS `mdb_identifiers` @@ -509,6 +503,18 @@ data: FOREIGN KEY (pid) REFERENCES mdb_identifiers (id) ) WITH SYSTEM VERSIONING; + CREATE TABLE IF NOT EXISTS `mdb_feed` + ( + fDBID bigint, + fID bigint, + fUserId character varying(36) not null, + fDataID bigint REFERENCES mdb_data (ID), + created timestamp NOT NULL DEFAULT NOW(), + PRIMARY KEY (fDBID, fID, fUserId, fDataID), + FOREIGN KEY (fDBID, fID) REFERENCES mdb_tables (tDBID, ID), + FOREIGN KEY (fUserId) REFERENCES mdb_users (id) + ) WITH SYSTEM VERSIONING; + CREATE TABLE IF NOT EXISTS `mdb_update` ( uUserID character varying(255) NOT NULL, diff --git a/helm/dbrepo/templates/metadata-secret.yaml b/helm/dbrepo/templates/metadata-secret.yaml index 3beda17fc57fe12ecb06021e3b81fe47e6a067f0..db8328b7a8e313b7e2110be1d29045136df3b8e7 100644 --- a/helm/dbrepo/templates/metadata-secret.yaml +++ b/helm/dbrepo/templates/metadata-secret.yaml @@ -7,9 +7,8 @@ metadata: namespace: {{ .Values.namespace }} stringData: ADMIN_EMAIL: "{{ .Values.metadataservice.admin.email }}" - ADMIN_PASSWORD: "{{ .Values.admin.password }}" ADMIN_USERNAME: "{{ .Values.admin.username }}" - ANALYSE_SERVICE_ENDPOINT: "{{ .Values.analyseservice.endpoint }}" + ADMIN_PASSWORD: "{{ .Values.admin.password }}" AUTH_SERVICE_ADMIN: "{{ .Values.authservice.auth.adminUser }}" AUTH_SERVICE_ADMIN_PASSWORD: "{{ .Values.authservice.auth.adminPassword }}" AUTH_SERVICE_CLIENT: "{{ .Values.authservice.client.id }}" @@ -30,6 +29,7 @@ stringData: DATACITE_USERNAME: "{{ .Values.metadataservice.datacite.username }}" DATACITE_PASSWORD: "{{ .Values.metadataservice.datacite.password }}" DELETED_RECORD: "{{ .Values.metadataservice.deletedRecord }}" + GATEWAY_SERVICE_ENDPOINT: "{{ .Values.gateway }}" GRANULARITY: "{{ .Values.metadataservice.granularity }}" JWT_PUBKEY: "{{ .Values.authservice.jwt.pubkey }}" LOG_LEVEL: "{{ ternary "trace" "info" .Values.metadataservice.image.debug }}" diff --git a/helm/dbrepo/values.prod.yaml b/helm/dbrepo/values.prod.yaml new file mode 100644 index 0000000000000000000000000000000000000000..93c0bf3d724c5f8a06308b020d0761dd26e27073 --- /dev/null +++ b/helm/dbrepo/values.prod.yaml @@ -0,0 +1,514 @@ +namespace: dbrepo + +hostname: example.com + +metadataDb: + fullnameOverride: metadata-db + image: + debug: false + host: metadata-db + rootUser: + user: root + password: dbrepo + jdbcExtraArgs: "" + db: + name: fda + metrics: + enabled: false + galera: + mariabackup: + user: mariabackup + password: mariabackup + initdbScriptsConfigMap: metadata-db-setup + service: + type: ClusterIP + annotations: { } + loadBalancerIP: "" + loadBalancerSourceRanges: [ ] + persistence: + enabled: true + replicaCount: 3 # uneven 3,5,7 + +authService: + fullnameOverride: auth-service + image: + debug: false + auth: + adminUser: fda + adminPassword: fda + postgresql: + enabled: false # not needed + extraStartupArgs: "--import-realm" + tls: + enabled: true + existingSecret: ingress-cert + usePem: true + metrics: + enabled: true + externalDatabase: + existingSecret: auth-service-secret + existingSecretDatabaseKey: db-name + existingSecretHostKey: db-host + existingSecretPortKey: db-port + existingSecretUserKey: db-username + existingSecretPasswordKey: db-password + client: + id: dbrepo-client + secret: MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG + extraEnvVarsCM: auth-service-config + extraVolumes: + - name: config-map + configMap: + name: auth-service-setup + extraVolumeMounts: + - name: config-map + mountPath: /opt/bitnami/keycloak/data/import + replicaCount: 2 + +authDb: + fullnameOverride: auth-db + host: auth-db-pgpool + port: 5432 + postgresql: + postgresPassword: postgres + username: metrics # implicit requirement for metrics container + password: metrics # implicit requirement for metrics container + repmgrPassword: repmgr # implicit requirement for rolling updates + database: keycloak + replicaCount: 3 + pgpool: + adminUsername: admin + adminPassword: admin + metrics: + enabled: true + service: + type: ClusterIP + annotations: { } + loadBalancerIP: "" + loadBalancerSourceRanges: [ ] + persistence: + enabled: true + size: 10Gi + +dataDb: + fullnameOverride: data-db + image: + debug: false + extraFlags: "--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci" + rootUser: + user: root + password: dbrepo + metrics: + enabled: true + galera: + mariabackup: + user: mariabackup + password: mariabackup + sidecars: + - name: sidecar + image: s210.dl.hpc.tuwien.ac.at/dbrepo/data-db-sidecar:1.4.2 + imagePullPolicy: Always + securityContext: + runAsUser: 1001 + runAsGroup: 1001 + ports: + - containerPort: 3305 + protocol: TCP + env: + - name: S3_STORAGE_ENDPOINT + value: http://storageservice-s3:9000 + - name: S3_ACCESS_KEY_ID + value: seaweedfsadmin + - name: S3_SECRET_ACCESS_KEY + value: seaweedfsadmin + volumeMounts: + - name: tmp # share between sidecar and galera container + mountPath: /tmp + service: + type: ClusterIP + annotations: { } + #loadBalancerIP: 1.2.3.4 + loadBalancerSourceRanges: [ ] + extraPorts: + - name: "sidecar" + port: 3305 + targetPort: 3305 + protocol: TCP + extraVolumeMounts: + - name: tmp + mountPath: /tmp + extraVolumes: + # - name: tmp + # emptyDir: {} + - name: tmp + persistentVolumeClaim: + claimName: data-db-shared + persistence: + enabled: true + size: 10Gi + replicaCount: 3 # uneven 3,5,7 + +searchdb: + fullnameOverride: search-db + host: search-db + port: 9200 + protocol: http + username: admin + password: admin + clusterName: search-db + masterService: search-db + replicas: 3 # uneven 3,5,7 + image: + debug: false + sysctlInit: + enabled: true + persistence: + enabled: true + size: 10Gi + service: + type: ClusterIP + annotations: { } + loadBalancerSourceRanges: [ ] + extraEnvs: + - name: DISABLE_INSTALL_DEMO_CONFIG + value: "true" + extraVolumeMounts: + - name: node-cert + mountPath: /usr/share/opensearch/config/tls + readOnly: true + extraVolumes: + - name: node-cert + secret: + secretName: search-db-cert + config: + opensearch.yml: | + cluster.name: search-db + network.host: 0.0.0.0 + plugins: + security: + ssl: + transport: + pemcert_filepath: tls/tls.crt + pemkey_filepath: tls/tls.key + pemtrustedcas_filepath: tls/ca.crt + enforce_hostname_verification: false + http: + #enabled: true # uncomment to force ssl connections + pemcert_filepath: tls/tls.crt + pemkey_filepath: tls/tls.key + pemtrustedcas_filepath: tls/ca.crt + allow_unsafe_democertificates: false + allow_default_init_securityindex: true + authcz: + admin_dn: + - CN=search-db + nodes_dn: + - CN=search-db + audit.type: internal_opensearch + enable_snapshot_restore_privilege: true + check_snapshot_restore_write_privileges: true + restapi: + roles_enabled: [ "all_access", "security_rest_api_access" ] + system_indices: + enabled: true + indices: + [ + ".opendistro-alerting-config", + ".opendistro-alerting-alert*", + ".opendistro-anomaly-results*", + ".opendistro-anomaly-detector*", + ".opendistro-anomaly-checkpoints", + ".opendistro-anomaly-detection-state", + ".opendistro-reports-*", + ".opendistro-notifications-*", + ".opendistro-notebooks", + ".opendistro-asynchronous-search-response*", + ] + +searchDbDashboard: + fullnameOverride: search-db-dashboard + opensearchHosts: http://search-db:9200 + extraInitContainers: + - name: init + image: s210.dl.hpc.tuwien.ac.at/dbrepo/search-db-init:1.4.2 + imagePullPolicy: Always + env: + - name: OPENSEARCH_HOST + value: http://search-db:9200 + extraVolumeMounts: + - name: tls + mountPath: /usr/share/opensearch-dashboards/tls + readOnly: true + - name: config + mountPath: /usr/share/opensearch-dashboards/config/opensearch_dashboards.yml + subPath: opensearch_dashboards.yml + readOnly: true + extraVolumes: + - name: tls + secret: + secretName: ingress-cert + - name: config + secret: + secretName: search-db-dashboard-secret + replicaCount: 2 + +uploadService: + enabled: true + image: + registry: docker.io + repository: tusproject/tusd + tag: v1.12 + replicaCount: 2 + +brokerService: + fullnameOverride: broker-service + image: + debug: true + url: http://broker-service:15672 + host: broker-service + port: 5672 + virtualHost: dbrepo + queueName: dbrepo + exchangeName: dbrepo + routingKey: dbrepo.# + connectionTimeout: 60000 + auth: + tls: + enabled: false + sslOptionsVerify: true + failIfNoPeerCert: true + existingSecret: ingress-cert + username: broker + password: broker + extraConfiguration: |- + default_vhost = dbrepo + default_user_tags.administrator = true + default_permissions.configure = .* + default_permissions.read = .* + default_permissions.write = .* + load_definitions = /etc/rabbitmq/definitions.json + log.console = true + listeners.tcp.1 = 0.0.0.0:5672 + auth_backends.1 = rabbit_auth_backend_oauth2 + auth_backends.2 = rabbit_auth_backend_internal + auth_oauth2.resource_server_id = rabbitmq + auth_oauth2.preferred_username_claims.1 = client_id + auth_oauth2.default_key = t2OCeCheJ9uwoBbNQjG_nN6WKiLcceTIAZmiTbGODFM + auth_oauth2.signing_keys.t2OCeCheJ9uwoBbNQjG_nN6WKiLcceTIAZmiTbGODFM = /etc/rabbitmq/cert.pem + auth_oauth2.signing_keys.id2 = /etc/rabbitmq/pubkey.pem + auth_oauth2.algorithms.1 = HS256 + auth_oauth2.algorithms.2 = RS256 + loadDefinition: + enabled: true + file: /etc/rabbitmq/definitions.json + existingSecret: broker-service-secret + extraVolumeMounts: + - name: secret-map + mountPath: /etc/rabbitmq/definitions.json + subPath: definitions.json + readOnly: true + - name: secret-map + mountPath: /etc/rabbitmq/pubkey.pem + subPath: pubkey.pem + readOnly: true + - name: secret-map + mountPath: /etc/rabbitmq/cert.pem + subPath: cert.pem + readOnly: true + extraVolumes: + - name: secret-map + secret: + secretName: broker-service-secret + extraPlugins: rabbitmq_prometheus rabbitmq_auth_backend_oauth2 rabbitmq_auth_mechanism_ssl + persistence: + enabled: false + size: 5Gi + service: + type: ClusterIP + # loadBalancerIP: + replicaCount: 2 + +analyseService: + enabled: true + image: + name: s210.dl.hpc.tuwien.ac.at/dbrepo/analyse-service:1.4.2 + pullPolicy: Always + debug: false + replicaCount: 2 + +metadataService: + enabled: true + image: + name: s210.dl.hpc.tuwien.ac.at/dbrepo/metadata-service:1.4.2 + pullPolicy: Always + debug: false + adminEmail: noreply@example.com + authService: + url: http://auth-service + website: http://example.com + repositoryName: Database Repository + datacite: + enabled: false + url: https://api.datacite.org + prefix: "" + username: "" + password: "" + rates: + deleteStaleFiles: 60 + mirror: 60 + obtainMetadata: 60 + deleteStaleQueries: 60 + replicaCount: 2 + +dataService: + enabled: true + image: + name: s210.dl.hpc.tuwien.ac.at/dbrepo/data-service:1.4.2 + pullPolicy: Always + debug: false + jwt: + pubkey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB" + consumerConcurrentMin: 1 + consumerConcurrentMax: 5 + requeueRejected: false + replicaCount: 2 + +searchService: + enabled: true + image: + name: s210.dl.hpc.tuwien.ac.at/dbrepo/search-service:1.4.2 + pullPolicy: Always + debug: false + replicaCount: 2 + +storageservice: + master: + enabled: true + filer: + enabled: true + replicas: 2 + enablePVC: false + storage: 25Gi + s3: + enabled: true + allowEmptyFolder: true + port: 9000 + enableAuth: true + skipAuthSecretCreation: true + existingConfigSecret: seaweedfs-s3-secret + volume: + enabled: true + replicas: 2 + s3: + enabled: true + replicas: 2 + port: 9000 + metricsPort: 9091 + enableAuth: true + skipAuthSecretCreation: true + existingConfigSecret: seaweedfs-s3-secret + auth: + username: seaweedfsadmin + password: seaweedfsadmin + +logservice: + fullnameOverride: log-service + config: + outputs: | + [OUTPUT] + Name opensearch + Match kube.* + Host search-db + Port 9200 + HTTP_User admin + HTTP_Passwd admin + Logstash_Format On + Replace_Dots On + Type _doc + Retry_Limit False + Suppress_Type_Name On + + [OUTPUT] + Name opensearch + Match host.* + Host search-db + Port 9200 + HTTP_User admin + HTTP_Passwd admin + Logstash_Format On + Logstash_Prefix node + Replace_Dots On + Type _doc + Retry_Limit False + Suppress_Type_Name On +# Replace_Dots On +# Suppress_Type_Name On + +ui: + enabled: true + image: + name: s210.dl.hpc.tuwien.ac.at/dbrepo/ui:1.4.2 + pullPolicy: Always + debug: false + public: + api: + client: {} + server: {} + title: "Database Repository" + logo: "/logo.svg" + icon: "/favicon.ico" + touch: "/apple-touch-icon.png" + broker: + host: example.com + port: + 5671: true + 5672: false + extra: "128.130.0.0/15" + database: + extra: "128.130.0.0/15" + pid: + default: + publisher: "Example University" + doi: + enabled: false + endpoint: https://doi.org + replicaCount: 2 + extraVolumes: [ ] + # - name: images-map + # configMap: + # name: ui-config + extraVolumeMounts: [ ] + # - name: images-map + # mountPath: /static/logo.svg + # subPath: logo.svg + +ingress: + enabled: true + className: nginx + tls: + enabled: true + secretName: ingress-cert + annotations: + basic: {} +# cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer + secure: +# cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + upload: +# cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer + nginx.ingress.kubernetes.io/proxy-body-size: 2G + rewriteApi: +# cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/rewrite-target: /api/$1 + rewriteRoot: +# cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/rewrite-target: /$1 + rewritePid: +# cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/rewrite-target: /api/pid/$1 diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index dc8cd7bdbaa7533296664612d77635ed7fe0d07c..d15d46c305eaa829415e181694d18ccd0279f429 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -173,13 +173,12 @@ datadb: service: extraPorts: - name: "sidecar" - port: 8080 + port: 80 targetPort: 8080 protocol: TCP sidecars: - name: sidecar image: s210.dl.hpc.tuwien.ac.at/dbrepo/data-db-sidecar:1.4.4 - imagePullPolicy: Always securityContext: runAsUser: 1001 runAsGroup: 0 @@ -431,7 +430,6 @@ brokerservice: ## @param analyseservice.enabled Enable the Broker Service. ## @skip analyseservice.image -## @param analyseservice.endpoint The url of the endpoint. ## @param analyseservice.s3.endpoint The S3-capable endpoint the microservice connects to. ## @param analyseservice.replicaCount The number of replicas. ## @@ -441,7 +439,6 @@ analyseservice: name: s210.dl.hpc.tuwien.ac.at/dbrepo/analyse-service:1.4.4 pullPolicy: Always debug: false - endpoint: http://analyse-service s3: endpoint: http://storageservice-s3:9000 replicaCount: 2 @@ -450,7 +447,6 @@ analyseservice: ## @param metadataservice.enabled Enable the Metadata Service. ## @skip metadataservice.image -## @param metadataservice.endpoint The Metadata Service endpoint. ## @param metadataservice.admin.email The OAI-PMH exposed admin e-mail. ## @param metadataservice.deletedRecord The OAI-PMH exposed delete policy. ## @param metadataservice.repositoryName The OAI-PMH exposed repository name. @@ -473,7 +469,6 @@ metadataservice: name: s210.dl.hpc.tuwien.ac.at/dbrepo/metadata-service:1.4.4 pullPolicy: Always debug: false - endpoint: http://metadata-service admin: email: noreply@example.com deletedRecord: permanent diff --git a/install.sh b/install.sh index 9850ccd35eaae4c71032655bbe72e97892aba0f1..eeba0c1d45db41b70408d78a1b3851ed51ae6ce4 100644 --- a/install.sh +++ b/install.sh @@ -58,7 +58,7 @@ fi # environment echo "[🚀] Gathering environment ..." mkdir -p ./dist -curl -sSL -o ./docker-compose.yml "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-${VERSION}/.docker/docker-compose.yml" +curl -sSL -o ./docker-compose.yml "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-${VERSION}/docker-compose.prod.yml" curl -sSL -o ./dist/2_setup-data.sql "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-${VERSION}/dbrepo-metadata-db/2_setup-data.sql" curl -sSL -o ./dist/rabbitmq.conf "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-${VERSION}/dbrepo-broker-service/rabbitmq.conf" curl -sSL -o ./dist/enabled_plugins "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-${VERSION}/dbrepo-broker-service/enabled_plugins" diff --git a/lib/python/Pipfile.lock b/lib/python/Pipfile.lock index 953bcf20f326a8e1fc3c313683f09d546271f963..554a33747d2a6ae6e9e80a30b90228bdf4d98ad2 100644 --- a/lib/python/Pipfile.lock +++ b/lib/python/Pipfile.lock @@ -18,85 +18,85 @@ "default": { "aiohttp": { "hashes": [ - "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8", - "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c", - "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475", - "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed", - "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf", - "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372", - "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81", - "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f", - "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1", - "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd", - "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a", - "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb", - "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46", - "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de", - "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78", - "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c", - "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771", - "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb", - "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430", - "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233", - "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156", - "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9", - "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59", - "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888", - "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c", - "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c", - "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da", - "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424", - "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2", - "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb", - "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8", - "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a", - "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10", - "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0", - "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09", - "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031", - "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4", - "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3", - "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa", - "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a", - "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe", - "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a", - "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2", - "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1", - "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323", - "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b", - "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b", - "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106", - "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac", - "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6", - "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832", - "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75", - "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6", - "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d", - "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72", - "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db", - "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a", - "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da", - "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678", - "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b", - "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24", - "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed", - "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f", - "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e", - "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58", - "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a", - "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342", - "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558", - "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2", - "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551", - "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595", - "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee", - "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11", - "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d", - "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7", - "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f" + "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168", + "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb", + "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5", + "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f", + "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc", + "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c", + "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29", + "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4", + "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc", + "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc", + "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63", + "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e", + "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d", + "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a", + "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60", + "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38", + "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b", + "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2", + "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53", + "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5", + "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4", + "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96", + "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58", + "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa", + "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321", + "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae", + "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce", + "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8", + "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194", + "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c", + "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf", + "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d", + "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869", + "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b", + "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52", + "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528", + "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5", + "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1", + "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4", + "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8", + "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d", + "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7", + "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5", + "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54", + "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3", + "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5", + "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c", + "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29", + "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3", + "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747", + "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672", + "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5", + "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11", + "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca", + "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768", + "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6", + "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2", + "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533", + "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6", + "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266", + "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d", + "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec", + "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5", + "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1", + "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b", + "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679", + "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283", + "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb", + "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b", + "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3", + "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051", + "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511", + "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e", + "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d", + "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542", + "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f" ], "markers": "python_version >= '3.8'", - "version": "==3.9.5" + "version": "==3.9.3" }, "aiosignal": { "hashes": [ @@ -108,11 +108,11 @@ }, "annotated-types": { "hashes": [ - "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", - "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" + "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", + "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d" ], "markers": "python_version >= '3.8'", - "version": "==0.7.0" + "version": "==0.6.0" }, "attrs": { "hashes": [ @@ -124,11 +124,11 @@ }, "certifi": { "hashes": [ - "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", - "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" + "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", + "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "markers": "python_version >= '3.6'", - "version": "==2024.6.2" + "version": "==2024.2.2" }, "charset-normalizer": { "hashes": [ @@ -311,11 +311,11 @@ }, "idna": { "hashes": [ - "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", - "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" ], "markers": "python_version >= '3.5'", - "version": "==3.7" + "version": "==3.6" }, "multidict": { "hashes": [ @@ -457,38 +457,39 @@ }, "pandas": { "hashes": [ - "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863", - "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2", - "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1", - "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad", - "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db", - "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76", - "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51", - "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32", - "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08", - "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b", - "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4", - "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921", - "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288", - "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee", - "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0", - "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24", - "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99", - "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151", - "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd", - "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce", - "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57", - "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef", - "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54", - "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a", - "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238", - "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23", - "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772", - "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce", - "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad" + "sha256:04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee", + "sha256:06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e", + "sha256:0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572", + "sha256:0f573ab277252ed9aaf38240f3b54cfc90fff8e5cab70411ee1d03f5d51f3944", + "sha256:101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403", + "sha256:11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89", + "sha256:1ba21b1d5c0e43416218db63037dbe1a01fc101dc6e6024bcad08123e48004ab", + "sha256:4aa1d8707812a658debf03824016bf5ea0d516afdea29b7dc14cf687bc4d4ec6", + "sha256:4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb", + "sha256:53680dc9b2519cbf609c62db3ed7c0b499077c7fefda564e330286e619ff0dd9", + "sha256:739cc70eaf17d57608639e74d63387b0d8594ce02f69e7a0b046f117974b3019", + "sha256:76f27a809cda87e07f192f001d11adc2b930e93a2b0c4a236fde5429527423be", + "sha256:7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd", + "sha256:88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c", + "sha256:8df8612be9cd1c7797c93e1c5df861b2ddda0b48b08f2c3eaa0702cf88fb5f88", + "sha256:94e714a1cca63e4f5939cdce5f29ba8d415d85166be3441165edd427dc9f6bc0", + "sha256:9bd8a40f47080825af4317d0340c656744f2bfdb6819f818e6ba3cd24c0e1397", + "sha256:9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc", + "sha256:a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2", + "sha256:af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7", + "sha256:c2ce852e1cf2509a69e98358e8458775f89599566ac3775e70419b98615f4b06", + "sha256:c38ce92cb22a4bea4e3929429aa1067a454dcc9c335799af93ba9be21b6beb51", + "sha256:c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0", + "sha256:c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a", + "sha256:df0c37ebd19e11d089ceba66eba59a168242fc6b7155cba4ffffa6eccdfb8f16", + "sha256:e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02", + "sha256:f02a3a6c83df4026e55b63c1f06476c9aa3ed6af3d89b4f04ea656ccdaaaa359", + "sha256:f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b", + "sha256:f9d3558d263073ed95e46f4650becff0c5e1ffe0fc3a015de3c79283dfbdb3df" ], "index": "pypi", - "version": "==2.2.2" + "markers": "python_version >= '3.9'", + "version": "==2.2.1" }, "pika": { "hashes": [ @@ -496,100 +497,102 @@ "sha256:b2a327ddddf8570b4965b3576ac77091b850262d34ce8c1d8cb4e4146aa4145f" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==1.3.2" }, "pydantic": { "hashes": [ - "sha256:c46c76a40bb1296728d7a8b99aa73dd70a48c3510111ff290034f860c99c419e", - "sha256:ea91b002777bf643bb20dd717c028ec43216b24a6001a280f83877fd2655d0b4" + "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6", + "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5" ], "index": "pypi", - "version": "==2.7.3" + "markers": "python_version >= '3.8'", + "version": "==2.6.4" }, "pydantic-core": { "hashes": [ - "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3", - "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8", - "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8", - "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30", - "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a", - "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8", - "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d", - "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc", - "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2", - "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab", - "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077", - "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e", - "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9", - "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9", - "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef", - "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1", - "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507", - "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528", - "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558", - "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b", - "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154", - "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724", - "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695", - "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9", - "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851", - "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805", - "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a", - "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5", - "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94", - "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c", - "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d", - "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef", - "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26", - "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2", - "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c", - "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0", - "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2", - "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4", - "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d", - "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2", - "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce", - "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34", - "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f", - "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d", - "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b", - "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07", - "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312", - "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057", - "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d", - "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af", - "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb", - "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd", - "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78", - "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b", - "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223", - "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a", - "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4", - "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5", - "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23", - "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a", - "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4", - "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8", - "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d", - "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443", - "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e", - "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f", - "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e", - "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d", - "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc", - "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443", - "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be", - "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2", - "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee", - "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f", - "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae", - "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864", - "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4", - "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951", - "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc" + "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a", + "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed", + "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979", + "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff", + "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5", + "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45", + "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340", + "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad", + "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23", + "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6", + "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7", + "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241", + "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda", + "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187", + "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba", + "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c", + "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2", + "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c", + "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132", + "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf", + "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972", + "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db", + "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade", + "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4", + "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8", + "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f", + "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9", + "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48", + "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec", + "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d", + "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9", + "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb", + "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4", + "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89", + "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c", + "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9", + "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da", + "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac", + "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b", + "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf", + "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e", + "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137", + "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1", + "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b", + "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8", + "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e", + "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053", + "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01", + "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe", + "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd", + "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805", + "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183", + "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8", + "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99", + "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820", + "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074", + "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256", + "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8", + "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975", + "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad", + "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e", + "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca", + "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df", + "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b", + "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a", + "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a", + "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721", + "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a", + "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f", + "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2", + "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97", + "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6", + "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed", + "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc", + "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1", + "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe", + "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120", + "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f", + "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a" ], "markers": "python_version >= '3.8'", - "version": "==2.18.4" + "version": "==2.16.3" }, "python-dateutil": { "hashes": [ @@ -608,11 +611,12 @@ }, "requests": { "hashes": [ - "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", - "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" ], "index": "pypi", - "version": "==2.32.3" + "markers": "python_version >= '3.7'", + "version": "==2.31.0" }, "six": { "hashes": [ @@ -636,15 +640,16 @@ "sha256:024d3d1745120098a85635e42242039ca6b1bc787f561ec974fffb45fc775c1b" ], "index": "pypi", + "markers": "python_full_version >= '3.5.3'", "version": "==1.0.3" }, "typing-extensions": { "hashes": [ - "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a", - "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1" + "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", + "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" ], "markers": "python_version >= '3.8'", - "version": "==4.12.1" + "version": "==4.11.0" }, "tzdata": { "hashes": [ @@ -770,19 +775,19 @@ }, "babel": { "hashes": [ - "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb", - "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413" + "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363", + "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287" ], - "markers": "python_version >= '3.8'", - "version": "==2.15.0" + "markers": "python_version >= '3.7'", + "version": "==2.14.0" }, "backports.tarfile": { "hashes": [ - "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", - "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991" + "sha256:2688f159c21afd56a07b75f01306f9f52c79aebcc5f4a117fb8fbb4445352c75", + "sha256:bcd36290d9684beb524d3fe74f4a2db056824c47746583f090b8e55daf0776e4" ], "markers": "python_version < '3.12'", - "version": "==1.2.0" + "version": "==1.0.0" }, "beautifulsoup4": { "hashes": [ @@ -798,15 +803,16 @@ "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4" ], "index": "pypi", + "markers": "python_version >= '3.8'", "version": "==1.2.1" }, "certifi": { "hashes": [ - "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", - "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" + "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", + "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "markers": "python_version >= '3.6'", - "version": "==2024.6.2" + "version": "==2024.2.2" }, "cffi": { "hashes": [ @@ -964,123 +970,125 @@ }, "coverage": { "hashes": [ - "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523", - "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f", - "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d", - "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb", - "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0", - "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c", - "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98", - "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83", - "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8", - "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7", - "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac", - "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84", - "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb", - "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3", - "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884", - "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614", - "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd", - "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807", - "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd", - "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8", - "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc", - "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db", - "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0", - "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08", - "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232", - "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d", - "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a", - "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1", - "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286", - "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303", - "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341", - "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84", - "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45", - "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc", - "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec", - "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd", - "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155", - "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52", - "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d", - "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485", - "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31", - "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d", - "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d", - "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d", - "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85", - "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce", - "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb", - "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974", - "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24", - "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56", - "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9", - "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35" + "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c", + "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63", + "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7", + "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f", + "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8", + "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf", + "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0", + "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384", + "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76", + "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7", + "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d", + "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70", + "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f", + "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818", + "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b", + "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d", + "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec", + "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083", + "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2", + "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9", + "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd", + "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade", + "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e", + "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a", + "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227", + "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87", + "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c", + "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e", + "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c", + "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e", + "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd", + "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec", + "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562", + "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8", + "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677", + "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357", + "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c", + "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd", + "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49", + "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286", + "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1", + "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf", + "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51", + "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409", + "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384", + "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e", + "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978", + "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57", + "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e", + "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2", + "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48", + "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4" ], "index": "pypi", - "version": "==7.5.3" + "markers": "python_version >= '3.8'", + "version": "==7.4.4" }, "cryptography": { "hashes": [ - "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad", - "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583", - "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b", - "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c", - "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1", - "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648", - "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949", - "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba", - "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c", - "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9", - "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d", - "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c", - "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e", - "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2", - "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d", - "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7", - "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70", - "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2", - "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7", - "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14", - "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe", - "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e", - "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71", - "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961", - "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7", - "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c", - "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28", - "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842", - "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902", - "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801", - "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a", - "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e" + "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee", + "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576", + "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d", + "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30", + "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413", + "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb", + "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da", + "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4", + "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd", + "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc", + "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8", + "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1", + "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc", + "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e", + "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8", + "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940", + "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400", + "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7", + "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16", + "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278", + "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74", + "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec", + "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1", + "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2", + "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c", + "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922", + "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a", + "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6", + "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1", + "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e", + "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac", + "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7" ], "markers": "python_version >= '3.7'", - "version": "==42.0.8" + "version": "==42.0.5" }, "docutils": { "hashes": [ - "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", - "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2" + "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", + "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b" ], - "markers": "python_version >= '3.9'", - "version": "==0.21.2" + "markers": "python_version >= '3.7'", + "version": "==0.20.1" }, "furo": { "hashes": [ - "sha256:490a00d08c0a37ecc90de03ae9227e8eb5d6f7f750edf9807f398a2bdf2358de", - "sha256:81f205a6605ebccbb883350432b4831c0196dd3d1bc92f61e1f459045b3d2b0b" + "sha256:3548be2cef45a32f8cdc0272d415fcb3e5fa6a0eb4ddfe21df3ecf1fe45a13cf", + "sha256:4d6b2fe3f10a6e36eb9cc24c1e7beb38d7a23fc7b3c382867503b7fcac8a1e02" ], "index": "pypi", - "version": "==2024.5.6" + "markers": "python_version >= '3.8'", + "version": "==2024.1.29" }, "idna": { "hashes": [ - "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", - "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" ], "markers": "python_version >= '3.5'", - "version": "==3.7" + "version": "==3.6" }, "imagesize": { "hashes": [ @@ -1124,11 +1132,11 @@ }, "jaraco.functools": { "hashes": [ - "sha256:3b24ccb921d6b593bdceb56ce14799204f473976e2a9d4b15b04d0f2c2326664", - "sha256:d33fa765374c0611b52f8b3a795f8900869aa88c84769d4d1746cd68fb28c3e8" + "sha256:c279cb24c93d694ef7270f970d499cab4d3813f4e08273f95398651a634f0925", + "sha256:daf276ddf234bea897ef14f43c4e1bf9eefeac7b7a82a4dd69228ac20acff68d" ], "markers": "python_version >= '3.8'", - "version": "==4.0.1" + "version": "==4.0.0" }, "jeepney": { "hashes": [ @@ -1140,19 +1148,19 @@ }, "jinja2": { "hashes": [ - "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", - "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d" + "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa", + "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" ], "markers": "python_version >= '3.7'", - "version": "==3.1.4" + "version": "==3.1.3" }, "keyring": { "hashes": [ - "sha256:2458681cdefc0dbc0b7eb6cf75d0b98e59f9ad9b2d4edd319d18f68bdca95e50", - "sha256:daaffd42dbda25ddafb1ad5fec4024e5bbcfe424597ca1ca452b299861e49f1b" + "sha256:26fc12e6a329d61d24aa47b22a7c5c3f35753df7d8f2860973cf94f4e1fb3427", + "sha256:7230ea690525133f6ad536a9b5def74a4bd52642abe594761028fc044d7c7893" ], "markers": "python_version >= '3.8'", - "version": "==25.2.1" + "version": "==25.1.0" }, "markdown-it-py": { "hashes": [ @@ -1275,19 +1283,19 @@ }, "pkginfo": { "hashes": [ - "sha256:6d4998d1cd42c297af72cc0eab5f5bab1d356fb8a55b828fa914173f8bc1ba05", - "sha256:dba885aa82e31e80d615119874384923f4e011c2a39b0c4b7104359e36cb7087" + "sha256:5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297", + "sha256:889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097" ], - "markers": "python_version >= '3.8'", - "version": "==1.11.0" + "markers": "python_version >= '3.6'", + "version": "==1.10.0" }, "pluggy": { "hashes": [ - "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", - "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981", + "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be" ], "markers": "python_version >= '3.8'", - "version": "==1.5.0" + "version": "==1.4.0" }, "pycparser": { "hashes": [ @@ -1299,27 +1307,28 @@ }, "pygments": { "hashes": [ - "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", - "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a" + "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", + "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" ], - "markers": "python_version >= '3.8'", - "version": "==2.18.0" + "markers": "python_version >= '3.7'", + "version": "==2.17.2" }, "pyproject-hooks": { "hashes": [ - "sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965", - "sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2" + "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8", + "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5" ], "markers": "python_version >= '3.7'", - "version": "==1.1.0" + "version": "==1.0.0" }, "pytest": { "hashes": [ - "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343", - "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977" + "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7", + "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044" ], "index": "pypi", - "version": "==8.2.2" + "markers": "python_version >= '3.8'", + "version": "==8.1.1" }, "readme-renderer": { "hashes": [ @@ -1331,11 +1340,12 @@ }, "requests": { "hashes": [ - "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", - "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" ], "index": "pypi", - "version": "==2.32.3" + "markers": "python_version >= '3.7'", + "version": "==2.31.0" }, "requests-mock": { "hashes": [ @@ -1343,6 +1353,7 @@ "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401" ], "index": "pypi", + "markers": "python_version >= '3.5'", "version": "==1.12.1" }, "requests-toolbelt": { @@ -1379,11 +1390,12 @@ }, "setuptools": { "hashes": [ - "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4", - "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0" + "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e", + "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c" ], "index": "pypi", - "version": "==70.0.0" + "markers": "python_version >= '3.8'", + "version": "==69.2.0" }, "snowballstemmer": { "hashes": [ @@ -1402,11 +1414,11 @@ }, "sphinx": { "hashes": [ - "sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3", - "sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc" + "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", + "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5" ], "markers": "python_version >= '3.9'", - "version": "==7.3.7" + "version": "==7.2.6" }, "sphinx-basic-ng": { "hashes": [ @@ -1466,11 +1478,12 @@ }, "twine": { "hashes": [ - "sha256:4d74770c88c4fcaf8134d2a6a9d863e40f08255ff7d8e2acb3cbbd57d25f6e9d", - "sha256:fe1d814395bfe50cfbe27783cb74efe93abeac3f66deaeb6c8390e4e92bacb43" + "sha256:89b0cc7d370a4b66421cc6102f269aa910fe0f1861c124f573cf2ddedbc10cf4", + "sha256:a262933de0b484c53408f9edae2e7821c1c45a3314ff2df9bdd343aa7ab8edc0" ], "index": "pypi", - "version": "==5.1.0" + "markers": "python_version >= '3.8'", + "version": "==5.0.0" }, "urllib3": { "hashes": [ @@ -1482,11 +1495,11 @@ }, "zipp": { "hashes": [ - "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19", - "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c" + "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b", + "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715" ], "markers": "python_version >= '3.8'", - "version": "==3.19.2" + "version": "==3.18.1" } } } diff --git a/lib/python/dbrepo/RestClient.py b/lib/python/dbrepo/RestClient.py index 0a03fd669bd8b8a2834b42fb59b8456a4b7edabf..c833079e0c89f84d85b5d81feb848b7d413c206e 100644 --- a/lib/python/dbrepo/RestClient.py +++ b/lib/python/dbrepo/RestClient.py @@ -128,7 +128,7 @@ class RestClient: logging.info(f"No username set!") return None - def get_users(self) -> List[UserBrief]: + def get_users(self) -> List[User]: """ Get all users. @@ -140,7 +140,7 @@ class RestClient: response = self._wrapper(method="get", url=url) if response.status_code == 200: body = response.json() - return TypeAdapter(List[UserBrief]).validate_python(body) + return TypeAdapter(List[User]).validate_python(body) raise ResponseCodeError(f'Failed to find users: response code: {response.status_code} is not 200 (OK)') def get_user(self, user_id: str) -> User: @@ -439,7 +439,7 @@ class RestClient: :raises NameExistsError: If a table with this name already exists. :raises ForbiddenError: If the action is not allowed. :raises MalformedError: If the payload is rejected by the service. - :raises NotExistsError: If the container does not exist. + :raises NotExistsError: If thecontainer does not exist. """ url = f'/api/database/{database_id}/table' response = self._wrapper(method="post", url=url, force_auth=True, @@ -459,7 +459,7 @@ class RestClient: raise ResponseCodeError( f'Failed to create table: response code: {response.status_code} is not 201 (CREATED)') - def get_tables(self, database_id: int) -> List[TableBrief]: + def get_tables(self, database_id: int) -> List[Table]: """ Get all tables. @@ -473,7 +473,7 @@ class RestClient: response = self._wrapper(method="get", url=url) if response.status_code == 200: body = response.json() - return TypeAdapter(List[TableBrief]).validate_python(body) + return TypeAdapter(List[Table]).validate_python(body) raise ResponseCodeError(f'Failed to find tables: response code: {response.status_code} is not 200 (OK)') def get_table(self, database_id: int, table_id: int) -> Table: @@ -758,7 +758,7 @@ class RestClient: """ url = f'/api/database/{database_id}/table/{table_id}/data' response = self._wrapper(method="post", url=url, force_auth=True, payload=CreateData(data=data)) - if response.status_code == 201: + if response.status_code == 202: return if response.status_code == 400 or response.status_code == 410: raise MalformedError(f'Failed to insert table data: service rejected malformed payload') @@ -767,7 +767,7 @@ class RestClient: if response.status_code == 404: raise NotExistsError(f'Failed to insert table data: not found') raise ResponseCodeError( - f'Failed to insert table data: response code: {response.status_code} is not 201 (CREATED)') + f'Failed to insert table data: response code: {response.status_code} is not 202 (ACCEPTED)') def import_table_data(self, database_id: int, table_id: int, separator: str, file_path: str, quote: str = None, skip_lines: int = 0, false_encoding: str = None, diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 5eae072f35610faf5315d7145544556036dfe7eb..6f00b545499c213d08ac6fa8c1fc2a0c4256f4a6 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -1,5 +1,6 @@ from __future__ import annotations +import uuid from dataclasses import field from enum import Enum import datetime @@ -27,7 +28,7 @@ class JwtAuth(BaseModel): refresh_expires_in: int not_before_policy: int = Field(alias='not-before-policy') scope: str - session_state: str + session_state: uuid.UUID token_type: str @@ -74,11 +75,11 @@ class UpdateUser(BaseModel): class UserBrief(BaseModel): id: str username: str - name: Optional[str] = None - orcid: Optional[str] = None - qualified_name: Optional[str] = None - given_name: Optional[str] = None - family_name: Optional[str] = None + name: str + orcid: str + qualified_name: str + given_name: str + family_name: str class Container(BaseModel): @@ -117,12 +118,12 @@ class ColumnBrief(BaseModel): class TableBrief(BaseModel): id: int - database_id: int name: str - description: Optional[str] + description: str + owner: UserBrief + columns: List[ColumnBrief] internal_name: str is_versioned: bool - owner: UserBrief class UserAttributes(BaseModel): @@ -149,6 +150,16 @@ class UpdateUserPassword(BaseModel): password: str +class UserBrief(BaseModel): + id: str + username: str + name: Optional[str] = None + orcid: Optional[str] = None + qualified_name: Optional[str] = None + given_name: Optional[str] = None + family_name: Optional[str] = None + + class AccessType(str, Enum): """ Enumeration of database access. @@ -504,8 +515,6 @@ class CreateTableColumn(BaseModel): name: str type: ColumnType null_allowed: bool - concept_uri: Optional[str] = None - unit_uri: Optional[str] = None index_length: Optional[int] = None size: Optional[int] = None d: Optional[int] = None @@ -987,44 +996,22 @@ class Unique(BaseModel): columns: List[ColumnMinimal] -class ForeignKeyReference(BaseModel): - id: int - foreign_key: ForeignKeyMinimal - column: ColumnMinimal - referenced_column: ColumnMinimal - - -class ReferenceType(str, Enum): - """ - Enumeration of reference types. - """ - RESTRICT = "restrict" - CASCADE = "cascade" - SET_NULL = "set_null" - NO_ACTION = "no_action" - SET_DEFAULT = "set_default" - - -class ForeignKeyMinimal(BaseModel): - id: int - - class ForeignKey(BaseModel): id: int name: str - references: List[ForeignKeyReference] - table: TableMinimal + columns: List[ColumnMinimal] referenced_table: TableMinimal - on_update: Optional[ReferenceType] = None - on_delete: Optional[ReferenceType] = None + referenced_columns: List[ColumnMinimal] + on_update: Optional[str] = None + on_delete: Optional[str] = None class CreateForeignKey(BaseModel): - columns: List[str] - referenced_table: str - referenced_columns: List[str] - on_update: Optional[ReferenceType] = None - on_delete: Optional[ReferenceType] = None + columns: List[Column] + referenced_table: Table + referenced_columns: List[Column] + on_update: Optional[str] = None + on_delete: Optional[str] = None class PrimaryKey(BaseModel): diff --git a/lib/python/tests/test_component_user.py b/lib/python/tests/test_component_user.py new file mode 100644 index 0000000000000000000000000000000000000000..bc9961bc7ec6c2f8d6938c50d80d8a041f473ca7 --- /dev/null +++ b/lib/python/tests/test_component_user.py @@ -0,0 +1,52 @@ +import logging +import unittest +import random +import string + +from dbrepo.RestClient import RestClient + + +def rand(size=6, chars=string.ascii_uppercase + string.digits): + return ''.join(random.choice(chars) for _ in range(size)) + + +class UserComponentTest(unittest.TestCase): + + def test_create_user_find_whoami_login_basic_oidc(self): + # params + username = rand(size=8).lower() + password = rand(size=8) + email = rand(size=8) + "@example.com" + print(f"creating user {username} with password {password} with email {email}") + # create user + client = RestClient(endpoint="http://localhost") + response = client.create_user(username=username, password=password, email=email) + self.assertEqual(username, response.username) + self.assertIsNotNone(response.id) + user_id = response.id + # find user + client = RestClient(endpoint="http://localhost", username=username, password=password) + response = client.get_user(user_id=user_id) + self.assertEqual(username, response.username) + self.assertEqual(user_id, response.id) + # whoami + response = client.whoami() + self.assertEqual(username, response) + # login basic + response = client.get_jwt_auth(username=username, password=password) + self.assertIsNotNone(response.id_token) + access_token = response.access_token + self.assertIsNotNone(response.access_token) + self.assertIsNotNone(response.refresh_token) + self.assertEqual(0, response.not_before_policy) + self.assertIsNotNone(response.expires_in) + self.assertIsNotNone(response.refresh_expires_in) + self.assertIsNotNone(response.session_state) + self.assertIsNotNone(response.scope) + # login oidc + client = RestClient(endpoint="http://localhost", password=access_token) + response = client.update_user(user_id=user_id, theme="light", language="en") + + +if __name__ == "__main__": + unittest.main() diff --git a/lib/python/tests/test_unit_table.py b/lib/python/tests/test_unit_table.py index 5dff01582ec536a116e4a996e60e9236c765db52..03f5aca1af29a71ed8e5494d23696cb01b25573a 100644 --- a/lib/python/tests/test_unit_table.py +++ b/lib/python/tests/test_unit_table.py @@ -8,7 +8,7 @@ from dbrepo.RestClient import RestClient from pandas import DataFrame from dbrepo.api.dto import Table, CreateTableConstraints, UserAttributes, User, Column, Constraints, ColumnType, Result, \ - Concept, Unit, TableStatistics, ColumnStatistic, PrimaryKey, TableMinimal, ColumnMinimal, TableBrief, UserBrief + Concept, Unit, TableStatistics, ColumnStatistic, PrimaryKey, TableMinimal, ColumnMinimal from dbrepo.api.exceptions import MalformedError, ForbiddenError, NotExistsError, NameExistsError, QueryStoreError, \ AuthenticationError @@ -126,14 +126,38 @@ class TableUnitTest(unittest.TestCase): def test_get_tables_succeeds(self): with requests_mock.Mocker() as mock: - exp = [TableBrief(id=2, - name="Test", - description="Test Table", - database_id=1, - internal_name="test", - owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise', - attributes=UserAttributes(theme='light')), - is_versioned=True)] + exp = [Table(id=2, + name="Test", + description="Test Table", + database_id=1, + internal_name="test", + creator=User(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise', + attributes=UserAttributes(theme='light')), + owner=User(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise', + attributes=UserAttributes(theme='light')), + created=datetime.datetime(2024, 1, 1, 0, 0, 0, 0, datetime.timezone.utc), + is_versioned=True, + created_by='8638c043-5145-4be8-a3e4-4b79991b0a16', + queue_name='test', + routing_key='dbrepo.test_database_1234.test', + is_public=True, + constraints=Constraints(uniques=[], + foreign_keys=[], + checks=[], + primary_key=[PrimaryKey(id=1, + table=TableMinimal(id=2, database_id=1), + column=ColumnMinimal(id=1, table_id=2, + database_id=1))]), + columns=[Column(id=1, + name="ID", + database_id=1, + table_id=2, + internal_name="id", + auto_generated=True, + is_primary_key=True, + column_type=ColumnType.BIGINT, + is_public=True, + is_null_allowed=False)])] # mock mock.get('/api/database/1/table', json=[exp[0].model_dump()]) # test @@ -356,7 +380,7 @@ class TableUnitTest(unittest.TestCase): def test_create_table_data_succeeds(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/1/table/9/data', status_code=201) + mock.post('/api/database/1/table/9/data', status_code=202) # test client = RestClient(username="a", password="b") client.create_table_data(database_id=1, table_id=9, diff --git a/make/gen.mk b/make/gen.mk index 14206d66334bed074579ad2bab7ef4642e8f914c..e6fceaf2ba3e40a0dc496f885448916a3eb3c766 100644 --- a/make/gen.mk +++ b/make/gen.mk @@ -10,12 +10,6 @@ gen-swagger-doc-fe: build-images ## Generate Swagger documentation and fetch. bash .docs/.swagger/swagger-generate.sh bash .docs/.swagger/swagger-site.sh docker compose down - openapi-merge-cli --config .docs/.swagger/openapi-merge.json - -.PHONY: gen-helm-doc -gen-helm-doc: build-helm ## Generate Helm documentation and schema - helm schema -input ./helm/dbrepo/values.yaml - readme-generator-for-helm --readme ./helm/dbrepo/README.md --values ./helm/dbrepo/values.yaml .PHONY: gen-dbrepo-doc gen-docs-doc: ## Generate DBRepo documentation. diff --git a/make/rel.mk b/make/rel.mk index c06bb234334f0f55fc0bcf4ab3a6becf04825a63..bf73c6bb8ecb239525a49a1e5dcbec731f1dd0db 100644 --- a/make/rel.mk +++ b/make/rel.mk @@ -2,28 +2,50 @@ .PHONY: tag-images tag-images: build-images ## Tag the docker images. - docker tag dbrepo-analyse-service:latest "${REPOSITORY_URL}/analyse-service:${APP_VERSION}" - docker tag dbrepo-auth-service:latest "${REPOSITORY_URL}/auth-service:${APP_VERSION}" - docker tag dbrepo-metadata-db:latest "${REPOSITORY_URL}/metadata-db:${APP_VERSION}" - docker tag dbrepo-ui:latest "${REPOSITORY_URL}/ui:${APP_VERSION}" - docker tag dbrepo-data-service:latest "${REPOSITORY_URL}/data-service:${APP_VERSION}" - docker tag dbrepo-metadata-service:latest "${REPOSITORY_URL}/metadata-service:${APP_VERSION}" - docker tag dbrepo-search-db:latest "${REPOSITORY_URL}/search-db:${APP_VERSION}" - docker tag dbrepo-data-db-sidecar:latest "${REPOSITORY_URL}/data-db-sidecar:${APP_VERSION}" - docker tag dbrepo-search-service:latest "${REPOSITORY_URL}/search-service:${APP_VERSION}" - docker tag dbrepo-search-service-init:latest "${REPOSITORY_URL}/search-service-init:${APP_VERSION}" - docker tag dbrepo-storage-service-init:latest "${REPOSITORY_URL}/storage-service-init:${APP_VERSION}" + docker tag dbrepo-analyse-service:latest "${REPOSITORY_1_URL}/analyse-service:${APP_VERSION}" + docker tag dbrepo-analyse-service:latest "${REPOSITORY_2_URL}/analyse-service:${APP_VERSION}" + docker tag dbrepo-auth-service:latest "${REPOSITORY_1_URL}/auth-service:${APP_VERSION}" + docker tag dbrepo-auth-service:latest "${REPOSITORY_2_URL}/auth-service:${APP_VERSION}" + docker tag dbrepo-metadata-db:latest "${REPOSITORY_1_URL}/metadata-db:${APP_VERSION}" + docker tag dbrepo-metadata-db:latest "${REPOSITORY_2_URL}/metadata-db:${APP_VERSION}" + docker tag dbrepo-ui:latest "${REPOSITORY_1_URL}/ui:${APP_VERSION}" + docker tag dbrepo-ui:latest "${REPOSITORY_2_URL}/ui:${APP_VERSION}" + docker tag dbrepo-data-service:latest "${REPOSITORY_1_URL}/data-service:${APP_VERSION}" + docker tag dbrepo-data-service:latest "${REPOSITORY_2_URL}/data-service:${APP_VERSION}" + docker tag dbrepo-metadata-service:latest "${REPOSITORY_1_URL}/metadata-service:${APP_VERSION}" + docker tag dbrepo-metadata-service:latest "${REPOSITORY_2_URL}/metadata-service:${APP_VERSION}" + docker tag dbrepo-search-db:latest "${REPOSITORY_1_URL}/search-db:${APP_VERSION}" + docker tag dbrepo-search-db:latest "${REPOSITORY_2_URL}/search-db:${APP_VERSION}" + docker tag dbrepo-data-db-sidecar:latest "${REPOSITORY_1_URL}/data-db-sidecar:${APP_VERSION}" + docker tag dbrepo-data-db-sidecar:latest "${REPOSITORY_2_URL}/data-db-sidecar:${APP_VERSION}" + docker tag dbrepo-search-service:latest "${REPOSITORY_1_URL}/search-service:${APP_VERSION}" + docker tag dbrepo-search-service:latest "${REPOSITORY_2_URL}/search-service:${APP_VERSION}" + docker tag dbrepo-search-service-init:latest "${REPOSITORY_1_URL}/search-service-init:${APP_VERSION}" + docker tag dbrepo-search-service-init:latest "${REPOSITORY_2_URL}/search-service-init:${APP_VERSION}" + docker tag dbrepo-storage-service-init:latest "${REPOSITORY_1_URL}/storage-service-init:${APP_VERSION}" + docker tag dbrepo-storage-service-init:latest "${REPOSITORY_2_URL}/storage-service-init:${APP_VERSION}" .PHONY: release-images release-images: tag-images ## Release the docker images. - docker push "${REPOSITORY_URL}/analyse-service:${APP_VERSION}" - docker push "${REPOSITORY_URL}/auth-service:${APP_VERSION}" - docker push "${REPOSITORY_URL}/metadata-db:${APP_VERSION}" - docker push "${REPOSITORY_URL}/ui:${APP_VERSION}" - docker push "${REPOSITORY_URL}/data-service:${APP_VERSION}" - docker push "${REPOSITORY_URL}/search-db:${APP_VERSION}" - docker push "${REPOSITORY_URL}/data-db-sidecar:${APP_VERSION}" - docker push "${REPOSITORY_URL}/metadata-service:${APP_VERSION}" - docker push "${REPOSITORY_URL}/search-service:${APP_VERSION}" - docker push "${REPOSITORY_URL}/search-service-init:${APP_VERSION}" - docker push "${REPOSITORY_URL}/storage-service-init:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/analyse-service:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/analyse-service:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/auth-service:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/auth-service:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/metadata-db:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/metadata-db:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/ui:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/ui:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/data-service:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/data-service:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/search-db:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/search-db:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/data-db-sidecar:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/data-db-sidecar:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/metadata-service:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/metadata-service:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/search-service:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/search-service:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/search-service-init:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/search-service-init:${APP_VERSION}" + docker push "${REPOSITORY_1_URL}/storage-service-init:${APP_VERSION}" + docker push "${REPOSITORY_2_URL}/storage-service-init:${APP_VERSION}" diff --git a/values.schema.json b/values.schema.json deleted file mode 100644 index 2cc52abfed3216d26a5e140292c82ffc2e023a8f..0000000000000000000000000000000000000000 --- a/values.schema.json +++ /dev/null @@ -1,1459 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "admin": { - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "analyseservice": { - "properties": { - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - }, - "s3": { - "properties": { - "endpoint": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "authservice": { - "properties": { - "auth": { - "properties": { - "adminPassword": { - "type": "string" - }, - "adminUser": { - "type": "string" - } - }, - "type": "object" - }, - "client": { - "properties": { - "id": { - "type": "string" - }, - "secret": { - "type": "string" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - }, - "extraEnvVarsCM": { - "type": "string" - }, - "extraStartupArgs": { - "type": "string" - }, - "extraVolumeMounts": { - "items": { - "properties": { - "mountPath": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "extraVolumes": { - "items": { - "properties": { - "configMap": { - "properties": { - "name": { - "type": "string" - } - }, - "type": "object" - }, - "name": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "fullnameOverride": { - "type": "string" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - } - }, - "type": "object" - }, - "jwt": { - "properties": { - "pubkey": { - "type": "string" - } - }, - "type": "object" - }, - "metrics": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "postgresql": { - "properties": { - "auth": { - "properties": { - "postgresPassword": { - "type": "string" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - }, - "tls": { - "properties": { - "enabled": { - "type": "boolean" - }, - "existingSecret": { - "type": "string" - }, - "usePem": { - "type": "boolean" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "brokerservice": { - "properties": { - "auth": { - "properties": { - "password": { - "type": "string" - }, - "tls": { - "properties": { - "enabled": { - "type": "boolean" - }, - "existingSecret": { - "type": "string" - }, - "failIfNoPeerCert": { - "type": "boolean" - }, - "sslOptionsVerify": { - "type": "boolean" - } - }, - "type": "object" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "connectionTimeout": { - "type": "integer" - }, - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - }, - "exchangeName": { - "type": "string" - }, - "extraConfiguration": { - "type": "string" - }, - "extraPlugins": { - "type": "string" - }, - "extraVolumes": { - "items": { - "properties": { - "name": { - "type": "string" - }, - "secret": { - "properties": { - "secretName": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "type": "array" - }, - "fullnameOverride": { - "type": "string" - }, - "host": { - "type": "string" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - } - }, - "type": "object" - }, - "loadDefinition": { - "properties": { - "enabled": { - "type": "boolean" - }, - "existingSecret": { - "type": "string" - } - }, - "type": "object" - }, - "persistence": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "port": { - "type": "integer" - }, - "queueName": { - "type": "string" - }, - "replicaCount": { - "type": "integer" - }, - "routingKey": { - "type": "string" - }, - "service": { - "properties": { - "managerPortEnabled": { - "type": "boolean" - }, - "type": { - "type": "string" - } - }, - "type": "object" - }, - "virtualHost": { - "type": "string" - } - }, - "type": "object" - }, - "clusterDomain": { - "type": "string" - }, - "datadb": { - "properties": { - "enabled": { - "type": "boolean" - }, - "extraFlags": { - "type": "string" - }, - "extraVolumeMounts": { - "items": { - "properties": { - "mountPath": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "extraVolumes": { - "items": { - "properties": { - "emptyDir": { - "properties": {}, - "type": "object" - }, - "name": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "fullnameOverride": { - "type": "string" - }, - "galera": { - "properties": { - "mariabackup": { - "properties": { - "password": { - "type": "string" - }, - "user": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - } - }, - "type": "object" - }, - "metrics": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "persistence": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - }, - "rootUser": { - "properties": { - "password": { - "type": "string" - }, - "user": { - "type": "string" - } - }, - "type": "object" - }, - "service": { - "properties": { - "extraPorts": { - "items": { - "properties": { - "name": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "protocol": { - "type": "string" - }, - "targetPort": { - "type": "integer" - } - }, - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "sidecars": { - "items": { - "properties": { - "envFrom": { - "items": { - "properties": { - "secretRef": { - "properties": { - "name": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "type": "array" - }, - "image": { - "type": "string" - }, - "imagePullPolicy": { - "type": "string" - }, - "livenessProbe": { - "properties": { - "exec": { - "properties": { - "command": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "type": "object" - }, - "initialDelaySeconds": { - "type": "integer" - }, - "periodSeconds": { - "type": "integer" - } - }, - "type": "object" - }, - "name": { - "type": "string" - }, - "ports": { - "items": { - "properties": { - "containerPort": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "protocol": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "readinessProbe": { - "properties": { - "exec": { - "properties": { - "command": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "type": "object" - }, - "initialDelaySeconds": { - "type": "integer" - }, - "periodSeconds": { - "type": "integer" - } - }, - "type": "object" - }, - "securityContext": { - "properties": { - "allowPrivilegeEscalation": { - "type": "boolean" - }, - "capabilities": { - "properties": { - "drop": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "type": "object" - }, - "runAsGroup": { - "type": "integer" - }, - "runAsNonRoot": { - "type": "boolean" - }, - "runAsUser": { - "type": "integer" - }, - "seccompProfile": { - "properties": { - "type": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "volumeMounts": { - "items": { - "properties": { - "mountPath": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "dataservice": { - "properties": { - "consumerConcurrentMax": { - "type": "integer" - }, - "consumerConcurrentMin": { - "type": "integer" - }, - "default": { - "properties": { - "date": { - "type": "integer" - }, - "time": { - "type": "integer" - }, - "timestamp": { - "type": "integer" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - }, - "grant": { - "properties": { - "read": { - "type": "string" - }, - "write": { - "type": "string" - } - }, - "type": "object" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - }, - "requeueRejected": { - "type": "boolean" - }, - "s3": { - "properties": { - "auth": { - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "bucket": { - "properties": { - "export": { - "type": "string" - }, - "import": { - "type": "string" - } - }, - "type": "object" - }, - "endpoint": { - "type": "string" - }, - "filePath": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "gateway": { - "type": "string" - }, - "hostname": { - "type": "string" - }, - "ingress": { - "properties": { - "annotations": { - "properties": { - "basic": { - "properties": {}, - "type": "object" - }, - "rewriteApi": { - "properties": { - "nginx.ingress.kubernetes.io/rewrite-target": { - "type": "string" - }, - "nginx.ingress.kubernetes.io/use-regex": { - "type": "string" - } - }, - "type": "object" - }, - "rewritePid": { - "properties": { - "nginx.ingress.kubernetes.io/rewrite-target": { - "type": "string" - }, - "nginx.ingress.kubernetes.io/use-regex": { - "type": "string" - } - }, - "type": "object" - }, - "rewriteRoot": { - "properties": { - "nginx.ingress.kubernetes.io/rewrite-target": { - "type": "string" - }, - "nginx.ingress.kubernetes.io/use-regex": { - "type": "string" - } - }, - "type": "object" - }, - "rewriteRootSecure": { - "properties": { - "nginx.ingress.kubernetes.io/backend-protocol": { - "type": "string" - }, - "nginx.ingress.kubernetes.io/force-ssl-redirect": { - "type": "string" - }, - "nginx.ingress.kubernetes.io/rewrite-target": { - "type": "string" - }, - "nginx.ingress.kubernetes.io/use-regex": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "className": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "tls": { - "properties": { - "enabled": { - "type": "boolean" - }, - "secretName": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "metadatadb": { - "properties": { - "db": { - "properties": { - "name": { - "type": "string" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - }, - "extraInitDbScripts": { - "properties": {}, - "type": "object" - }, - "fullnameOverride": { - "type": "string" - }, - "galera": { - "properties": { - "mariabackup": { - "properties": { - "password": { - "type": "string" - }, - "user": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "host": { - "type": "string" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - } - }, - "type": "object" - }, - "initdbScriptsConfigMap": { - "type": "string" - }, - "jdbcExtraArgs": { - "type": "string" - }, - "metrics": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "persistence": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - }, - "rootUser": { - "properties": { - "password": { - "type": "string" - }, - "user": { - "type": "string" - } - }, - "type": "object" - }, - "service": { - "properties": { - "annotations": { - "properties": {}, - "type": "object" - }, - "loadBalancerIP": { - "type": "string" - }, - "loadBalancerSourceRanges": { - "type": "array" - }, - "type": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "metadataservice": { - "properties": { - "admin": { - "properties": { - "email": { - "type": "string" - } - }, - "type": "object" - }, - "datacite": { - "properties": { - "enabled": { - "type": "boolean" - }, - "password": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "url": { - "type": "string" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "deletedRecord": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - }, - "granularity": { - "type": "string" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - }, - "repositoryName": { - "type": "string" - }, - "s3": { - "properties": { - "auth": { - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "bucket": { - "properties": { - "export": { - "type": "string" - }, - "import": { - "type": "string" - } - }, - "type": "object" - }, - "endpoint": { - "type": "string" - } - }, - "type": "object" - }, - "sparql": { - "properties": { - "connectionTimeout": { - "type": "integer" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "namespace": { - "type": "string" - }, - "searchdb": { - "properties": { - "clusterName": { - "type": "string" - }, - "config": { - "properties": { - "opensearch.yml": { - "type": "string" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - }, - "extraEnvs": { - "items": { - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "extraVolumeMounts": { - "items": { - "properties": { - "mountPath": { - "type": "string" - }, - "name": { - "type": "string" - }, - "readOnly": { - "type": "boolean" - } - }, - "type": "object" - }, - "type": "array" - }, - "extraVolumes": { - "items": { - "properties": { - "name": { - "type": "string" - }, - "secret": { - "properties": { - "secretName": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "type": "array" - }, - "fullnameOverride": { - "type": "string" - }, - "host": { - "type": "string" - }, - "masterService": { - "type": "string" - }, - "password": { - "type": "string" - }, - "persistence": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "port": { - "type": "integer" - }, - "protocol": { - "type": "string" - }, - "replicas": { - "type": "integer" - }, - "service": { - "properties": { - "annotations": { - "properties": {}, - "type": "object" - }, - "loadBalancerSourceRanges": { - "type": "array" - }, - "type": { - "type": "string" - } - }, - "type": "object" - }, - "sysctlInit": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "searchservice": { - "properties": { - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - }, - "init": { - "properties": { - "image": { - "properties": { - "name": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - } - }, - "type": "object" - }, - "storageservice": { - "properties": { - "enabled": { - "type": "boolean" - }, - "filer": { - "properties": { - "enablePVC": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "replicas": { - "type": "integer" - }, - "s3": { - "properties": { - "allowEmptyFolder": { - "type": "boolean" - }, - "enableAuth": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "existingConfigSecret": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "skipAuthSecretCreation": { - "type": "boolean" - } - }, - "type": "object" - }, - "storage": { - "type": "string" - } - }, - "type": "object" - }, - "init": { - "properties": { - "image": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - }, - "master": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, - "s3": { - "properties": { - "auth": { - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - }, - "type": "object" - }, - "bucket": { - "properties": { - "export": { - "type": "string" - }, - "import": { - "type": "string" - } - }, - "type": "object" - }, - "enableAuth": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "existingConfigSecret": { - "type": "string" - }, - "metricsPort": { - "type": "integer" - }, - "port": { - "type": "integer" - }, - "replicas": { - "type": "integer" - }, - "skipAuthSecretCreation": { - "type": "boolean" - } - }, - "type": "object" - }, - "volume": { - "properties": { - "enabled": { - "type": "boolean" - }, - "replicas": { - "type": "integer" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "strategyType": { - "type": "string" - }, - "ui": { - "properties": { - "enabled": { - "type": "boolean" - }, - "extraVolumeMounts": { - "type": "array" - }, - "extraVolumes": { - "type": "array" - }, - "image": { - "properties": { - "debug": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "pullPolicy": { - "type": "string" - } - }, - "type": "object" - }, - "public": { - "properties": { - "api": { - "properties": { - "client": { - "type": "string" - }, - "server": { - "type": "string" - } - }, - "type": "object" - }, - "broker": { - "properties": { - "extra": { - "type": "string" - }, - "host": { - "type": "string" - }, - "port": { - "properties": { - "5671": { - "type": "boolean" - }, - "5672": { - "type": "boolean" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "database": { - "properties": { - "extra": { - "type": "string" - } - }, - "type": "object" - }, - "doi": { - "properties": { - "enabled": { - "type": "boolean" - }, - "endpoint": { - "type": "string" - } - }, - "type": "object" - }, - "icon": { - "type": "string" - }, - "links": { - "properties": { - "keycloak": { - "properties": { - "href": { - "type": "string" - }, - "text": { - "type": "string" - } - }, - "type": "object" - }, - "rabbitmq": { - "properties": { - "href": { - "type": "string" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "logo": { - "type": "string" - }, - "pid": { - "properties": { - "default": { - "properties": { - "publisher": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "title": { - "type": "string" - }, - "touch": { - "type": "string" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - } - }, - "type": "object" - }, - "uploadservice": { - "properties": { - "containerArgs": { - "items": { - "type": "string" - }, - "type": "array" - }, - "enabled": { - "type": "boolean" - }, - "envFrom": { - "items": { - "properties": { - "secretRef": { - "properties": { - "name": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "type": "array" - }, - "fullnameOverride": { - "type": "string" - }, - "image": { - "properties": { - "repository": { - "type": "string" - }, - "tag": { - "type": "string" - } - }, - "type": "object" - }, - "replicaCount": { - "type": "integer" - } - }, - "type": "object" - } - }, - "type": "object" -}