From 84ba9ddd4d3cc2be2132f1eaae1d28299241bea3 Mon Sep 17 00:00:00 2001 From: "marcel.kocisek" Date: Wed, 3 Sep 2025 15:52:49 +0200 Subject: [PATCH] Return whole project nfo dump from project versions :( --- server/mergin/sync/public_api_v2.yaml | 235 ++++++++++++++++-- .../mergin/sync/public_api_v2_controller.py | 19 +- server/mergin/tests/test_public_api_v2.py | 4 +- 3 files changed, 223 insertions(+), 35 deletions(-) diff --git a/server/mergin/sync/public_api_v2.yaml b/server/mergin/sync/public_api_v2.yaml index 4a4f7904..9ed062d5 100644 --- a/server/mergin/sync/public_api_v2.yaml +++ b/server/mergin/sync/public_api_v2.yaml @@ -304,7 +304,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/ProjectVersion" + $ref: "#/components/schemas/Project" "204": $ref: "#/components/responses/NoContent" "400": @@ -334,11 +334,11 @@ paths: - $ref: "#/components/schemas/StorageLimitHit" - $ref: "#/components/schemas/DataSyncError" "423": - description: Project is locked for any upload + description: Project is locked for any upload content: - application/problem+json: - schema: - $ref: "#/components/schemas/ProjectLocked" + application/problem+json: + schema: + $ref: "#/components/schemas/ProjectLocked" x-openapi-router-controller: mergin.sync.public_api_v2_controller components: @@ -381,13 +381,13 @@ components: - detail TrialExpired: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" example: code: TrialExpired detail: Failed to push changes. Ask the workspace owner to log in to their Mergin Maps dashboard StorageLimitHit: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" type: object properties: current_usage: @@ -401,13 +401,13 @@ components: storage_limit: 24865 ProjectLocked: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" example: code: ProjectLocked detail: The project is currently locked and you cannot make changes to it (ProjectLocked) ProjectVersionExists: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" type: object properties: client_version: @@ -419,7 +419,7 @@ components: detail: Project version mismatch (ProjectVersionExists) AnotherUploadRunning: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" type: object properties: client_version: @@ -431,7 +431,7 @@ components: detail: Another process is running (AnotherUploadRunning) DataSyncError: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" type: object properties: failed_files: @@ -443,7 +443,7 @@ components: "survey.gpkg": "Corrupted file" UploadError: allOf: - - $ref: '#/components/schemas/CustomError' + - $ref: "#/components/schemas/CustomError" example: code: UploadError detail: "Project version could not be created (UploadError)" @@ -541,23 +541,216 @@ components: nullable: true allOf: - $ref: "#/components/schemas/File" - ProjectVersion: + MerginTag: + type: string + enum: + - valid_qgis + - mappin_use + - input_use + example: valid_qgis + Access: + type: object + properties: + ownersnames: + type: array + nullable: false + items: + type: string + example: [john.doe] + writersnames: + type: array + nullable: false + items: + type: string + example: [john.doe] + editorsnames: + type: array + nullable: false + items: + type: string + example: [john.doe] + readersnames: + type: array + nullable: false + items: + type: string + example: [john.doe] + public: + type: boolean + example: true + owners: + type: array + nullable: false + items: + type: integer + example: [1] + writers: + type: array + nullable: false + items: + type: integer + example: [1] + editors: + type: array + nullable: false + items: + type: integer + example: [1] + readers: + type: array + nullable: false + items: + type: integer + example: [1] + FileInfo: type: object + required: + - path + - size + - checksum properties: + path: + type: string + example: media/favicon.ico + checksum: + description: sha1 hash + type: string + example: 9adb76bf81a34880209040ffe5ee262a090b62ab + size: + type: integer + format: int64 + example: 1024 + mtime: + deprecated: true + type: string + format: date-time + example: 2018-11-30T08:47:58.636074Z + diff: + type: object + nullable: true + required: + - path + - checksum + properties: + path: + type: string + description: unique diff filename + example: survey.gpkg-diff-15eqn2q + checksum: + type: string + example: 45dfdfbf81a34asdf209040ffe5fasdf2a090bfa + size: + type: integer + example: 512 + history: + type: object + description: map with version names as keys and file info as values + additionalProperties: + type: object + required: + - path + - size + - checksum + - change + properties: + path: + type: string + example: media/favicon.ico + checksum: + description: sha1 hash + type: string + example: 9adb76bf81a34880209040ffe5ee262a090b62ab + size: + type: integer + format: int64 + example: 1024 + change: + type: string + example: added + enum: + - added + - updated + - removed + expiration: + nullable: true + type: string + format: date-time + example: 2019-02-26T08:47:58.636074Z + Project: + type: object + required: + - name + properties: + id: + type: string + example: f9ef87ac-1dae-48ab-85cb-062a4784fb83 + description: Project UUID name: type: string - example: v1 - author: + example: mergin + namespace: type: string - example: john.doe + example: mergin + creator: + nullable: true + type: integer + example: 1 + description: Project creator ID created: type: string format: date-time example: 2018-11-30T08:47:58.636074Z - project_name: + updated: type: string - example: survey - namespace: + nullable: true + format: date-time + example: 2018-11-30T08:47:58.636074Z + description: Last modified + version: type: string - example: john.doe - \ No newline at end of file + nullable: true + example: v2 + description: Last project version + disk_usage: + type: integer + example: 25324373 + description: Project size in bytes + permissions: + type: object + properties: + delete: + type: boolean + example: false + update: + type: boolean + example: false + upload: + type: boolean + example: true + tags: + type: array + nullable: true + items: + $ref: "#/components/schemas/MerginTag" + uploads: + type: array + nullable: true + items: + type: string + example: 669b838e-a30b-4338-b2b6-3da144742a82 + description: UUID for ongoing upload + access: + $ref: "#/components/schemas/Access" + files: + type: array + items: + allOf: + - $ref: "#/components/schemas/FileInfo" + role: + nullable: true + type: string + enum: + - reader + - editor + - writer + - owner diff --git a/server/mergin/sync/public_api_v2_controller.py b/server/mergin/sync/public_api_v2_controller.py index 32c05595..6717a083 100644 --- a/server/mergin/sync/public_api_v2_controller.py +++ b/server/mergin/sync/public_api_v2_controller.py @@ -39,7 +39,12 @@ ) from .permissions import ProjectPermissions, require_project_by_uuid from .public_api_controller import catch_sync_failure -from .schemas import ProjectMemberSchema, ProjectVersionSchema, UploadChunkSchema +from .schemas import ( + ProjectMemberSchema, + ProjectVersionSchema, + UploadChunkSchema, + ProjectSchema, +) from .storages.disk import move_to_tmp, save_to_file from .utils import get_device_id, get_ip, get_user_agent, get_chunk_location from .workspace import WorkspaceRole @@ -337,17 +342,7 @@ def create_project_version(id): finally: # remove artifacts upload.clear() - - return ( - ProjectVersionSchema( - exclude=( - "files", - "changes", - "changesets", - ) - ).dump(pv), - 201, - ) + return ProjectSchema().dump(project), 201 @auth_required diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index 330f58fa..85177190 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -297,7 +297,7 @@ def test_create_version(client, data, expected, err_code): response = client.post(f"v2/projects/{project.id}/versions", json=data) assert response.status_code == expected if expected == 201: - assert response.json["name"] == "v2" + assert response.json["version"] == "v2" assert project.latest_version == 2 assert all(not os.path.exists(chunk) for chunk in chunks) else: @@ -491,7 +491,7 @@ def test_full_push(client): }, ) assert response.status_code == 201 - assert response.json["name"] == "v2" + assert response.json["version"] == "v2" assert project.latest_version == 2 assert os.path.exists( os.path.join(project.storage.project_dir, "v2", test_file["path"])