diff --git a/Docker.README.md b/Docker.README.md index 0a4d9c54a..3cf20e7cc 100644 --- a/Docker.README.md +++ b/Docker.README.md @@ -509,7 +509,7 @@ Configuration --- In production, the DDS server must be configured with the information for a live Duke Authentication Service microservice. This requires three Environment variables: -* AUTH_SERVICE_ID: The SERVICE_ID configured in the live Duke Authentication Service +* AUTH_SERVICE_SERVICE_ID: The SERVICE_ID configured in the live Duke Authentication Service * AUTH_SERVICE_BASE_URI: The Base URI to the live Duke Authentication Service, e.g. URI/api/v1/app/status should return {'status': 'ok'} * AUTH_SERVICE_NAME: A Description of the Service used in the apiexplorer and portal frontends diff --git a/api_docs/api_basics.apib b/api_docs/api_basics.apib new file mode 100644 index 000000000..48fa27fc9 --- /dev/null +++ b/api_docs/api_basics.apib @@ -0,0 +1,158 @@ +FORMAT: 1A + +# API Change Log and Basics + +## Group << API Summary + +## Group API Change Log +07-Feb-2017 +------------- ++ Simplified *Auth Provider Affiliates* response payload based on feedback from development team. ++ In *API Basics - Collection Pagination* - added default and max `per_page` pagination rules. ++ For `GET /auth_providers/{id}/affiliates{?full_name_contains}` - endpoint now requires a minumum of three characters for `full_name_contains` query parameter. + +20-Dec-2016 +------------- ++ For serialization of `user` resource - changed the format of the composite `auth_provider` object to be consistent with format returned by *Authentication Providers* actions. *Note:* In addition to user endpoints, this impacts list/view *Provenance Relations* which contain `user` in the response when the returned relation is `wasAttributedTo` or `wasAssociatedWith`. ++ Moved `/user/api_token` to the *Current User* resource - endpoint is now `/current_user/api_token`. In addition, modified request payload and changed HTTP verb to a `POST` for this operation. ++ Added `login_initiation_url`, `is_deprecated`, `is_default` properties to *Auth Providers* resource. ++ Changed `NOT_IMPLEMENTED_*` labels for endpoints to `NOT_IMPL_*` to improve readablility of rendered docs. ++ Changed HTTP verb from `GET` to `POST` for endpoint `/auth_providers/{id}/affiliates/{uid}/dds_user`. Added endpoint `GET /auth_providers/{id}/affiliates/{uid}` to get a specific auth provider (i.e. Duke) affiliate. + +19-Dec-2016 +-------------- ++ Added Home links to each of the sub-directories ++ Added links to each of the Web Portal instances (dev, ua_test and prod) ++ Added links to each of the API Explorer instances (dev, ua_test and prod) ++ Added user/get api_token endpoint documentation + +14-Dec-2016 +-------------- ++ Changed format of overall Apiary document to incorporate links to endpoint groupings ++ Moved apiary apib files to their own folder rather than have them scattered throughout root ++ Created a bash script to loop through and then generate the apiary html files. ++ Changed all endpoints to include typical response codes (this will align more so with the swagger documentation) + +30-Nov-2016 +-------------- ++ Fixed example request payload for *Search Objects* endpoint. ++ For *Search Provenance Origin* endpoint, removed validation of file versions query param; if file version does not exist, then no provenance nodes/relations are returned. + +17-Oct-2016 +-------------- ++ For *Search Provenance* - changed `/search/provenance/was_generated_by` to `/search/provenance/origin`; this search action now includes `wasDerivedFrom` file versions in the results. ++ For *Metadata* - changed `/templates{?name}` to `/templates{?name_contains}` - facilitates contains search vs. exact match. ++ Changed `/templates/{id}/properties{?key}` to `/templates/{id}/properties` - if we need `key` based lookup we will extend API to return the instance by `key`, not an array of 1. ++ Changed `/meta/{object_kind}/{object_id}{?meta_template_name}` to `/meta/{object_kind}/{object_id}` - if we need `template_name` based lookup we will extend API to return the instance by `template_name`, not an array of 1. + +23-Sep-2016 +-------------- ++ Added *Authentication Providers* actions - formalizes metadata for supported auth providers and provides endpoint to search for affiliates (potential DDS users) in context of the provider. In addition, supports getting a DDS user identity for a valid affiliate - this endpoint introduces a proposed change to user payload. + +## Group API Basics + +Web Portal +-------------- +There is a Web Portal that allows users to interact with the Web services API. Access is currently restricted to Duke staff with a valid Duke NetID and password. To access the Web portal, Duke staff must successfully authenticate via the Duke single sign-on process. ++ [Development](https://dev.dataservice.duke.edu/) ++ [Test](https://uatest.dataservice.duke.edu/) ++ [Production](https://dataservice.duke.edu/) + +Programmatic Keys +-------------- +In an effort to promote provenance, all programmatic access to the API must utilize the concept of a software agent. From the Web portal, an authorized user can generate secret keys for both a software agent and their user account. In tandem, these secret keys can be used to obtain an access token from a programmatic context. For usage details, see the actions for **Software Agents** and **Current User**. + +Exploring the API +-------------- +In addition to the API usage documentation herein, users may experiment with the live API actions in a test environment via the API Explorer. ++ [Development](https://apidev.dataservice.duke.edu/apiexplorer) ++ [Test](https://apiuatest.dataservice.duke.edu/apiexplorer) ++ [Production](https://api.dataservice.duke.edu/apiexplorer) + +Collection Pagination +-------------- +For actions that return a collection of resources/objects, the number of objects returned will be paginated. The number of objects returned per page, and the desired page can be controlled using the query parameters `page`, and `per_page`. For example: `/projects?per_page=25` will return the first 25 projects, and `/projects?page=3&per_page=25` will return the third batch of 25 projects. Collection payloads will always be returned as an array of objects; the `results` property will reference the array as follows: ++ Response + + { + "results": [ + { }, + { }, + ] + } + +*If `per_page` is not specified by the client, the default is `100`; the maximum `per_page` that can be specified is `1000`.* + +To make it easy for clients to manage pagination, the following headers will always be included in the response: + +* X-Total: The total number of objects that would be returned by the query unpaginated +* X-Total-Pages: The total number of pages given X-Total and X-Per-Page +* X-Page: Current Page (passed in as query parameter) +* X-Per-Page: per_page (passed in as query parameter) +* X-Next-Page: Next page to be collected +* X-Prev-Page: Previous page (will be empty on first page) + +Audit Object +-------------- +Resource payloads may include a composite audit object. An example structure of that object is represented here and will be referenced by the `audit` property in resource specific payloads. + ++ Response + + "audit": { + "created_on": "2015-01-01T12:00:00Z", + "created_by": { + "id": "ce245d81-bae1-452b-8589-24f736ca7735", + "username": "mrgardner01", + "full_name": "Matthew Gardner", + "software_agent": { + "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", + "name": "Hashing computation agent" + } + }, + "last_updated_on": "2015-01-01T13:00:00Z", + "last_updated_by": { + "id": "d240ef3d-8d43-441b-be90-78f51a02e47f", + "username": "jturner01", + "full_name": "Jon Turner", + "software_agent": null + }, + "deleted_on": null, + "deleted_by": null + } + +API Errors +---------------- +We should respond with context appropriate error codes, especially for 400 class errors, using the [Standard List](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) + +* 400: no API token, validation errors +* 401: bad API token +* 403: user performing request which they do not have permission to perform +* 404: user requesting resource that does not exist + +All error responses should include a JSON response that provides the HTTP status code, details of the error that occurred, and possible steps to address the problem. For example: ++ Response + + { + "error": "404", + "reason": "Project does not exist", + "suggestion": "You may have chosen the wrong ID." + } + +Validation errors require a field-level breakdown with an array of errors (even if multiple errors occur for the same field), each describing the field with the error, and message describing the error encountered. ++ Response + + { + "error": "400", + "reason": "validation failed", + "suggestion": "Fix the following invalid fields and resubmit" + "errors" : [ + { + "field" : "name", + "message" : "Project needs a name." + }, + { + "field" : "principal_investigator", + "message" : "Principal Investigator must be specified for each project." + } + ] + } diff --git a/api_docs/apiary.apib b/api_docs/apiary.apib new file mode 100644 index 000000000..249d2a964 --- /dev/null +++ b/api_docs/apiary.apib @@ -0,0 +1,36 @@ +FORMAT: 1A + +# Duke Data Service API Summary + +The Duke Data Service (DDS) API allows Duke researchers to store, organize, retrieve, share and generate provenance for data. + +This the documentation for the Data Service API. Key focuses are on API endpoints that enhance usability for "shallow end of the pool" users, endpoints that support the needs of investigators for managing their research groups, endpoints that accommodate shared resource and core facility needs, endpoints that support SOM administration of data resources, and endpoints that facilitate reproducible scientific workflows. There are tensions to resolve to meet these needs, and we should consider whether the API might be broken up into multiple APIs, whether some business logic be pushed to the users, etc. + +Adhere as well as possible to the [Heroku API Design Best Practices:](https://geemus.gitbooks.io/http-api-design/content/en/index.html) requiring secure TLS connections, versioning in the accepts header, supporting Etags, including a Request-id in each response header, among others. + +### **[API Change Log and Basics](/apidocs/api_basics.html)** ++ Contains change log and general usage details (i.e. authentication, standard errors, pagination, etc.) + +### **[Users, Software Agents, and Auth Providers](/apidocs/users_software_agents.html)** ++ Contains endpoints for Current User, Users, Software Agents, Authentication Providers + +### **[Authorization](/apidocs/authorization.html)** ++ Contains endpoints for Authorization Roles, System Permissions + +### **[Projects](/apidocs/projects.html)** ++ Contains endpoints for Projects, Project Member Permissions, Project Affiliates + +### **[Folders and Files](/apidocs/folders_files.html)** ++ Contains endpoints for Folders, Uploads, Files, File Versions, Browse Project/Folder Tree (Search Children), Storage Providers + +### **[Provenance](/apidocs/provenance.html)** ++ Contains endpoints for Provenance Activities, Provenance Relations, Search Provenance Graph + +### **[Metadata](/apidocs/metadata.html)** ++ Contains endpoints for Tags and Metadata (Key/Value Pairs) + +### **[Search](/apidocs/search.html)** ++ Contains endpoint Search Objects + +### **[Core Facility Workflow](/apidocs/core_facility_workflow.html)** ++ Contains endpoints for Project Transfers diff --git a/api_docs/authorization.apib b/api_docs/authorization.apib new file mode 100644 index 000000000..a93b015b9 --- /dev/null +++ b/api_docs/authorization.apib @@ -0,0 +1,198 @@ +FORMAT: 1A + +# Authorization Resources + +## Group << API Summary + +## Group Authorization Roles +Represents the set of discrete permissions that can be granted to a user. + +**Authorization Roles:** + +| role | name | description | permission(s) | +|:-----|:-----|:------------|:--------------| +| **system_admin** | System Admin | Can manage system level permissions and perform all operations across all projects | system_admin | +| **project_admin** | Project Admin | Can update project details, delete project, manage project level permissions and perform all file operations | view_project, update_project, delete_project, manage_project_permissions, download_file, create_file, update_file, delete_file | +| **project_viewer** | Project Viewer | Can only view project and file metadata | view_project | +| **file_downloader** | File Downloader | Can download files | view_project, download_file | +| **file_uploader** | File Uploader | Can upload files | view_project, create_file, update_file | +| **file_editor** | File Editor | Can view, download, create, update and delete files | view_project, download_file, create_file, update_file, delete_file | + + +**Permissions:** + +| permission | description | +|:------------|:------------| +| **system_admin** | Can manage system level permissions and perform all operations across all projects | +| **view_project** | Can view project and file metadata | +| **update_project** | Can update project header details and project affiliations | +| **delete_project** | Can delete project | +| **manage_project_permissions** | Can grant/revoke project level permissions | +| **download_file** | Can download file | +| **create_file** | Can upload new file and modify file metadata | +| **update_file** | Can upload new version of existing file and modify file metadata | +| **delete_file** | Can delete a file | + +## Authorization Roles collection [/auth_roles{?context}] ++ Parameters + + context (string, optional, `system`) ... The `context` or scope in which permission can be granted; valid context values are `system` or `project`. + +### List roles [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Unsupported Context + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "system_admin", + "name": "System Admin", + "description": "Can manage system level permissions and perform all operations across all projects", + "permissions": [ + { + "id": "system_admin" + } + ], + "contexts": ["system"], + "is_deprecated": false + } + ] + } + +## Authorization Role instance [/auth_roles/{id}] ++ Parameters + + id (string, required, `file_editor`) ... The unique `id` for an authorization role. + +### View role [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Unknown AuthRole + ++ Response 200 (application/json) + + { + "id": "file_editor", + "name": "File Editor", + "description": "Can view, download, create, update and delete files", + "permissions": [ + { + "id": "view_project" + }, + { + "id": "download_file" + } + ], + "contexts": ["project"], + "is_deprecated": false + } + +## Group System Permissions +Represents system level authorization roles that have been granted to a user. + +## System Permissions collection [/system/permissions] + +### List system permissions [GET] +>**Permission:** system_admin +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Response 200 (application/json) + + { + "results": [ + { + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "auth_role": { + "id": "system_admin", + "name": "System Admin", + "description": "Can manage system level permissions and perform all operations across all projects" + } + } + ] + } + +## System Permission instance [/system/permissions/{user_id}] ++ Parameters + + user_id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique id of the user. + +### Grant system permission [PUT] +>**Permission:** system_admin +- - - - - + +>**Rules** +- - - - - ++ Revokes any existing system level authorization role for the user and grants the new role. ++ The role specified must be a system level authorization role (i.e. `system` in `auth_role.contexts`). + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: User or AuthRole Does not Exist + ++ Request (application/json) + + { + "auth_role": {"id": "system_admin"} + } + ++ Response 200 + + { + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "auth_role": { + "id": "system_admin", + "name": "System Admin", + "description": "Can manage system level permissions and perform all operations across all projects" + } + } + +### View system permission [GET] +>**Permission:** system_admin +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: User Does not Exist + ++ Response 200 + + { + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "auth_role": { + "id": "system_admin", + "name": "System Admin", + "description": "Can manage system level permissions and perform all operations across all projects" + } + } + +### Revoke system permission [DELETE] +>**Permission:** system_admin +- - - - - +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 404: User Does not Exist + ++ Response 204 diff --git a/api_docs/breaking_changes.apib b/api_docs/breaking_changes.apib new file mode 100644 index 000000000..c8fa0287e --- /dev/null +++ b/api_docs/breaking_changes.apib @@ -0,0 +1,13 @@ +FORMAT: 1A + +# API Breaking Change Notices + +Changes that impact exisiting API consumers are posted here by the development team prior to deployment. + +## Group << API Summary + +## Group Breaking Changes +27-Jan-2017 +------------- ++ Breaking changes 1... ++ Breaking chnage 2... \ No newline at end of file diff --git a/api_docs/core_facility_workflow.apib b/api_docs/core_facility_workflow.apib new file mode 100644 index 000000000..cee7747d4 --- /dev/null +++ b/api_docs/core_facility_workflow.apib @@ -0,0 +1,351 @@ +FORMAT: 1A + +# Core Facility Workflow Resources + +## Group << API Summary + +## Group Project Transfer +**Proposed endpoints to meet the needs of the GCB project transfer workflow** +The *Project Transfer* actions can be used by research core facilities to formally transfer ownership of a project to a researcher (customer). These endpoints support the transfer workflow and retain a record of the transfer history. + +## Project Transfer collection [/projects/{id}/transfers] ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. + +### Initiate a project transfer [POST] +Initiates a project transfer from the current owner (i.e. `project_admin`) to a new owner or list of owners. +>**Permission:** manage_project_permissions +- - - - - + +>**Request Properties** +- - - - - ++ **to_users (object[ ], required)** - The list of users to transfer project ownership to. ++ **to_users[ ].id (string, required)** - The unique `id` of a user. + +>**Response Properties** +- - - - - ++ **from_user (object)** - The user who initiated the project transfer. ++ **status (string)** - The current status of the project transfer; defaults to `pending`. ++ **status_comment (string)** - An optional comment that can be provided when status transfers to a terminal state. + +>**Rules:** +- - - - - ++ There must be no existing transfers for the `project` in a `pending` state. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Project transfer already exists +* 401: Unauthorized +* 403: Forbidden + ++ Request (application/json) + + { + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712" + } + ] + } + ++ Response 201 (application/json) + + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "pending", + "status_comment": null, + "audit": { } + } + +### List project transfers [GET] +>**Permission:** authenticated [scope: manage_project_permissions, transfer initiator (i.e. `from_user`), or a transfer recipient (i.e. in `to_users`)] +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project does not exist + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "pending", + "status_comment": null, + "audit": { } + } + ] + } + +## Project Transfer instance [/project_transfers/{id}] ++ Parameters + + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. + +### View a project transfer [GET] +>**Permission:** manage_project_permissions, transfer initiator (i.e. `from_user`), or a transfer recipient (i.e. in `to_users`) +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden +* 404: Project transfer does not exist + ++ Response 200 (application/json) + + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "pending", + "status_comment": null, + "audit": { } + } + +## Accept a project transfer [PUT /project_transfers/{id}/accept] +Accept a *pending* project transfer. +>**Permission:** transfer recipient (i.e. in `to_users`)] +- - - - - + +>**Properties** +- - - - - ++ **status_comment (string, optional)** - An optional comment that can be provided. + +>**Rules:** +- - - - - ++ The project transfer must be in a `pending` state. ++ All exisiting permissions for the project are removed, `project_viewer` is granted to the transfer initiater (i.e. `from_user`), and `project_admin` is granted to the list of recipients (i.e. `to_users`) + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden +* 404: Project transfer does not exist + ++ Parameters + + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. + ++ Request (application/json) + + { + "status_comment": "This data looks great..." + } + ++ Response 200 (application/json) + + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "accepted", + "status_comment": "This data looks great...", + "audit": { } + } + +## Reject a project transfer [PUT /project_transfers/{id}/reject] +Reject a *pending* project transfer. +>**Permission:** transfer recipient (i.e. in `to_users`)] +- - - - - + +>**Properties** +- - - - - ++ **status_comment (string, optional)** - An optional comment that can be provided. + +>**Rules:** +- - - - - ++ The project transfer must be in a `pending` state. + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden +* 404: Project transfer does not exist + ++ Parameters + + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. + ++ Request (application/json) + + { + "status_comment": "Missing alignment files..." + } + ++ Response 200 (application/json) + + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "rejected", + "status_comment": "Missing alignment files...", + "audit": { } + } + +## Cancel a project transfer [PUT /project_transfers/{id}/cancel] +Cancel a *pending* project transfer. +>**Permission:** manage_project_permissions +- - - - - + +>**Properties** +- - - - - ++ **status_comment (string, optional)** - An optional comment that can be provided. + +>**Rules:** +- - - - - ++ The project transfer must be in a `pending` state. + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden +* 404: Project transfer does not exist + ++ Parameters + + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. + ++ Request (application/json) + + { + "status_comment": "Sent to the wrong PI..." + } + ++ Response 200 (application/json) + + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "canceled", + "status_comment": "Sent to the wrong PI...", + "audit": { } + } + +## View All Project Transfers [/project_transfers{?status}] ++ Parameters + + status (string, optional, `pending`) ... The `status` of the project transfer; can be one of `pending`,`accepted`, or `canceled`. + +### View All Project Transfers [GET] +Used to retrieve all project transfers visible to the current user, optionally filtered by status. +>**Permission:** authenticated [scope: manage_project_permissions, transfer initiator (i.e. `from_user`), or a transfer recipient (i.e. in `to_users`)] +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Unsupported status + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "from_user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "to_users": [ + { + "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", + "username": "cbrandon01", + "full_name": "Chad Brandon" + } + ], + "status": "pending", + "status_comment": null, + "audit": { } + } + ] + } diff --git a/api_docs/folders_files.apib b/api_docs/folders_files.apib new file mode 100644 index 000000000..922348241 --- /dev/null +++ b/api_docs/folders_files.apib @@ -0,0 +1,1511 @@ +FORMAT: 1A + +# Folder and File Resources + +## Group << API Summary + +## Group Storage Providers +Represents an external service that provides physical storage space for files. + +## Storage Providers collection [/storage_providers] + +### List storage providers [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage", + "chunk_hash_algorithm": "md5", + "is_deprecated": false + }, + { + "id": "t4479f73-0774-4f96-afc7-9d251e65by88", + "name": "amazon_s3_glacier", + "description": "Amazon Glacier Cloud Storage", + "chunk_hash_algorithm": "sha1", + "is_deprecated": false + } + ] + } + +## Storage Provider instance [/storage_providers/{id}] ++ Parameters + + id (string, required, `g5579f73-0558-4f96-afc7-9d251e65bv33`) ... The unique `id` of the storage provider. + + +### View storage provider [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: StorageProvider Does not Exist + ++ Response 200 (application/json) + + { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke Office of Information Technology Storage", + "chunk_hash_algorithm": "md5", + "is_deprecated": false + } + +## Group Folders +A folder is a container for files and sub-folders; folders are located in the top-level project root or a parent folder. + +## Folders collection [/folders] + +### Create folder [POST] +>**Permission:** create_file +- - - - - + +>**Request Properties** +- - - - - ++ **parent.kind (string, required)** - The kind of parent container for the folder; this can be a project (i.e. `dds-project`) or a folder (i.e. `dds-folder`). ++ **parent.id (string, required)** - The unique id of the parent. ++ **name (string, required)** - A short name for the folder. + +>**Response Properties** +- - - - - ++ **ancestors (object[ ])** - Represents entire ancestral path, from the root node (project or folder), down to its parent, in hierarchical order. + +**Response messages:** +* 200: This will never happen +* 201: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Project Does not Exist, Parent Folder does not exist in Project + ++ Request (application/json) + + { + "parent": { + "kind": "dds-folder", + "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" + }, + "name": "Raw Data" + } + ++ Response 201 (application/json) + + { + "kind": "dds-folder", + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "Raw Data", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "audit": { } + } + +## Folder instance [/folders/{id}] ++ Parameters + + id (string, required, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... The unique `id` of the folder. + +### View folder [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Folder does not exist + ++ Response 200 (application/json) + + { + "kind": "dds-folder", + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "Raw Data", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "audit": { } + } + +### Delete folder [DELETE] +>**Permission:** delete_file +- - - - - + +>**Rules** +- - - - - ++ This operation recursively deletes all of the folder children (i.e. folders, files and file versions). + +**Response messages:** +* 200: This will never happen +* 204: Successfully Deleted +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Folder does not exist + ++ Response 204 + +## Move folder [PUT /folders/{id}/move] +>**Permission:** create_file +- - - - - + +>**Rules** +- - - - - ++ The destination folder cannot be a child of the folder being moved. + +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Folder does not exist, Parent does not exist. + ++ Parameters + + id (string, required, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... The unique `id` of the folder. + ++ Request (application/json) + + { + "parent": { + "kind": "dds-folder", + "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" + } + } + ++ Response 200 (application/json) + + { + "kind": "dds-folder", + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", + "parent": { + "kind": "dds-folder", + "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" + }, + "name": "Raw Data", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc", + "name": "Flow Core" + } + ], + "is_deleted": false, + "audit": { } + } + +## Rename folder [PUT /folders/{id}/rename] +>**Permission:** create_file +- - - - - +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Folder does not exist + ++ Parameters + + id (string, required, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... The unique `id` of the folder. + ++ Request (application/json) + + { + "name": "Model Data" + } + ++ Response 200 (application/json) + + { + "kind": "dds-folder", + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", + "parent": { + "kind": "dds-folder", + "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" + }, + "name": "Model Data", + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc", + "name": "Flow Core" + } + ], + "is_deleted": false, + "audit": { } + } + +## Group Uploads +All files must be uploaded using a multi-part/chunked upload process. Although this places more burden on clients to divide larger files into chunks and send each chunk separately, the result is a more robust process that allows failed chunks to be resent. The following actions must be used by the client to manage the chunked upload process. + +## Uploads collection [/projects/{id}/uploads] ++ Parameters + + id (required, string, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... Globally unique `id` of the project. + +### Initiate chunked upload [POST] +This is the first step in uploading a large file. An upload objects is created along with a composite status object that can be polled by client agents to track the progress of the chunked upload. +>**Permission:** create_file +- - - - - + +>**Request Properties** +- - - - - ++ **name (string, required)** - The name of the client file to upload. ++ **content_type (string, optional)** - Valid content type per [media types](https://en.wikipedia.org/wiki/Internet_media_type). ++ **size (number, required)** - The size in bytes of entire file (computed by client). + +>**Response Properties** +- - - - - ++ **chunks (object)** - The chunks the client has requested to upload. ++ **storage_location (object)** - Object that contains target storage details. ++ **status (object)** - Object used to track status of overall file upload. + +**Response messages:** +* 200: This will never happen +* 201: Created Successfully +* 401: Unauthorized +* 404: Project Does not Exist + ++ Request (application/json) + + { + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "content_type": "application/octet-stream", + "size": 30024000 + } + ++ Response 201 (application/json) + + { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "content_type": "application/octet-stream", + "size": 30024000, + "hashes": [ ], + "chunks": [ ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", "description": + "Duke OIT Storage" + }, + "status": { + "initiated_on": "2015-07-10T13:00:00Z", + "completed_on": null, + "error_on": null, + "error_message": null + }, + "audit": { } + } + +### List chunked uploads [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project Does not Exist + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "content_type": "application/octet-stream", + "hashes": [ ], + "chunks": [ ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + }, + "status": { + "initiated_on": "2015-07-10T13:00:00Z", + "completed_on": null, + "error_on": null, + "error_message": null + }, + "audit": { } + } + ] + } + +## Upload instance [/uploads/{id}] ++ Parameters + + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. + +### View chunked upload [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Upload does not exist + ++ Response 200 (application/json) + + { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "content_type": "application/octet-stream", + "size": 30024000, + "hashes": [ ], + "chunks": [ + { + "number": 1, + "size": 10000, + "hash": { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5" + } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": + "Duke OIT Storage" + }, + "status": { + "initiated_on": "2015-07-10T13:00:00Z", + "completed_on": null, + "error_on": null, + "error_message": null + }, + "audit": { } + } + +## Get pre-signed chunk URL [PUT /uploads/{id}/chunks] +Generates and returns a pre-signed URL that can be used by client to upload a file chunk to the storage provider. This step is repeated for each chunk. If the chunk uploads fails, the client must call this action again to get a new pre-signed URL for the chunk number, then retry the chunk upload. +>**Permission:** create_file +- - - - - + +>**Request Properties** +- - - - - ++ **number (number, required)** - The chunk number. ++ **size (number, required)** - The size of the chunk in bytes (computed by client). ++ **hash.value (string, required)** - The chunk hash (computed by client). ++ **hash.algorithm (string, required)** - The hash algorithm used (i.e. md5, sha256, sha1, etc.); this must be the default algorithm (i.e. `chunk_hash_algorithm`) supported by storage provider (see **Storage Providers** actions) + +>**Response Properties** +- - - - - ++ **http_verb (string)** - The http verb to use for uploading the next chunk. ++ **host (string)** - The storage provider host. ++ **url (string)** - The pre-signed URL for uploading the chunk to the storage provider. ++ **http_headers (object[ ])** - Array of headers (i.e. key/value pairs) that must be included in the client upload request. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Upload does not exist +* 500: Unexpected StorageProviderException experienced + ++ Parameters + + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. + ++ Request (application/json) + + { + "number": 1, + "size": 5024000, + "hash": { + "value": "ey23df2207d99a74fbe169e3eba035e633b65d76", + "algorithm": "md5" + } + } + ++ Response 200 (application/json) + + { + "http_verb": "PUT", + "host": "duke_data_service_prod.s3.amazonaws.com", + "url": "/666be35a-98e0-4c2e-9a17-7bc009f9bb23?partNumber=1&uploadId=EXAMPLEJZ6e0YupT2...&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN...", + "http_headers": [ + { "Content-Length": "5024000" } + ] + } + +## Complete chunked file upload [PUT /uploads/{id}/complete] +This operation is called by the client after all file chunks have been successfully uploaded to the storage provider. +>**Permission:** create_file +- - - - - + +>**Properties** +- - - - - ++ **hash.value (string, required)** - The entire file hash (computed by client). ++ **hash.algorithm (string, required)** - The algorithm used by client to compute entire file hash (i.e. md5, sha256, sha1, etc.). + +>**Rules** +- - - - - ++ If the storage provider requires the individual chunks to be assembled, such as Amazon S3, this operation will call the storage provider actions to assemble the parts into a single file object. ++ The reported `hash.value` must be a valid algorithm - supported/valid algorithms are: `md5`, `sha256`, and `sha1`. ++ The client hash for each chunk must equal the storage provider hash for the same chunk, or an upload error is reported. ++ The client reported file size (bytes) must equal the storage provider reported file size, or an upload error is reported. ++ If there are no errors, the `upload_status.completed_on` is set to the current timestamp. + +**Response messages:** +* 200: Success +* 400: IntegrityException: reported file size or chunk hashes do not match that computed by StorageProvider +* 401: Unauthorized +* 404: Upload does not exist +* 500: Unexpected StorageProviderException experienced + ++ Parameters + + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. + ++ Request + + { + "hash": { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5" + } + } + ++ Response 200 (application/json) + + { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "content_type": "application/octet-stream", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "chunks": [ + { + "number": 1, + "size": 5024000, + "hash": { + "value": "jw23df2207d99a74fbe169e3eba035e633b65d88", + "algorithm": "md5" + } + }, + { + "number": 2, + "size": 5024000, + "hash": { + "value": "ry23df2207d99a74fbe169e3eba035e633b65dkq", + "algorithm": "md5" + } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + }, + "status": { + "initiated_on": "2015-07-10T13:00:00Z", + "completed_on": "2015-07-10T13:00:00Z", + "error_on": null, + "error_message": null + }, + "audit": { } + } + +## Report upload hash [PUT /uploads/{id}/hashes] +Report a hash (fingerprint) for the uploaded file. +>**Permission:** update_file +- - - - - + +>**Properties** +- - - - - ++ **value (string, required)** - The entire file hash (computed by client). ++ **algorithm (string, required)** - The algorithm used by client to compute entire file hash (i.e. md5, sha256, sha1, etc.). + +>**Rules** +- - - - - ++ The reported `value` must be a valid algorithm - supported/valid algorithms are: `md5`, `sha256`, and `sha1`. ++ The upload must be in a completed state (i.e. `upload_status.completed_on`). + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 404: Upload does not exist +* 500: Unexpected StorageProviderException experienced + ++ Parameters + + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. + ++ Request + + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5" + } + ++ Response 200 (application/json) + + { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "content_type": "application/octet-stream", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "chunks": [ + { + "number": 1, + "size": 5024000, + "hash": { + "value": "jw23df2207d99a74fbe169e3eba035e633b65d88", + "algorithm": "md5" + } + }, + { + "number": 2, + "size": 5024000, + "hash": { + "value": "ry23df2207d99a74fbe169e3eba035e633b65dkq", + "algorithm": "md5" + } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + }, + "status": { + "initiated_on": "2015-07-10T13:00:00Z", + "completed_on": "2015-07-10T13:00:00Z", + "error_on": null, + "error_message": null + }, + "audit": { } + } + +## Group Files +A file resource represents a virtual container for a physical data file (i.e. `upload`) that is persisted in a storage backend supported by Duke Data Services (e.g. Duke OIT Swift Service). + +## Files collection [/files] + +### Create file [POST] +Creates a file metadata resource; the client is responsible for the creation of this resource after confirming the associated physical file has been successfully uploaded to a storage provider (see `Uploads` actions). + +*Note: A file is a versionable resource; this action creates the initial version of a file. New file versions can be created (uploaded) via the* `/file/{id}/update` *action. Versions can be managed via the* **File Versions** *actions.* + +>**Permission:** create_file +- - - - - + +>**Properties** +- - - - - ++ **parent.kind (string, required)** - The kind of parent container for the file; this can be a project (i.e. `dds-project`) or a folder (i.e. `dds-folder`). ++ **parent.id (string, required)** - The unique id of the parent. ++ **upload.id (string, required)** - The unique id for an upload that completed successfully. ++ **label (string, optional)** - An optional version label for the file. + +>**Rules** +- - - - - ++ The current user must be the user who uploaded the file. ++ The parent object (`dds-project` or `dds-folder`) must be associated with the same project that the upload is associated with. ++ The upload must be in a completed state (i.e. `upload.completed_on != null`). + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Upload has an IntegrityException +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Project Does not Exist, Parent Folder or Upload does not exist in Project + ++ Request (application/json) + + { + "parent": { + "kind": "dds-folder", + "id": "ad9115b8-1e4a-4399-b606-56622eb462e1" + }, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23" + }, + "label": "Initial raw data from device" + } + ++ Response 201 (application/json) + + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 1, + "label": "Initial raw data from device", + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + +## File instance [/files/{id}] ++ Parameters + + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. + +### View file [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Response 200 (application/json) + + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 1, + "label": "Initial raw data from device", + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + +### Update file [PUT] +Updates one or more file resource properties; if this action includes an `upload.id` property in the request, a new file version is created and associated to the file - this becomes the `current_version` of the file (see **File Versions**). + +*Note: Only the* `upload` *and* `label` *properties for the file are versioned; all other file properties and relationships, such as name, tags, metadata properties, etc. are not versioned, and they will not vary from version to version.* + +>**Permission:** update_file +- - - - - + +>**Properties** +- - - - - ++ **upload.id (string, optional)** - An optional unique id for an upload that completed successfully; if specified, a new file version is created. ++ **label (string, optional)** - An optional version label for the file. + +>**Rules** +- - - - - ++ The current user must be the user who uploaded the file. ++ The upload must be in a completed state (i.e. `upload.completed_on != null`). ++ Only `upload.id`, `label` properties can be updated via this action. ++ New versions are assigned the next sequential `version` number. (see **File Versions**) + +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Request (application/json) + + { + "upload": { + "id": "422f8778-a62c-4918-8b1b-f398a041345a" + }, + "label": "Post pairwise sequence alignment" + } + ++ Response 200 (application/json) + + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", + "name": "Sequencing Archive" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 2, + "label": "Post pairwise sequence alignment", + "upload": { + "id": "56a0431f-5a89-455a-aa2d-996ae9226601", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + +### Delete file [DELETE] +>**Permission:** delete_file +- - - - - + +>**Rules** +- - - - - ++ This operation recursively deletes all the related file versions. + +**Response messages:** +* 200: This will never happen +* 204: Successfully Deleted +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Response 204 + +## Get file download URL [GET /files/{id}/url] +Generates and returns a storage provider specific pre-signed URL that client can use to download file; the download URL is for the current version of the specified file. + +*Note: This action returns URL to download current version of the file - to download a prior version see* **File Versions** *actions.* + +>**Permission:** download_file +- - - - - +**Response messages:** +* 200: Success +* 301: Redirect to file +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Parameters + + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. + ++ Response 200 (application/json) + + { + "http_verb": "GET", + "host": "swift.oit.duke.edu", + "url": "/v1/AUTH_dev/418da9e8-7d01-4761-982c-811d95ac6653/0618a1bc-5042-48d2-af66-ed171354bf6b?temp_url_sig=93b5c5a2c920f0d4962c391d932e4054ec76916c&temp_url_expires=1448918738", + "http_headers": [ ] + } + +## Move file [PUT /files/{id}/move] +Move file to a different parent project or parent folder. + +>**Permission:** create_file +- - - - - +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist, Parent does not exist in Project + ++ Parameters + + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. + ++ Request (application/json) + + { + "parent": { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" + } + } + ++ Response 200 (application/json) + + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", + "name": "Sequencing Archive" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 2, + "label": "Post pairwise sequence alignment", + "upload": { + "id": "56a0431f-5a89-455a-aa2d-996ae9226601", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + +## Rename file [PUT /files/{id}/rename] +Change the name of a file. + +>**Permission:** update_file +- - - - - +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Parameters + + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. + + ++ Request (application/json) + + { + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata" + } + ++ Response 200 (application/json) + + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", + "name": "Sequencing Archive" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 2, + "label": "Post pairwise sequence alignment", + "upload": { + "id": "56a0431f-5a89-455a-aa2d-996ae9226601", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + +## Group File Versions +The actions herein are used to interact with prior versions of a file resource. + +*Note: Only the* `upload` *and* `label` *properties for the file are versioned; all other file properties and relationships, such as name, tags, etc. are not versioned, and they will not vary from version to version.* + +## File Versions collection [/files/{id}/versions] ++ Parameters + + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. + +### List file versions [GET] +This action can be used to list all prior versions of a file, including the current version. + +>**Permission:** view_project +- - - - - + +>**Rules** +- - - - - ++ File versions that have been deleted (i.e. `"is_deleted": true`) are included in this listing, but are immutable. + +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Response 200 (application/json) + + { + "results": [ + { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Initial raw data from device", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + } + ] + } + +## File Version instance [/file_versions/{id}] ++ Parameters + + id (string, required, `89ef1e77-1a0b-40a8-aaca-260d13987f2b`) ... The unique `id` of the file version. + +### View file version [GET] +>**Permission** view_project +- - - - - +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Response 200 (application/json) + + { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Initial raw data from device", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + } + +### Update file version [PUT] +>**Permission:** update_file +- - - - - + +>**Rules** +- - - - - ++ Only the `label` property for a file version can be updated via this action. + +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File does not exist + ++ Request (application/json) + + { + "label": "Post pairwise sequence alignment (piecewise)" + } + ++ Response 200 (application/json) + + { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Post pairwise sequence alignment (piecewise)", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + } + +### Delete file version [DELETE] +>**Permission:** delete_file +- - - - - + +>**Rules** +- - - - - ++ The current file version cannot be deleted. + +**Response messages:** +* 200: This will never happen +* 204: Successfully Deleted +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File version does not exist + ++ Response 204 + +## Get file version download URL [GET /file_versions/{id}/url] +Generates and returns a storage provider specific pre-signed URL that client can use to download the file version. +>**Permission:** download_file +- - - - - +**Response messages:** +* 200: Success +* 301: Redirect to file version +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File version does not exist + ++ Parameters + + id (string, required, `89ef1e77-1a0b-40a8-aaca-260d13987f2b`) ... The unique `id` of the file version. + ++ Response 200 (application/json) + + { + "http_verb": "GET", + "host": "swift.oit.duke.edu", + "url": "/v1/AUTH_dev/418da9e8-7d01-4761-982c-811d95ac6653/0618a1bc-5042-48d2-af66-ed171354bf6b?temp_url_sig=93b5c5a2c920f0d4962c391d932e4054ec76916c&temp_url_expires=1448918738", + "http_headers": [ ] + } + +## Promote file version [POST /file_versions/{id}/current] +This action can be used to promote a prior file version to the current version. This actually mints a copy of the specified version and puts it on the top of the version stack. +>**Permission:** update_file +- - - - - + +>**Rules** +- - - - - ++ The current file version cannot be promoted. + +**Response messages:** +* 201: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: File version does not exist + ++ Parameters + + id (string, required, `89ef1e77-1a0b-40a8-aaca-260d13987f2b`) ... The unique `id` of the file version to be promoted to the current version. + ++ Response 201 (application/json) + + { + "kind": "dds-file-version", + "id": "66ed147e-2312-4974-999a-58ec77230182", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 3, + "label": "Post pairwise sequence alignment (piecewise)", + "is_deleted": false, + "upload": { + "id": "56a0431f-5a89-455a-aa2d-996ae9226601", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + } + +## Group Search Children +Search for the children (i.e. folders and files) of a project or folder. + +## Search project children [GET /projects/{id}/children{?name_contains,kind}] +>**Permission:** view_project +- - - - - + +>**Rules** +- - - - - ++ Searches the immediate children of the project unless the `name_contains` parameter is specified; when specified, the `name_contains` parameter invokes a recursive search of the project hierarchy. ++ Folders/files that have been deleted (i.e. `"is_deleted": true`) are not included in search. + +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Project does not exist + ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. + + name_contains (string, optional, `Sequencing`) ... Returns children where their `name` contains the specified string. + + kind (string, optional, `dds-folder`) ... Returns children of the specified kind; supported kinds are `dds-folder` and `dds-file`. + ++ Response 200 (application/json) + + { + "results": [ + { + "kind": "dds-folder", + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "Raw Data", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "audit": { } + }, + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", + "name": "Sequencing Archive" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 1, + "label": "Initial raw data from device", + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + ] + } + +## Search folder children [GET /folders/{id}/children{?name_contains,kind}] +>**Permission:** view_project +- - - - - + +>**Rules** +- - - - - ++ Searches the immediate children of the folder unless the `name_contains` parameter is specified; when specified, the `name_contains` parameter invokes a recursive search of the folder hierarchy. ++ Folders/files that have been deleted (i.e. `"is_deleted": true`) are not included in search. + +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Folder does not exist + ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the folder. + + name_contains (string, optional, `Sequencing`) ... Returns children where their `name` contains the specified string. + + kind (string, optional, `dds-folder`) ... Returns children of the specified kind; supported kinds are `dds-folder` and `dds-file`. + ++ Response 200 (application/json) + + { + "results": [ + { + "kind": "dds-folder", + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "Raw Data", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "audit": { } + }, + { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "parent": { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" + }, + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", + "name": "Sequencing Archive" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 1, + "label": "Initial raw data from device", + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { } + } + ] + } diff --git a/api_docs/metadata.apib b/api_docs/metadata.apib new file mode 100644 index 000000000..6b5fc967c --- /dev/null +++ b/api_docs/metadata.apib @@ -0,0 +1,720 @@ +FORMAT: 1A + +# Metadata Resources + +## Group << API Summary + +## Group Tags +A tag is a label (i.e. word or phrase) that can be associated to an object to facilitate classification and searching. + +*Note: Tags are composite metadata that become part of the tagged resource - they do not live in a global namespace. Only tagging of files* (i.e. `dds-file`) *is currently supported.* + +## Tags collection [/tags/{object_kind}/{object_id}] ++ Parameters + + object_kind (string, required, `dds-file`) ... The kind of object. + + object_id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique id of the object. + +### Create object tag [POST] +>**Permission:** update_file when tagged object is file (`dds-file`) +- - - - - + +>**Properties** +- - - - - ++ **label (string, required)** - The textual tag content. + +>**Rules:** +- - - - - ++ The specified `label` must not already exist for the `(object.kind, object.id)`, the `label` comparison is *case-insensitive*. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Tag requires a label +* 401: Unauthorized +* 404: Tag does not exist + ++ Request (application/json) + + { + "label": "SMRT sequencing" + } + ++ Response 201 (application/json) + + { + "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", + "object": { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111" + }, + "label": "SMRT sequencing", + "audit": { } + } + +### List object tags [GET] +>**Permission:** view_project when tagged object is file (`dds-file`) +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", + "object": { + "kind": "dds-file", "id": + "777be35a-98e0-4c2e-9a17-7bc009f9b111" + }, + "label": "SMRT sequencing", + "audit": { } + } + ] + } + +## Append a list of object tags [POST /tags/{object_kind}/{object_id}/append] +Append a list of tags to an object. +>**Permission:** update_file when tagged object is file (`dds-file`) +- - - - - + +>**Properties** +- - - - - ++ **tags (object[], required)** - An array of tags to apply to the object; object structure is as follows: ++ **label (string, required)** - The textual tag content. + +>**Rules:** +- - - - - ++ If the object has an exisiting tag with the specified `label`, the `label` is ignored and a tag is not appended (i.e. created); the `label` comparison is *case-insensitive*. ++ The request must specify at least one `label`. ++ The response only contains the list of `tags` that were appended (i.e. created). + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Tag requires a label +* 401: Unauthorized +* 404: Tag does not exist + ++ Parameters + + object_kind (string, required, `dds-file`) ... The kind of object. + + object_id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique id of the object. + ++ Request (application/json) + + { + "tags": [ + {"label": "SMRT sequencing"} + ] + } + ++ Response 201 (application/json) + + { + "results": [ + { + "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", + "object": { + "kind": "dds-file", "id": + "777be35a-98e0-4c2e-9a17-7bc009f9b111" + }, + "label": "SMRT sequencing", + "audit": { } + } + ] + } + +## List tag labels [GET /tags/labels{?object_kind,label_contains}] +Get a list of the **distinct** tag `label` values visible to the current user. + +*Note: Intent of this action is to allow Web and native UX apps to render tag clouds and enable auto-complete widgets.* + +>**Permission:** authenticated [scope: view_project when tagged object is file (`dds-file`)] +- - - - - + +>**Rules:** +- - - - - ++ The returned tags are sorted in most recently used (i.e. `last_used_on`) order. + +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Parameters + + object_kind (string, optional, `dds-file`) ... Restricts search scope to tags for this kind of object. + + label_contains (string, optional, `sequen`) ... If provided, searches for tags that contain this text fragment. + ++ Response 200 (application/json) + + { + "results": [ + { + "label": "SMRT sequencing", + "count": 47, + "last_used_on": "2015-01-01T12:10:00Z" + }, + { + "label": "Polony sequencing", + "count": 21, + "last_used_on": "2015-01-01T12:05:00Z" + }, + { + "label": "DNA nanoball sequencing", + "count": 13, + "last_used_on": "2015-01-01T12:00:00Z" + } + ] + } + +## Tag instance [/tags/{id}] ++ Parameters + + id (string, required, `66211c4e-a49e-42d7-9793-87989d56e1e3`) ... The unique id of the tag. + +### View tag [GET] +>**Permission:** view_project when tagged object is file (`dds-file`) +- - - - - +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Tag does not exist + ++ Response 200 (application/json) + + { + "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", + "object": { + "kind": "dds-file", + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111" }, + "label": "SMRT sequencing", + "audit": { } + } + +### Delete tag [DELETE] +>**Permission:** update_file when tagged object is file (`dds-file`) +- - - - - + +**Response messages:** +* 204: Successfully Deleted +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Tag does not exist + ++ Response 204 + +## Group Metadata +The metadata actions allow researchers to define, store, and associate custom attributes with their digital assets (e.g. activities, files, etc.). Unlike *Tags*, which are just textual labels, metadata are structured `key:value` pairs. For example, an experiment (i.e. represented as a provenance *Activity*) may have the following metadata properties: `[{"assay": "ChIP-seq"}, {"organism": "Mus Musculus"}, {"biosample_type": "tissue"}]`. + +Metadata must be defined and captured in the context of a metadata template. Templates allow related keys (i.e. properties) to be grouped together. For example, a template named *seq_platform_info* may contain properties that describe the characteristics of the sequencing platform. In addition, templates enforce data type (i.e. string, integer, etc.) integrity for the contained keys, so that clients are type aware when referencing key values from a search or data processing perspective. Metatdata templates are global in scope and visible to all users. + +## Metadata Templates collection [/templates] + +### Create metadata template [POST] +>**Permission:** authenticated +- - - - - + +>**Properties** +- - - - - ++ **name (string, required)** - The unique name of the template; the name must meet the following criteria: + - contain only alphanumerics and underscores + - no whitespace + - maximum of 60 characters ++ **label (string, required)** - A short display label for the template. ++ **description (string, optional)** - A verbose description of the template. + +>**Rules:** +- - - - - ++ The template `name` must be unique in the global context. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Validation Error +* 401: Unauthorized + ++ Request (application/json) + + { + "name": "sequencing_file_info", + "label": "Sequencing File Info", + "description": "Extended attributes for sequencing output files." + } + ++ Response 201 (application/json) + + { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info", + "label": "Sequencing File Info", + "description": "Extended attributes for sequencing output files.", + "audit": { } + } + +## List metadata templates [GET /templates{?name_contains}] +List all of the global metadata templates. +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Parameters + + name_contains (string, optional, `Sequencing`) ... Returns templates in which `name` contains the specified string. + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info", + "label": "Sequencing File Info", + "description": "Extended attributes for sequencing output files.", + "audit": { } + } + ] + } + +## Metadata Template instance [/templates/{id}] ++ Parameters + + id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique `id` of the template. + + +### View metadata template [GET] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden (template restricted) +* 404: Template does not exist + ++ Response 200 (application/json) + + { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info", + "label": "Sequencing File Info", + "description": "Extended attributes for sequencing output files (raw and processed).", + "audit": { } + } + +### Update metadata template [PUT] +>**Permission:** creator or system_admin +- - - - - + +>**Rules** +- - - - - ++ The `name` cannot be updated if the template has been associated to one or more DDS objects. + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden (template restricted) +* 404: Template does not exist + ++ Request (application/json) + + { + "description": "Extended attributes for sequencing output files (raw and processed)." + } + ++ Response 200 (application/json) + + { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info", + "label": "Sequencing File Info", + "description": "Extended attributes for sequencing output files (raw and processed).", + "audit": { } + } + +### Delete metadata template [DELETE] +>**Permission:** creator or system_admin +- - - - - + +>**Rules** +- - - - - ++ The template cannot be deleted if it has been associated to one or more DDS objects. + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden (template restricted) +* 404: Template does not exist + ++ Response 204 + +## Metadata Properties collection [/templates/{id}/properties] ++ Parameters + + id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique `id` of the template. + +### Create metadata property [POST] +>**Permission:** template creator or system_admin +- - - - - + +>**Properties** +- - - - - ++ **key (string, required)** - The unique key for the property; the key must meet the following criteria: + - contain only alphanumerics and underscores + - no whitespace + - maximum of 60 characters ++ **label (string, required)** - A short display label for the property. ++ **description (string, required)** - A verbose description of the property. ++ **type (string, required)** - The datatype of the key's value; currenty only the Elasticsearch core datatypes are supported: [Elasticsearch Core Datatypes](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html). + +>**Rules:** +- - - - - ++ The property `key` must be unique within the context of the template. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Validation Error +* 401: Unauthorized + ++ Request (application/json) + + { + "key": "output_type", + "label": "Output Type", + "description": "The type of data in the sequencing output file.", + "type": "string" + } + ++ Response 201 (application/json) + + { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "key": "output_type", + "label": "Output Type", + "description": "The type of data in the sequencing output file.", + "type": "string", + "audit": { } + } + +## List metadata properties [GET /templates/{id}/properties] +List metadata template properties. +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Parameters + + id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique `id` of the template. + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "key": "output_type", + "label": "Output Type", + "description": "The type of data in the sequencing output file.", + "type": "string", + "audit": { } + } + ] + } + +## Metadata Property instance [/template_properties/{id}] ++ Parameters + + id (string, required, `48d34c8f-4284-4327-9ca6-7a9145a1c957`) ... The unique `id` of the template property. + + +### View metadata property [GET] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden (property restricted) +* 404: Property does not exist + ++ Response 200 (application/json) + + { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "key": "output_type", + "label": "Output Type", + "description": "The type of data in the sequencing output file. (alignments, peaks, signal)", + "type": "string", + "audit": { } + } + +### Update metadata property [PUT] +>**Permission:** creator or system_admin +- - - - - + +>**Rules** +- - - - - ++ The `key` or `type` cannot be updated if the template property has been associated to one or more DDS objects. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden (template property restricted) +* 404: Property does not exist + ++ Request (application/json) + + { + "description": "The type of data in the sequencing output file. (alignments, peaks, signal)" + } + + ++ Response 200 (application/json) + + { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "key": "output_type", + "label": "Output Type", + "description": "The type of data in the sequencing output file. (alignments, peaks, signal)", + "type": "string", + "audit": { } + } + +### Delete metadata property [DELETE] +>**Permission:** creator or system_admin +- - - - - + +>**Rules** +- - - - - ++ The template property cannot be deleted if it is assigned to one or more DDS objects. + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden (template property restricted) +* 404: Template property does not exist + ++ Response 204 + +## Object Metadata instance [/meta/{object_kind}/{object_id}/{template_id}] ++ Parameters + + object_kind (string, required, `dds-file`) ... The kind of object. + + object_id (string, required, `b80a2679-f6bf-46da-acaa-b7a4582b1eda`) ... The unique id of the object. + + template_id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique id of the template. + +### Create object metadata [POST] +Used to create a metadata template instance for a corresponding DDS object (i.e. `dds-file`). When creating metadata, only values that adhere to the metadata template schema will be accepted. +>**Permission:** update_file when annotated object is file (`dds-file`) +- - - - - + +>**Properties** +- - - - - ++ **properties (object[ ], required)** - A list of the `key:value` pairs to set for the template instance. ++ **properties[ ].key (string, required)** - The property key to set. ++ **properties[ ].value (any, required)** - The key value. + +>**Rules:** +- - - - - ++ All specified `key:values` must adhere to the metadata template schema or a validation error will be returned. ++ If the template instance already exists for the DDS object, a validation (unique conflict) error will be returned and the update method should be used. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Validation Error +* 401: Unauthorized +* 404: Object or template does not exist +* 409: Template instance already exists for the DDS object + ++ Request (application/json) + + { + "properties": [ + { + "key": "output_type", + "value": "alignments" + } + ] + } + ++ Response 201 (application/json) + + { + "object": { + "kind": "dds-file", + "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" + }, + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "properties": [ + { + "template_property": { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "key": "output_type" + }, + "value": "alignments" + } + ] + } + +### View object metadata [GET] +Used to retrieve the metadata template instance for a corresponding DDS object. +>**Permission:** authenticated [scope: view_project when annotated object is file (`dds-file`)] +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden +* 404: Object or template does not exist + ++ Response 200 (application/json) + + { + "object": { + "kind": "dds-file", + "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" + }, + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "properties": [ + { + "template_property": { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "key": "output_type" + }, + "value": "alignments" + } + ] + } + +### Update object metadata [PUT] +Used to update a metadata template instance for a corresponding DDS object (i.e. `dds-file`). When updating metadata, only values that adhere to the metadata template schema will be accepted. +>**Permission:** update_file when annotated object is file (`dds-file`) +- - - - - + +>**Properties** +- - - - - ++ **properties (object[ ], required)** - A list of the `key:value` pairs to set for the template instance. ++ **properties[ ].key (string, required)** - The property key to set. ++ **properties[ ].value (any, required)** - The key value. + +>**Rules:** +- - - - - ++ All specified `key:values` must adhere to the metadata template schema or a validation error will be returned. ++ If the specified `key` already exists, the value is updated, otherwise it is appended to the template instance. ++ If the template instance specified does not exist, a validation error will be returned and the create method should be used. + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden +* 404: Object or template does not exist + ++ Request (application/json) + + { + "properties": [ + { + "key": "output_type", + "value": "peaks" + } + ] + } + ++ Response 200 (application/json) + + { + "object": { + "kind": "dds-file", + "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" + }, + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "properties": [ + { + "template_property": { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "key": "output_type" + }, + "value": "peaks" + } + ] + } + +### Delete object metadata [DELETE] +Used to delete the metadata template instance. +>**Permission:** update_file when annotated object is file (`dds-file`) +- - - - - + +**Response messages:** +* 200: This will never happen +* 204: Successfully Deleted +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: Object or template does not exist + ++ Response 204 + +## View All Object Metadata [/meta/{object_kind}/{object_id}] ++ Parameters + + object_kind (string, required, `dds-file`) ... The kind of object. + + object_id (string, required, `b80a2679-f6bf-46da-acaa-b7a4582b1eda`) ... The unique id of the object. + +### View All Object Metadata [GET] +Used to retrieve all metadata associated with a DDS object, optionally find a template instance by name. +>**Permission:** authenticated [scope: view_project when annotated object is file (`dds-file`)] +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Object or template does not exist + ++ Response 200 (application/json) + + { + "results": [ + { + "object": { + "kind": "dds-file", + "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" + }, + "template": { + "id": "168f3f51-6800-403a-973d-78b23c08049b", + "name": "sequencing_file_info" + }, + "properties": [ + { + "template_property": { + "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", + "key": "output_type" + }, + "value": "alignments" + } + ] + } + ] + } diff --git a/api_docs/projects.apib b/api_docs/projects.apib new file mode 100644 index 000000000..6d548c943 --- /dev/null +++ b/api_docs/projects.apib @@ -0,0 +1,458 @@ +FORMAT: 1A + +# Project Resources + +## Group << API Summary + +## Group Projects +Represents a container for storing, organizing, retrieving and sharing research data files and their associated metadata. + +## Projects collection [/projects] + +### Create project [POST] +>**Permission:** authenticated +- - - - - + +>**Rules** +- - - - - ++ User who creates project is granted the `project_admin` authorization role. + +**Response messages:** +* 200: This will never happen +* 201: Created Successfully +* 400: Project Name Already Exists +* 401: Unauthorized +* 404: Project Does not Exist + ++ Request (application/json) + + { + "name": "Knockout Mouse Project (KOMP)", + "description": "Goal of generating a targeted knockout mutation..." + } + ++ Response 201 (application/json) + + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)", + "description": "Goal of generating a targeted knockout mutation...", + "is_deleted": false, + "audit": { } + } + +### List projects [GET] +>**Permission:** authenticated [scope: view_project] +- - - - - + +>**Rules** +- - - - - ++ Projects that have been deleted (i.e. `"is_deleted": true`) are not included. + +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Response 200 (application/json) + + { + "results": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)", + "description": "Goal of generating a targeted knockout mutation...", + "is_deleted": false, + "audit": { } + } + ] + } + +## Project instance [/projects/{id}] ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. + + +### View project [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden +* 404: Project does not exist + ++ Response 200 + + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)", + "description": "Goal of generating a targeted knockout mutation...", + "is_deleted": false, + "audit": { } + } + +### Update project [PUT] +>**Permission:** update_project +- - - - - + +>**Rules** +- - - - - ++ Only `name` and `description` properties may be updated via this action. + +**Response messages:** +* 200: Success +* 400: Project Name Already Exists +* 401: Unauthorized +* 403: Forbidden +* 404: Project Does not Exist + ++ Request (application/json) + + { + "name": "Knockout Mouse Project (KOMP)", + "description": "Goal of generating a targeted knockout mutation..." + } + ++ Response 200 + + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", + "name": "Knockout Mouse Project (KOMP)", + "description": "Goal of generating a targeted knockout mutation...", + "is_deleted": false, + "audit": { } + } + +### Delete project [DELETE] +>**Permission:** delete_project +- - - - - + +>**Rules** +- - - - - ++ This operation recursively deletes all of the project children (i.e. folders,files and file versions). + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden +* 404: Project Does not Exist + ++ Response 204 + +## NOT_IMPL_NEW Project usage [GET /projects/{id}/usage] +View summary usage for the project. + +>**Permission:** view_project +- - - - - + +>**Properties** +- - - - - ++ **member_count (number)** - Total number of users granted a project level permission. ++ **file_count (integer)** - Total number of files contained in the project. ++ **storage_bytes (integer)** - Total bytes for all files contained in the project. + +>**Rules** +- - - - - ++ Deleted objects (i.e. `"is_deleted": true`) are excluded from all counts/totals. + +**Response messages:** +* 200: Success + ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. + ++ Response 200 (application/json) + + { + "member_count": 10, + "file_count": 126, + "storage_bytes": 804006007009 + } + +## Group Project Member Permissions +Represents project level authorization roles that have been granted to a user. + +## Project Permissions collection [/projects/{id}/permissions] ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. + +### List project permissions [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project Does not Exist + ++ Response 200 (application/json) + + { + "results": [ + { + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "auth_role": { + "id": "file_editor", + "name": "File Editor", + "description": "Can view, download, create, update and delete files" + } + } + ] + } + +## Project Permission instance [/projects/{project_id}/permissions/{user_id}] ++ Parameters + + project_id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique id of the project. + + user_id (string, required, `c1179f73-0558-4f96-afc7-9d251e65b7bb`) ... The unique id of the user. + +### Grant project permission [PUT] +>**Permission:** manage_project_permissions +- - - - - + +>**Rules** +- - - - - ++ Revokes any existing project level authorization role for the user and grants the new role. ++ The role specified must be a project level authorization role (i.e. `project` in `auth_role.contexts`). ++ The current user cannot grant or revoke their own project level role. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project or User Does not Exist + ++ Request (application/json) + + { + "auth_role": {"id": "file_editor"} + } + ++ Response 200 + + { + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "auth_role": { + "id": "file_editor", + "name": "File Editor", + "description": "Can view, download, create, update and delete files" + } + } + +### View project permission [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project or User Does not Exist + ++ Response 200 + + { + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "full_name": "Matthew Gardner" + }, + "auth_role": { + "id": "file_editor", + "name": "File Editor", + "description": "Can view, download, create, update and delete files" + } + } + +### Revoke project permission [DELETE] +>**Permission:** manage_project_permissions +- - - - - + +>**Rules** +- - - - - ++ The project must have at least one user with the `project_admin` role. ++ The current user cannot revoke their own project level role. + +**Response messages:** +* 200: This will never happen +* 204: Successfully Deleted +* 401: Unauthorized +* 404: Project, User or Authrole Does not Exist + ++ Response 204 + +## Group Project Roles +Represents an organizational role that an individual (i.e. user) may assume in the context of a project. These organizational roles have no relationship to authorization roles. + +**Project Roles:** + +| role | name | description | +|:-----|:-----|:------------| +| **principal_investigator** | Principal Investigator | Lead investigator for the research project | +| **research_coordinator** | Research Coordinator | Coordinator for the research project | + +## Project Roles collection [/project_roles] + +### List project roles [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "principal_investigator", + "name": "Principal Investigator", + "description": "Lead investigator for the research project", + "is_deprecated": false + }, + { + "id": "research_coordinator", + "name": "Research Coordinator", + "description": "Coordinator for the research project", + "is_deprecated": false + } + ] + } + +## Project Role instance [/project_roles/{id}] ++ Parameters + + id (string, required, `principal_investigator`) ... The unique `id` for a project role. + +### View project role [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Unknown ProjectRole + ++ Response 200 (application/json) + + { + "id": "principal_investigator", + "name": "Principal Investigator", + "description": "Lead investigator for the research project", + "is_deprecated": false + } + +### Group Project Affiliates +Represents an individual that plays some project level role of interest from a collaboration perspective. The affiliate must be a registered user. + +## Affiliates collection [/projects/{id}/affiliates] ++ Parameters + + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. + +### List affiliates [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project Does not Exist + ++ Response 200 (application/json) + + { + "results": [ + { + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu" + }, + "project_role": { + "id": "principal_investigator", + "name": "Principal Investigator" + } + } + ] + } + +## Affiliate instance [/projects/{project_id}/affiliates/{user_id}] ++ Parameters + + project_id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique id of the project. + + user_id (string, required, `c1179f73-0558-4f96-afc7-9d251e65b7bb`) ... The unique id of the user. + +### Associate affiliate [PUT] +>**Permission:** update_project +- - - - - + +>**Rules** +- - - - - ++ Deletes any existing project role for the user and assigns new role. + +**Response messages:** +* 200: Success +* 400: Project Name Already Exists +* 401: Unauthorized +* 404: Project Does not Exist + ++ Request (application/json) + + { + "project_role": {"id": "principal_investigator"} + } + ++ Response 200 + + { + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu" + }, + "project_role": { + "id": "principal_investigator", + "name": "Principal Investigator" + } + } + +### View affiliate [GET] +>**Permission:** view_project +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Project Does not Exist + ++ Response 200 + + { + "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, + "user": { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu" + }, + "project_role": { + "id": "principal_investigator", + "name": "Principal Investigator" + } + } + +### Delete affiliate [DELETE] +>**Permission:** update_project +- - - - - +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 404: Project Does not Exist + ++ Response 204 diff --git a/api_docs/provenance.apib b/api_docs/provenance.apib new file mode 100644 index 000000000..c40ac3328 --- /dev/null +++ b/api_docs/provenance.apib @@ -0,0 +1,1017 @@ +FORMAT: 1A + +# Provenance Resources + +## Group << API Summary + +## Group Provenance Activities +Represents the main record of provenance in DDS; it is analogous to *Activity* defined in the [W3C Specification on Provenance](https://www.w3.org/TR/prov-primer/). Activities are recorded/tracked by researchers and their *Software Agents* with the intent of maintaining comprehensive data provenance. + +*Note: Provenance relations to an activity, such as* `used` *and* `wasGeneratedBy` *are managed through the* **Provenance Relations** *API actions.* + +## Activities collection [/activities] + +### Create activity [POST] +>**Permission:** authenticated +- - - - - + +>**Properties** +- - - - - ++ **name (string, required)** - A short name for this activity. ++ **description (string, optional)** - A verbose description for this activity. ++ **started_on (string, optional)** - The time this activity was started; defaults to the current datetime if not specified. ++ **ended_on (string, optional)** - The time this activity ended. + +>**Rules** +- - - - - ++ The `ended_on` time must be greater than or equal to the `started_on` time. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Activity requires a name +* 401: Unauthorized +* 403: Forbidden + ++ Request (application/json) + + { + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity" + } + ++ Response 201 (application/json) + + { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": null, + "is_deleted": false, + "audit": { } + } + +### List activities [GET] +>**Permission:** +- - - - - ++ authenticated [scope: creator *or* visiblity to single entity that has a provenance relation to the activity] + +>**Rules** +- - - - - ++ Activities that have been deleted (i.e. `"is_deleted": true`) are not included. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden + ++ Response 200 (application/json) + + { + "results": [ + { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": null, + "is_deleted": false, + "audit": { } + } + ] + } + +## Activities instance [/activities/{id}] ++ Parameters + + id (string, required, `a1ff02a4-b7e9-999d-87x1-66f4c881jka1`) ... The unique id of the activity. + +### View activity [GET] +>**Permission:** +- - - - - ++ creator *or* visiblity to single entity that has a provenance relation to the activity + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden +* 404: Activity does not exist + ++ Response 200 (application/json) + + { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": null, + "is_deleted": false, + "audit": { } + } + +### Update activity [PUT] +>**Permission:** creator +- - - - - + +>**Rules** +- - - - - ++ Only `name`, `description`, `started_on`, and `ended_on` properties may be updated via this action. + +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden (activity restricted) +* 404: Activity does not exist + ++ Request (application/json) + + { + "ended_on": "2015-01-01T14:30:00Z" + } + ++ Response 200 (application/json) + + { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": "2015-01-01T14:30:00Z", + "is_deleted": false, + "audit": { } + } + +### Delete activity [DELETE] +>**Permission:** creator +- - - - - + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden (activity restricted) +* 404: Activity does not exist + ++ Response 204 + +## Group Provenance Relations +Represents provenance relations as defined in the [W3C Specification on Provenance](https://www.w3.org/TR/prov-primer/). Relations are recorded/tracked by researchers and their *Software Agents* with the intent of maintaining comprehensive data provenance. + +## Relations collection [/relations] + +### Create used relation [POST /relations/used] +>**Permission:** creator of the activity *and* visibility to the `used` entity +- - - - - + +>**Properties** +- - - - - ++ **activity.id (string, required)** - The activity that used the entity. ++ **entity.kind (string, required)** - The kind of entity that was used; this must be a file version (i.e. `dds-file-version`). ++ **entity.id (string, required)** - The unique id of the used entity. + +>**Rules** +- - - - - ++ An entity (i.e. `file_version`) cannot be used and generated by the same activity (i.e. `dds-activity`). + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Activity and Entity are required, Activity generated Entity +* 401: Unauthorized +* 403: Forbidden + ++ Request (application/json) + + { + "activity": { + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" + }, + "entity": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b" + } + } + ++ Response 201 (application/json) + + { + "kind": "dds-relation-used", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "from": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": "2015-01-01T14:30:00Z", + "is_deleted": false, + "audit": { } + }, + "to": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Post pairwise sequence alignment (piecewise)", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "audit": { } + } + +### Create was generated by relation [POST /relations/was_generated_by] +>**Permission:** creator of the activity *and* update_file for the `wasGeneratedBy` entity +- - - - - + +>**Properties** +- - - - - ++ **entity.kind (string, required)** - The kind of entity that was generated; this must be a file version (i.e. `dds-file-version`). ++ **entity.id (string, required)** - The unique id of the generated entity. ++ **activity.id (string, required)** - The activity that generated the entity. + +>**Rules** +- - - - - ++ An entity (i.e. `file_version`) can be generated by one and only one activity (i.e. `dds-activity`). ++ An entity (i.e. `file_version`) cannot be used and generated by the same activity (i.e. `dds-activity`). + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Activity and Entity are required, Entity can only be generated by one Activity, cannot be used by the same Activity +* 401: Unauthorized +* 403: Forbidden + ++ Request (application/json) + + { + "entity": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" + }, + "activity": { + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" + } + } + ++ Response 201 (application/json) + + { + "kind": "dds-relation-was-generated-by", + "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", + "from": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "to": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": "2015-01-01T14:30:00Z", + "is_deleted": false, + "audit": { } + }, + "audit": { } + } + +### Create was derived from relation [POST /relations/was_derived_from] +>**Permission:** visibility to the `used` entity and update_file for the `generated` entity. +- - - - - + +>**Properties** +- - - - - ++ **generated_entity.kind (string, required)** - The kind of entity generated by the derivation; this must be a file version (i.e. `dds-file-version`). ++ **generated_entity.id (string, required)** - The unique id of the generated entity. ++ **used_entity.kind (string, required)** - The kind of entity used by the derivation; this must be a file version (i.e. `dds-file-version`). ++ **used_entity.id (string, required)** - The unique id of the used entity. + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Activity and Entity are required +* 401: Unauthorized +* 403: Forbidden + ++ Request (application/json) + + { + "generated_entity": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" + }, + "used_entity": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b" + } + } + ++ Response 201 (application/json) + + { + "kind": "dds-relation-was-derived-from", + "id": "6bf31123-b078-4655-ae4e-be599d52adc5", + "from": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "to": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Initial raw data from device", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "audit": { } + } + +### Create was invalidated by relation [POST /relations/was_invalidated_by] +>**Permission:** creator of the activity *and* delete_file for `wasInvalidatedBy` entity +- - - - - + +>**Properties** +- - - - - ++ **entity.kind (string, required)** - The kind of entity that was invalidated; this must be a file version (i.e. `dds-file-version`). ++ **entity.id (string, required)** - The unique id of the invalidated entity. ++ **activity.id (string, required)** - The activity that invalidated the entity. + +>**Rules** +- - - - - ++ The `invalidated` entity must be in a deleted state (i.e. `"is_deleted": true`). ++ An entity (i.e. `file_version`) can be invalidated by one and only one activity (i.e. `dds-activity`). + +**Response messages:** +* 200: This will never happen +* 201: Successfully Created +* 400: Activity and Entity are required +* 401: Unauthorized +* 403: Forbidden + ++ Request (application/json) + + { + "entity": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" + }, + "activity": { + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" + } + } + ++ Response 201 (application/json) + + { + "kind": "dds-relation-was-generated-by", + "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", + "from": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "to": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": "2015-01-01T14:30:00Z", + "is_deleted": false, + "audit": { } + }, + "audit": { } + } + +### NOT_IMPL_CHANGE List provenance relations [GET /relations/{object_kind}/{object_id}] +List the relations for a provenance node; this only lists direct relations for the node that are a single hop away. +>**Permission:** visibility to the specified (starting) provenance node (i.e. `object_kind`, `object_id`) - which may be an activity *or* an entity +- - - - - + +>**Rules** +- - - - - ++ Provenance relations that have been deleted (i.e. `"is_deleted": true`) are not included. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden +* 404: Object kind or id does not exist + ++ Parameters + + object_kind (string, required, `dds-activity`) ... The kind of provenance node; can be one of dds-activity or dds-file-version. + + object_id (string, required, `a1ff02a4-b7e9-999d-87x1-66f4c881jka1`) ... The unique id of the node. + ++ Response 200 (application/json) + + { + "results": [ + { + "kind": "dds-relation-used", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "from": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": "2015-01-01T14:30:00Z", + "is_deleted": false, + "audit": { } + }, + "to": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Post pairwise sequence alignment (piecewise)", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "audit": { } + } + ] + } + +## Relation instance [/relations/{id}] ++ Parameters + + id (string, required, `ac242faf-fba0-4293-a949-0b82ae7ba810`) ... The unique id of the provenance relation. + +### NOT_IMPL_CHANGE View relation [GET] +>**Permission:** visibility to a single node for the specified relation - which may be the activity *or* the entity + +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 403: Forbidden +* 404: Relation does not exist + ++ Response 200 (application/json) + + { + "kind": "dds-relation-used", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "from": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "is_deleted": false, + "audit": { } + }, + "to": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 1, + "label": "Post pairwise sequence alignment (piecewise)", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "audit": { } + } + ++ Response 200 (application/json) + + { + "kind": "dds-relation-was-associated-with", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "from": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", + "started_on": "2015-01-01T12:00:00Z", + "ended_on": "2015-01-01T14:30:00Z", + "is_deleted": false, + "audit": { } + }, + "to": { + "kind": "dds-user", + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu", + "auth_provider": { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "affiliate": { + "uid": "mrgardner01" + } + }, + "last_login_on": "2015-01-01T12:00:00Z", + "audit": { } + }, + "audit": { } + } + ++ Response 200 (application/json) + + { + "kind": "dds-relation-was-attributed-to", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "from": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "to": { + "kind": "dds-user", + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu", + "auth_provider": { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "affiliate": { + "uid": "mrgardner01" + } + }, + "last_login_on": "2015-01-01T12:00:00Z", + "audit": { } + }, + "audit": { } + } + ++ Response 200 (application/json) + + { + "kind": "dds-relation-was-attributed-to", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "from": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", + "project": { + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" + } + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + }, + "audit": { } + }, + "to": { + "kind": "dds-software-agent", + "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", + "name": "Sample pipeline agent", + "description": null, + "repo_url": null, + "is_deleted": false, + "audit": { } + }, + "audit": { } + } + +### Delete relation [DELETE] +>**Permission:** creator + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden +* 404: Relation does not exist + ++ Response 204 + +## Group Search Provenance +The `Provenance Relations` API actions allows users and software agents to record the use and production of entities (i.e. files, file versions, etc.) by research activities, which may be influenced in various ways by agents. The resulting provenace chain is organized as a [graph structure](https://en.wikipedia.org/wiki/Graph_database). The search API can be used by client applications to extract the provenace graph in a JSON data format that can be transformed to a visual representation. + +*Note: The provenance graph structure is stored in a* [Neo4J](http://neo4j.com) *database and ubiquitous JavaScript libraries can be used for* [graph rendering](http://neo4j.com/developer/guide-data-visualization). + +## Search Provenance [POST /search/provenance] +Given a starting node, returns a graph structure for the provenance chain. This structure is based on the Neo4J JSON graph format. +>**Permission:** visibility to the specified (starting) provenance node (i.e. `start_node.kind`, `start_node.id`) - which may be an activity *or* an entity +- - - - - + +>**Rules:** +- - - - - ++ If the user does not have visibilty to a `node` in the resulting graph, the `properties` attribute for that `node` will be a partial resource containing: `kind`, `id`, and `is_deleted`. + +>**Properties** +- - - - - ++ **start_node.kind (string, required)** - The kind of provenance node; can be one of `dds-activity` or `dds-file-version`. ++ **start_node.id (string, required)** - The unique id of the node. ++ **max_hops (number, optional)** - The max number of hops (degree of node separation) to traverse from the starting node; defaults to infinity. + +**Response messages:** +* 200: This will never happen +* 201: Success +* 401: Unauthorized +* 404: start_node or start_node kind does not exist + ++ Request (application/json) + + { + "start_node": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" + } + } + ++ Response 201 (application/json) + + { + "graph": { + "nodes": [ + { + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "labels": ["Activity"], + "properties": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "is_deleted": false, + "audit": { } + } + }, + { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "labels": ["File Version"], + "properties": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" + }, + "version": 1, + "label": "Initial raw data from device", + "is_deleted": false, + "audit": { } + } + }, + { + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "labels": ["File Version"], + "properties": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "audit": { } + } + } + ], + "relationships": [ + { + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "type": "used", + "start_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "end_node": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "properties": { + "kind": "dds-relation-used", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "audit": { } + } + }, + { + "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", + "type": "wasGeneratedBy", + "start_node": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "end_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "properties": { + "kind": "dds-relation-was-generated-by", + "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", + "audit": { } + } + } + ] + } + } + +## Search Provenance Origin [POST /search/provenance/origin] +This is a targeted query that navigates "up" the provenance chain for a file version to see how it was generated (i.e. by what activity) and from what source file versions. Given a list of file versions, this action perform the following query for each *File Version*: + +1. Gets all related *wasDerivedFrom* file versions (if they exist). +2. Gets the generating activity (if it exists). +3. For the generating activity, gets the list of *wasGeneratedBy* and *used* file versions. + +A graph structure of the unique nodes and relationships is returned. + +>**Rules:** +- - - - - ++ For file versions that do not exist, no provenance nodes/relations will be returned ++ If a file version does not have a generating activity, then only the file version node is returned. ++ If the user does not have visibilty to a `node` in the resulting graph, the `properties` attribute for that `node` will be a partial resource containing: `kind`, `id`, and `is_deleted`. + +>**Properties** +- - - - - ++ **file_versions (object[ ], required)** - The list of file versions (i.e. `dds-file-version`) ++ **file_versions[ ].id (string, required)** - The unique file version id. + +**Response messages:** +* 200: This will never happen +* 201: Success +* 401: Unauthorized + ++ Request (application/json) + + { + "file_versions": [ + { + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" + } + ] + } + ++ Response 200 (application/json) + + { + "graph": { + "nodes": [ + { + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "labels": ["Activity"], + "properties": { + "kind": "dds-activity", + "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "name": "RF PI3-Kinase", + "is_deleted": false, + "audit": { } + } + }, + { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "labels": ["File Version"], + "properties": { + "kind": "dds-file-version", + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" + }, + "version": 1, + "label": "Initial raw data from device", + "is_deleted": false, + "audit": { } + } + }, + { + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "labels": ["File Version"], + "properties": { + "kind": "dds-file-version", + "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "file": { + "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", + "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" + }, + "version": 2, + "label": "Alignment performed on raw data", + "is_deleted": false, + "audit": { } + } + } + ], + "relationships": [ + { + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "type": "used", + "start_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "end_node": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "properties": { + "kind": "dds-relation-used", + "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", + "audit": { } + } + }, + { + "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", + "type": "wasGeneratedBy", + "start_node": "1b80a313-97cf-482d-8d17-9b911bf815b3", + "end_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", + "properties": { + "kind": "dds-relation-was-generated-by", + "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", + "audit": { } + } + } + ] + } + } diff --git a/api_docs/search.apib b/api_docs/search.apib new file mode 100644 index 000000000..793ad9f6f --- /dev/null +++ b/api_docs/search.apib @@ -0,0 +1,104 @@ +FORMAT: 1A + +# Search Resources + +## Group << API Summary + +## Group Search Objects +The search action can be used to find specific DDS objects (e.g. folders, files, etc.). The DDS platform leverages [Elasticsearch](https://www.elastic.co/) to perform document based searches. All queries must be specified in [Elasticsearch Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html). + +*Note: Only search for DDS folders and files* (i.e. `dds-folder`, `dds-file`) *is currently supported. These objects are replicated to Elasticsearch as indexed documents. The objects (i.e. documents) are extended with a* `tags` *and* `meta` *property when stored in Elaticsearch. These properties have composite metadata to facilitate search. See response payload for concrete example format of these properties.* + +## Search Objects [POST /search] +Search for DDS objects (i.e. Elasticsearch documents). +>**Permission:** authenticated [scope: view_project for objects of kind (`dds-folder`, `dds-file`)] +- - - - - + +>**Properties** +- - - - - ++ **include_kinds (string[ ], required)** - The kind of objects (i.e. Elasticsearch document types) to include in the search; can include folders and/or files (i.e. `dds-folder`, `dds-file`). ++ **search_query (object, required)** - The Elasticsearch query criteria (i.e. Query DSL). + +**Response messages:** +* 200: This will never happen +* 201: Success +* 401: Unauthorized +* 404: One or more included kinds is not supported, or not indexed + ++ Request (application/json) + + { + "include_kinds": ["dds-file"], + "search_query": { + "query": { + "match" : { + "_all" : "SMRT sequencing" + } + } + } + } + ++ Response 201 (application/json) + + { + "results": [ + { + "kind": "dds-file", + "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda", + "parent": { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" + }, + "name": "ENCFF000SJR.bam", + "project": { + "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" + }, + "ancestors": [ + { + "kind": "dds-project", + "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", "name": "Knockout Mouse Project (KOMP)" + }, + { + "kind": "dds-folder", + "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", + "name": "Sequencing Core" + } + ], + "is_deleted": false, + "current_version": { + "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", + "version": 1, + "label": "Processed sequence data", + "upload": { + "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", + "size": 30024000, + "hashes": [ + { + "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", + "algorithm": "md5", + "audit": { } + } + ], + "storage_provider": { + "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", + "name": "duke_oit_swift", + "description": "Duke OIT Storage" + } + } + }, + "audit": { }, + "tags": [ + "SMRT sequencing", + "GCB lab" + ], + "meta": [ + { + "sequencing_file_info": { + "output_type": "alignments", + "mapping_assembly": "hg19" + } + } + ] + } + ] + } diff --git a/api_docs/users_software_agents.apib b/api_docs/users_software_agents.apib new file mode 100644 index 000000000..bb812bad9 --- /dev/null +++ b/api_docs/users_software_agents.apib @@ -0,0 +1,610 @@ +FORMAT: 1A + +# User and Software Agent Resources + +## Group << API Summary + +## Group Software Agents +Represents a software agent and associated secret that can be used to access the API actions from programmatic clients, such as research core pipelines, or background jobs/tasks (e.g. hash computations, deletion of storage for failed uploads, etc.). In an effort to promote provenance, all programmatic access to the API must be via an agent secret key in tandem with a user account secret key (see **Current User** actions). + +## Software Agents collection [/software_agents] + +## Create software agent [POST] +Creates software agent and an associated secret API key; the secret key is visible and managed through the `software_agents/{id}/api_key` action. +>**Permission:** authenticated +- - - - - + +>**Properties** +- - - - - ++ **name (string)** - A short name for the software agent. ++ **description (string, optional)** - A verbose description for the software agent. ++ **repo_url (string, optional)** - The url of the repository (e.g. Git, Bitbucket, etc.) that contains the agent source code. + +**Response messages:** +* 200: This will never happen +* 201: Created Successfully +* 400: Software agent requires a name +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) + ++ Request (application/json) + + { + "name": "Hash computation agent" + } + ++ Response 201 (application/json) + + { + "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", + "name": "Hash computation agent", + "description": null, + "repo_url": null, + "is_deleted": false, + "audit": { } + } + +## List software agents [GET] +>**Permission:** authenticated +- - - - - + +>**Rules** +- - - - - ++ Software Agents that have been deleted (i.e. `"is_deleted": true`) are not included. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", + "name": "Hash computation agent", + "description": null, + "repo_url": null, + "is_deleted": false, + "audit": { } + } + ] + } + +## Software Agent instance [/software_agents/{id}] ++ Parameters + + id (string, required, `9a4c28a2-ec18-40ed-b75c-3bf5b309715`) ... The unique `id` for a software agent. + +## View software agent [GET] +>**Permission:** authenticated +- - - - - +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) +* 404: Software Agent Does not Exist + ++ Response 200 (application/json) + + { + "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", + "name": "Hash computation agent", + "description": null, + "repo_url": null, + "is_deleted": false, + "audit": { } + } + +## Update software agent [PUT] +>**Permission:** creator or system_admin +- - - - - +**Response messages:** +* 200: Success +* 400: Validation Error +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) +* 404: Software Agent Does not Exist + ++ Request (application/json) + + { + "repo_url": "https://github.com/mgardnerpsu/dukeds-dredd" + } + ++ Response 200 (application/json) + + { + "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", + "name": "Hash computation agent", + "description": null, + "repo_url": "https://github.com/mgardnerpsu/dukeds-dredd", + "is_deleted": false, + "audit": { } + } + +## Delete software agent [DELETE] +>**Permission:** creator or system_admin + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) +* 404: Software Agent Does not Exist + ++ Response 204 + +## Software Agent API Key [/software_agents/{id}/api_key] +Generates a secret key for the software agent that can be used to access the API actions from a scripting context (i.e. bash, python, R, etc...); this secret key must be used in tandem with a valid user secret key (see **Current User** actions). + ++ Parameters + + id (string, required, `9a4c28a2-ec18-40ed-b75c-3bf5b309715`) ... The unique `id` for a software agent. + +## Generate software agent API key [PUT] +Generates a new secret key for the software agent. + +>**Permission:** creator or system_admin +- - - - - + +>**Rules** +- - - - - ++ If the software agent already has an API key, this action deletes exisiting key and generates a new key. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) +* 404: Software Agent Does not Exist + ++ Response 200 (application/json) + + { + "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + "created_on": "2015-06-01T12:00:00Z" + } + +## View software agent API key [GET] +Shows the secret key for the software agent. + +>**Permission:** creator or system_admin +- - - - - + +>**Properties** +- - - - - ++ **key (string)** - A secret key that can be used in tandem with a user secret key to obtain an API access token. ++ **created_on (datetime)** - The date the software agent key was generated. + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) +* 404: Software Agent Does not Exist + ++ Response 200 (application/json) + + { + "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...", + "created_on": "2015-01-01T12:00:00Z" + } + +## Delete software agent API key [DELETE] +>**Permission:** creator or system_admin +- - - - - + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden (softrware_agent restricted) +* 404: Software Agent Does not Exist + ++ Response 204 + +## Software Agent Access Token [/software_agents/api_token] + +## Get software agent access token [POST] +Using a software agent secret key and a user secret key, get an access token. + +>**Permission:** public +- - - - - + +>**Request Properties** +- - - - - ++ **agent_key (string)** - The secret key for a software agent. ++ **user_key (string)** - The secret key for a user. + +>**Response Properties** +- - - - - ++ **api_token (string)** - The access token. ++ **expires_on (number)** - Token expiration as posix/epoch time. ++ **time_to_live (number)** - The number of seconds token is valid for; can be used by client apps to compare relative to their local time, and determine if token must be refreshed. + +>**Rules** +- - - - - ++ The agent associated with the agent key must not have been logically deleted. + +**Response messages:** +* 200: This will never happen +* 201: Success +* 400: Missing Required Keys +* 404: Software Agent or User Does not Exist + ++ Request + + { + "agent_key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + "user_key": "klmOiJKV1QiLYHkl098EfNiJJIUzI1NiJ93R..." + } + ++ Response 201 (application/json) + + { + "api_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6I...", + "expires_on": 1455571739, + "time_to_live": 14400 + } + +## Group Current User +Represents the current application user. + +## NOT_IMPL_CHANGE View current user [GET /current_user] +Get profile for the currently authenticated user. +>**Permission:** authenticated +- - - - - + +>**Rules** +- - - - - ++ The `agent` property is populated if user is authenticated via software agent token, otherwise the `agent` property is `null`. + +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header + ++ Response 200 (application/json) + + { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu", + "auth_provider": { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "affiliate": { + "uid": "mrgardner01" + } + }, + "agent": null, + "last_login_on": "2015-01-01T12:00:00Z", + "audit": { } + } + +## NOT_IMPL_NEW Get current user access token [POST /current_user/api_token] +This allows a Web or native UX client to present an access token (i.e. OAuth token) from a registered authentication service and get an API token. + +>**Permission:** authenticated +- - - - - + +>**Request Properties** +- - - - - ++ **access_token (string)** - A valid (non-expired) token for an authtication provider. ++ **auth_provider_id (string)** - A supported authentiction provider. + +>**Response Properties** ++ **api_token (string)** - The access token. ++ **expires_on (number)** - Token expiration as posix/epoch time. ++ **time_to_live (number)** - The number of seconds token is valid for; can be used by client apps to compare relative to their local time, and determine if token must be refreshed. + +**Response messages:** +* 201: Success +* 401: Missing, or Invalid API Token + ++ Request + + { + "access_token": "KjTWXC67OiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpNjK88T...", + "auth_provider_id": "a3967cab-6cfd-4d3c-b118-56e6b11d4022" + } + ++ Response 201 (application/json) + + { + "api_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6I...", + "expires_on": 1455571739, + "time_to_live": 14400 + } + +## View current user usage [GET /current_user/usage] +View summary usage for current user across all projects. +>**Permission:** authenticated [scope: view_project] +- - - - - + +>**Properties** +- - - - - ++ **project_count (number)** - Total number of projects where the user has been granted a project level authorization role. ++ **file_count (integer)** - Total number of files the user has created (i.e. uploaded) across all projects. ++ **storage_bytes (integer)** - Total bytes for files the user has created (i.e. uploaded) across all projects. + +>**Rules** +- - - - - ++ Deleted objects (i.e. `"is_deleted": true`) are excluded from all counts/totals. ++ Counts/totals are only for project resources that are visible to the current user. + +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header + ++ Response 200 (application/json) + + { + "project_count": 10, + "file_count": 126, + "storage_bytes": 304006007009 + } + +### Current User API Key [/current_user/api_key] + +## Generate current user API key [PUT] +Generates a secret key for the current user that can be used to access the API actions from a scripting context (i.e. bash, python, R, etc...); this secret key must be used in tandem with a valid software agent secret key (see **Software Agents** actions). +>**Permission:** authenticated +- - - - - + +>**Properties** +- - - - - ++ **key (string)** - A secret key that can be used in tandem with a software agent secret key to obtain an API access token. ++ **created_on (datetime)** - The date the user key was generated. + +>**Rules** +- - - - - ++ If the current user already has an API key, this action deletes their exisiting key and generates a new key. + +**Response messages:** +* 200: Success +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 403: Forbidden (software_agent restricted) + ++ Response 200 (application/json) + + { + "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + "created_on": "2015-01-01T12:00:00Z" + } + +## View current user API key [GET] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 403: Forbidden (software_agent restricted) +* 404: Current User or ApiKey Does not Exist + ++ Response 200 (application/json) + + { + "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjY...", + "created_on": "2015-01-01T12:00:00Z" + } + +## Delete current user API key [DELETE] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 204: Successfully Deleted +* 401: Unauthorized +* 403: Forbidden (software_agent restricted) +* 404: Current User Does not Exist + ++ Response 204 + +## Group Users +Represents registered users. + +## NOT_IMPL_CHANGE Users collection [/users{?full_name_contains,first_name_begins_with,last_name_begins_with}] + +### List users [GET] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Parameters + + full_name_contains (string, optional, `gardner`) ... Returns users where their full name contains the specified string. + + first_name_begins_with (string, optional, `mat`) ... Returns users where their first name begins with the specified string. + + last_name_begins_with (string, optional, `gar`) ... Returns users where their last name begins with the specified string. + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "auth_provider": { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "affiliate": { + "uid": "mrgardner01" + } + }, + "last_login_on": "2015-01-01T12:00:00Z", + "audit": { } + } + ] + } + +## NOT_IMPL_CHANGE User instance [/users/{id}] ++ Parameters + + id (string, required, `c1179f73-0558-4f96-afc7-9d251e65b7bb`) ... The unique `id` for a user. + +### View user [GET] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Valid API Token in 'Authorization' Header +* 401: Missing, Expired, or Invalid API Token in 'Authorization' Header +* 404: User does not exist + ++ Response 200 (application/json) + + { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu", + "auth_provider": { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "affiliate": { + "uid": "mrgardner01" + } + }, + "last_login_on": "2015-01-01T12:00:00Z", + "audit": { } + } + +## Group Auth Providers +Represents the authentication providers (services) that are supported by DDS. + +## Auth Providers collection [/auth_providers] + +### List auth providers [GET] +>**Permission:** public +- - - - - + ++ Response 200 (application/json) + + { + "results": [ + { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "is_deprecated": false, + "is_default": true, + "is_affiliate_search_provided": true, + "login_initiation_url": "https://das.duke.edu/authenticate?response_type=token&client_id=abc123" + } + ] + } + +## Auth Provider instance [/auth_providers/{id}] ++ Parameters + + id (string, required, `3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c`) ... The unique `id` of the authentication provider. + +### View auth provider [GET] +>**Permission:** public +- - - - - + ++ Response 200 (application/json) + + { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "is_deprecated": false, + "is_default": true, + "is_affiliate_search_provided": true, + "login_initiation_url": "https://das.duke.edu/authenticate?response_type=token&client_id=abc123" + } + +### Group Auth Provider Affiliates + +## NOT_IMPL_NEW List auth provider affiliates [GET /auth_providers/{id}/affiliates{?full_name_contains}] +Get a list of affiliates (potential users), for a supported authentication provider. +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized + ++ Parameters + + id (string, required, `3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c`) ... The unique `id` of the authentication provider. + + full_name_contains (string, required, `gard`) ... Returns affiliates where their full name contains the specified string; the supplied string must have a minimum length of three characters, otherwise an empty array is returned. + ++ Response 200 (application/json) + + { + "results": + [ + { + "uid": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu" + } + ] + } + +### NOT_IMPL_NEW View auth provider affiliate [GET /auth_providers/{id}/affiliates/{uid}] +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: Success +* 401: Unauthorized +* 404: Auth provider or affiliate does not exist + ++ Parameters + + id (string, required, `duke`) ... The `id` of an authentication provider (service) supported by the DDS application. + + uid (string, required, `gardner001`) ... The unique `uid` (user id) in the context of the specified auth provider. + ++ Response 200 (application/json) + + { + "uid": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu" + } + +### NOT_IMPL_NEW Create or Get user account for affiliate [POST /auth_providers/{id}/affiliates/{uid}/dds_user] +Transform an institutional affiliates UID, such as a Duke NetID, to a DDS specific user identity; can be used by clients prior to calling DDS APIs that require a DDS user in the request payload. +>**Permission:** authenticated +- - - - - + +**Response messages:** +* 200: This will never happen +* 201: Created Successfully (or user already registered) +* 401: Unauthorized +* 404: Auth provider or affiliate does not exist + +>**Rules** +- - - - - ++ If the affiliate has already been registered in DDS, the exisitng DDS user is not modified, and a `201` response is returned. + ++ Parameters + + id (string, required, `duke`) ... The `id` of an authentication provider (service) supported by the DDS application. + + uid (string, required, `gardner001`) ... The unique `uid` (user id) in the context of the specified auth provider. + ++ Response 201 (application/json) + + { + "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", + "username": "mrgardner01", + "first_name": "Matthew", + "last_name": "Gardner", + "full_name": "Matthew Gardner", + "email": "mrgardner01@duke.edu", + "auth_provider": { + "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", + "name": "duke", + "affiliate": { + "uid": "mrgardner01" + } + }, + "last_login_on": "2015-01-01T12:00:00Z", + "audit": { } + } diff --git a/apiary.apib b/apiary.apib deleted file mode 100644 index 3d95a2d80..000000000 --- a/apiary.apib +++ /dev/null @@ -1,4395 +0,0 @@ -FORMAT: 1A -HOST: https://apidev.dataservice.duke.edu/api/v1 - -# Duke Data Service - -The Duke Data Service (DDS) API allows Duke researchers to store, organize, retrieve and share data. - -This the documentation for the Data Service API. Key focuses are on API endpoints that enhance usability for "shallow end of the pool" users, endpoints that support the needs of investigators for managing their research groups, endpoints that accommodate shared resource and core facility needs, endpoints that support SOM administration of data resources, and endpoints that facilitate reproducible scientific workflows. There are tensions to resolve to meet these needs, and we should consider whether the API might be broken up into multiple APIs, whether some business logic be pushed to the users, etc. - -Adhere as well as possible to the [Heroku API Design Best Practices:](https://geemus.gitbooks.io/http-api-design/content/en/index.html) requiring secure TLS connections, versioning in the accepts header, supporting Etags, including a Request-id in each response header, among others. - -## API Change Log - -02-Aug-2016 --------------- -+ Changed URI format of `POST /tags` to `POST /tags/{object_kind}/{object_id}` - tags are always created for a specific object. -+ Changed `GET /tags/labels` to include a `last_used_on` property in the response; the response is sorted in descending order by this new property. -+ Added endpoint `POST /tags/{object_kind}/{object_id}/append` - allows clients to append a collection of tags to an object. - -02-Sep-2016 --------------- -+ Removed *Provenance Inferred* section - implementation will no longer auto-generate inferred provenance relation based on audit trail. -+ Refactored Metadata *Properties* actions to follow URI pattern liken to `Tags`. - -07-Sep-2016 --------------- -+ Added endpoint `/search/provenance/was_generated_by` - allows targeted search "up" the provenance chain for a set of file versions. -+ Added rules/constraints for *Provenance Relations* actions. - -12-Sep-2016 --------------- -+ Refactored *Metadata* actions - objects can now be annotated with metadata via bulk `POST` and `PUT` actions. -+ Added `name` query param to `GET /templates` and `key` query param to `GET /templates/{id}/properties`; these query params allow clients to lookup templates and template properties by their alternate unique key. - -23-Sep-2016 --------------- -+ Added *Authentication Providers* actions - formalizes metadata for supported auth providers and provides endpoint to search for affiliates (potential DDS users) in context of the provider. In addition, supports getting a DDS user identity for a valid affiliate - this endpoint introduces a proposed change to user payload. - -17-Oct-2016 --------------- -+ For *Search Provenance* - changed `/search/provenance/was_generated_by` to `/search/provenance/origin`; this search action now includes `wasDerivedFrom` file versions in the results. -+ For *Metadata* - changed `/templates{?name}` to `/templates{?name_contains}` - facilitates contains search vs. exact match. -+ Changed `/templates/{id}/properties{?key}` to `/templates/{id}/properties` - if we need `key` based lookup we will extend API to return the instance by `key`, not an array of 1. -+ Changed `/meta/{object_kind}/{object_id}{?meta_template_name}` to `/meta/{object_kind}/{object_id}` - if we need `template_name` based lookup we will extend API to return the instance by `template_name`, not an array of 1. - - -## Group API Usage - -Web Portal --------------- -There is a [Web portal](https://dataservice.duke.edu) that allows users to interact with the Web services API. Access is currently restricted to Duke staff with a valid Duke NetID and password. To access the Web portal, Duke staff must successfully authenticate via the Duke single sign-on process. - -Programmatic Keys --------------- -In an effort to promote provenance, all programmatic access to the API must utilize the concept of a software agent. From the Web portal, an authorized user can generate secret keys for both a software agent and their user account. In tandem, these secret keys can be used to obtain an access token from a programmatic context. For usage details, see the actions for **Software Agents** and **Current User**. - -Exploring the API --------------- -In addition to the API usage documentation herein, users may experiment with the live API actions in a test environment via the [API Explorer](https://apidev.dataservice.duke.edu/apiexplorer). - -Collection Pagination --------------- -For actions that return a collection of resources/objects, the number of objects returned will be paginated. The number of objects returned per page, and the desired page can be controlled using the query parameters `page`, and `per_page`. For example: `/projects?per_page=25` will return the first 25 projects, and `/projects?page=3&per_page=25` will return the third batch of 25 projects. Collection payloads will always be returned as an array of objects; the `results` property will reference the array as follows: - - { - "results": [ - { }, - { }, - ] - } - -To make it easy for clients to manage pagination, the following headers will always be included in the response: - -* X-Total: The total number of objects that would be returned by the query unpaginated -* X-Total-Pages: The total number of pages given X-Total and X-Per-Page -* X-Page: Current Page (passed in as query parameter) -* X-Per-Page: per_page (passed in as query parameter) -* X-Next-Page: Next page to be collected -* X-Prev-Page: Previous page (will be empty on first page) - -Audit Object --------------- -Resource payloads may include a composite audit object. An example structure of that object is represented here and will be referenced by the `audit` property in resource specific payloads. - - "audit": { - "created_on": "2015-01-01T12:00:00Z", - "created_by": { - "id": "ce245d81-bae1-452b-8589-24f736ca7735", - "username": "mrgardner01", - "full_name": "Matthew Gardner", - "software_agent": { - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Hashing computation agent" - } - }, - "last_updated_on": "2015-01-01T13:00:00Z", - "last_updated_by": { - "id": "d240ef3d-8d43-441b-be90-78f51a02e47f", - "username": "jturner01", - "full_name": "Jon Turner", - "software_agent": null - }, - "deleted_on": null, - "deleted_by": null - } - -API Errors ----------------- -We should respond with context appropriate error codes, especially for 400 class errors, using the [Standard List](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) - -* 400: no API token, validation errors -* 401: bad API token -* 403: user performing request which they do not have permission to perform -* 404: user requesting resource that does not exist - -All error responses should include a JSON response that provides the HTTP status code, details of the error that occurred, and possible steps to address the problem. For example: - - { - "error": "404", - "reason": "Project does not exist", - "suggestion": "You may have chosen the wrong ID." - } - -Validation errors require a field-level breakdown with an array of errors (even if multiple errors occur for the same field), each describing the field with the error, and message describing the error encountered. - - { - "error": "400", - "reason": "validation failed", - "suggestion": "Fix the following invalid fields and resubmit" - "errors" : [ - { - "field" : "name", - "message" : "Project needs a name." - }, - { - "field" : "principal_investigator", - "message" : "Principal Investigator must be specified for each project." - } - ] - } - -## Group Authorization Roles -Represents the set of discrete permissions that can be granted to a user. - -**Authorization Roles:** - -| role | name | description | permission(s) | -|:-----|:-----|:------------|:--------------| -| **system_admin** | System Admin | Can manage system level permissions and perform all operations across all projects | system_admin | -| **project_admin** | Project Admin | Can update project details, delete project, manage project level permissions and perform all file operations | view_project, update_project, delete_project, manage_project_permissions, download_file, create_file, update_file, delete_file | -| **project_viewer** | Project Viewer | Can only view project and file metadata | view_project | -| **file_downloader** | File Downloader | Can download files | view_project, download_file | -| **file_uploader** | File Uploader | Can upload files | view_project, create_file, update_file | -| **file_editor** | File Editor | Can view, download, create, update and delete files | view_project, download_file, create_file, update_file, delete_file | - - -**Permissions:** - -| permission | description | -|:------------|:------------| -| **system_admin** | Can manage system level permissions and perform all operations across all projects | -| **view_project** | Can view project and file metadata | -| **update_project** | Can update project header details and project affiliations | -| **delete_project** | Can delete project | -| **manage_project_permissions** | Can grant/revoke project level permissions | -| **download_file** | Can download file | -| **create_file** | Can upload new file and modify file metadata | -| **update_file** | Can upload new version of existing file and modify file metadata | -| **delete_file** | Can delete a file | - -## Authorization Roles collection [/auth_roles{?context}] -+ Parameters - + context (string, optional, `system`) ... The `context` or scope in which permission can be granted; valid context values are `system` or `project`. - -### List roles [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "system_admin", - "name": "System Admin", - "description": "Can manage system level permissions and perform all operations across all projects", - "permissions": [ - { - "id": "system_admin" - } - ], - "contexts": ["system"], - "is_deprecated": false - } - ] - } - -## Authorization Role instance [/auth_roles/{id}] -+ Parameters - + id (string, required, `file_editor`) ... The unique `id` for an authorization role. - -### View role [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "file_editor", - "name": "File Editor", - "description": "Can view, download, create, update and delete files", - "permissions": [ - { - "id": "view_project" - }, - { - "id": "download_file" - } - ], - "contexts": ["project"], - "is_deprecated": false - } - -## Group Software Agents -Represents a software agent and associated secret that can be used to access the API actions from programmatic clients, such as research core pipelines, or background jobs/tasks (e.g. hash computations, deletion of storage for failed uploads, etc.). In an effort to promote provenance, all programmatic access to the API must be via an agent secret key in tandem with a user account secret key (see **Current User** actions). - -## Software Agents collection [/software_agents] - -## Create software agent [POST] -Creates software agent and an associated secret API key; the secret key is visible and managed through the `software_agents/{id}/api_key` action. ->**Permission:** authenticated -- - - - - - ->**Properties** -- - - - - -+ **name (string)** - A short name for the software agent. -+ **description (string, optional)** - A verbose description for the software agent. -+ **repo_url (string, optional)** - The url of the repository (e.g. Git, Bitbucket, etc.) that contains the agent source code. - -+ Request (application/json) - - { - "name": "Hash computation agent" - } - -+ Response 201 (application/json) - - { - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Hash computation agent", - "description": null, - "repo_url": null, - "is_deleted": false, - "audit": { } - } - -## List software agents [GET] ->**Permission:** authenticated -- - - - - - ->**Rules** -- - - - - -+ Software Agents that have been deleted (i.e. `"is_deleted": true`) are not included. - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Hash computation agent", - "description": null, - "repo_url": null, - "is_deleted": false, - "audit": { } - } - ] - } - -## Software Agent instance [/software_agents/{id}] -+ Parameters - + id (string, required, `9a4c28a2-ec18-40ed-b75c-3bf5b309715`) ... The unique `id` for a software agent. - -## View software agent [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Hash computation agent", - "description": null, - "repo_url": null, - "is_deleted": false, - "audit": { } - } - -## Update software agent [PUT] ->**Permission:** creator or system_admin -- - - - - - -+ Request (application/json) - - { - "repo_url": "https://github.com/mgardnerpsu/dukeds-dredd" - } - -+ Response 200 (application/json) - - { - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Hash computation agent", - "description": null, - "repo_url": "https://github.com/mgardnerpsu/dukeds-dredd", - "is_deleted": false, - "audit": { } - } - -## Delete software agent [DELETE] ->**Permission:** creator or system_admin - -+ Response 204 - -## Software Agent API Key [/software_agents/{id}/api_key] -Generates a secret key for the software agent that can be used to access the API actions from a scripting context (i.e. bash, python, R, etc...); this secret key must be used in tandem with a valid user secret key (see **Current User** actions). - -+ Parameters - + id (string, required, `9a4c28a2-ec18-40ed-b75c-3bf5b309715`) ... The unique `id` for a software agent. - -## Generate software agent API key [PUT] -Generates a new secret key for the software agent. - ->**Permission:** creator or system_admin -- - - - - - ->**Rules** -- - - - - -+ If the software agent already has an API key, this action deletes exisiting key and generates a new key. - -+ Response 200 (application/json) - - { - "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", - "created_on": "2015-06-01T12:00:00Z" - } - -## View software agent API key [GET] -Shows the secret key for the software agent. - ->**Permission:** creator or system_admin -- - - - - - ->**Properties** -- - - - - -+ **key (string)** - A secret key that can be used in tandem with a user secret key to obtain an API access token. -+ **created_on (datetime)** - The date the software agent key was generated. - -+ Response 200 (application/json) - - { - "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...", - "created_on": "2015-01-01T12:00:00Z" - } - -## Delete software agent API key [DELETE] ->**Permission:** creator or system_admin -- - - - - - -+ Response 204 - -## Software Agent Access Token [/software_agents/api_token] - -## Get software agent access token [POST] -Using a software agent secret key and a user secret key, get an access token. - ->**Permission:** public -- - - - - - ->**Request Properties** -- - - - - -+ **agent_key (string)** - The secret key for a software agent. -+ **user_key (string)** - The secret key for a user. - ->**Response Properties** -- - - - - -+ **api_token (string)** - The access token. -+ **expire_on (number)** - Token expiration as posix/epoch time. -+ **time_to_live (number)** - The number of seconds token is valid for; can be used by client apps to compare relative to their local time, and determine if token must be refreshed. - ->**Rules** -- - - - - -+ The agent associated with the agent key must not have been logically deleted. - -+ Request - - { - "agent_key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", - "user_key": "klmOiJKV1QiLYHkl098EfNiJJIUzI1NiJ93R..." - } - -+ Response 201 (application/json) - - { - "api_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6I...", - "expire_on": 1455571739, - "time_to_live": 14400 - } - -## Group Current User -Represents the currently authenticated user. - -## Current User instance [/current_user] - -### View current user [GET] -Get profile for the currently authenticated user. ->**Permission:** authenticated -- - - - - - ->**Rules** -- - - - - -+ The `agent` property is populated if user is authenticated via software agent token, otherwise the `agent` property is `null`. - -+ Response 200 (application/json) - - { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "source": "duke_shibboleth", - "uid": "gardner100" - }, - "agent": { - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Hashing computation agent" - }, - "last_login_on": "2015-01-01T12:00:00Z", - "audit": { } - } - -## Current user usage [GET /current_user/usage] -View summary usage for current user across all projects. ->**Permission:** authenticated [scope: view_project] -- - - - - - ->**Properties** -- - - - - -+ **project_count (number)** - Total number of projects where the user has been granted a project level authorization role. -+ **file_count (integer)** - Total number of files the user has created (i.e. uploaded) across all projects. -+ **storage_bytes (integer)** - Total bytes for files the user has created (i.e. uploaded) across all projects. - ->**Rules** -- - - - - -+ Deleted objects (i.e. `"is_deleted": true`) are excluded from all counts/totals. -+ Counts/totals are only for project resources that are visible to the current user. - -+ Response 200 (application/json) - - { - "project_count": 10, - "file_count": 126, - "storage_bytes": 304006007009 - } - -## Current User API Key [/current_user/api_key] - -## Generate current user API key [PUT] -Generates a secret key for the current user that can be used to access the API actions from a scripting context (i.e. bash, python, R, etc...); this secret key must be used in tandem with a valid software agent secret key (see **Software Agents** actions). ->**Permission:** authenticated -- - - - - - ->**Properties** -- - - - - -+ **key (string)** - A secret key that can be used in tandem with a software agent secret key to obtain an API access token. -+ **created_on (datetime)** - The date the user key was generated. - ->**Rules** -- - - - - -+ If the current user already has an API key, this action deletes their exisiting key and generates a new key. - -+ Response 200 (application/json) - - { - "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", - "created_on": "2015-01-01T12:00:00Z" - } - -## View current user API key [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjY...", - "created_on": "2015-01-01T12:00:00Z" - } - -## Delete current user API key [DELETE] ->**Permission:** authenticated -- - - - - - -+ Response 204 - -## Group Users -Represents registered users. - -## Users collection [/users{?full_name_contains,first_name_begins_with,last_name_begins_with}] - -### List users [GET] ->**Permission:** authenticated -- - - - - - -+ Parameters - + full_name_contains (string, optional, `gardner`) ... Returns users where their full name contains the specified string. - + first_name_begins_with (string, optional, `mat`) ... Returns users where their first name begins with the specified string. - + last_name_begins_with (string, optional, `gar`) ... Returns users where their last name begins with the specified string. - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "source": "duke_shibboleth", - "uid": "gardner100" - }, - "last_login_on": "2015-01-01T12:00:00Z", - "audit": { } - } - ] - } - -## User instance [/users/{id}] -+ Parameters - + id (string, required, `c1179f73-0558-4f96-afc7-9d251e65b7bb`) ... The unique `id` for a user. - -### View user [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "source": "duke_shibboleth", - "uid": "gardner100" - }, - "last_login_on": "2015-01-01T12:00:00Z", - "audit": { } - } - -## Group System Permissions -Represents system level authorization roles that have been granted to a user. - -## System Permissions collection [/system/permissions] - -### List system permissions [GET] ->**Permission:** system_admin -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "auth_role": { - "id": "system_admin", - "name": "System Admin", - "description": "Can manage system level permissions and perform all operations across all projects" - } - } - ] - } - -## System Permission instance [/system/permissions/{user_id}] -+ Parameters - + user_id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique id of the user. - -+ Model (application/json) - - + Body - - { - "user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "auth_role": { - "id": "system_admin", - "name": "System Admin", - "description": "Can manage system level permissions and perform all operations across all projects" - } - } - -### Grant system permission [PUT] ->**Permission:** system_admin -- - - - - - ->**Rules** -- - - - - -+ Revokes any existing system level authorization role for the user and grants the new role. -+ The role specified must be a system level authorization role (i.e. `system` in `auth_role.contexts`). - -+ Request (application/json) - - { - "auth_role": {"id": "system_admin"} - } - -+ Response 200 - - [System Permission instance][] - -### View system permission [GET] ->**Permission:** system_admin -- - - - - - -+ Response 200 - - [System Permission instance][] - -### Revoke system permission [DELETE] ->**Permission:** system_admin -- - - - - - -+ Response 204 - -## Group Projects -Represents a container for storing, organizing, retrieving and sharing research data files and their associated metadata. - -## Projects collection [/projects] - -### Create project [POST] ->**Permission:** authenticated -- - - - - - ->**Rules** -- - - - - -+ User who creates project is granted the `project_admin` authorization role. - -+ Request (application/json) - - { - "name": "Knockout Mouse Project (KOMP)", - "description": "Goal of generating a targeted knockout mutation..." - } - -+ Response 201 (application/json) - - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)", - "description": "Goal of generating a targeted knockout mutation...", - "is_deleted": false, - "audit": { } - } - -### List projects [GET] ->**Permission:** authenticated [scope: view_project] -- - - - - - ->**Rules** -- - - - - -+ Projects that have been deleted (i.e. `"is_deleted": true`) are not included. - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)", - "description": "Goal of generating a targeted knockout mutation...", - "is_deleted": false, - "audit": { } - } - ] - } - -## Project instance [/projects/{id}] -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. - -+ Model (application/json) - - + Body - - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)", - "description": "Goal of generating a targeted knockout mutation...", - "is_deleted": false, - "audit": { } - } - -### View project [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 - - [Project instance][] - -### Update project [PUT] ->**Permission:** update_project -- - - - - - ->**Rules** -- - - - - -+ Only `name` and `description` properties may be updated via this action. - -+ Request (application/json) - - { - "name": "Knockout Mouse Project (KOMP)", - "description": "Goal of generating a targeted knockout mutation..." - } - -+ Response 200 - - [Project instance][] - - -### Delete project [DELETE] ->**Permission:** delete_project -- - - - - - ->**Rules** -- - - - - -+ This operation recursively deletes all of the project children (i.e. folders,files and file versions). - -+ Response 204 - -## NOT_IMPLEMENTED_NEW Project usage [GET /projects/{id}/usage] -View summary usage for the project. - ->**Permission:** view_project -- - - - - - ->**Properties** -- - - - - -+ **member_count (number)** - Total number of users granted a project level permission. -+ **file_count (integer)** - Total number of files contained in the project. -+ **storage_bytes (integer)** - Total bytes for all files contained in the project. - ->**Rules** -- - - - - -+ Deleted objects (i.e. `"is_deleted": true`) are excluded from all counts/totals. - -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. - -+ Response 200 (application/json) - - { - "member_count": 10, - "file_count": 126, - "storage_bytes": 804006007009 - } - -## Group Project Permissions -Represents project level authorization roles that have been granted to a user. - -## Project Permissions collection [/projects/{id}/permissions] -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. - -### List project permissions [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, - "user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "auth_role": { - "id": "file_editor", - "name": "File Editor", - "description": "Can view, download, create, update and delete files" - } - } - ] - } - -## Project Permission instance [/projects/{project_id}/permissions/{user_id}] -+ Parameters - + project_id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique id of the project. - + user_id (string, required, `c1179f73-0558-4f96-afc7-9d251e65b7bb`) ... The unique id of the user. - -+ Model (application/json) - - + Body - - { - "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, - "user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "auth_role": { - "id": "file_editor", - "name": "File Editor", - "description": "Can view, download, create, update and delete files" - } - } - -### Grant project permission [PUT] ->**Permission:** manage_project_permissions -- - - - - - ->**Rules** -- - - - - -+ Revokes any existing project level authorization role for the user and grants the new role. -+ The role specified must be a project level authorization role (i.e. `project` in `auth_role.contexts`). -+ The current user cannot grant or revoke their own project level role. - -+ Request (application/json) - - { - "auth_role": {"id": "file_editor"} - } - -+ Response 200 - - [Project Permission instance][] - -### View project permission [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 - - [Project Permission instance][] - -### Revoke project permission [DELETE] ->**Permission:** manage_project_permissions -- - - - - - ->**Rules** -- - - - - -+ The project must have at least one user with the `project_admin` role. -+ The current user cannot revoke their own project level role. - -+ Response 204 - -## Group Project Roles -Represents an organizational role that an individual (i.e. user) may assume in the context of a project. These organizational roles have no relationship to authorization roles. - -**Project Roles:** - -| role | name | description | -|:-----|:-----|:------------| -| **principal_investigator** | Principal Investigator | Lead investigator for the research project | -| **research_coordinator** | Research Coordinator | Coordinator for the research project | - -## Project Roles collection [/project_roles] - -### List project roles [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "principal_investigator", - "name": "Principal Investigator", - "description": "Lead investigator for the research project", - "is_deprecated": false - }, - { - "id": "research_coordinator", - "name": "Research Coordinator", - "description": "Coordinator for the research project", - "is_deprecated": false - } - ] - } - -## Project Role instance [/project_roles/{id}] -+ Parameters - + id (string, required, `principal_investigator`) ... The unique `id` for a project role. - -### View project role [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "principal_investigator", - "name": "Principal Investigator", - "description": "Lead investigator for the research project", - "is_deprecated": false - } - -### Group Affiliates -Represents an individual that plays some project level role of interest from a collaboration perspective. The affiliate must be a registered user. - -## Affiliates collection [/projects/{id}/affiliates] -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. - -### List affiliates [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, - "user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu" - }, - "project_role": { - "id": "principal_investigator", - "name": "Principal Investigator" - } - } - ] - } - -## Affiliate instance [/projects/{project_id}/affiliates/{user_id}] -+ Parameters - + project_id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique id of the project. - + user_id (string, required, `c1179f73-0558-4f96-afc7-9d251e65b7bb`) ... The unique id of the user. - -+ Model (application/json) - - + Body - - { - "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, - "user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu" - }, - "project_role": { - "id": "principal_investigator", - "name": "Principal Investigator" - } - } - -### Associate affiliate [PUT] ->**Permission:** update_project -- - - - - - ->**Rules** -- - - - - -+ Deletes any existing project role for the user and assigns new role. - -+ Request (application/json) - - { - "project_role": {"id": "principal_investigator"} - } - -+ Response 200 - - [Affiliate instance][] - -### View affiliate [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 - - [Affiliate instance][] - -### Delete affiliate [DELETE] ->**Permission:** update_project -- - - - - - -+ Response 204 - -## Group Storage Providers -Represents an external service that provides physical storage space for files. - -## Storage Providers collection [/storage_providers] - -### List storage providers [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage", - "chunk_hash_algorithm": "md5", - "is_deprecated": false - }, - { - "id": "t4479f73-0774-4f96-afc7-9d251e65by88", - "name": "amazon_s3_glacier", - "description": "Amazon Glacier Cloud Storage", - "chunk_hash_algorithm": "sha1", - "is_deprecated": false - } - ] - } - -## Storage Provider instance [/storage_providers/{id}] -+ Parameters - + id (string, required, `g5579f73-0558-4f96-afc7-9d251e65bv33`) ... The unique `id` of the storage provider. - - -### View storage provider [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke Office of Information Technology Storage", - "chunk_hash_algorithm": "md5", - "is_deprecated": false - } - -## Group Folders -A folder is a container for files and sub-folders; folders are located in the top-level project root or a parent folder. - -## Folders collection [/folders] - -### Create folder [POST] ->**Permission:** create_file -- - - - - - ->**Request Properties** -- - - - - -+ **parent.kind (string, required)** - The kind of parent container for the folder; this can be a project (i.e. `dds-project`) or a folder (i.e. `dds-folder`). -+ **parent.id (string, required)** - The unique id of the parent. -+ **name (string, required)** - A short name for the folder. - ->**Response Properties** -- - - - - -+ **ancestors (object[ ])** - Represents entire ancestral path, from the root node (project or folder), down to its parent, in hierarchical order. - -+ Request (application/json) - - { - "parent": { - "kind": "dds-folder", - "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" - }, - "name": "Raw Data" - } - -+ Response 201 (application/json) - - { - "kind": "dds-folder", - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "Raw Data", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "audit": { } - } - -## Folder instance [/folders/{id}] -+ Parameters - + id (string, required, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... The unique `id` of the folder. - -### View folder [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 (application/json) - - { - "kind": "dds-folder", - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "Raw Data", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "audit": { } - } - -### Delete folder [DELETE] ->**Permission:** delete_file -- - - - - - ->**Rules** -- - - - - -+ This operation recursively deletes all of the folder children (i.e. folders, files and file versions). - -+ Response 204 - -## Move folder [PUT /folders/{id}/move] ->**Permission:** create_file -- - - - - - ->**Rules** -- - - - - -+ The destination folder cannot be a child of the folder being moved. - -+ Parameters - + id (string, required, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... The unique `id` of the folder. - -+ Request (application/json) - - { - "parent": { - "kind": "dds-folder", - "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" - } - } - -+ Response 200 (application/json) - - { - "kind": "dds-folder", - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", - "parent": { - "kind": "dds-folder", - "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" - }, - "name": "Raw Data", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc", - "name": "Flow Core" - } - ], - "is_deleted": false, - "audit": { } - } - -## Rename folder [PUT /folders/{id}/rename] ->**Permission:** create_file -- - - - - - -+ Parameters - + id (string, required, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... The unique `id` of the folder. - -+ Request (application/json) - - { - "name": "Model Data" - } - -+ Response 200 (application/json) - - { - "kind": "dds-folder", - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", - "parent": { - "kind": "dds-folder", - "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc" - }, - "name": "Model Data", - "project": {"id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"}, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc", - "name": "Flow Core" - } - ], - "is_deleted": false, - "audit": { } - } - -## Group Uploads -All files must be uploaded using a multi-part/chunked upload process. Although this places more burden on clients to divide larger files into chunks and send each chunk separately, the result is a more robust process that allows failed chunks to be resent. The following actions must be used by the client to manage the chunked upload process. - -## Uploads collection [/projects/{id}/uploads] -+ Parameters - + id (required, string, `d5ae02a4-b9e6-473d-87c4-66f4c881ae7a`) ... Globally unique `id` of the project. - -### Initiate chunked upload [POST] -This is the first step in uploading a large file. An upload objects is created along with a composite status object that can be polled by client agents to track the progress of the chunked upload. ->**Permission:** create_file -- - - - - - ->**Request Properties** -- - - - - -+ **name (string, required)** - The name of the client file to upload. -+ **content_type (string, optional)** - Valid content type per [media types](https://en.wikipedia.org/wiki/Internet_media_type). -+ **size (number, required)** - The size in bytes of entire file (computed by client). - ->**Response Properties** -- - - - - -+ **chunks (object)** - The chunks the client has requested to upload. -+ **storage_location (object)** - Object that contains target storage details. -+ **status (object)** - Object used to track status of overall file upload. - -+ Request (application/json) - - { - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "content_type": "application/octet-stream", - "size": 30024000 - } - -+ Response 201 (application/json) - - { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "content_type": "application/octet-stream", - "size": 30024000, - "hashes": [ ], - "chunks": [ ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", "description": - "Duke OIT Storage" - }, - "status": { - "initiated_on": "2015-07-10T13:00:00Z", - "completed_on": null, - "error_on": null, - "error_message": null - }, - "audit": { } - } - -### List chunked uploads [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "content_type": "application/octet-stream", - "hashes": [ ], - "chunks": [ ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - }, - "status": { - "initiated_on": "2015-07-10T13:00:00Z", - "completed_on": null, - "error_on": null, - "error_message": null - }, - "audit": { } - } - ] - } - -## Upload instance [/uploads/{id}] -+ Parameters - + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. - -### View chunked upload [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 (application/json) - - { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "content_type": "application/octet-stream", - "size": 30024000, - "hashes": [ ], - "chunks": [ - { - "number": 1, - "size": 10000, - "hash": { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5" - } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": - "Duke OIT Storage" - }, - "status": { - "initiated_on": "2015-07-10T13:00:00Z", - "completed_on": null, - "error_on": null, - "error_message": null - }, - "audit": { } - } - -## Get pre-signed chunk URL [PUT /uploads/{id}/chunks] -Generates and returns a pre-signed URL that can be used by client to upload a file chunk to the storage provider. This step is repeated for each chunk. If the chunk uploads fails, the client must call this action again to get a new pre-signed URL for the chunk number, then retry the chunk upload. ->**Permission:** create_file -- - - - - - ->**Request Properties** -- - - - - -+ **number (number, required)** - The chunk number. -+ **size (number, required)** - The size of the chunk in bytes (computed by client). -+ **hash.value (string, required)** - The chunk hash (computed by client). -+ **hash.algorithm (string, required)** - The hash algorithm used (i.e. md5, sha256, sha1, etc.); this must be the default algorithm (i.e. `chunk_hash_algorithm`) supported by storage provider (see **Storage Providers** actions) - ->**Response Properties** -- - - - - -+ **http_verb (string)** - The http verb to use for uploading the next chunk. -+ **host (string)** - The storage provider host. -+ **url (string)** - The pre-signed URL for uploading the chunk to the storage provider. -+ **http_headers (object[ ])** - Array of headers (i.e. key/value pairs) that must be included in the client upload request. - -+ Parameters - + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. - -+ Request (application/json) - - { - "number": 1, - "size": 5024000, - "hash": { - "value": "ey23df2207d99a74fbe169e3eba035e633b65d76", - "algorithm": "md5" - } - } - -+ Response 200 (application/json) - - { - "http_verb": "PUT", - "host": "duke_data_service_prod.s3.amazonaws.com", - "url": "/666be35a-98e0-4c2e-9a17-7bc009f9bb23?partNumber=1&uploadId=EXAMPLEJZ6e0YupT2...&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN...", - "http_headers": [ - { "Content-Length": "5024000" } - ] - } - -## Complete chunked file upload [PUT /uploads/{id}/complete] -This operation is called by the client after all file chunks have been successfully uploaded to the storage provider. ->**Permission:** create_file -- - - - - - ->**Properties** -- - - - - -+ **hash.value (string, required)** - The entire file hash (computed by client). -+ **hash.algorithm (string, required)** - The algorithm used by client to compute entire file hash (i.e. md5, sha256, sha1, etc.). - ->**Rules** -- - - - - -+ If the storage provider requires the individual chunks to be assembled, such as Amazon S3, this operation will call the storage provider actions to assemble the parts into a single file object. -+ The reported `hash.value` must be a valid algorithm - supported/valid algorithms are: `md5`, `sha256`, and `sha1`. -+ The client hash for each chunk must equal the storage provider hash for the same chunk, or an upload error is reported. -+ The client reported file size (bytes) must equal the storage provider reported file size, or an upload error is reported. -+ If there are no errors, the `upload_status.completed_on` is set to the current timestamp. - -+ Parameters - + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. - -+ Request - - { - "hash": { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5" - } - } - -+ Response 200 (application/json) - - { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "content_type": "application/octet-stream", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "chunks": [ - { - "number": 1, - "size": 5024000, - "hash": { - "value": "jw23df2207d99a74fbe169e3eba035e633b65d88", - "algorithm": "md5" - } - }, - { - "number": 2, - "size": 5024000, - "hash": { - "value": "ry23df2207d99a74fbe169e3eba035e633b65dkq", - "algorithm": "md5" - } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - }, - "status": { - "initiated_on": "2015-07-10T13:00:00Z", - "completed_on": "2015-07-10T13:00:00Z", - "error_on": null, - "error_message": null - }, - "audit": { } - } - -## Report upload hash [PUT /uploads/{id}/hashes] -Report a hash (fingerprint) for the uploaded file. ->**Permission:** update_file -- - - - - - ->**Properties** -- - - - - -+ **value (string, required)** - The entire file hash (computed by client). -+ **algorithm (string, required)** - The algorithm used by client to compute entire file hash (i.e. md5, sha256, sha1, etc.). - ->**Rules** -- - - - - -+ The reported `value` must be a valid algorithm - supported/valid algorithms are: `md5`, `sha256`, and `sha1`. -+ The upload must be in a completed state (i.e. `upload_status.completed_on`). - -+ Parameters - + id (string, required, `666be35a-98e0-4c2e-9a17-7bc009f9bb23`) ... The unique `id` of the upload. - -+ Request - - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5" - } - -+ Response 200 (application/json) - - { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "project": {"id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"}, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "content_type": "application/octet-stream", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "chunks": [ - { - "number": 1, - "size": 5024000, - "hash": { - "value": "jw23df2207d99a74fbe169e3eba035e633b65d88", - "algorithm": "md5" - } - }, - { - "number": 2, - "size": 5024000, - "hash": { - "value": "ry23df2207d99a74fbe169e3eba035e633b65dkq", - "algorithm": "md5" - } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - }, - "status": { - "initiated_on": "2015-07-10T13:00:00Z", - "completed_on": "2015-07-10T13:00:00Z", - "error_on": null, - "error_message": null - }, - "audit": { } - } - - -## Group Files -A file resource represents a virtual container for a physical data file (i.e. `upload`) that is persisted in a storage backend supported by Duke Data Services (e.g. Duke OIT Swift Service). - -## Files collection [/files] - -### Create file [POST] -Creates a file metadata resource; the client is responsible for the creation of this resource after confirming the associated physical file has been successfully uploaded to a storage provider (see `Uploads` actions). - -*Note: A file is a versionable resource; this action creates the initial version of a file. New file versions can be created (uploaded) via the* `/file/{id}/update` *action. Versions can be managed via the* **File Versions** *actions.* - ->**Permission:** create_file -- - - - - - ->**Properties** -- - - - - -+ **parent.kind (string, required)** - The kind of parent container for the file; this can be a project (i.e. `dds-project`) or a folder (i.e. `dds-folder`). -+ **parent.id (string, required)** - The unique id of the parent. -+ **upload.id (string, required)** - The unique id for an upload that completed successfully. -+ **label (string, optional)** - An optional version label for the file. - ->**Rules** -- - - - - -+ The current user must be the user who uploaded the file. -+ The parent object (`dds-project` or `dds-folder`) must be associated with the same project that the upload is associated with. -+ The upload must be in a completed state (i.e. `upload.completed_on != null`). - -+ Request (application/json) - - { - "parent": { - "kind": "dds-folder", - "id": "ad9115b8-1e4a-4399-b606-56622eb462e1" - }, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23" - }, - "label": "Initial raw data from device" - } - -+ Response 201 (application/json) - - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 1, - "label": "Initial raw data from device", - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - -## File instance [/files/{id}] -+ Parameters - + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. - -### View file [GET] ->**Permission:** view_project -- - - - - - -+ Response 200 (application/json) - - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 1, - "label": "Initial raw data from device", - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - -### Update file [PUT] -Updates one or more file resource properties; if this action includes an `upload.id` property in the request, a new file version is created and associated to the file - this becomes the `current_version` of the file (see **File Versions**). - -*Note: Only the* `upload` *and* `label` *properties for the file are versioned; all other file properties and relationships, such as name, tags, metadata properties, etc. are not versioned, and they will not vary from version to version.* - ->**Permission:** update_file -- - - - - - ->**Properties** -- - - - - -+ **upload.id (string, optional)** - An optional unique id for an upload that completed successfully; if specified, a new file version is created. -+ **label (string, optional)** - An optional version label for the file. - ->**Rules** -- - - - - -+ The current user must be the user who uploaded the file. -+ The upload must be in a completed state (i.e. `upload.completed_on != null`). -+ Only `upload.id`, `label` properties can be updated via this action. -+ New versions are assigned the next sequential `version` number. (see **File Versions**) - -+ Request (application/json) - - { - "upload": { - "id": "422f8778-a62c-4918-8b1b-f398a041345a" - }, - "label": "Post pairwise sequence alignment" - } - -+ Response 200 (application/json) - - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", - "name": "Sequencing Archive" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 2, - "label": "Post pairwise sequence alignment", - "upload": { - "id": "56a0431f-5a89-455a-aa2d-996ae9226601", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - -### Delete file [DELETE] ->**Permission:** delete_file -- - - - - - ->**Rules** -- - - - - -+ This operation recursively deletes all the related file versions. - -+ Response 204 - -## Get file download URL [GET /files/{id}/url] -Generates and returns a storage provider specific pre-signed URL that client can use to download file; the download URL is for the current version of the specified file. - -*Note: This action returns URL to download current version of the file - to download a prior version see* **File Versions** *actions.* - ->**Permission:** download_file -- - - - - - -+ Parameters - + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. - -+ Response 200 (application/json) - - { - "http_verb": "GET", - "host": "swift.oit.duke.edu", - "url": "/v1/AUTH_dev/418da9e8-7d01-4761-982c-811d95ac6653/0618a1bc-5042-48d2-af66-ed171354bf6b?temp_url_sig=93b5c5a2c920f0d4962c391d932e4054ec76916c&temp_url_expires=1448918738", - "http_headers": [ ] - } - -## Move file [PUT /files/{id}/move] -Move file to a different parent project or parent folder. - ->**Permission:** create_file -- - - - - - -+ Parameters - + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. - -+ Request (application/json) - - { - "parent": { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" - } - } - -+ Response 200 (application/json) - - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", - "name": "Sequencing Archive" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 2, - "label": "Post pairwise sequence alignment", - "upload": { - "id": "56a0431f-5a89-455a-aa2d-996ae9226601", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - -## Rename file [PUT /files/{id}/rename] -Change the name of a file. - ->**Permission:** update_file -- - - - - - -+ Parameters - + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. - - -+ Request (application/json) - - { - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata" - } - -+ Response 200 (application/json) - - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", - "name": "Sequencing Archive" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 2, - "label": "Post pairwise sequence alignment", - "upload": { - "id": "56a0431f-5a89-455a-aa2d-996ae9226601", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - -## Group File Versions -The actions herein are used to interact with prior versions of a file resource. - -*Note: Only the* `upload` *and* `label` *properties for the file are versioned; all other file properties and relationships, such as name, tags, etc. are not versioned, and they will not vary from version to version.* - -## File Versions collection [/files/{id}/versions] -+ Parameters - + id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique `id` of the file. - -### List file versions [GET] -This action can be used to list all prior versions of a file, including the current version. - ->**Permission:** view_project -- - - - - - ->**Rules** -- - - - - -+ File versions that have been deleted (i.e. `"is_deleted": true`) are included in this listing, but are immutable. - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Initial raw data from device", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - } - ] - } - -## File Version instance [/file_versions/{id}] -+ Parameters - + id (string, required, `89ef1e77-1a0b-40a8-aaca-260d13987f2b`) ... The unique `id` of the file version. - -### View file version [GET] ->**Permission** view_project -- - - - - - -+ Response 200 (application/json) - - { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Initial raw data from device", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - } - -### Update file version [PUT] ->**Permission:** update_file -- - - - - - ->**Rules** -- - - - - -+ Only the `label` property for a file version can be updated via this action. - -+ Request (application/json) - - { - "label": "Post pairwise sequence alignment (piecewise)" - } - -+ Response 200 (application/json) - - { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Post pairwise sequence alignment (piecewise)", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - } - -### Delete file version [DELETE] ->**Permission:** delete_file -- - - - - - ->**Rules** -- - - - - -+ The current file version cannot be deleted. - -+ Response 204 - -## Get file version download URL [GET /file_versions/{id}/url] -Generates and returns a storage provider specific pre-signed URL that client can use to download the file version. ->**Permission:** download_file -- - - - - - -+ Parameters - + id (string, required, `89ef1e77-1a0b-40a8-aaca-260d13987f2b`) ... The unique `id` of the file version. - -+ Response 200 (application/json) - - { - "http_verb": "GET", - "host": "swift.oit.duke.edu", - "url": "/v1/AUTH_dev/418da9e8-7d01-4761-982c-811d95ac6653/0618a1bc-5042-48d2-af66-ed171354bf6b?temp_url_sig=93b5c5a2c920f0d4962c391d932e4054ec76916c&temp_url_expires=1448918738", - "http_headers": [ ] - } - -## Promote file version [POST /file_versions/{id}/current] -This action can be used to promote a prior file version to the current version. This actually mints a copy of the specified version and puts it on the top of the version stack. ->**Permission:** update_file -- - - - - - ->**Rules** -- - - - - -+ The current file version cannot be promoted. - -+ Parameters - + id (string, required, `89ef1e77-1a0b-40a8-aaca-260d13987f2b`) ... The unique `id` of the file version to be promoted to the current version. - -+ Response 201 (application/json) - - { - "kind": "dds-file-version", - "id": "66ed147e-2312-4974-999a-58ec77230182", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 3, - "label": "Post pairwise sequence alignment (piecewise)", - "is_deleted": false, - "upload": { - "id": "56a0431f-5a89-455a-aa2d-996ae9226601", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - } - -## Group Search Children -Search for the children (i.e. folders and files) of a project or folder. - -## Search project children [GET /projects/{id}/children{?name_contains,kind}] ->**Permission:** view_project -- - - - - - ->**Rules** -- - - - - -+ Searches the immediate children of the project unless the `name_contains` parameter is specified; when specified, the `name_contains` parameter invokes a recursive search of the project hierarchy. -+ Folders/files that have been deleted (i.e. `"is_deleted": true`) are not included in search. - -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. - + name_contains (string, optional, `Sequencing`) ... Returns children where their `name` contains the specified string. - + kind (string, optional, `dds-folder`) ... Returns children of the specified kind; supported kinds are `dds-folder` and `dds-file`. - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-folder", - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "Raw Data", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "audit": { } - }, - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", - "name": "Sequencing Archive" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 1, - "label": "Initial raw data from device", - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - ] - } - -## Search folder children [GET /folders/{id}/children{?name_contains,kind}] ->**Permission:** view_project -- - - - - - ->**Rules** -- - - - - -+ Searches the immediate children of the folder unless the `name_contains` parameter is specified; when specified, the `name_contains` parameter invokes a recursive search of the folder hierarchy. -+ Folders/files that have been deleted (i.e. `"is_deleted": true`) are not included in search. - -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the folder. - + name_contains (string, optional, `Sequencing`) ... Returns children where their `name` contains the specified string. - + kind (string, optional, `dds-folder`) ... Returns children of the specified kind; supported kinds are `dds-folder` and `dds-file`. - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-folder", - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "Raw Data", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "audit": { } - }, - { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "parent": { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e" - }, - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", - "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e", - "name": "Sequencing Archive" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 1, - "label": "Initial raw data from device", - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { } - } - ] - } - -## Group Provenance Activities -Represents the main record of provenance in DDS; it is analogous to *Activity* defined in the [W3C Specification on Provenance](https://www.w3.org/TR/prov-primer/). Activities are recorded/tracked by researchers and their *Software Agents* with the intent of maintaining comprehensive data provenance. - -*Note: Provenance relations to an activity, such as* `used` *and* `wasGeneratedBy` *are managed through the* **Provenance Relations** *API actions.* - -## Activities collection [/activities] - -### Create activity [POST] ->**Permission:** authenticated -- - - - - - ->**Properties** -- - - - - -+ **name (string, required)** - A short name for this activity. -+ **description (string, optional)** - A verbose description for this activity. -+ **started_on (string, optional)** - The time this activity was started; defaults to the current datetime if not specified. -+ **ended_on (string, optional)** - The time this activity ended. - ->**Rules** -- - - - - -+ The `ended_on` time must be greater than or equal to the `started_on` time. - -+ Request (application/json) - - { - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity" - } - -+ Response 201 (application/json) - - { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": null, - "is_deleted": false, - "audit": { } - } - -### List activities [GET] ->**Permission:** -- - - - - -+ authenticated [scope: creator *or* visiblity to single entity that has a provenance relation to the activity] - ->**Rules** -- - - - - -+ Activities that have been deleted (i.e. `"is_deleted": true`) are not included. - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": null, - "is_deleted": false, - "audit": { } - } - ] - } - -## Activities instance [/activities/{id}] -+ Parameters - + id (string, required, `a1ff02a4-b7e9-999d-87x1-66f4c881jka1`) ... The unique id of the activity. - -### View activity [GET] ->**Permission:** -- - - - - -+ creator *or* visiblity to single entity that has a provenance relation to the activity - -+ Response 200 (application/json) - - { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": null, - "is_deleted": false, - "audit": { } - } - -### Update activity [PUT] ->**Permission:** creator -- - - - - - ->**Rules** -- - - - - -+ Only `name`, `description`, `started_on`, and `ended_on` properties may be updated via this action. - -+ Request (application/json) - - { - "ended_on": "2015-01-01T14:30:00Z" - } - -+ Response 200 (application/json) - - { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - } - -### Delete activity [DELETE] ->**Permission:** creator -- - - - - - -+ Response 204 - -## Group Provenance Relations -Represents provenance relations as defined in the [W3C Specification on Provenance](https://www.w3.org/TR/prov-primer/). Relations are recorded/tracked by researchers and their *Software Agents* with the intent of maintaining comprehensive data provenance. - -## Relations collection [/relations] - -### Create used relation [POST /relations/used] ->**Permission:** creator of the activity *and* visibility to the `used` entity -- - - - - - ->**Properties** -- - - - - -+ **activity.id (string, required)** - The activity that used the entity. -+ **entity.kind (string, required)** - The kind of entity that was used; this must be a file version (i.e. `dds-file-version`). -+ **entity.id (string, required)** - The unique id of the used entity. - ->**Rules** -- - - - - -+ An entity (i.e. `file_version`) cannot be used and generated by the same activity (i.e. `dds-activity`). - -+ Request (application/json) - - { - "activity": { - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" - }, - "entity": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b" - } - } - -+ Response 201 (application/json) - - { - "kind": "dds-relation-used", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "from": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - }, - "to": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Post pairwise sequence alignment (piecewise)", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "audit": { } - } - -### Create was generated by relation [POST /relations/was_generated_by] ->**Permission:** creator of the activity *and* update_file for the `wasGeneratedBy` entity -- - - - - - ->**Properties** -- - - - - -+ **entity.kind (string, required)** - The kind of entity that was generated; this must be a file version (i.e. `dds-file-version`). -+ **entity.id (string, required)** - The unique id of the generated entity. -+ **activity.id (string, required)** - The activity that generated the entity. - ->**Rules** -- - - - - -+ An entity (i.e. `file_version`) can be generated by one and only one activity (i.e. `dds-activity`). -+ An entity (i.e. `file_version`) cannot be used and generated by the same activity (i.e. `dds-activity`). - -+ Request (application/json) - - { - "entity": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" - }, - "activity": { - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" - } - } - -+ Response 201 (application/json) - - { - "kind": "dds-relation-was-generated-by", - "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", - "from": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "to": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - }, - "audit": { } - } - -### Create was derived from relation [POST /relations/was_derived_from] ->**Permission:** visibility to the `used` entity and update_file for the `generated` entity. -- - - - - - ->**Properties** -- - - - - -+ **generated_entity.kind (string, required)** - The kind of entity generated by the derivation; this must be a file version (i.e. `dds-file-version`). -+ **generated_entity.id (string, required)** - The unique id of the generated entity. -+ **used_entity.kind (string, required)** - The kind of entity used by the derivation; this must be a file version (i.e. `dds-file-version`). -+ **used_entity.id (string, required)** - The unique id of the used entity. - -+ Request (application/json) - - { - "generated_entity": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" - }, - "used_entity": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b" - } - } - -+ Response 201 (application/json) - - { - "kind": "dds-relation-was-derived-from", - "id": "6bf31123-b078-4655-ae4e-be599d52adc5", - "from": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "to": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Initial raw data from device", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "audit": { } - } - -### Create was invalidated by relation [POST /relations/was_invalidated_by] ->**Permission:** creator of the activity *and* delete_file for `wasInvalidatedBy` entity -- - - - - - ->**Properties** -- - - - - -+ **entity.kind (string, required)** - The kind of entity that was invalidated; this must be a file version (i.e. `dds-file-version`). -+ **entity.id (string, required)** - The unique id of the invalidated entity. -+ **activity.id (string, required)** - The activity that invalidated the entity. - ->**Rules** -- - - - - -+ The `invalidated` entity must be in a deleted state (i.e. `"is_deleted": true`). -+ An entity (i.e. `file_version`) can be invalidated by one and only one activity (i.e. `dds-activity`). - -+ Request (application/json) - - { - "entity": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" - }, - "activity": { - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" - } - } - -+ Response 201 (application/json) - - { - "kind": "dds-relation-was-generated-by", - "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", - "from": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "to": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - }, - "audit": { } - } - - -### List provenance relations [GET /relations/{object_kind}/{object_id}] -List the relations for a provenance node; this only lists direct relations for the node that are a single hop away. ->**Permission:** visibility to the specified (starting) provenance node (i.e. `object_kind`, `object_id`) - which may be an activity *or* an entity -- - - - - - ->**Rules** -- - - - - -+ Provenance relations that have been deleted (i.e. `"is_deleted": true`) are not included. - -+ Parameters - + object_kind (string, required, `dds-activity`) ... The kind of provenance node; can be one of dds-activity or dds-file-version. - + object_id (string, required, `a1ff02a4-b7e9-999d-87x1-66f4c881jka1`) ... The unique id of the node. - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-relation-used", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "from": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - }, - "to": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Post pairwise sequence alignment (piecewise)", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "audit": { } - } - ] - } - -## Relation instance [/relations/{id}] -+ Parameters - + id (string, required, `ac242faf-fba0-4293-a949-0b82ae7ba810`) ... The unique id of the provenance relation. - -### View relation [GET] ->**Permission:** visibility to a single node for the specified relation - which may be the activity *or* the entity - -+ Response 200 (application/json) - - { - "kind": "dds-relation-used", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "from": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - }, - "to": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 1, - "label": "Post pairwise sequence alignment (piecewise)", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "audit": { } - } - -+ Response 200 (application/json) - - { - "kind": "dds-relation-was-associated-with", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "from": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity", - "started_on": "2015-01-01T12:00:00Z", - "ended_on": "2015-01-01T14:30:00Z", - "is_deleted": false, - "audit": { } - }, - "to": { - "kind": "dds-user", - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "source": "duke_shibboleth", - "uid": "gardner100" - }, - "last_login_on": "2015-01-01T12:00:00Z", - "audit": { } - }, - "audit": { } - } - -+ Response 200 (application/json) - - { - "kind": "dds-relation-was-attributed-to", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "from": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "to": { - "kind": "dds-user", - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "source": "duke_shibboleth", - "uid": "gardner100" - }, - "last_login_on": "2015-01-01T12:00:00Z", - "audit": { } - }, - "audit": { } - } - -+ Response 200 (application/json) - - { - "kind": "dds-relation-was-attributed-to", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "from": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - } - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - }, - "audit": { } - }, - "to": { - "kind": "dds-software-agent", - "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f", - "name": "Sample pipeline agent", - "description": null, - "repo_url": null, - "is_deleted": false, - "audit": { } - }, - "audit": { } - } - -### Delete relation [DELETE] ->**Permission:** creator - -+ Response 204 - -## Group Search Provenance -The `Provenance Relations` API actions allows users and software agents to record the use and production of entities (i.e. files, file versions, etc.) by research activities, which may be influenced in various ways by agents. The resulting provenace chain is organized as a [graph structure](https://en.wikipedia.org/wiki/Graph_database). The search API can be used by client applications to extract the provenace graph in a JSON data format that can be transformed to a visual representation. - -*Note: The provenance graph structure is stored in a* [Neo4J](http://neo4j.com) *database and ubiquitous JavaScript libraries can be used for* [graph rendering](http://neo4j.com/developer/guide-data-visualization). - -## Search Provenance [POST /search/provenance] -Given a starting node, returns a graph structure for the provenance chain. This structure is based on the Neo4J JSON graph format. ->**Permission:** visibility to the specified (starting) provenance node (i.e. `start_node.kind`, `start_node.id`) - which may be an activity *or* an entity -- - - - - - ->**Rules:** -- - - - - -+ If the user does not have visibilty to a `node` in the resulting graph, the `properties` attribute for that `node` will be a partial resource containing: `kind`, `id`, and `is_deleted`. - ->**Properties** -- - - - - -+ **start_node.kind (string, required)** - The kind of provenance node; can be one of `dds-activity` or `dds-file-version`. -+ **start_node.id (string, required)** - The unique id of the node. -+ **max_hops (number, optional)** - The max number of hops (degree of node separation) to traverse from the starting node; defaults to infinity. - -+ Request (application/json) - - { - "start_node": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1" - } - } - -+ Response 200 (application/json) - - { - "graph": { - "nodes": [ - { - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "labels": ["Activity"], - "properties": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "is_deleted": false, - "audit": { } - } - }, - { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "labels": ["File Version"], - "properties": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" - }, - "version": 1, - "label": "Initial raw data from device", - "is_deleted": false, - "audit": { } - } - }, - { - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "labels": ["File Version"], - "properties": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "audit": { } - } - } - ], - "relationships": [ - { - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "type": "used", - "start_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "end_node": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "properties": { - "kind": "dds-relation-used", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "audit": { } - } - }, - { - "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", - "type": "wasGeneratedBy", - "start_node": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "end_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "properties": { - "kind": "dds-relation-was-generated-by", - "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", - "audit": { } - } - } - ] - } - } - -## NOT_IMPLEMENTED_NEW Search Provenance wasGeneratedBy [POST /search/provenance/origin] -This is a targeted query that navigates "up" the provenance chain for a file version to see how it was generated (i.e. by what activity) and from what source file versions. Given a list of file versions, this action perform the following query for each *File Version*: - -1. Gets all related *wasDerivedFrom* file versions (if they exist). -2. Gets the generating activity (if it exists). -3. For the generating activity, gets the list of *wasGeneratedBy* and *used* file versions. - -A graph structure of the unique nodes and relationships is returned. - ->**Rules:** -- - - - - -+ All of the provided file versions must exist or a validation error is returned. -+ If a file version does not have a generating activity, then only the file version node is returned. -+ If the user does not have visibilty to a `node` in the resulting graph, the `properties` attribute for that `node` will be a partial resource containing: `kind`, `id`, and `is_deleted`. - ->**Properties** -- - - - - -+ **file_versions (object[ ], required)** - The list of file versions (i.e. `dds-file-version`) -+ **file_versions[ ].id (string, required)** - The unique file version id. - -+ Request (application/json) - - { - "file_versions": [ - { - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3" - } - ] - } - -+ Response 200 (application/json) - - { - "graph": { - "nodes": [ - { - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "labels": ["Activity"], - "properties": { - "kind": "dds-activity", - "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "name": "RF PI3-Kinase", - "is_deleted": false, - "audit": { } - } - }, - { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "labels": ["File Version"], - "properties": { - "kind": "dds-file-version", - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" - }, - "version": 1, - "label": "Initial raw data from device", - "is_deleted": false, - "audit": { } - } - }, - { - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "labels": ["File Version"], - "properties": { - "kind": "dds-file-version", - "id": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "file": { - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111", - "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata" - }, - "version": 2, - "label": "Alignment performed on raw data", - "is_deleted": false, - "audit": { } - } - } - ], - "relationships": [ - { - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "type": "used", - "start_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "end_node": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "properties": { - "kind": "dds-relation-used", - "id": "ac242faf-fba0-4293-a949-0b82ae7ba810", - "audit": { } - } - }, - { - "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", - "type": "wasGeneratedBy", - "start_node": "1b80a313-97cf-482d-8d17-9b911bf815b3", - "end_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1", - "properties": { - "kind": "dds-relation-was-generated-by", - "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95", - "audit": { } - } - } - ] - } - } - -## Group Tags -A tag is a label (i.e. word or phrase) that can be associated to an object to facilitate classification and searching. - -*Note: Tags are composite metadata that become part of the tagged resource - they do not live in a global namespace. Only tagging of files* (i.e. `dds-file`) *is currently supported.* - -## Tags collection [/tags/{object_kind}/{object_id}] -+ Parameters - + object_kind (string, required, `dds-file`) ... The kind of object. - + object_id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique id of the object. - -### Create object tag [POST] ->**Permission:** update_file when tagged object is file (`dds-file`) -- - - - - - ->**Properties** -- - - - - -+ **label (string, required)** - The textual tag content. - ->**Rules:** -- - - - - -+ The specified `label` must not already exist for the `(object.kind, object.id)`, the `label` comparison is *case-insensitive*. - -+ Request (application/json) - - { - "label": "SMRT sequencing" - } - -+ Response 201 (application/json) - - { - "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", - "object": { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111" - }, - "label": "SMRT sequencing", - "audit": { } - } - - -### List object tags [GET] ->**Permission:** view_project when tagged object is file (`dds-file`) -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", - "object": { - "kind": "dds-file", "id": - "777be35a-98e0-4c2e-9a17-7bc009f9b111" - }, - "label": "SMRT sequencing", - "audit": { } - } - ] - } - -## Append a list of object tags [POST /tags/{object_kind}/{object_id}/append] -Append a list of tags to an object. ->**Permission:** update_file when tagged object is file (`dds-file`) -- - - - - - ->**Properties** -- - - - - -+ **tags (object[], required)** - An array of tags to apply to the object; object structure is as follows: -+ **label (string, required)** - The textual tag content. - ->**Rules:** -- - - - - -+ If the object has an exisiting tag with the specified `label`, the `label` is ignored and a tag is not appended (i.e. created); the `label` comparison is *case-insensitive*. -+ The request must specify at least one `label`. -+ The response only contains the list of `tags` that were appended (i.e. created). - -+ Parameters - + object_kind (string, required, `dds-file`) ... The kind of object. - + object_id (string, required, `777be35a-98e0-4c2e-9a17-7bc009f9b111`) ... The unique id of the object. - -+ Request (application/json) - - { - "tags": [ - {"label": "SMRT sequencing"} - ] - } - -+ Response 201 (application/json) - - { - "results": [ - { - "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", - "object": { - "kind": "dds-file", "id": - "777be35a-98e0-4c2e-9a17-7bc009f9b111" - }, - "label": "SMRT sequencing", - "audit": { } - } - ] - } - -## List tag labels [GET /tags/labels{?object_kind,label_contains}] -Get a list of the **distinct** tag `label` values visible to the current user. - -*Note: Intent of this action is to allow Web and native UX apps to render tag clouds and enable auto-complete widgets.* - ->**Permission:** authenticated [scope: view_project when tagged object is file (`dds-file`)] -- - - - - - ->**Rules:** -- - - - - -+ The returned tags are sorted in most recently used (i.e. `last_used_on`) order. - -+ Parameters - + object_kind (string, optional, `dds-file`) ... Restricts search scope to tags for this kind of object. - + label_contains (string, optional, `sequen`) ... If provided, searches for tags that contain this text fragment. - -+ Response 200 (application/json) - - { - "results": [ - { - "label": "SMRT sequencing", - "count": 47, - "last_used_on": "2015-01-01T12:10:00Z" - }, - { - "label": "Polony sequencing", - "count": 21, - "last_used_on": "2015-01-01T12:05:00Z" - }, - { - "label": "DNA nanoball sequencing", - "count": 13, - "last_used_on": "2015-01-01T12:00:00Z" - } - ] - } - -## Tag instance [/tags/{id}] -+ Parameters - + id (string, required, `66211c4e-a49e-42d7-9793-87989d56e1e3`) ... The unique id of the tag. - -### View tag [GET] ->**Permission:** view_project when tagged object is file (`dds-file`) -- - - - - - -+ Response 200 (application/json) - - { - "id": "66211c4e-a49e-42d7-9793-87989d56e1e3", - "object": { - "kind": "dds-file", - "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111" }, - "label": "SMRT sequencing", - "audit": { } - } - -### Delete tag [DELETE] ->**Permission:** update_file when tagged object is file (`dds-file`) -- - - - - - -+ Response 204 - -## Group Metadata -The metadata actions allow researchers to define, store, and associate custom attributes with their digital assets (e.g. activities, files, etc.). Unlike *Tags*, which are just textual labels, metadata are structured `key:value` pairs. For example, an experiment (i.e. represented as a provenance *Activity*) may have the following metadata properties: `[{"assay": "ChIP-seq"}, {"organism": "Mus Musculus"}, {"biosample_type": "tissue"}]`. - -Metadata must be defined and captured in the context of a metadata template. Templates allow related keys (i.e. properties) to be grouped together. For example, a template named *seq_platform_info* may contain properties that describe the characteristics of the sequencing platform. In addition, templates enforce data type (i.e. string, integer, etc.) integrity for the contained keys, so that clients are type aware when referencing key values from a search or data processing perspective. Metatdata templates are global in scope and visible to all users. - -## Metadata Templates collection [/templates] - -### Create metadata template [POST] ->**Permission:** authenticated -- - - - - - ->**Properties** -- - - - - -+ **name (string, required)** - The unique name of the template; the name must meet the following criteria: - - contain only alphanumerics and underscores - - no whitespace - - maximum of 60 characters -+ **label (string, required)** - A short display label for the template. -+ **description (string, optional)** - A verbose description of the template. - ->**Rules:** -- - - - - -+ The template `name` must be unique in the global context. - -+ Request (application/json) - - { - "name": "sequencing_file_info", - "label": "Sequencing File Info", - "description": "Extended attributes for sequencing output files." - } - -+ Response 201 (application/json) - - { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info", - "label": "Sequencing File Info", - "description": "Extended attributes for sequencing output files.", - "audit": { } - } - -## List metadata templates [GET /templates{?name_contains}] -List all of the global metadata templates. ->**Permission:** authenticated -- - - - - - -+ Parameters - + name_contains (string, optional, `Sequencing`) ... Returns templates in which `name` contains the specified string. - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info", - "label": "Sequencing File Info", - "description": "Extended attributes for sequencing output files.", - "audit": { } - } - ] - } - -## Metadata Template instance [/templates/{id}] -+ Parameters - + id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique `id` of the template. - - -### View metadata template [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info", - "label": "Sequencing File Info", - "description": "Extended attributes for sequencing output files (raw and processed).", - "audit": { } - } - -### Update metadata template [PUT] ->**Permission:** creator or system_admin -- - - - - - ->**Rules** -- - - - - -+ The `name` cannot be updated if the template has been associated to one or more DDS objects. - -+ Request (application/json) - - { - "description": "Extended attributes for sequencing output files (raw and processed)." - } - -+ Response 200 (application/json) - - { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info", - "label": "Sequencing File Info", - "description": "Extended attributes for sequencing output files (raw and processed).", - "audit": { } - } - - -### Delete metadata template [DELETE] ->**Permission:** creator or system_admin -- - - - - - ->**Rules** -- - - - - -+ The template cannot be deleted if it has been associated to one or more DDS objects. - -+ Response 204 - -## Metadata Properties collection [/templates/{id}/properties] -+ Parameters - + id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique `id` of the template. - -### Create metadata property [POST] ->**Permission:** template creator or system_admin -- - - - - - ->**Properties** -- - - - - -+ **key (string, required)** - The unique key for the property; the key must meet the following criteria: - - contain only alphanumerics and underscores - - no whitespace - - maximum of 60 characters -+ **label (string, required)** - A short display label for the property. -+ **description (string, required)** - A verbose description of the property. -+ **type (string, required)** - The datatype of the key's value; currenty only the Elasticsearch core datatypes are supported: [Elasticsearch Core Datatypes](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html). - ->**Rules:** -- - - - - -+ The property `key` must be unique within the context of the template. - -+ Request (application/json) - - { - "key": "output_type", - "label": "Output Type", - "description": "The type of data in the sequencing output file.", - "type": "string" - } - -+ Response 201 (application/json) - - { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "key": "output_type", - "label": "Output Type", - "description": "The type of data in the sequencing output file.", - "type": "string", - "audit": { } - } - -## List metadata properties [GET /templates/{id}/properties] -List metadata template properties. ->**Permission:** authenticated -- - - - - - -+ Parameters - + id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique `id` of the template. - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "key": "output_type", - "label": "Output Type", - "description": "The type of data in the sequencing output file.", - "type": "string", - "audit": { } - } - ] - } - -## Metadata Property instance [/template_properties/{id}] -+ Parameters - + id (string, required, `48d34c8f-4284-4327-9ca6-7a9145a1c957`) ... The unique `id` of the template property. - - -### View metadata property [GET] ->**Permission:** authenticated -- - - - - - -+ Response 200 (application/json) - - { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "key": "output_type", - "label": "Output Type", - "description": "The type of data in the sequencing output file. (alignments, peaks, signal)", - "type": "string", - "audit": { } - } - -### Update metadata property [PUT] ->**Permission:** creator or system_admin -- - - - - - ->**Rules** -- - - - - -+ The `key` or `type` cannot be updated if the template property has been associated to one or more DDS objects. - -+ Request (application/json) - - { - "description": "The type of data in the sequencing output file. (alignments, peaks, signal)" - } - - -+ Response 200 (application/json) - - { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "key": "output_type", - "label": "Output Type", - "description": "The type of data in the sequencing output file. (alignments, peaks, signal)", - "type": "string", - "audit": { } - } - -### Delete metadata property [DELETE] ->**Permission:** creator or system_admin -- - - - - - ->**Rules** -- - - - - -+ The template property cannot be deleted if it is assigned to one or more DDS objects. - -+ Response 204 - -## Object Metadata instance [/meta/{object_kind}/{object_id}/{template_id}] -+ Parameters - + object_kind (string, required, `dds-file`) ... The kind of object. - + object_id (string, required, `b80a2679-f6bf-46da-acaa-b7a4582b1eda`) ... The unique id of the object. - + template_id (string, required, `168f3f51-6800-403a-973d-78b23c08049b`) ... The unique id of the template. - -### Create object metadata [POST] -Used to create a metadata template instance for a corresponding DDS object (i.e. `dds-file`). When creating metadata, only values that adhere to the metadata template schema will be accepted. ->**Permission:** update_file when annotated object is file (`dds-file`) -- - - - - - ->**Properties** -- - - - - -+ **properties (object[ ], required)** - A list of the `key:value` pairs to set for the template instance. -+ **properties[ ].key (string, required)** - The property key to set. -+ **properties[ ].value (any, required)** - The key value. - ->**Rules:** -- - - - - -+ All specified `key:values` must adhere to the metadata template schema or a validation error will be returned. -+ If the template instance already exists for the DDS object, a validation (unique conflict) error will be returned and the update method should be used. - -+ Request (application/json) - - { - "properties": [ - { - "key": "output_type", - "value": "alignments" - } - ] - } - -+ Response 201 (application/json) - - { - "object": { - "kind": "dds-file", - "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" - }, - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "properties": [ - { - "template_property": { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "key": "output_type" - }, - "value": "alignments" - } - ] - } - -### View object metadata [GET] -Used to retrieve the metadata template instance for a corresponding DDS object. ->**Permission:** authenticated [scope: view_project when annotated object is file (`dds-file`)] -- - - - - - -+ Response 200 (application/json) - - { - "object": { - "kind": "dds-file", - "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" - }, - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "properties": [ - { - "template_property": { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "key": "output_type" - }, - "value": "alignments" - } - ] - } - -### Update object metadata [PUT] -Used to update a metadata template instance for a corresponding DDS object (i.e. `dds-file`). When updating metadata, only values that adhere to the metadata template schema will be accepted. ->**Permission:** update_file when annotated object is file (`dds-file`) -- - - - - - ->**Properties** -- - - - - -+ **properties (object[ ], required)** - A list of the `key:value` pairs to set for the template instance. -+ **properties[ ].key (string, required)** - The property key to set. -+ **properties[ ].value (any, required)** - The key value. - ->**Rules:** -- - - - - -+ All specified `key:values` must adhere to the metadata template schema or a validation error will be returned. -+ If the specified `key` already exists, the value is updated, otherwise it is appended to the template instance. -+ If the template instance specified does not exist, a validation error will be returned and the create method should be used. - -+ Request (application/json) - - { - "properties": [ - { - "key": "output_type", - "value": "peaks" - } - ] - } - -+ Response 200 (application/json) - - { - "object": { - "kind": "dds-file", - "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" - }, - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "properties": [ - { - "template_property": { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "key": "output_type" - }, - "value": "peaks" - } - ] - } - -### Delete object metadata [DELETE] -Used to delete the metadata template instance. ->**Permission:** update_file when annotated object is file (`dds-file`) -- - - - - - -+ Response 204 - -## View All Object Metadata [/meta/{object_kind}/{object_id}] -+ Parameters - + object_kind (string, required, `dds-file`) ... The kind of object. - + object_id (string, required, `b80a2679-f6bf-46da-acaa-b7a4582b1eda`) ... The unique id of the object. - -### View All Object Metadata [GET] -Used to retrieve all metadata associated with a DDS object, optionally find a template instance by name. ->**Permission:** authenticated [scope: view_project when annotated object is file (`dds-file`)] -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "object": { - "kind": "dds-file", - "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda" - }, - "template": { - "id": "168f3f51-6800-403a-973d-78b23c08049b", - "name": "sequencing_file_info" - }, - "properties": [ - { - "template_property": { - "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957", - "key": "output_type" - }, - "value": "alignments" - } - ] - } - ] - } - -## Group Search Objects -The search action can be used to find specific DDS objects (e.g. folders, files, etc.). The DDS platform leverages [Elasticsearch](https://www.elastic.co/) to perform document based searches. All queries must be specified in [Elasticsearch Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html). - -*Note: Only search for DDS folders and files* (i.e. `dds-folder`, `dds-file`) *is currently supported. These objects are replicated to Elasticsearch as indexed documents. The objects (i.e. documents) are extended with a* `tags` *and* `meta` *property when stored in Elaticsearch. These properties have composite metadata to facilitate search. See response payload for concrete example format of these properties.* - -*Deprecation: The* **Search Children** *actions will be deprecated once this action has been implemented.* - -## Search Objects [POST /search] -Search for DDS objects (i.e. Elasticsearch documents). ->**Permission:** authenticated [scope: view_project for objects of kind (`dds-folder`, `dds-file`)] -- - - - - - ->**Properties** -- - - - - -+ **include_kinds (string[ ], required)** - The kind of objects (i.e. Elasticsearch document types) to include in the search; can include folders and/or files (i.e. `dds-folder`, `dds-file`). -+ **search_query (object, required)** - The Elasticsearch query criteria (i.e. Query DSL). - -+ Request (application/json) - - { - "include_kinds": ["dds-file"], - "search_query": { - "query": { - "match" : { - "_all" : "SMRT sequencing" - } - } - } - -+ Response 200 (application/json) - - { - "results": [ - { - "kind": "dds-file", - "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda", - "parent": { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy" - }, - "name": "ENCFF000SJR.bam", - "project": { - "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a" - }, - "ancestors": [ - { - "kind": "dds-project", - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1", "name": "Knockout Mouse Project (KOMP)" - }, - { - "kind": "dds-folder", - "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy", - "name": "Sequencing Core" - } - ], - "is_deleted": false, - "current_version": { - "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b", - "version": 1, - "label": "Processed sequence data", - "upload": { - "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23", - "size": 30024000, - "hashes": [ - { - "value": "cf23df2207d99a74fbe169e3eba035e633b65d94", - "algorithm": "md5", - "audit": { } - } - ], - "storage_provider": { - "id": "g5579f73-0558-4f96-afc7-9d251e65bv33", - "name": "duke_oit_swift", - "description": "Duke OIT Storage" - } - } - }, - "audit": { }, - "tags": [ - "SMRT sequencing", - "GCB lab" - ], - "meta": [ - { - "sequencing_file_info": { - "output_type": "alignments", - "mapping_assembly": "hg19" - } - } - ] - } - ] - } - -## Group Project Transfer -**Proposed endpoints to meet the needs of the GCB project transfer workflow** -The *Project Transfer* actions can be used by research core facilities to formally transfer ownership of a project to a researcher (customer). These endpoints support the transfer workflow and retain a record of the transfer history. - -## Project Transfer collection [/projects/{id}/transfers] -+ Parameters - + id (string, required, `ca29f7df-33ca-46dd-a015-92c46fdb6fd1`) ... The unique `id` of the project. - -### NOT_IMPLEMENTED_NEW Initiate a project transfer [POST] -Initiates a project transfer from the current owner (i.e. `project_admin`) to a new owner or list of owners. ->**Permission:** manage_project_permissions -- - - - - - ->**Request Properties** -- - - - - -+ **to_users (object[ ], required)** - The list of users to transfer project ownership to. -+ **to_users[ ].id (string, required)** - The unique `id` of a user. - ->**Response Properties** -- - - - - -+ **from_user (object)** - The user who initiated the project transfer. -+ **status (string)** - The current status of the project transfer; defaults to `pending`. -+ **status_comment (string)** - An optional comment that can be provided when status transfers to a terminal state. - ->**Rules:** -- - - - - -+ There must be no existing transfers for the `project` in a `pending` state. - -+ Request (application/json) - - { - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712" - } - ] - } - -+ Response 201 (application/json) - - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "pending", - "status_comment": null, - "audit": { } - } - -### NOT_IMPLEMENTED_NEW List project transfers [GET] ->**Permission:** authenticated [scope: manage_project_permissions, transfer initiator (i.e. `from_user`), or a transfer recipient (i.e. in `to_users`)] -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "pending", - "status_comment": null, - "audit": { } - } - ] - } - -## Project Transfer instance [/project_transfers/{id}] -+ Parameters - + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. - -### NOT_IMPLEMENTED_NEW View a project transfer [GET] ->**Permission:** manage_project_permissions, transfer initiator (i.e. `from_user`), or a transfer recipient (i.e. in `to_users`) -- - - - - - -+ Response 200 (application/json) - - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "pending", - "status_comment": null, - "audit": { } - } - -## NOT_IMPLEMENTED_NEW Accept a project transfer [PUT /project_transfers/{id}/accept] -Accept a *pending* project transfer. ->**Permission:** transfer recipient (i.e. in `to_users`)] -- - - - - - ->**Properties** -- - - - - -+ **status_comment (string, optional)** - An optional comment that can be provided. - ->**Rules:** -- - - - - -+ The project transfer must be in a `pending` state. -+ All exisiting permissions for the project are removed, `project_viewer` is granted to the transfer initiater (i.e. `from_user`), and `project_admin` is granted to the list of recipients (i.e. `to_users`) - -+ Parameters - + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. - -+ Request (application/json) - - { - "status_comment": "This data looks great..." - } - -+ Response 200 (application/json) - - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "accepted", - "status_comment": "This data looks great...", - "audit": { } - } - -## NOT_IMPLEMENTED_NEW Reject a project transfer [PUT /project_transfers/{id}/reject] -Reject a *pending* project transfer. ->**Permission:** transfer recipient (i.e. in `to_users`)] -- - - - - - ->**Properties** -- - - - - -+ **status_comment (string, optional)** - An optional comment that can be provided. - ->**Rules:** -- - - - - -+ The project transfer must be in a `pending` state. - -+ Parameters - + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. - -+ Request (application/json) - - { - "status_comment": "Missing alignment files..." - } - -+ Response 200 (application/json) - - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "rejected", - "status_comment": "Missing alignment files...", - "audit": { } - } - -## NOT_IMPLEMENTED_NEW Cancel a project transfer [PUT /project_transfers/{id}/cancel] -Cancel a *pending* project transfer. ->**Permission:** manage_project_permissions -- - - - - - ->**Properties** -- - - - - -+ **status_comment (string, optional)** - An optional comment that can be provided. - ->**Rules:** -- - - - - -+ The project transfer must be in a `pending` state. - -+ Parameters - + id (string, required, `be8ac3c5-84e9-4969-8308-21cd5456946d`) ... The unique `id` of the project transfer. - -+ Request (application/json) - - { - "status_comment": "Sent to the wrong PI..." - } - -+ Response 200 (application/json) - - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "canceled", - "status_comment": "Sent to the wrong PI...", - "audit": { } - } - -## View All Project Transfers [/project_transfers{?status}] -+ Parameters - + status (string, optional, `pending`) ... The `status` of the project transfer; can be one of `pending`,`accepted`, or `canceled`. - -### NOT_IMPLEMENTED_NEW View All Project Transfers [GET] -Used to retrieve all project transfers visible to the current user, optionally filtered by status. ->**Permission:** authenticated [scope: manage_project_permissions, transfer initiator (i.e. `from_user`), or a transfer recipient (i.e. in `to_users`)] -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "be8ac3c5-84e9-4969-8308-21cd5456946d", - "project": { - "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1" - }, - "from_user": { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "full_name": "Matthew Gardner" - }, - "to_users": [ - { - "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712", - "username": "cbrandon01", - "full_name": "Chad Brandon" - } - ], - "status": "pending", - "status_comment": null, - "audit": { } - } - ] - } - -## Group Authentication Providers -Represents the authentication providers (services) that are supported by DDS. - -## Authentication Providers collection [/auth_providers] - -### NOT_IMPLEMENTED_NEW List authentication providers [GET] ->**Permission:** public -- - - - - - -+ Response 200 (application/json) - - { - "results": [ - { - "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", - "name": "duke", - "description": "Duke Authentication Service" - } - ] - } - -## Authentication Provider instance [/auth_providers/{id}] -+ Parameters - + id (string, required, `3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c`) ... The unique `id` of the authentication provider. - -### NOT_IMPLEMENTED_NEW View authentication provider [GET] ->**Permission:** public -- - - - - - -+ Response 200 (application/json) - - { - "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", - "name": "duke", - "description": "Duke Authentication Service" - } - -## NOT_IMPLEMENTED_NEW Get All Authentication Provider Affiliates [GET /auth_providers/{id}/affiliates{?full_name_contains}] -Get a list of affiliates (potential users), for a supported authentication provider. ->**Permission:** public -- - - - - - -+ Parameters - + id (string, required, `3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c`) ... The unique `id` of the authentication provider. - + full_name_contains (string, optional, `gardner`) ... Returns affiliates where their full name contains the specified string. - -+ Response 200 (application/json) - - { - "results": - [ - { - "uid": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", - "name": "duke" - } - } - ] - } - -### NOT_IMPLEMENTED_NEW View User by Auth Provider ID [GET /auth_providers/{id}/affiliates/{uid}/dds_user] -Transform an institutional affiliates UID, such as a Duke NetID, to a DDS specific user identity; can be used by clients prior to calling DDS APIs that require a DDS user in the request payload. ->**Permission:** authenticated -- - - - - - ->**Rules:** -- - - - - -+ If the `id` and `uid` are valid and a corresponding DDS user does not exist, the affiliate is registered as DDS user and returned. - -+ Parameters - + id (string, required, `duke`) ... The `id` of an authentication provider (service) supported by the DDS application. - + uid (string, required, `gardner001`) ... The unique `uid` (user id) in the context of the specified auth provider. - -+ Response 200 (application/json) - - { - "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb", - "username": "mrgardner01", - "first_name": "Matthew", - "last_name": "Gardner", - "full_name": "Matthew Gardner", - "email": "mrgardner01@duke.edu", - "auth_provider": { - "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c", - "name": "duke", - "affiliate": { - "uid": "mrgardner01" - } - }, - "last_login_on": "2015-01-01T12:00:00Z", - "audit": { } - } diff --git a/app/api/dds/v1/activities_api.rb b/app/api/dds/v1/activities_api.rb index 498d1114d..c69edc6ee 100644 --- a/app/api/dds/v1/activities_api.rb +++ b/app/api/dds/v1/activities_api.rb @@ -20,8 +20,8 @@ class ActivitiesAPI < Grape::API detail 'Creates an activity for the given payload.' named 'create activity' failure [ - [200, 'This will never actually happen'], - [201, 'Created Successfully'], + [200, 'This will never happen'], + [201, 'Successfully Created'], [400, 'Activity requires a name'], [401, 'Unauthorized'], [403, 'Forbidden'] @@ -76,9 +76,9 @@ class ActivitiesAPI < Grape::API named 'update activity' failure [ [200, 'Success'], + [400, 'Validation Error'], [401, 'Unauthorized'], [403, 'Forbidden (activity restricted)'], - [400, 'Validation Error'], [404, 'Activity Does not Exist'] ] end diff --git a/app/api/dds/v1/auth_providers_api.rb b/app/api/dds/v1/auth_providers_api.rb new file mode 100644 index 000000000..5591b425b --- /dev/null +++ b/app/api/dds/v1/auth_providers_api.rb @@ -0,0 +1,33 @@ +module DDS + module V1 + class AuthProvidersAPI < Grape::API + helpers PaginationParams + + desc 'List Authentication Providers' do + detail 'Lists Authentication Providers' + named 'list Authentication Providers' + failure [ + [200, 'Success'] + ] + end + params do + use :pagination + end + get '/auth_providers', root: 'results', each_serializer: AuthenticationServiceSerializer do + paginate(AuthenticationService) + end + + desc 'Show Authentication Provider Details' do + detail 'Show Authentication Provider Details' + named 'show authentication provider details' + failure [ + [200, 'Success'], + [404, 'Authentication Provider Does not Exist'] + ] + end + get '/auth_providers/:id', root: false, serializer: AuthenticationServiceSerializer do + AuthenticationService.find(params[:id]) + end + end + end +end diff --git a/app/api/dds/v1/base.rb b/app/api/dds/v1/base.rb index a5a56cbd5..915922514 100644 --- a/app/api/dds/v1/base.rb +++ b/app/api/dds/v1/base.rb @@ -152,6 +152,14 @@ def not_implemented_error! } error!(error_body, 405) end + + def get_auth_service(service_id = nil) + if service_id + AuthenticationService.where(service_id: service_id).take or raise InvalidAuthenticationServiceIDException.new() + else + AuthenticationService.where(is_default: true).take! + end + end end rescue_from ActiveRecord::RecordNotFound do |e| @@ -195,6 +203,22 @@ def not_implemented_error! error!(error_json, 500) end + rescue_from InvalidAccessTokenException do + error!({ + error: 401, + reason: 'invalid access_token', + suggestion: 'token not properly signed' + },401) + end + + rescue_from InvalidAuthenticationServiceIDException do + error!({ + error: 401, + reason: 'invalid access_token', + suggestion: 'authentication service not registered' + },401) + end + mount DDS::V1::UsersAPI mount DDS::V1::SystemPermissionsAPI mount DDS::V1::AppAPI @@ -219,6 +243,7 @@ def not_implemented_error! mount DDS::V1::PropertiesAPI mount DDS::V1::MetaTemplatesAPI mount DDS::V1::ProjectTransfersAPI + mount DDS::V1::AuthProvidersAPI add_swagger_documentation \ doc_version: '0.0.2', hide_documentation_path: true, diff --git a/app/api/dds/v1/children_api.rb b/app/api/dds/v1/children_api.rb index 3fa7ed6ae..7b3077750 100644 --- a/app/api/dds/v1/children_api.rb +++ b/app/api/dds/v1/children_api.rb @@ -1,6 +1,8 @@ module DDS module V1 class ChildrenAPI < Grape::API + helpers PaginationParams + desc 'List folder children' do detail 'Returns the immediate children of the folder.' named 'list folder children' @@ -12,6 +14,7 @@ class ChildrenAPI < Grape::API end params do optional :name_contains, type: String, desc: 'list children whose name contains this string' + use :pagination end get '/folders/:id/children', root: 'results' do authenticate! @@ -23,7 +26,7 @@ class ChildrenAPI < Grape::API else descendants = policy_scope(folder.descendants).where(Container.arel_table[:name].matches("%#{name_contains}%")) end - descendants.where(is_deleted: false) + paginate(descendants.where(is_deleted: false)) end desc 'List project children' do @@ -37,6 +40,7 @@ class ChildrenAPI < Grape::API end params do optional :name_contains, type: String, desc: 'list children whose name contains this string' + use :pagination end get '/projects/:id/children', root: 'results' do authenticate! @@ -48,7 +52,7 @@ class ChildrenAPI < Grape::API else descendants = project.containers.where(Container.arel_table[:name].matches("%#{name_contains}%")) end - policy_scope(descendants).where(is_deleted: false) + paginate(policy_scope(descendants).where(is_deleted: false)) end end end diff --git a/app/api/dds/v1/current_user_api.rb b/app/api/dds/v1/current_user_api.rb index ae2ee4539..deea78dc7 100644 --- a/app/api/dds/v1/current_user_api.rb +++ b/app/api/dds/v1/current_user_api.rb @@ -80,7 +80,7 @@ class CurrentUserAPI < Grape::API detail 'Delete a Current User API key' named 'delete current_user api_key' failure [ - [200, 'Success'], + [204, 'Successfully Deleted'], [401, 'Unauthorized'], [403, 'Forbidden (software_agent restricted)'], [404, 'Current User Does not Exist'] diff --git a/app/api/dds/v1/file_versions_api.rb b/app/api/dds/v1/file_versions_api.rb index 14e44839c..ba4c63e8e 100644 --- a/app/api/dds/v1/file_versions_api.rb +++ b/app/api/dds/v1/file_versions_api.rb @@ -84,7 +84,7 @@ class FileVersionsAPI < Grape::API detail 'Generates and returns a storage provider specific pre-signed URL that client can use to download the file version.' named 'download file_version' failure [ - [200, "This will never happen"], + [200, "Success"], [301, 'Redirect to file version'], [401, "Missing, Expired, or Invalid API Token in 'Authorization' Header"], [404, 'File version does not exist'] diff --git a/app/api/dds/v1/files_api.rb b/app/api/dds/v1/files_api.rb index 68807cf72..2fa733bcf 100644 --- a/app/api/dds/v1/files_api.rb +++ b/app/api/dds/v1/files_api.rb @@ -5,7 +5,7 @@ class FilesAPI < Grape::API detail 'Creates a project file for the given payload.' named 'create project file' failure [ - [200, "this will never happen"], + [200, "This will never happen"], [201, "Successfully Created"], [400, 'Upload has an IntegrityException'], [401, "Missing, Expired, or Invalid API Token in 'Authorization' Header"], @@ -114,7 +114,7 @@ class FilesAPI < Grape::API detail 'Generates and returns a storage provider specific pre-signed URL that client can use to download file.' named 'download file' failure [ - [200, "This will never happen"], + [200, "Success"], [301, 'Redirect to file'], [401, "Missing, Expired, or Invalid API Token in 'Authorization' Header"], [404, 'File does not exist'] diff --git a/app/api/dds/v1/meta_templates_api.rb b/app/api/dds/v1/meta_templates_api.rb index e441d55ea..58a6415ee 100644 --- a/app/api/dds/v1/meta_templates_api.rb +++ b/app/api/dds/v1/meta_templates_api.rb @@ -33,7 +33,8 @@ class MetaTemplatesAPI < Grape::API [201, 'Successfully Created'], [400, 'Validation error'], [401, 'Unauthorized'], - [404, 'Object or template does not exist'] + [404, 'Object or template does not exist'], + [409, 'Template instance already exists for the DDS object'] ] end params do @@ -64,7 +65,15 @@ class MetaTemplatesAPI < Grape::API if meta_template.save meta_template else - validation_error!(meta_template) + if meta_template.errors.added? :template, :taken + error!({ + error: '409', + reason: 'unique conflict', + suggestion: 'Resubmit as an update request' + }, 409) + else + validation_error!(meta_template) + end end end @@ -93,9 +102,9 @@ class MetaTemplatesAPI < Grape::API named 'update object metadata' failure [ [200, 'Success'], + [400, 'Validation Error'], [401, 'Unauthorized'], [403, 'Forbidden'], - [400, 'Validation Error'], [404, 'Object or Template does not exist'] ] end diff --git a/app/api/dds/v1/project_affiliates_api.rb b/app/api/dds/v1/project_affiliates_api.rb index 273499520..beb645515 100644 --- a/app/api/dds/v1/project_affiliates_api.rb +++ b/app/api/dds/v1/project_affiliates_api.rb @@ -5,6 +5,7 @@ class ProjectAffiliatesAPI < Grape::API detail 'Deletes any existing project role for the user and assigns new role.' named 'create project affiliation' failure [ + [200, 'Success'], [400, 'Project Name Already Exists'], [401, 'Unauthorized'], [404, 'Project Does not Exist'] @@ -37,6 +38,7 @@ class ProjectAffiliatesAPI < Grape::API detail 'List project affiliations' named 'list project affiliation' failure [ + [200, 'Success'], [401, 'Unauthorized'], [404, 'Project Does not Exist'] ] @@ -52,6 +54,7 @@ class ProjectAffiliatesAPI < Grape::API detail 'View project level affiliation for a user' named 'get project affiliation' failure [ + [200, 'Success'], [401, 'Unauthorized'], [404, 'Project Does not Exist'] ] @@ -69,6 +72,7 @@ class ProjectAffiliatesAPI < Grape::API detail 'Remove project level affiliation for a user' named 'delete project affiliation' failure [ + [204, 'Successfully Deleted'], [401, 'Unauthorized'], [404, 'Project Does not Exist'] ] diff --git a/app/api/dds/v1/project_permissions_api.rb b/app/api/dds/v1/project_permissions_api.rb index dc0be45b6..588c0a7e7 100644 --- a/app/api/dds/v1/project_permissions_api.rb +++ b/app/api/dds/v1/project_permissions_api.rb @@ -36,18 +36,18 @@ class ProjectPermissionsAPI < Grape::API permission_params = declared(params) project = hide_logically_deleted Project.find(params[:project_id]) user = User.find(params[:user_id]) - if permission = ProjectPermission.find_by(project: project, user: user) + if permission = ProjectPermission.find_by(project: project, user: user) authorize permission, :update? else permission = ProjectPermission.new(project: project, user: user) authorize permission, :create? end - + permission.auth_role = AuthRole.find(permission_params[:auth_role][:id]) unless permission.auth_role raise ActiveRecord::RecordNotFound.new(message: "Couldn't find AuthRole with id #{permission_params[:auth_role][:id]}") end - + if permission.save permission else @@ -80,8 +80,8 @@ class ProjectPermissionsAPI < Grape::API detail 'Revoke project permissions' named 'revoke project permissions' failure [ - [200, 'this will never happen'], - [204, 'Success'], + [200, 'This will never happen'], + [204, 'Successfully Deleted'], [401, 'Unauthorized'], [404, 'Project or User Does not Exist'] ] diff --git a/app/api/dds/v1/project_transfers_api.rb b/app/api/dds/v1/project_transfers_api.rb index eca9cc5f6..60f8a5d3c 100644 --- a/app/api/dds/v1/project_transfers_api.rb +++ b/app/api/dds/v1/project_transfers_api.rb @@ -9,7 +9,7 @@ class ProjectTransfersAPI < Grape::API named 'initiate project transfer' failure [ [200, 'This will never actually happen'], - [201, 'Created Successfully'], + [201, 'Successfully Created'], [400, 'Project Transfer Already Exists'], [401, 'Unauthorized'], [403, 'Forbidden'] @@ -36,13 +36,162 @@ class ProjectTransfersAPI < Grape::API }) end authorize project_transfer, :create? + if project_transfer.save + project_transfer + else + validation_error!(project_transfer) + end + end + + desc 'List project transfers' do + detail 'list project transfers' + named 'list project transfers' + failure [ + [200, 'Success'], + [401, 'Unauthorized'], + [404, 'Project does not exist'] + ] + end + get '/projects/:project_id/transfers', root: 'results' do + authenticate! + project = Project.find(params[:project_id]) + policy_scope(ProjectTransfer).where(project: project) + end + + desc 'View a project transfer' do + detail 'Used to view an instance of a project transfer.' + named 'view a project transfer' + failure [ + [200, 'Success'], + [401, 'Unauthorized'], + [403, 'Forbidden'], + [404, 'Project transfer does not exist'] + ] + end + get '/project_transfers/:id', root: false do + authenticate! + project_transfer = ProjectTransfer.find(params[:id]) + authorize project_transfer, :show? + project_transfer + end + desc 'Reject a project transfer' do + detail 'Reject a pending project transfer.' + named 'reject a project transfer' + failure [ + [200, 'Success'], + [400, 'Validation Error'], + [401, 'Unauthorized'], + [403, 'Forbidden'], + [404, 'Project transfer does not exist'] + ] + end + params do + requires :id, type: String, desc: 'The unique id of the project transfer.' + optional :status_comment, type: String, desc: 'An optional comment that can be provided.' + end + put '/project_transfers/:id/reject', root: false do + authenticate! + project_transfer = ProjectTransfer.find(params[:id]) + project_transfer_params = declared(params, {include_missing: false}, [:status_comment]) + project_transfer.status = 'rejected' + project_transfer.status_comment = project_transfer_params[:status_comment] if project_transfer_params[:status_comment] + authorize project_transfer, :update? if project_transfer.save project_transfer else validation_error!(project_transfer) end + end + desc 'Cancel a project transfer' do + detail 'Cancel a pending project transfer.' + named 'cancel a project transfer' + failure [ + [200, 'Success'], + [400, 'Validation Error'], + [401, 'Unauthorized'], + [403, 'Forbidden'], + [404, 'Project transfer does not exist'] + ] + end + params do + requires :id, type: String, desc: 'The unique id of the project transfer.' + optional :status_comment, type: String, desc: 'An optional comment that can be provided.' + end + put '/project_transfers/:id/cancel', root: false do + authenticate! + project_transfer = ProjectTransfer.find(params[:id]) + project_transfer_params = declared(params, {include_missing: false}, [:status_comment]) + project_transfer.status = 'canceled' + project_transfer.status_comment = project_transfer_params[:status_comment] if project_transfer_params[:status_comment] + authorize project_transfer, :destroy? + if project_transfer.save + project_transfer + else + validation_error!(project_transfer) + end + end + + desc 'Accept a project transfer' do + detail 'Accept a pending project transfer.' + named 'accept a project transfer' + failure [ + [200, 'Success'], + [400, 'Validation Error'], + [401, 'Unauthorized'], + [403, 'Forbidden'], + [404, 'Project transfer does not exist'] + ] + end + params do + requires :id, type: String, desc: 'The unique id of the project transfer.' + optional :status_comment, type: String, desc: 'An optional comment that can be provided.' + end + put '/project_transfers/:id/accept', root: false do + authenticate! + project_transfer = ProjectTransfer.find(params[:id]) + project_transfer_params = declared(params, {include_missing: false}, [:status_comment]) + authorize project_transfer, :update? + project_transfer.status = 'accepted' + project_transfer.status_comment = project_transfer_params[:status_comment] if project_transfer_params[:status_comment] + if project_transfer.save + project_transfer + else + validation_error!(project_transfer) + end + end + + desc 'View all project transfers' do + detail 'View all project transfers.' + named 'view all project transfers' + failure [ + [200, 'Success'], + [401, 'Unauthorized'], + [404, 'Unsupported Status'] + ] + end + params do + optional :status, values: ProjectTransfer.statuses.keys, + type: String, + desc: 'Status must be one of the allowed statuses' + end + rescue_from Grape::Exceptions::ValidationErrors do |e| + error_json = { + "error" => "404", + "reason" => "Unknown Status", + "suggestion" => "Status should be one of the following: #{ProjectTransfer.statuses.keys}", + } + error!(error_json, 404) + end + get '/project_transfers', root: 'results' do + authenticate! + project_transfer_params = declared(params, include_missing: false) + project_transfers = policy_scope(ProjectTransfer) + if project_transfer_params[:status] + project_transfers = project_transfers.where(status: ProjectTransfer.statuses[project_transfer_params[:status]]) + end + project_transfers end end end diff --git a/app/api/dds/v1/projects_api.rb b/app/api/dds/v1/projects_api.rb index 6651824d5..cb947fdaf 100644 --- a/app/api/dds/v1/projects_api.rb +++ b/app/api/dds/v1/projects_api.rb @@ -1,6 +1,8 @@ module DDS module V1 class ProjectsAPI < Grape::API + helpers PaginationParams + desc 'Create a project' do detail 'Creates a project for the given payload.' named 'create project' @@ -46,10 +48,13 @@ class ProjectsAPI < Grape::API [401, 'Unauthorized'] ] end + params do + use :pagination + end get '/projects', root: 'results' do authenticate! authorize Project.new, :index? - policy_scope(Project).where(is_deleted: false) + paginate(policy_scope(Project).where(is_deleted: false)) end desc 'View project details' do @@ -77,9 +82,9 @@ class ProjectsAPI < Grape::API named 'update project' failure [ [200, 'Success'], + [400, 'Project Name Already Exists'], [401, 'Unauthorized'], [403, 'Forbidden'], - [400, 'Project Name Already Exists'], [404, 'Project Does not Exist'] ] end diff --git a/app/api/dds/v1/properties_api.rb b/app/api/dds/v1/properties_api.rb index 6a29ee645..e7dca6452 100644 --- a/app/api/dds/v1/properties_api.rb +++ b/app/api/dds/v1/properties_api.rb @@ -79,9 +79,9 @@ class PropertiesAPI < Grape::API named 'update template property' failure [ [200, 'Success'], + [400, 'Validation Error'], [401, 'Unauthorized'], [403, 'Forbidden (template property restricted)'], - [400, 'Validation Error'], [404, 'Property Does not Exist'] ] end diff --git a/app/api/dds/v1/relations_api.rb b/app/api/dds/v1/relations_api.rb index b2ac0f456..319c9140c 100644 --- a/app/api/dds/v1/relations_api.rb +++ b/app/api/dds/v1/relations_api.rb @@ -6,8 +6,8 @@ class RelationsAPI < Grape::API detail 'Creates a WasUsedBy relationship. Entity cannot be used by an Activity that generated the same Entity.' named 'create used relation' failure [ - [200, 'This will never actually happen'], - [201, 'Created Successfully'], + [200, 'This will never happen'], + [201, 'Successfully Created'], [400, 'Activity and Entity are required, Activity generated Entity.'], [401, 'Unauthorized'], [403, 'Forbidden'] @@ -26,7 +26,7 @@ class RelationsAPI < Grape::API authenticate! relation_params = declared(params, include_missing: false) activity = Activity.find(relation_params[:activity][:id]) - #todo change this when we allow other entities to be used by activities + # TODO change this when we allow other entities to be used by activities entity = FileVersion.find(relation_params[:entity][:id]) relation = UsedProvRelation.new( @@ -47,8 +47,8 @@ class RelationsAPI < Grape::API detail 'Creates a WasGeneratedBy relationship. Entity can only be generated by one Activity, and cannot be used by the same Activity.' named 'create was generated by relation' failure [ - [200, 'This will never actually happen'], - [201, 'Created Successfully'], + [200, 'This will never happen'], + [201, 'Successfully Created'], [400, 'Activity and Entity are required, Entity can only be generated by one Activity, cannot be used by the same Activity.'], [401, 'Unauthorized'], [403, 'Forbidden'] @@ -87,8 +87,8 @@ class RelationsAPI < Grape::API detail 'Creates a WasDerivedFrom relationship.' named 'create was derived from relation' failure [ - [200, 'This will never actually happen'], - [201, 'Created Successfully'], + [200, 'This will never happen'], + [201, 'Successfully Created'], [400, 'Activity and Entity are required'], [401, 'Unauthorized'], [403, 'Forbidden'] @@ -128,8 +128,8 @@ class RelationsAPI < Grape::API detail 'Creates a WasInvalidatedBy relationship.' named 'create was invalidated by relation' failure [ - [200, 'This will never actually happen'], - [201, 'Created Successfully'], + [200, 'This will never happen'], + [201, 'Successfully Created'], [400, 'Activity and Entity are required'], [401, 'Unauthorized'], [403, 'Forbidden'] @@ -164,6 +164,35 @@ class RelationsAPI < Grape::API end end + desc 'List provenance relations' do + detail 'List the relations for a provenance node; this only lists direct relations for the node that are a single hop away.' + named 'List provenance relations' + failure [ + [200, 'Success'], + [401, 'Unauthorized'], + [403, 'Forbidden'], + [404, 'Object kind or id Does not Exist'] + ] + end + params do + requires :object_kind, type: String, desc: 'Object kind' + requires :object_id, type: String, desc: 'Object UUID' + end + get '/relations/:object_kind/:object_id', root: 'results' do + authenticate! + object_params = declared(params, include_missing: false) + root_node = KindnessFactory.by_kind( + object_params[:object_kind] + ).find(object_params[:object_id]) + authorize root_node, :show? + prov_relationsq = ProvRelation.arel_table + ProvRelation.where( + prov_relationsq[:relatable_from_id].eq(root_node.id).or( + prov_relationsq[:relatable_to_id].eq(root_node.id) + ) + ).where(is_deleted: false) + end + desc 'View relation' do detail 'Show information about a Relation. Requires ownership of the relation, or visibility to a single node for the specified relation' named 'View relation' @@ -204,35 +233,6 @@ class RelationsAPI < Grape::API prov_relation.update(is_deleted: true) body false end - - desc 'List provenance relations' do - detail 'List the relations for a provenance node; this only lists direct relations for the node that are a single hop away.' - named 'List provenance relations' - failure [ - [200, 'Success'], - [401, 'Unauthorized'], - [403, 'Forbidden'], - [404, 'Object kind or id Does not Exist'] - ] - end - params do - requires :object_kind, type: String, desc: 'Object kind' - requires :object_id, type: String, desc: 'Object UUID' - end - get '/relations/:object_kind/:object_id', root: 'results' do - authenticate! - object_params = declared(params, include_missing: false) - root_node = KindnessFactory.by_kind( - object_params[:object_kind] - ).find(object_params[:object_id]) - authorize root_node, :show? - prov_relationsq = ProvRelation.arel_table - ProvRelation.where( - prov_relationsq[:relatable_from_id].eq(root_node.id).or( - prov_relationsq[:relatable_to_id].eq(root_node.id) - ) - ).where(is_deleted: false) - end end end end diff --git a/app/api/dds/v1/search_api.rb b/app/api/dds/v1/search_api.rb index df00f18e2..531ffa058 100644 --- a/app/api/dds/v1/search_api.rb +++ b/app/api/dds/v1/search_api.rb @@ -5,7 +5,7 @@ class SearchAPI < Grape::API detail 'Search Provenance related to a start_node by max_hops degrees of separation (default inifinite)' named 'Search Provenance' failure [ - [200, 'Will never happen'], + [200, 'This will never happen'], [201, 'Success'], [401, 'Unauthorized'], [404, 'start_node or start_node kind does not exist'] @@ -35,7 +35,7 @@ class SearchAPI < Grape::API detail 'This is a targeted query that navigates "up" the provenance chain for a file version to see how it was generated (i.e. by what activity) and from what source file versions. Given a list of file versions, this action perform the following query for each file version: 1. Gets the generating activity. 2. For the generating activity, gets the list of wasGeneratedBy and used file versions. A graph structure of the unique nodes and relationships is returned.' named 'Search Provenance wasGeneratedBy' failure [ - [200, 'Will never happen'], + [200, 'This will never happen'], [201, 'Success'], [401, 'Unauthorized'] ] @@ -45,10 +45,10 @@ class SearchAPI < Grape::API requires :id, type: String, desc: 'The unique file version id.' end end - post '/search/provenance/was_generated_by', root: 'graph', serializer: ProvenanceGraphSerializer do + post '/search/provenance/origin', root: 'graph', serializer: ProvenanceGraphSerializer do authenticate! prov_params = declared(params, include_missing: false) - WasGeneratedByProvenanceGraph.new( + OriginProvenanceGraph.new( file_versions: prov_params[:file_versions], policy_scope: method(:policy_scope)) end @@ -57,21 +57,21 @@ class SearchAPI < Grape::API detail 'Search for DDS objects using the elasticsearch query_dsl on supported kinds of objects' named 'Search Objects' failure [ - [200, 'Will never happen'], + [200, 'This will never happen'], [201, 'Success'], [401, 'Unauthorized'], - [404, 'one or more included kinds is not supported, or not indexed'] + [404, 'One or more included kinds is not supported, or not indexed'] ] end params do - requires :included_kinds, type: Array[String], desc: 'The kind of objects (i.e. Elasticsearch document types) to include in the search; can include folders and/or files (i.e. dds-folder, dds-file)' + requires :include_kinds, type: Array[String], desc: 'The kind of objects (i.e. Elasticsearch document types) to include in the search; can include folders and/or files (i.e. dds-folder, dds-file)' requires :search_query, type: Hash, desc: 'The Elasticsearch query criteria (i.e. Query DSL)' end post '/search', root: false do authenticate! search_params = declared(params, include_missing: false) indices = [] - search_params[:included_kinds].each do |included_kind| + search_params[:include_kinds].each do |included_kind| kinded_model = KindnessFactory.kind_map[included_kind] raise NameError.new("object_kind #{included_kind} Not Supported") unless kinded_model indices << kinded_model diff --git a/app/api/dds/v1/software_agents_api.rb b/app/api/dds/v1/software_agents_api.rb index 051fd2626..c896ac0b0 100644 --- a/app/api/dds/v1/software_agents_api.rb +++ b/app/api/dds/v1/software_agents_api.rb @@ -75,9 +75,9 @@ class SoftwareAgentsAPI < Grape::API named 'update software agent' failure [ [200, 'Success'], + [400, 'Validation Error'], [401, 'Unauthorized'], [403, 'Forbidden (software_agent restricted)'], - [400, 'Validation Error'], [404, 'Software Agent Does not Exist'] ] end @@ -167,7 +167,7 @@ class SoftwareAgentsAPI < Grape::API detail 'delete software_agent api_key' named 'delete software_agent api_key' failure [ - [204, 'Success'], + [204, 'Successfully Deleted'], [401, 'Unauthorized'], [403, 'Forbidden (software_agent restricted)'], [404, 'Software Agent Does not Exist'] diff --git a/app/api/dds/v1/system_permissions_api.rb b/app/api/dds/v1/system_permissions_api.rb index f721163a3..072a6686a 100644 --- a/app/api/dds/v1/system_permissions_api.rb +++ b/app/api/dds/v1/system_permissions_api.rb @@ -33,7 +33,7 @@ class SystemPermissionsAPI < Grape::API authenticate! system_params = declared(params, include_missing: false) user = User.find(params[:user_id]) - permission = SystemPermission.find_by(user: user) || + permission = SystemPermission.find_by(user: user) || SystemPermission.new(user: user) permission.auth_role = AuthRole.find(system_params[:auth_role][:id]) authorize permission, :create? @@ -66,7 +66,7 @@ class SystemPermissionsAPI < Grape::API detail 'Deletes system permissions for a given user' named 'delete permissions' failure [ - [200, 'Success'], + [204, 'Successfully Deleted'], [401, 'Unauthorized'], [404, 'User Does not Exist'] ] diff --git a/app/api/dds/v1/tags_api.rb b/app/api/dds/v1/tags_api.rb index afd60a308..29f88a486 100644 --- a/app/api/dds/v1/tags_api.rb +++ b/app/api/dds/v1/tags_api.rb @@ -77,7 +77,7 @@ class TagsAPI < Grape::API ) authorize tag, :create? if taggable_object.tags << tag - new_tags << tag + new_tags << tag end end new_tags @@ -129,7 +129,6 @@ class TagsAPI < Grape::API detail 'Deletes the tag' named 'delete tag' failure [ - [200, "This will never happen"], [204, 'Successfully Deleted'], [401, "Missing, Expired, or Invalid API Token in 'Authorization' Header"], [404, 'Tag does not exist'] diff --git a/app/api/dds/v1/templates_api.rb b/app/api/dds/v1/templates_api.rb index 4d31daf49..4a58f74b1 100644 --- a/app/api/dds/v1/templates_api.rb +++ b/app/api/dds/v1/templates_api.rb @@ -37,13 +37,13 @@ class TemplatesAPI < Grape::API ] end params do - optional :name, type: String, desc: 'list templates whose name contains this string' + optional :name_contains, type: String, desc: 'list templates whose name contains the specified string' end get '/templates', root: 'results' do authenticate! template_params = declared(params, include_missing: false) - if template_params[:name] - template = Template.where("name = ?", template_params[:name]) + if name_contains = template_params[:name_contains] + template = Template.where(Template.arel_table[:name].matches("%#{name_contains}%")) else Template.all end @@ -74,9 +74,9 @@ class TemplatesAPI < Grape::API named 'update template' failure [ [200, 'Success'], + [400, 'Validation Error'], [401, 'Unauthorized'], [403, 'Forbidden (template restricted)'], - [400, 'Validation Error'], [404, 'Template Does not Exist'] ] end diff --git a/app/api/dds/v1/uploads_api.rb b/app/api/dds/v1/uploads_api.rb index 51c3b635b..10246e964 100644 --- a/app/api/dds/v1/uploads_api.rb +++ b/app/api/dds/v1/uploads_api.rb @@ -9,7 +9,7 @@ class UploadsAPI < Grape::API detail 'This is the first step in uploading a large file. An upload objects is created along with a composite status object used to track the progress of the chunked upload.' named 'create upload' failure [ - [200, 'This will never actually happen'], + [200, 'This will never happen'], [201, 'Created Successfully'], [401, 'Unauthorized'], [404, 'Project Does not Exist'] @@ -111,6 +111,7 @@ class UploadsAPI < Grape::API upload = Upload.find(params[:id]) if chunk = Chunk.find_by(upload: upload, number: chunk_params[:number]) authorize chunk, :update? + chunk.touch else chunk = Chunk.new({upload: upload, number: chunk_params[:number]}) authorize chunk, :create? @@ -132,9 +133,9 @@ class UploadsAPI < Grape::API named 'complete upload' failure [ [200, 'Success'], + [400, 'IntegrityException: reported file size or chunk hashes do not match that computed by StorageProvider'], [401, 'Unauthorized'], [404, 'Upload Does not Exist'], - [400, 'IntegrityException: reported file size or chunk hashes do not match that computed by StorageProvider'], [500, 'Unexpected StorageProviderException experienced'] ] end @@ -171,9 +172,9 @@ class UploadsAPI < Grape::API named 'report upload hash' failure [ [200, 'Success'], + [400, 'Validation Error'], [401, 'Unauthorized'], [404, 'Upload Does not Exist'], - [400, 'Validation Error'], [500, 'Unexpected StorageProviderException experienced'] ] end diff --git a/app/api/dds/v1/users_api.rb b/app/api/dds/v1/users_api.rb index 99adcf933..39f46783a 100644 --- a/app/api/dds/v1/users_api.rb +++ b/app/api/dds/v1/users_api.rb @@ -4,7 +4,7 @@ class UsersAPI < Grape::API helpers PaginationParams desc 'api_token' do - detail 'This allows a client to present an access token from a registred authentication service and get an api token' + detail 'This allows a client to present an access token from a registered authentication service and get an api token' named 'api_token' failure [ [200,'Success'], @@ -13,59 +13,29 @@ class UsersAPI < Grape::API end params do requires :access_token + optional :authentication_service_id, type: String, desc: 'authentication service uuid' end rescue_from Grape::Exceptions::ValidationErrors do |e| error_json = { "error" => 400, "reason" => "no access_token", - "suggestion" => "you might need to login through an authenticaton service"#, + "suggestion" => "you might need to login through an authentication service"#, } error!(error_json, 400) end - rescue_from JWT::VerificationError do - error!({ - error: 401, - reason: 'invalid access_token', - suggestion: 'token not properly signed' - },401) - end get '/user/api_token', serializer: ApiTokenSerializer do token_info_params = declared(params) - encoded_access_token = token_info_params[:access_token] - if access_token = JWT.decode(encoded_access_token, Rails.application.secrets.secret_key_base)[0] - auth_service = AuthenticationService.where(service_id: access_token['service_id']).take - if auth_service - authorized_user = auth_service.user_authentication_services.where(uid: access_token['uid']).first - if authorized_user - authorized_user.user.update_attribute(:last_login_at, DateTime.now) - else - auth_service.with_lock do - new_user = User.new( - id: SecureRandom.uuid, - username: access_token['uid'], - etag: SecureRandom.hex, - email: access_token['email'], - display_name: access_token['display_name'], - first_name: access_token['first_name'], - last_login_at: DateTime.now, - last_name: access_token['last_name'] - ) - authorized_user = new_user.user_authentication_services.build( - uid: access_token['uid'], - authentication_service: auth_service - ) - populate_audit_store_with_user(new_user) - new_user.save! - end - end - ApiToken.new(user: authorized_user.user, user_authentication_service: authorized_user) - else - error!({ - error: 401, - reason: 'invalid access_token', - suggestion: 'authenticaton service not recognized' - }, 401) - end + + auth_service = get_auth_service( + token_info_params[:authentication_service_id]) + authorized_user = auth_service.get_user_for_access_token(token_info_params[:access_token]) + authorized_user.last_login_at = DateTime.now + populate_audit_store_with_user(authorized_user) + if authorized_user.save + api_token = ApiToken.new(user: authorized_user, user_authentication_service:authorized_user.current_user_authenticaiton_service) + api_token + else + validation_error!(authorized_user) end end diff --git a/app/controllers/apidocs_controller.rb b/app/controllers/apidocs_controller.rb deleted file mode 100644 index 271955541..000000000 --- a/app/controllers/apidocs_controller.rb +++ /dev/null @@ -1,4 +0,0 @@ -class ApidocsController < ApplicationController - def index - end -end diff --git a/app/controllers/swaggerui_controller.rb b/app/controllers/swaggerui_controller.rb index 7cddc9815..aba34f035 100644 --- a/app/controllers/swaggerui_controller.rb +++ b/app/controllers/swaggerui_controller.rb @@ -1,6 +1,4 @@ class SwaggeruiController < ApplicationController def index - @auth_service = AuthenticationService.first - @state = SecureRandom.hex end end diff --git a/app/models/associated_with_prov_relation.rb b/app/models/associated_with_prov_relation.rb new file mode 100644 index 000000000..6634e7204 --- /dev/null +++ b/app/models/associated_with_prov_relation.rb @@ -0,0 +1,7 @@ +# AttributedtoProvRelation is a ProvRelation through Single Table inheritance + +class AssociatedWithProvRelation < ProvRelation + def kind + 'dds-relation-was-associated-with' + end +end diff --git a/app/models/associated_with_software_agent_prov_relation.rb b/app/models/associated_with_software_agent_prov_relation.rb index ff65b42d7..e0890f668 100644 --- a/app/models/associated_with_software_agent_prov_relation.rb +++ b/app/models/associated_with_software_agent_prov_relation.rb @@ -1,6 +1,6 @@ # AssociatedWithSoftwareAgentProvRelation is a ProvRelation through Single Table inheritance -class AssociatedWithSoftwareAgentProvRelation < ProvRelation +class AssociatedWithSoftwareAgentProvRelation < AssociatedWithProvRelation # AssociatedWithSoftwareAgentProvRelation requires relationship_type 'was-associated-with' # which maps to a Graph::WasAssociatedWith graphed relationship validates :relationship_type, inclusion: { in: %w(was-associated-with), diff --git a/app/models/associated_with_user_prov_relation.rb b/app/models/associated_with_user_prov_relation.rb index ef186eb5f..7f28d3aed 100644 --- a/app/models/associated_with_user_prov_relation.rb +++ b/app/models/associated_with_user_prov_relation.rb @@ -1,6 +1,6 @@ # AssociatedWithUserProvRelation is a ProvRelation through Single Table inheritance -class AssociatedWithUserProvRelation < ProvRelation +class AssociatedWithUserProvRelation < AssociatedWithProvRelation # AssociatedWithUserProvRelation requires relationship_type 'was-associated-with' # which maps to a Graph::WasAssociatedWith graphed relationship validates :relationship_type, inclusion: { in: %w(was-associated-with), diff --git a/app/models/attributed_to_prov_relation.rb b/app/models/attributed_to_prov_relation.rb new file mode 100644 index 000000000..3c6ac860d --- /dev/null +++ b/app/models/attributed_to_prov_relation.rb @@ -0,0 +1,7 @@ +# AttributedtoProvRelation is a ProvRelation through Single Table inheritance + +class AttributedToProvRelation < ProvRelation + def kind + 'dds-relation-was-attributed-to' + end +end diff --git a/app/models/attributed_to_software_agent_prov_relation.rb b/app/models/attributed_to_software_agent_prov_relation.rb index 27c3cd43b..4e64d8ee9 100644 --- a/app/models/attributed_to_software_agent_prov_relation.rb +++ b/app/models/attributed_to_software_agent_prov_relation.rb @@ -1,6 +1,6 @@ # AttributedToSoftwareAgentProvRelation is a ProvRelation through Single Table inheritance -class AttributedToSoftwareAgentProvRelation < ProvRelation +class AttributedToSoftwareAgentProvRelation < AttributedToProvRelation # AttributedToSoftwareAgentProvRelation requires relationship_type 'was-attributed-to' # which maps to a Graph::WasAttributedTo graphed relationship validates :relatable_from_type, inclusion: { in: %w(FileVersion), diff --git a/app/models/attributed_to_user_prov_relation.rb b/app/models/attributed_to_user_prov_relation.rb index 24abcfd7c..2c68c2ca5 100644 --- a/app/models/attributed_to_user_prov_relation.rb +++ b/app/models/attributed_to_user_prov_relation.rb @@ -1,6 +1,7 @@ -# AttributedToUserProvRelation is a ProvRelation through Single Table inheritance +# AttributedToUserProvRelation is a AttributedToProvRelation +# AttributedtoProvRelation is a ProvRelation through Single Table inheritance -class AttributedToUserProvRelation < ProvRelation +class AttributedToUserProvRelation < AttributedToProvRelation # AttributedToUserProvRelation requires relationship_type 'was-attributed-to' # which maps to a Graph::WasAttributedTo graphed relationship validates :relatable_from_type, inclusion: { in: %w(FileVersion), diff --git a/app/models/authentication_service.rb b/app/models/authentication_service.rb index 99ed4bb71..5730d9420 100644 --- a/app/models/authentication_service.rb +++ b/app/models/authentication_service.rb @@ -4,4 +4,18 @@ class AuthenticationService < ActiveRecord::Base validates :service_id, presence: true validates :name, presence: true validates :base_uri, presence: true + validates :client_id, presence: true + validates :login_initiation_uri, presence: true + validates :login_response_type, presence: true + validates :is_default, uniqueness: true, if: :is_default + + def login_initiation_url + [ + base_uri, + login_initiation_uri + ].join('/') + '?' + [ + "response_type=#{login_response_type}", + "client_id=#{client_id}" + ].join('&') + end end diff --git a/app/models/data_file.rb b/app/models/data_file.rb index c081e7206..e358db63c 100644 --- a/app/models/data_file.rb +++ b/app/models/data_file.rb @@ -67,22 +67,112 @@ def new_file_version_needed? end def as_indexed_json(options={}) - DataFileSearchDocumentSerializer.new(self).as_json + Search::DataFileSerializer.new(self).as_json end settings index: { number_of_shards: 1 } do mappings dynamic: 'false' do - indexes :id + indexes :kind, type: "string", index: "not_analyzed" + indexes :id, type: "string", index: "not_analyzed" + indexes :label + + indexes :parent do + indexes :kind, type: "string", index: "not_analyzed" + indexes :id, type: "string", index: "not_analyzed" + end + indexes :name + indexes :audit do + indexes :created_on, type: "date", format: "strict_date_optional_time||epoch_millis" + indexes :created_by do + indexes :id, type: "string", index: "not_analyzed" + indexes :username + indexes :full_name + indexes :agent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + end + + indexes :last_updated_on, type: "date", format: "strict_date_optional_time||epoch_millis" + indexes :last_updated_by do + indexes :id, type: "string", index: "not_analyzed" + indexes :username + indexes :full_name + indexes :agent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + end + + indexes :deleted_on, type: "date", format: "strict_date_optional_time||epoch_millis" + indexes :deleted_by do + indexes :id, type: "string", index: "not_analyzed" + indexes :username + indexes :full_name + indexes :agent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + end + end + indexes :is_deleted, type: "boolean" indexes :created_at, type: "date", format: "strict_date_optional_time||epoch_millis" indexes :updated_at, type: "date", format: "strict_date_optional_time||epoch_millis" - indexes :label + indexes :tags do indexes :label, type: "string", fields: { raw: {type: "string", index: "not_analyzed"} } end + + indexes :current_version do + indexes :id, type: "string", index: "not_analyzed" + indexes :version, type: "integer" + indexes :label + + indexes :upload do + indexes :id, type: "string", index: "not_analyzed" + indexes :size, type: "long" #https://github.com/karmi/retire/issues/474 + indexes :storage_provider do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + indexes :description + end + + indexes :hashes do + indexes :algorithm, type: "string", index: "not_analyzed" + indexes :value, type: "string", index: "not_analyzed" + end + end + end + + indexes :project do + indexes :id, type: "string", index: "not_analyzed" + indexes :name, type: "string" + end + + indexes :ancestors do + indexes :kind, type: "string", index: "not_analyzed" + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + + indexes :creator do + indexes :id, type: "string", index: "not_analyzed" + indexes :username, type: "string" + indexes :first_name, type: "string" + indexes :last_name, type: "string" + indexes :email, type: "string" + end end end + + def creator + return unless current_file_version + create_audit = current_file_version.audits.find_by(action: "create") + return unless create_audit + create_audit.user + end end diff --git a/app/models/derived_from_file_version_prov_relation.rb b/app/models/derived_from_file_version_prov_relation.rb index c0e820095..703291e89 100644 --- a/app/models/derived_from_file_version_prov_relation.rb +++ b/app/models/derived_from_file_version_prov_relation.rb @@ -14,4 +14,8 @@ class DerivedFromFileVersionProvRelation < ProvRelation def set_relationship_type self.relationship_type = 'was-derived-from' end + + def kind + 'dds-relation-was-derived-from' + end end diff --git a/app/models/duke_authentication_service.rb b/app/models/duke_authentication_service.rb new file mode 100644 index 000000000..0fe1903dc --- /dev/null +++ b/app/models/duke_authentication_service.rb @@ -0,0 +1,34 @@ +class DukeAuthenticationService < AuthenticationService + def get_user_for_access_token(encoded_access_token) + begin + access_token = JWT.decode(encoded_access_token, Rails.application.secrets.secret_key_base)[0] + user_authentication_service = user_authentication_services.find_by(uid: access_token['uid']) + if user_authentication_service + user = user_authentication_service.user + user.current_user_authenticaiton_service = user_authentication_service + user + else + user = User.find_by(username: access_token['uid']) + unless user + user = User.new( + id: SecureRandom.uuid, + username: access_token['uid'], + etag: SecureRandom.hex, + email: access_token['email'], + display_name: access_token['display_name'], + first_name: access_token['first_name'], + last_name: access_token['last_name'] + ) + end + user_authentication_service = user.user_authentication_services.build( + uid: access_token['uid'], + authentication_service: self + ) + user.current_user_authenticaiton_service = user_authentication_service + user + end + rescue JWT::VerificationError, JWT::DecodeError + raise InvalidAccessTokenException + end + end +end diff --git a/app/models/folder.rb b/app/models/folder.rb index d6ddcd293..2c52c0bf8 100644 --- a/app/models/folder.rb +++ b/app/models/folder.rb @@ -4,7 +4,7 @@ class Folder < Container has_many :children, class_name: "Container", foreign_key: "parent_id", autosave: true has_many :folders, -> { readonly }, foreign_key: "parent_id" has_many :meta_templates, as: :templatable - + after_set_parent_attribute :set_project_to_parent_project validates :project_id, presence: true, immutable: true @@ -33,16 +33,85 @@ def is_deleted=(val) end def as_indexed_json(options={}) - FolderSearchDocumentSerializer.new(self).as_json + Search::FolderSerializer.new(self).as_json end settings index: { number_of_shards: 1 } do mappings dynamic: 'false' do - indexes :id + indexes :kind, type: "string", index: "not_analyzed" + indexes :id, type: "string", index: "not_analyzed" + indexes :label + + indexes :parent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name, type: "string" + end + indexes :name indexes :is_deleted, type: "boolean" + indexes :audit do + indexes :created_on, type: "date", format: "strict_date_optional_time||epoch_millis" + indexes :created_by do + indexes :id, type: "string", index: "not_analyzed" + indexes :username + indexes :full_name + indexes :agent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + end + + indexes :last_updated_on, type: "date", format: "strict_date_optional_time||epoch_millis" + indexes :last_updated_by do + indexes :id, type: "string", index: "not_analyzed" + indexes :username + indexes :full_name + indexes :agent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + end + + indexes :deleted_on, type: "date", format: "strict_date_optional_time||epoch_millis" + indexes :deleted_by do + indexes :id, type: "string", index: "not_analyzed" + indexes :username + indexes :full_name + indexes :agent do + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + end + end + indexes :created_at, type: "date", format: "strict_date_optional_time||epoch_millis" indexes :updated_at, type: "date", format: "strict_date_optional_time||epoch_millis" + + indexes :project do + indexes :id, type: "string", index: "not_analyzed" + indexes :name, type: "string" + end + + indexes :ancestors do + indexes :kind, type: "string", index: "not_analyzed" + indexes :id, type: "string", index: "not_analyzed" + indexes :name + end + + indexes :creator do + indexes :id, type: "string", index: "not_analyzed" + indexes :username, type: "string" + indexes :first_name, type: "string" + indexes :last_name, type: "string" + indexes :email, type: "string" + end + end end + + def creator + creation_audit = audits.find_by(action: "create") + return unless creation_audit + creation_audit.user + end end diff --git a/app/models/generated_by_activity_prov_relation.rb b/app/models/generated_by_activity_prov_relation.rb index 52d670e46..b0e723d32 100644 --- a/app/models/generated_by_activity_prov_relation.rb +++ b/app/models/generated_by_activity_prov_relation.rb @@ -32,4 +32,8 @@ def generating_activity errors.add(:relatable_to_id, "GeneratedByActivityProvRelation cannot be made to an Activity that has a UsedProvRelation to the generated FileVersion") end end + + def kind + 'dds-relation-was-generated-by' + end end diff --git a/app/models/invalid_access_token_exception.rb b/app/models/invalid_access_token_exception.rb new file mode 100644 index 000000000..5afdd2a31 --- /dev/null +++ b/app/models/invalid_access_token_exception.rb @@ -0,0 +1,2 @@ +class InvalidAccessTokenException < StandardError +end diff --git a/app/models/invalid_authentication_service_id_exception.rb b/app/models/invalid_authentication_service_id_exception.rb new file mode 100644 index 000000000..c7ece9fc2 --- /dev/null +++ b/app/models/invalid_authentication_service_id_exception.rb @@ -0,0 +1,2 @@ +class InvalidAuthenticationServiceIDException < StandardError +end diff --git a/app/models/invalidated_by_activity_prov_relation.rb b/app/models/invalidated_by_activity_prov_relation.rb index c4831b2e8..7c565bd00 100644 --- a/app/models/invalidated_by_activity_prov_relation.rb +++ b/app/models/invalidated_by_activity_prov_relation.rb @@ -22,4 +22,8 @@ def relatable_from_must_be_deleted def set_relationship_type self.relationship_type = 'was-invalidated-by' end + + def kind + 'dds-relation-was-invalidated-by' + end end diff --git a/app/models/kindness_factory.rb b/app/models/kindness_factory.rb index a9b8588bd..3d1f040cf 100644 --- a/app/models/kindness_factory.rb +++ b/app/models/kindness_factory.rb @@ -6,10 +6,8 @@ class KindnessFactory Project, DataFile, Folder, - AssociatedWithUserProvRelation, - AssociatedWithSoftwareAgentProvRelation, - AttributedToUserProvRelation, - AttributedToSoftwareAgentProvRelation, + AssociatedWithProvRelation, + AttributedToProvRelation, DerivedFromFileVersionProvRelation, GeneratedByActivityProvRelation, InvalidatedByActivityProvRelation, diff --git a/app/models/meta_property.rb b/app/models/meta_property.rb index 7fe9e2ab7..091f35207 100644 --- a/app/models/meta_property.rb +++ b/app/models/meta_property.rb @@ -6,6 +6,8 @@ class MetaProperty < ActiveRecord::Base belongs_to :meta_template, touch: true belongs_to :property + delegate :data_type, to: :property, allow_nil: true + # callbacks before_validation :set_property_from_key before_create :create_mapping @@ -16,6 +18,16 @@ class MetaProperty < ActiveRecord::Base uniqueness: {scope: [:meta_template_id], case_sensitive: false} validates :meta_template, presence: true validates :value, presence: true + validates :value, numericality: true, if: :numeric_data_type? + validates_each :value, if: :date_data_type? do |record, attr, value| + message = 'is not a valid date (format: yyyy-MM-dd[THH:mm[:ss]])' + begin + parsed_date = DateTime.parse(value) + rescue + end + record.errors.add(attr, message) unless parsed_date && + parsed_date.to_s(:iso8601).start_with?(value) + end validates_each :key do |record, attr, value| record.errors.add(attr, 'key is not in the template') if value && !record.property @@ -92,4 +104,24 @@ def index_templatable_document meta_template.templatable.reload meta_template.templatable.__elasticsearch__.index_document end + +private + def date_data_type? + data_type && data_type.to_s == 'date' + end + + def numeric_data_type? + data_type && numeric_data_types.include?(data_type.to_s) + end + + def numeric_data_types + [ + 'long', + 'integer', + 'short', + 'byte', + 'double', + 'float' + ] + end end diff --git a/app/models/meta_template.rb b/app/models/meta_template.rb index d17a414fc..685d73771 100644 --- a/app/models/meta_template.rb +++ b/app/models/meta_template.rb @@ -15,6 +15,12 @@ class MetaTemplate < ActiveRecord::Base !templatable_classes.include?(value.class) end + before_validation :lock_it_down + + def lock_it_down + template.lock! if template + end + def project_permissions templatable.project_permissions end diff --git a/app/models/openid_authentication_service.rb b/app/models/openid_authentication_service.rb new file mode 100644 index 000000000..a870bc559 --- /dev/null +++ b/app/models/openid_authentication_service.rb @@ -0,0 +1,42 @@ +class OpenidAuthenticationService < AuthenticationService + validates :client_secret, presence: true + + def get_user_for_access_token(token) + raise InvalidAccessTokenException.new if token.nil? + user_info = get_userinfo(token) + uid = user_info['dukeNetID'] + user_authentication_service = user_authentication_services.find_by(uid: uid) + if user_authentication_service + user = user_authentication_service.user + user.current_user_authenticaiton_service = user_authentication_service + user + else + user = User.where(username: uid).take + unless user + user = User.new( + id: SecureRandom.uuid, + username: uid, + etag: SecureRandom.hex, + email: user_info['email'], + display_name: user_info['name'], + first_name: user_info['given_name'], + last_name: user_info['family_name'] + ) + end + user_authentication_service = user.user_authentication_services.build( + uid: uid, + authentication_service: self + ) + user.current_user_authenticaiton_service = user_authentication_service + user + end + end + + def get_userinfo(token) + resp = HTTParty.post("#{base_uri}/userinfo", + body: "access_token=#{token}" + ) + raise InvalidAccessTokenException.new unless resp.response.code.to_i == 200 + JSON.parse(resp.body) + end +end diff --git a/app/models/was_generated_by_provenance_graph.rb b/app/models/origin_provenance_graph.rb similarity index 96% rename from app/models/was_generated_by_provenance_graph.rb rename to app/models/origin_provenance_graph.rb index 9c9b31a46..d0903f880 100644 --- a/app/models/was_generated_by_provenance_graph.rb +++ b/app/models/origin_provenance_graph.rb @@ -1,4 +1,4 @@ -class WasGeneratedByProvenanceGraph < ProvenanceGraph +class OriginProvenanceGraph < ProvenanceGraph #pass a method with ProvenanceGraph.new(focus, policy_scope: method(:method_name)) def initialize(file_versions:, policy_scope:) super(policy_scope) diff --git a/app/models/project_transfer.rb b/app/models/project_transfer.rb index 3c8b86f04..1c180678a 100644 --- a/app/models/project_transfer.rb +++ b/app/models/project_transfer.rb @@ -12,16 +12,35 @@ class ProjectTransfer < ActiveRecord::Base validates :project, presence: true validates :status, uniqueness: { scope: [:project_id], - case_sensitive: false, message: 'Pending transfer already exists' }, if: :pending? + validates_each :status, on: :update, unless: :status_was_pending? do |record, attr, value| + record.errors.add(attr, 'cannot be changed when not pending') + end + validates :status_comment, immutable: true, unless: :status_was_pending? validates :from_user, presence: true validates :project_transfer_users, presence: true - private + enum status: [:pending, :rejected, :accepted, :canceled] + + #callbacks + before_validation :reassign_permissions + + def status_was_pending? + status_was == 'pending' + end - def pending? - status && status.downcase == 'pending' + def reassign_permissions + if accepted? + project.project_permissions.destroy_all + project_viewer = AuthRole.find("project_viewer") + project_admin = AuthRole.find("project_admin") + project.project_permissions.build(user: from_user, auth_role: project_viewer) + to_users.each do |to_user| + project.project_permissions.build(user: to_user, auth_role: project_admin) + end + project.save + end end end diff --git a/app/models/property.rb b/app/models/property.rb index 456403144..aacea2cd8 100644 --- a/app/models/property.rb +++ b/app/models/property.rb @@ -6,7 +6,7 @@ class Property < ActiveRecord::Base has_many :meta_properties validates :key, presence: true, - uniqueness: {case_sensitive: false}, + uniqueness: {scope: :template_id, case_sensitive: false}, format: {with: /\A[a-z0-9_]*\z/i}, length: {maximum: 60} validates :key, immutable: true, if: :has_meta_properties? diff --git a/app/models/prov_relation.rb b/app/models/prov_relation.rb index deb764042..de711166a 100644 --- a/app/models/prov_relation.rb +++ b/app/models/prov_relation.rb @@ -23,10 +23,6 @@ class ProvRelation < ActiveRecord::Base belongs_to :relatable_from, polymorphic: true belongs_to :relatable_to, polymorphic: true - def kind - super(self.class.name.underscore) - end - def create_graph_relation super( relationship_type.split('-').map{|part| part.capitalize}.join(''), diff --git a/app/models/software_agent.rb b/app/models/software_agent.rb index 9a4d88228..db9a5e0f1 100644 --- a/app/models/software_agent.rb +++ b/app/models/software_agent.rb @@ -19,4 +19,8 @@ def create_graph_node def graph_node super('Agent') end + + def kind + super('software-agent') + end end diff --git a/app/models/used_prov_relation.rb b/app/models/used_prov_relation.rb index 28639520e..edcf71b72 100644 --- a/app/models/used_prov_relation.rb +++ b/app/models/used_prov_relation.rb @@ -24,4 +24,8 @@ def using_activity errors.add(:relatable_from_id, "UsedProvRelation cannot be made from an Activity that has a GeneratedByActivityProvRelation to the used FileVersion") end end + + def kind + 'dds-relation-used' + end end diff --git a/app/models/user.rb b/app/models/user.rb index 260a6034c..17990f86e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,7 +9,7 @@ class User < ActiveRecord::Base default_scope { order('created_at DESC') } audited except: :last_login_at - attr_accessor :current_software_agent + attr_accessor :current_software_agent, :current_user_authenticaiton_service has_many :user_authentication_services accepts_nested_attributes_for :user_authentication_services diff --git a/app/policies/associated_with_prov_relation_policy.rb b/app/policies/associated_with_prov_relation_policy.rb new file mode 100644 index 000000000..6b8bbf758 --- /dev/null +++ b/app/policies/associated_with_prov_relation_policy.rb @@ -0,0 +1,41 @@ +class AssociatedWithProvRelationPolicy < ApplicationPolicy + def index? + false + end + + def update? + false + end + + def show? + permission + end + + def create? + permission + end + + def destroy? + system_permission || record.creator_id == user.id + end + + class Scope < Scope + def resolve + if user.system_permission + scope + else + prov_relation_scope = scope.where(creator: user) + prov_relation_scope = prov_relation_scope.union( + AssociatedWithProvRelation.where( + relatable_to_id: Activity.where(creator: user) + )) + prov_relation_scope + end + end + end + + def permission + system_permission || + record.relatable_to.creator_id == user.id + end +end diff --git a/app/policies/associated_with_software_agent_prov_relation_policy.rb b/app/policies/associated_with_software_agent_prov_relation_policy.rb index 8bf8f982b..ab5c9ebfe 100644 --- a/app/policies/associated_with_software_agent_prov_relation_policy.rb +++ b/app/policies/associated_with_software_agent_prov_relation_policy.rb @@ -1,41 +1,2 @@ -class AssociatedWithSoftwareAgentProvRelationPolicy < ApplicationPolicy - def index? - false - end - - def update? - false - end - - def show? - permission - end - - def create? - permission - end - - def destroy? - system_permission || record.creator_id == user.id - end - - class Scope < Scope - def resolve - if user.system_permission - scope - else - prov_relation_scope = scope.where(creator: user) - prov_relation_scope = prov_relation_scope.union( - AssociatedWithSoftwareAgentProvRelation.where( - relatable_to_id: Activity.where(creator: user) - )) - prov_relation_scope - end - end - end - - def permission - system_permission || - record.relatable_to.creator_id == user.id - end +class AssociatedWithSoftwareAgentProvRelationPolicy < AssociatedWithProvRelationPolicy end diff --git a/app/policies/associated_with_user_prov_relation_policy.rb b/app/policies/associated_with_user_prov_relation_policy.rb index a5644d976..5e3a811c1 100644 --- a/app/policies/associated_with_user_prov_relation_policy.rb +++ b/app/policies/associated_with_user_prov_relation_policy.rb @@ -1,43 +1,2 @@ -class AssociatedWithUserProvRelationPolicy < ApplicationPolicy - def index? - false - end - - def update? - false - end - - def show? - permission - end - - def create? - system_permission || - (record.relatable_to.creator_id == user.id && - record.relatable_from.id == user.id) - end - - def destroy? - system_permission || record.creator_id == user.id - end - - class Scope < Scope - def resolve - if user.system_permission - scope - else - prov_relation_scope = scope.where(creator: user) - prov_relation_scope = prov_relation_scope.union( - AssociatedWithUserProvRelation.where( - relatable_to_id: Activity.where(creator: user) - )) - prov_relation_scope - end - end - end - - def permission - system_permission || - record.relatable_to.creator_id == user.id - end +class AssociatedWithUserProvRelationPolicy < AssociatedWithProvRelationPolicy end diff --git a/app/policies/attributed_to_prov_relation_policy.rb b/app/policies/attributed_to_prov_relation_policy.rb new file mode 100644 index 000000000..932c0ad1e --- /dev/null +++ b/app/policies/attributed_to_prov_relation_policy.rb @@ -0,0 +1,48 @@ +class AttributedToProvRelationPolicy < ApplicationPolicy + def index? + false + end + + def update? + false + end + + def show? + permission :view_project + end + + def create? + permission :view_project + end + + def destroy? + system_permission || record.creator_id == user.id + end + + class Scope < Scope + def resolve + if user.system_permission + scope + else + prov_relation_scope = scope.where(creator: user) + prov_relation_scope = prov_relation_scope.union( + AttributedToProvRelation.where( + relatable_from_id: policy_scope(FileVersion.all) + )) + prov_relation_scope + end + end + end + + def permission(auth_role_permission=nil) + system_permission || project_permission(auth_role_permission) + end + + def project_permission(auth_role_permission=nil) + project_permissions = record.relatable_from.project_permissions.where(user: user) + if auth_role_permission + project_permissions = project_permissions.joins(:auth_role).merge(AuthRole.with_permission(auth_role_permission)) + end + project_permissions.take + end +end diff --git a/app/policies/attributed_to_software_agent_prov_relation_policy.rb b/app/policies/attributed_to_software_agent_prov_relation_policy.rb index f069ac75f..3b95bb093 100644 --- a/app/policies/attributed_to_software_agent_prov_relation_policy.rb +++ b/app/policies/attributed_to_software_agent_prov_relation_policy.rb @@ -1,48 +1,2 @@ -class AttributedToSoftwareAgentProvRelationPolicy < ApplicationPolicy - def index? - false - end - - def update? - false - end - - def show? - permission :view_project - end - - def create? - permission :view_project - end - - def destroy? - system_permission || record.creator_id == user.id - end - - class Scope < Scope - def resolve - if user.system_permission - scope - else - prov_relation_scope = scope.where(creator: user) - prov_relation_scope = prov_relation_scope.union( - AttributedToSoftwareAgentProvRelation.where( - relatable_from_id: policy_scope(FileVersion.all) - )) - prov_relation_scope - end - end - end - - def permission(auth_role_permission=nil) - system_permission || project_permission(auth_role_permission) - end - - def project_permission(auth_role_permission=nil) - project_permissions = record.relatable_from.project_permissions.where(user: user) - if auth_role_permission - project_permissions = project_permissions.joins(:auth_role).merge(AuthRole.with_permission(auth_role_permission)) - end - project_permissions.take - end +class AttributedToSoftwareAgentProvRelationPolicy < AttributedToProvRelationPolicy end diff --git a/app/policies/attributed_to_user_prov_relation_policy.rb b/app/policies/attributed_to_user_prov_relation_policy.rb index cf32a606d..c2c5cddcb 100644 --- a/app/policies/attributed_to_user_prov_relation_policy.rb +++ b/app/policies/attributed_to_user_prov_relation_policy.rb @@ -1,50 +1,2 @@ -class AttributedToUserProvRelationPolicy < ApplicationPolicy - def index? - false - end - - def update? - false - end - - def show? - permission :view_project - end - - def create? - system_permission || - (project_permission(:view_project) && - record.relatable_to.id == user.id) - end - - def destroy? - system_permission || record.creator_id == user.id - end - - class Scope < Scope - def resolve - if user.system_permission - scope - else - prov_relation_scope = scope.where(creator: user) - prov_relation_scope = prov_relation_scope.union( - AttributedToUserProvRelation.where( - relatable_from_id: policy_scope(FileVersion.all) - )) - prov_relation_scope - end - end - end - - def permission(auth_role_permission=nil) - system_permission || project_permission(auth_role_permission) - end - - def project_permission(auth_role_permission=nil) - project_permissions = record.relatable_from.project_permissions.where(user: user) - if auth_role_permission - project_permissions = project_permissions.joins(:auth_role).merge(AuthRole.with_permission(auth_role_permission)) - end - project_permissions.take - end +class AttributedToUserProvRelationPolicy < AttributedToProvRelationPolicy end diff --git a/app/serializers/authentication_service_serializer.rb b/app/serializers/authentication_service_serializer.rb new file mode 100644 index 000000000..7b4515ef5 --- /dev/null +++ b/app/serializers/authentication_service_serializer.rb @@ -0,0 +1,3 @@ +class AuthenticationServiceSerializer < ActiveModel::Serializer + attributes :id, :service_id, :name, :is_deprecated, :is_default, :login_initiation_url +end diff --git a/app/serializers/project_preview_serializer.rb b/app/serializers/project_preview_serializer.rb index 7c6b0ecdc..9c7463620 100644 --- a/app/serializers/project_preview_serializer.rb +++ b/app/serializers/project_preview_serializer.rb @@ -1,3 +1,3 @@ class ProjectPreviewSerializer < ActiveModel::Serializer - attributes :id + attributes :id, :name end diff --git a/app/serializers/property_preview_serializer.rb b/app/serializers/property_preview_serializer.rb index 28da9b52b..033cae7dc 100644 --- a/app/serializers/property_preview_serializer.rb +++ b/app/serializers/property_preview_serializer.rb @@ -1,3 +1,3 @@ class PropertyPreviewSerializer < ActiveModel::Serializer - attributes :id, :key + attributes :id, :key, :label end diff --git a/app/serializers/data_file_search_document_serializer.rb b/app/serializers/search/data_file_serializer.rb similarity index 50% rename from app/serializers/data_file_search_document_serializer.rb rename to app/serializers/search/data_file_serializer.rb index 09a885240..514163501 100644 --- a/app/serializers/data_file_search_document_serializer.rb +++ b/app/serializers/search/data_file_serializer.rb @@ -1,11 +1,12 @@ -class DataFileSearchDocumentSerializer < ActiveModel::Serializer - attributes :id, :name, :is_deleted, :created_at, :updated_at, :label, :meta +class Search::DataFileSerializer < DataFileSerializer + attributes :kind, :id, :parent, :name, :audit, :is_deleted, + :created_at, + :updated_at, + :label, + :meta - has_many :tags, serializer: TagSearchDocumentSerializer - - def is_deleted - object.is_deleted? - end + has_many :tags, serializer: Search::TagSummarySerializer + has_one :creator, serializer: Search::UserSummarySerializer def meta object.meta_templates.each_with_object({}) do |meta_template, metadata| diff --git a/app/serializers/folder_search_document_serializer.rb b/app/serializers/search/folder_serializer.rb similarity index 60% rename from app/serializers/folder_search_document_serializer.rb rename to app/serializers/search/folder_serializer.rb index 892e55fa8..f86c5afc3 100644 --- a/app/serializers/folder_search_document_serializer.rb +++ b/app/serializers/search/folder_serializer.rb @@ -1,9 +1,8 @@ -class FolderSearchDocumentSerializer < ActiveModel::Serializer - attributes :id, :name, :is_deleted, :created_at, :updated_at, :label, :meta +class Search::FolderSerializer < FolderSerializer + attributes :kind, :id, :parent, :name, :is_deleted, :audit, + :created_at, :updated_at, :label, :meta - def is_deleted - object.is_deleted? - end + has_one :creator, serializer: Search::UserSummarySerializer def meta object.meta_templates.each_with_object({}) do |meta_template, metadata| diff --git a/app/serializers/search/tag_summary_serializer.rb b/app/serializers/search/tag_summary_serializer.rb new file mode 100644 index 000000000..65a3da19d --- /dev/null +++ b/app/serializers/search/tag_summary_serializer.rb @@ -0,0 +1,3 @@ +class Search::TagSummarySerializer < ActiveModel::Serializer + attributes :label +end diff --git a/app/serializers/search/user_summary_serializer.rb b/app/serializers/search/user_summary_serializer.rb new file mode 100644 index 000000000..5a6f9af70 --- /dev/null +++ b/app/serializers/search/user_summary_serializer.rb @@ -0,0 +1,3 @@ +class Search::UserSummarySerializer < ActiveModel::Serializer + attributes :id, :username, :email, :first_name, :last_name +end diff --git a/app/serializers/tag_search_document_serializer.rb b/app/serializers/tag_search_document_serializer.rb deleted file mode 100644 index d5569d2d6..000000000 --- a/app/serializers/tag_search_document_serializer.rb +++ /dev/null @@ -1,3 +0,0 @@ -class TagSearchDocumentSerializer < ActiveModel::Serializer - attributes :label -end diff --git a/app/views/apidocs/index.html b/app/views/apidocs/index.html deleted file mode 100644 index 1df4d240e..000000000 --- a/app/views/apidocs/index.html +++ /dev/null @@ -1,4265 +0,0 @@ -Duke Data Service Back to top

Duke Data Service

The Duke Data Service (DDS) API allows Duke researchers to store, organize, retrieve and share data.

-

This the documentation for the Data Service API. Key focuses are on API endpoints that enhance usability for “shallow end of the pool” users, endpoints that support the needs of investigators for managing their research groups, endpoints that accommodate shared resource and core facility needs, endpoints that support SOM administration of data resources, and endpoints that facilitate reproducible scientific workflows. There are tensions to resolve to meet these needs, and we should consider whether the API might be broken up into multiple APIs, whether some business logic be pushed to the users, etc.

-

Adhere as well as possible to the Heroku API Design Best Practices: requiring secure TLS connections, versioning in the accepts header, supporting Etags, including a Request-id in each response header, among others.

-

API Change Log

-

02-Aug-2016

-
    -
  • -

    Changed URI format of POST /tags to POST /tags/{object_kind}/{object_id} - tags are always created for a specific object.

    -
  • -
  • -

    Changed GET /tags/labels to include a last_used_on property in the response; the response is sorted in descending order by this new property.

    -
  • -
  • -

    Added endpoint POST /tags/{object_kind}/{object_id}/append - allows clients to append a collection of tags to an object.

    -
  • -
-

02-Sep-2016

-
    -
  • -

    Removed Provenance Inferred section - implementation will no longer auto-generate inferred provenance relation based on audit trail.

    -
  • -
  • -

    Refactored Metadata Properties actions to follow URI pattern liken to Tags.

    -
  • -
-

07-Sep-2016

-
    -
  • -

    Added endpoint /search/provenance/was_generated_by - allows targeted search “up” the provenance chain for a set of file versions.

    -
  • -
  • -

    Added rules/constraints for Provenance Relations actions.

    -
  • -
-

12-Sep-2016

-
    -
  • -

    Refactored Metadata actions - objects can now be annotated with metadata via bulk POST and PUT actions.

    -
  • -
  • -

    Added name query param to GET /templates and key query param to GET /templates/{id}/properties; these query params allow clients to lookup templates and template properties by their alternate unique key.

    -
  • -
-

23-Sep-2016

-
    -
  • Added Authentication Providers actions - formalizes metadata for supported auth providers and provides endpoint to search for affiliates (potential DDS users) in context of the provider. In addition, supports getting a DDS user identity for a valid affiliate - this endpoint introduces a proposed change to user payload.
  • -
-

17-Oct-2016

-
    -
  • -

    For Search Provenance - changed /search/provenance/was_generated_by to /search/provenance/origin; this search action now includes wasDerivedFrom file versions in the results.

    -
  • -
  • -

    For Metadata - changed /templates{?name} to /templates{?name_contains} - facilitates contains search vs. exact match.

    -
  • -
  • -

    Changed /templates/{id}/properties{?key} to /templates/{id}/properties - if we need key based lookup we will extend API to return the instance by key, not an array of 1.

    -
  • -
  • -

    Changed /meta/{object_kind}/{object_id}{?meta_template_name} to /meta/{object_kind}/{object_id} - if we need template_name based lookup we will extend API to return the instance by template_name, not an array of 1.

    -
  • -
-

API Usage

Web Portal

-

There is a Web portal that allows users to interact with the Web services API. Access is currently restricted to Duke staff with a valid Duke NetID and password. To access the Web portal, Duke staff must successfully authenticate via the Duke single sign-on process.

-

Programmatic Keys

-

In an effort to promote provenance, all programmatic access to the API must utilize the concept of a software agent. From the Web portal, an authorized user can generate secret keys for both a software agent and their user account. In tandem, these secret keys can be used to obtain an access token from a programmatic context. For usage details, see the actions for Software Agents and Current User.

-

Exploring the API

-

In addition to the API usage documentation herein, users may experiment with the live API actions in a test environment via the API Explorer.

-

Collection Pagination

-

For actions that return a collection of resources/objects, the number of objects returned will be paginated. The number of objects returned per page, and the desired page can be controlled using the query parameters page, and per_page. For example: /projects?per_page=25 will return the first 25 projects, and /projects?page=3&per_page=25 will return the third batch of 25 projects. Collection payloads will always be returned as an array of objects; the results property will reference the array as follows:

-
{
-    "results": [
-        { },
-        { },
-    ]
-}
-

To make it easy for clients to manage pagination, the following headers will always be included in the response:

-
    -
  • -

    X-Total: The total number of objects that would be returned by the query unpaginated

    -
  • -
  • -

    X-Total-Pages: The total number of pages given X-Total and X-Per-Page

    -
  • -
  • -

    X-Page: Current Page (passed in as query parameter)

    -
  • -
  • -

    X-Per-Page: per_page (passed in as query parameter)

    -
  • -
  • -

    X-Next-Page: Next page to be collected

    -
  • -
  • -

    X-Prev-Page: Previous page (will be empty on first page)

    -
  • -
-

Audit Object

-

Resource payloads may include a composite audit object. An example structure of that object is represented here and will be referenced by the audit property in resource specific payloads.

-
"audit": {
-    "created_on": "2015-01-01T12:00:00Z",
-    "created_by": {
-        "id": "ce245d81-bae1-452b-8589-24f736ca7735",
-        "username": "mrgardner01",
-        "full_name": "Matthew Gardner",
-        "software_agent": {
-            "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-            "name": "Hashing computation agent"
-        }
-    },
-    "last_updated_on": "2015-01-01T13:00:00Z",
-    "last_updated_by": {
-        "id": "d240ef3d-8d43-441b-be90-78f51a02e47f",
-        "username": "jturner01",
-        "full_name": "Jon Turner",
-        "software_agent": null
-    },
-    "deleted_on": null,
-    "deleted_by": null
-}
-

API Errors

-

We should respond with context appropriate error codes, especially for 400 class errors, using the Standard List

-
    -
  • -

    400: no API token, validation errors

    -
  • -
  • -

    401: bad API token

    -
  • -
  • -

    403: user performing request which they do not have permission to perform

    -
  • -
  • -

    404: user requesting resource that does not exist

    -
  • -
-

All error responses should include a JSON response that provides the HTTP status code, details of the error that occurred, and possible steps to address the problem. For example:

-
{
-    "error": "404",
-    "reason": "Project does not exist",
-    "suggestion": "You may have chosen the wrong ID."
-}
-

Validation errors require a field-level breakdown with an array of errors (even if multiple errors occur for the same field), each describing the field with the error, and message describing the error encountered.

-
{
-    "error": "400",
-    "reason": "validation failed",
-    "suggestion": "Fix the following invalid fields and resubmit"
-    "errors" : [
-        {
-            "field" : "name",
-            "message" : "Project needs a name."
-        },
-        {
-            "field" : "principal_investigator",
-            "message" : "Principal Investigator must be specified for each project."
-        }
-    ]
-}
-

Authorization Roles

Represents the set of discrete permissions that can be granted to a user.

-

Authorization Roles:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
rolenamedescriptionpermission(s)
system_adminSystem AdminCan manage system level permissions and perform all operations across all projectssystem_admin
project_adminProject AdminCan update project details, delete project, manage project level permissions and perform all file operationsview_project, update_project, delete_project, manage_project_permissions, download_file, create_file, update_file, delete_file
project_viewerProject ViewerCan only view project and file metadataview_project
file_downloaderFile DownloaderCan download filesview_project, download_file
file_uploaderFile UploaderCan upload filesview_project, create_file, update_file
file_editorFile EditorCan view, download, create, update and delete filesview_project, download_file, create_file, update_file, delete_file
-

Permissions:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
permissiondescription
system_adminCan manage system level permissions and perform all operations across all projects
view_projectCan view project and file metadata
update_projectCan update project header details and project affiliations
delete_projectCan delete project
manage_project_permissionsCan grant/revoke project level permissions
download_fileCan download file
create_fileCan upload new file and modify file metadata
update_fileCan upload new version of existing file and modify file metadata
delete_fileCan delete a file
-

Authorization Roles collection

List roles
GET/auth_roles{?context}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/auth_roles?context=system
URI Parameters
HideShow
context
string (optional) Example: system

The context or scope in which permission can be granted; valid context values are system or project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "system_admin",
-      "name": "System Admin",
-      "description": "Can manage system level permissions and perform all operations across all projects",
-      "permissions": [
-        {
-          "id": "system_admin"
-        }
-      ],
-      "contexts": [
-        "system"
-      ],
-      "is_deprecated": false
-    }
-  ]
-}

Authorization Role instance

View role
GET/auth_roles/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/auth_roles/file_editor
URI Parameters
HideShow
id
string (required) Example: file_editor

The unique id for an authorization role.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "file_editor",
-  "name": "File Editor",
-  "description": "Can view, download, create, update and delete files",
-  "permissions": [
-    {
-      "id": "view_project"
-    },
-    {
-      "id": "download_file"
-    }
-  ],
-  "contexts": [
-    "project"
-  ],
-  "is_deprecated": false
-}

Software Agents

Represents a software agent and associated secret that can be used to access the API actions from programmatic clients, such as research core pipelines, or background jobs/tasks (e.g. hash computations, deletion of storage for failed uploads, etc.). In an effort to promote provenance, all programmatic access to the API must be via an agent secret key in tandem with a user account secret key (see Current User actions).

-

Software Agents collection

Create software agent
POST/software_agents

Creates software agent and an associated secret API key; the secret key is visible and managed through the software_agents/{id}/api_key action.

-
-

Permission: authenticated

-
-
-
-

Properties

-
-
-
    -
  • name (string) - A short name for the software agent.
  • -
  • description (string, optional) - A verbose description for the software agent.
  • -
  • repo_url (string, optional) - The url of the repository (e.g. Git, Bitbucket, etc.) that contains the agent source code.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/software_agents
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "Hash computation agent"
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-  "name": "Hash computation agent",
-  "description": null,
-  "repo_url": null,
-  "is_deleted": false,
-  "audit": {}
-}

List software agents
GET/software_agents

-

Permission: authenticated

-
-
-
-

Rules

-
-
-
    -
  • Software Agents that have been deleted (i.e. "is_deleted": true) are not included.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/software_agents
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-      "name": "Hash computation agent",
-      "description": null,
-      "repo_url": null,
-      "is_deleted": false,
-      "audit": {}
-    }
-  ]
-}

Software Agent instance

View software agent
GET/software_agents/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/software_agents/9a4c28a2-ec18-40ed-b75c-3bf5b309715
URI Parameters
HideShow
id
string (required) Example: 9a4c28a2-ec18-40ed-b75c-3bf5b309715

The unique id for a software agent.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-  "name": "Hash computation agent",
-  "description": null,
-  "repo_url": null,
-  "is_deleted": false,
-  "audit": {}
-}

Update software agent
PUT/software_agents/{id}

-

Permission: creator or system_admin

-
-
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/software_agents/9a4c28a2-ec18-40ed-b75c-3bf5b309715
URI Parameters
HideShow
id
string (required) Example: 9a4c28a2-ec18-40ed-b75c-3bf5b309715

The unique id for a software agent.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "repo_url": "https://github.com/mgardnerpsu/dukeds-dredd"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-  "name": "Hash computation agent",
-  "description": null,
-  "repo_url": "https://github.com/mgardnerpsu/dukeds-dredd",
-  "is_deleted": false,
-  "audit": {}
-}

Delete software agent
DELETE/software_agents/{id}

-

Permission: creator or system_admin

-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/software_agents/9a4c28a2-ec18-40ed-b75c-3bf5b309715
URI Parameters
HideShow
id
string (required) Example: 9a4c28a2-ec18-40ed-b75c-3bf5b309715

The unique id for a software agent.

-
Response  204

Software Agent API Key

Generates a secret key for the software agent that can be used to access the API actions from a scripting context (i.e. bash, python, R, etc…); this secret key must be used in tandem with a valid user secret key (see Current User actions).

-

Generate software agent API key
PUT/software_agents/{id}/api_key

Generates a new secret key for the software agent.

-
-

Permission: creator or system_admin

-
-
-
-

Rules

-
-
-
    -
  • If the software agent already has an API key, this action deletes exisiting key and generates a new key.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/software_agents/9a4c28a2-ec18-40ed-b75c-3bf5b309715/api_key
URI Parameters
HideShow
id
string (required) Example: 9a4c28a2-ec18-40ed-b75c-3bf5b309715

The unique id for a software agent.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
-  "created_on": "2015-06-01T12:00:00Z"
-}

View software agent API key
GET/software_agents/{id}/api_key

Shows the secret key for the software agent.

-
-

Permission: creator or system_admin

-
-
-
-

Properties

-
-
-
    -
  • key (string) - A secret key that can be used in tandem with a user secret key to obtain an API access token.
  • -
  • created_on (datetime) - The date the software agent key was generated.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/software_agents/9a4c28a2-ec18-40ed-b75c-3bf5b309715/api_key
URI Parameters
HideShow
id
string (required) Example: 9a4c28a2-ec18-40ed-b75c-3bf5b309715

The unique id for a software agent.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...",
-  "created_on": "2015-01-01T12:00:00Z"
-}

Delete software agent API key
DELETE/software_agents/{id}/api_key

-

Permission: creator or system_admin

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/software_agents/9a4c28a2-ec18-40ed-b75c-3bf5b309715/api_key
URI Parameters
HideShow
id
string (required) Example: 9a4c28a2-ec18-40ed-b75c-3bf5b309715

The unique id for a software agent.

-
Response  204

Software Agent Access Token

Get software agent access token
POST/software_agents/api_token

Using a software agent secret key and a user secret key, get an access token.

-
-

Permission: public

-
-
-
-

Request Properties

-
-
-
    -
  • agent_key (string) - The secret key for a software agent.
  • -
  • user_key (string) - The secret key for a user.
  • -
-
-

Response Properties

-
-
-
    -
  • api_token (string) - The access token.
  • -
  • expire_on (number) - Token expiration as posix/epoch time.
  • -
  • time_to_live (number) - The number of seconds token is valid for; can be used by client apps to compare relative to their local time, and determine if token must be refreshed.
  • -
-
-

Rules

-
-
-
    -
  • The agent associated with the agent key must not have been logically deleted.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/software_agents/api_token
Request
HideShow
Body
{
-  "agent_key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
-  "user_key": "klmOiJKV1QiLYHkl098EfNiJJIUzI1NiJ93R..."
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "api_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6I...",
-  "expire_on": 1455571739,
-  "time_to_live": 14400
-}

Current User

Represents the currently authenticated user.

-

Current User instance

View current user
GET/current_user

Get profile for the currently authenticated user.

-
-

Permission: authenticated

-
-
-
-

Rules

-
-
-
    -
  • The agent property is populated if user is authenticated via software agent token, otherwise the agent property is null.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/current_user
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-  "username": "mrgardner01",
-  "first_name": "Matthew",
-  "last_name": "Gardner",
-  "full_name": "Matthew Gardner",
-  "email": "mrgardner01@duke.edu",
-  "auth_provider": {
-    "source": "duke_shibboleth",
-    "uid": "gardner100"
-  },
-  "agent": {
-    "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-    "name": "Hashing computation agent"
-  },
-  "last_login_on": "2015-01-01T12:00:00Z",
-  "audit": {}
-}

Current user usage
GET/current_user/usage

View summary usage for current user across all projects.

-
-

Permission: authenticated [scope: view_project]

-
-
-
-

Properties

-
-
-
    -
  • project_count (number) - Total number of projects where the user has been granted a project level authorization role.
  • -
  • file_count (integer) - Total number of files the user has created (i.e. uploaded) across all projects.
  • -
  • storage_bytes (integer) - Total bytes for files the user has created (i.e. uploaded) across all projects.
  • -
-
-

Rules

-
-
-
    -
  • Deleted objects (i.e. "is_deleted": true) are excluded from all counts/totals.
  • -
  • Counts/totals are only for project resources that are visible to the current user.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/current_user/usage
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "project_count": 10,
-  "file_count": 126,
-  "storage_bytes": 304006007009
-}

Current User API Key

Generate current user API key
PUT/current_user/api_key

Generates a secret key for the current user that can be used to access the API actions from a scripting context (i.e. bash, python, R, etc…); this secret key must be used in tandem with a valid software agent secret key (see Software Agents actions).

-
-

Permission: authenticated

-
-
-
-

Properties

-
-
-
    -
  • key (string) - A secret key that can be used in tandem with a software agent secret key to obtain an API access token.
  • -
  • created_on (datetime) - The date the user key was generated.
  • -
-
-

Rules

-
-
-
    -
  • If the current user already has an API key, this action deletes their exisiting key and generates a new key.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/current_user/api_key
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
-  "created_on": "2015-01-01T12:00:00Z"
-}

View current user API key
GET/current_user/api_key

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/current_user/api_key
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "key": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjY...",
-  "created_on": "2015-01-01T12:00:00Z"
-}

Delete current user API key
DELETE/current_user/api_key

-

Permission: authenticated

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/current_user/api_key
Response  204

Users

Represents registered users.

-

Users collection

List users
GET/users{?full_name_contains,first_name_begins_with,last_name_begins_with}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/users?full_name_contains=gardner&first_name_begins_with=mat&last_name_begins_with=gar
URI Parameters
HideShow
full_name_contains
string (optional) Example: gardner

Returns users where their full name contains the specified string.

-
first_name_begins_with
string (optional) Example: mat

Returns users where their first name begins with the specified string.

-
last_name_begins_with
string (optional) Example: gar

Returns users where their last name begins with the specified string.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-      "username": "mrgardner01",
-      "first_name": "Matthew",
-      "last_name": "Gardner",
-      "full_name": "Matthew Gardner",
-      "email": "mrgardner01@duke.edu",
-      "auth_provider": {
-        "source": "duke_shibboleth",
-        "uid": "gardner100"
-      },
-      "last_login_on": "2015-01-01T12:00:00Z",
-      "audit": {}
-    }
-  ]
-}

User instance

View user
GET/users/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/users/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id for a user.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-  "username": "mrgardner01",
-  "first_name": "Matthew",
-  "last_name": "Gardner",
-  "full_name": "Matthew Gardner",
-  "email": "mrgardner01@duke.edu",
-  "auth_provider": {
-    "source": "duke_shibboleth",
-    "uid": "gardner100"
-  },
-  "last_login_on": "2015-01-01T12:00:00Z",
-  "audit": {}
-}

System Permissions

Represents system level authorization roles that have been granted to a user.

-

System Permissions collection

List system permissions
GET/system/permissions

-

Permission: system_admin

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/system/permissions
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "user": {
-        "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-        "username": "mrgardner01",
-        "full_name": "Matthew Gardner"
-      },
-      "auth_role": {
-        "id": "system_admin",
-        "name": "System Admin",
-        "description": "Can manage system level permissions and perform all operations across all projects"
-      }
-    }
-  ]
-}

System Permission instance

Grant system permission
PUT/system/permissions/{user_id}

-

Permission: system_admin

-
-
-
-

Rules

-
-
-
    -
  • Revokes any existing system level authorization role for the user and grants the new role.
  • -
  • The role specified must be a system level authorization role (i.e. system in auth_role.contexts).
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/system/permissions/ca29f7df-33ca-46dd-a015-92c46fdb6fd1
URI Parameters
HideShow
user_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the user.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "auth_role": {
-    "id": "system_admin"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "auth_role": {
-    "id": "system_admin",
-    "name": "System Admin",
-    "description": "Can manage system level permissions and perform all operations across all projects"
-  }
-}

View system permission
GET/system/permissions/{user_id}

-

Permission: system_admin

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/system/permissions/ca29f7df-33ca-46dd-a015-92c46fdb6fd1
URI Parameters
HideShow
user_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the user.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "auth_role": {
-    "id": "system_admin",
-    "name": "System Admin",
-    "description": "Can manage system level permissions and perform all operations across all projects"
-  }
-}

Revoke system permission
DELETE/system/permissions/{user_id}

-

Permission: system_admin

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/system/permissions/ca29f7df-33ca-46dd-a015-92c46fdb6fd1
URI Parameters
HideShow
user_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the user.

-
Response  204

Projects

Represents a container for storing, organizing, retrieving and sharing research data files and their associated metadata.

-

Projects collection

Create project
POST/projects

-

Permission: authenticated

-
-
-
-

Rules

-
-
-
    -
  • User who creates project is granted the project_admin authorization role.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/projects
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "Knockout Mouse Project (KOMP)",
-  "description": "Goal of generating a targeted knockout mutation..."
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-project",
-  "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-  "name": "Knockout Mouse Project (KOMP)",
-  "description": "Goal of generating a targeted knockout mutation...",
-  "is_deleted": false,
-  "audit": {}
-}

List projects
GET/projects

-

Permission: authenticated [scope: view_project]

-
-
-
-

Rules

-
-
-
    -
  • Projects that have been deleted (i.e. "is_deleted": true) are not included.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)",
-      "description": "Goal of generating a targeted knockout mutation...",
-      "is_deleted": false,
-      "audit": {}
-    }
-  ]
-}

Project instance

View project
GET/projects/{id}

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-project",
-  "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-  "name": "Knockout Mouse Project (KOMP)",
-  "description": "Goal of generating a targeted knockout mutation...",
-  "is_deleted": false,
-  "audit": {}
-}

Update project
PUT/projects/{id}

-

Permission: update_project

-
-
-
-

Rules

-
-
-
    -
  • Only name and description properties may be updated via this action.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "Knockout Mouse Project (KOMP)",
-  "description": "Goal of generating a targeted knockout mutation..."
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-project",
-  "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-  "name": "Knockout Mouse Project (KOMP)",
-  "description": "Goal of generating a targeted knockout mutation...",
-  "is_deleted": false,
-  "audit": {}
-}

Delete project
DELETE/projects/{id}

-

Permission: delete_project

-
-
-
-

Rules

-
-
-
    -
  • This operation recursively deletes all of the project children (i.e. folders,files and file versions).
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Response  204

NOT_IMPLEMENTED_NEW Project usage
GET/projects/{id}/usage

View summary usage for the project.

-
-

Permission: view_project

-
-
-
-

Properties

-
-
-
    -
  • member_count (number) - Total number of users granted a project level permission.
  • -
  • file_count (integer) - Total number of files contained in the project.
  • -
  • storage_bytes (integer) - Total bytes for all files contained in the project.
  • -
-
-

Rules

-
-
-
    -
  • Deleted objects (i.e. "is_deleted": true) are excluded from all counts/totals.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/usage
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "member_count": 10,
-  "file_count": 126,
-  "storage_bytes": 804006007009
-}

Project Permissions

Represents project level authorization roles that have been granted to a user.

-

Project Permissions collection

List project permissions
GET/projects/{id}/permissions

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/permissions
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      },
-      "user": {
-        "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-        "username": "mrgardner01",
-        "full_name": "Matthew Gardner"
-      },
-      "auth_role": {
-        "id": "file_editor",
-        "name": "File Editor",
-        "description": "Can view, download, create, update and delete files"
-      }
-    }
-  ]
-}

Project Permission instance

Grant project permission
PUT/projects/{project_id}/permissions/{user_id}

-

Permission: manage_project_permissions

-
-
-
-

Rules

-
-
-
    -
  • Revokes any existing project level authorization role for the user and grants the new role.
  • -
  • The role specified must be a project level authorization role (i.e. project in auth_role.contexts).
  • -
  • The current user cannot grant or revoke their own project level role.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/permissions/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
project_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
user_id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id of the user.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "auth_role": {
-    "id": "file_editor"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "auth_role": {
-    "id": "file_editor",
-    "name": "File Editor",
-    "description": "Can view, download, create, update and delete files"
-  }
-}

View project permission
GET/projects/{project_id}/permissions/{user_id}

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/permissions/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
project_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
user_id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id of the user.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "auth_role": {
-    "id": "file_editor",
-    "name": "File Editor",
-    "description": "Can view, download, create, update and delete files"
-  }
-}

Revoke project permission
DELETE/projects/{project_id}/permissions/{user_id}

-

Permission: manage_project_permissions

-
-
-
-

Rules

-
-
-
    -
  • The project must have at least one user with the project_admin role.
  • -
  • The current user cannot revoke their own project level role.
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/permissions/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
project_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
user_id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id of the user.

-
Response  204

Project Roles

Represents an organizational role that an individual (i.e. user) may assume in the context of a project. These organizational roles have no relationship to authorization roles.

-

Project Roles:

- - - - - - - - - - - - - - - - - - - - -
rolenamedescription
principal_investigatorPrincipal InvestigatorLead investigator for the research project
research_coordinatorResearch CoordinatorCoordinator for the research project
-

Project Roles collection

List project roles
GET/project_roles

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/project_roles
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "principal_investigator",
-      "name": "Principal Investigator",
-      "description": "Lead investigator for the research project",
-      "is_deprecated": false
-    },
-    {
-      "id": "research_coordinator",
-      "name": "Research Coordinator",
-      "description": "Coordinator for the research project",
-      "is_deprecated": false
-    }
-  ]
-}

Project Role instance

View project role
GET/project_roles/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/project_roles/principal_investigator
URI Parameters
HideShow
id
string (required) Example: principal_investigator

The unique id for a project role.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "principal_investigator",
-  "name": "Principal Investigator",
-  "description": "Lead investigator for the research project",
-  "is_deprecated": false
-}

Affiliates

Represents an individual that plays some project level role of interest from a collaboration perspective. The affiliate must be a registered user.

-

Affiliates collection

List affiliates
GET/projects/{id}/affiliates

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/affiliates
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      },
-      "user": {
-        "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-        "full_name": "Matthew Gardner",
-        "email": "mrgardner01@duke.edu"
-      },
-      "project_role": {
-        "id": "principal_investigator",
-        "name": "Principal Investigator"
-      }
-    }
-  ]
-}

Affiliate instance

Associate affiliate
PUT/projects/{project_id}/affiliates/{user_id}

-

Permission: update_project

-
-
-
-

Rules

-
-
-
    -
  • Deletes any existing project role for the user and assigns new role.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/affiliates/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
project_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
user_id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id of the user.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "project_role": {
-    "id": "principal_investigator"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "full_name": "Matthew Gardner",
-    "email": "mrgardner01@duke.edu"
-  },
-  "project_role": {
-    "id": "principal_investigator",
-    "name": "Principal Investigator"
-  }
-}

View affiliate
GET/projects/{project_id}/affiliates/{user_id}

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/affiliates/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
project_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
user_id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id of the user.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "full_name": "Matthew Gardner",
-    "email": "mrgardner01@duke.edu"
-  },
-  "project_role": {
-    "id": "principal_investigator",
-    "name": "Principal Investigator"
-  }
-}

Delete affiliate
DELETE/projects/{project_id}/affiliates/{user_id}

-

Permission: update_project

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/affiliates/c1179f73-0558-4f96-afc7-9d251e65b7bb
URI Parameters
HideShow
project_id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
user_id
string (required) Example: c1179f73-0558-4f96-afc7-9d251e65b7bb

The unique id of the user.

-
Response  204

Storage Providers

Represents an external service that provides physical storage space for files.

-

Storage Providers collection

List storage providers
GET/storage_providers

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/storage_providers
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-      "name": "duke_oit_swift",
-      "description": "Duke OIT Storage",
-      "chunk_hash_algorithm": "md5",
-      "is_deprecated": false
-    },
-    {
-      "id": "t4479f73-0774-4f96-afc7-9d251e65by88",
-      "name": "amazon_s3_glacier",
-      "description": "Amazon Glacier Cloud Storage",
-      "chunk_hash_algorithm": "sha1",
-      "is_deprecated": false
-    }
-  ]
-}

Storage Provider instance

View storage provider
GET/storage_providers/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/storage_providers/g5579f73-0558-4f96-afc7-9d251e65bv33
URI Parameters
HideShow
id
string (required) Example: g5579f73-0558-4f96-afc7-9d251e65bv33

The unique id of the storage provider.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-  "name": "duke_oit_swift",
-  "description": "Duke Office of Information Technology Storage",
-  "chunk_hash_algorithm": "md5",
-  "is_deprecated": false
-}

Folders

A folder is a container for files and sub-folders; folders are located in the top-level project root or a parent folder.

-

Folders collection

Create folder
POST/folders

-

Permission: create_file

-
-
-
-

Request Properties

-
-
-
    -
  • parent.kind (string, required) - The kind of parent container for the folder; this can be a project (i.e. dds-project) or a folder (i.e. dds-folder).
  • -
  • parent.id (string, required) - The unique id of the parent.
  • -
  • name (string, required) - A short name for the folder.
  • -
-
-

Response Properties

-
-
-
    -
  • ancestors (object[ ]) - Represents entire ancestral path, from the root node (project or folder), down to its parent, in hierarchical order.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/folders
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "parent": {
-    "kind": "dds-folder",
-    "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc"
-  },
-  "name": "Raw Data"
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-folder",
-  "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-  },
-  "name": "Raw Data",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-      "name": "Sequencing Core"
-    }
-  ],
-  "is_deleted": false,
-  "audit": {}
-}

Folder instance

View folder
GET/folders/{id}

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/folders/d5ae02a4-b9e6-473d-87c4-66f4c881ae7a
URI Parameters
HideShow
id
string (required) Example: d5ae02a4-b9e6-473d-87c4-66f4c881ae7a

The unique id of the folder.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-folder",
-  "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-  },
-  "name": "Raw Data",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-      "name": "Sequencing Core"
-    }
-  ],
-  "is_deleted": false,
-  "audit": {}
-}

Delete folder
DELETE/folders/{id}

-

Permission: delete_file

-
-
-
-

Rules

-
-
-
    -
  • This operation recursively deletes all of the folder children (i.e. folders, files and file versions).
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/folders/d5ae02a4-b9e6-473d-87c4-66f4c881ae7a
URI Parameters
HideShow
id
string (required) Example: d5ae02a4-b9e6-473d-87c4-66f4c881ae7a

The unique id of the folder.

-
Response  204

Move folder
PUT/folders/{id}/move

-

Permission: create_file

-
-
-
-

Rules

-
-
-
    -
  • The destination folder cannot be a child of the folder being moved.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/folders/d5ae02a4-b9e6-473d-87c4-66f4c881ae7a/move
URI Parameters
HideShow
id
string (required) Example: d5ae02a4-b9e6-473d-87c4-66f4c881ae7a

The unique id of the folder.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "parent": {
-    "kind": "dds-folder",
-    "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-folder",
-  "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc"
-  },
-  "name": "Raw Data",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc",
-      "name": "Flow Core"
-    }
-  ],
-  "is_deleted": false,
-  "audit": {}
-}

Rename folder
PUT/folders/{id}/rename

-

Permission: create_file

-
-
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/folders/d5ae02a4-b9e6-473d-87c4-66f4c881ae7a/rename
URI Parameters
HideShow
id
string (required) Example: d5ae02a4-b9e6-473d-87c4-66f4c881ae7a

The unique id of the folder.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "Model Data"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-folder",
-  "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc"
-  },
-  "name": "Model Data",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "482be8c5-209d-4e3b-afaf-cb66686ffbcc",
-      "name": "Flow Core"
-    }
-  ],
-  "is_deleted": false,
-  "audit": {}
-}

Uploads

All files must be uploaded using a multi-part/chunked upload process. Although this places more burden on clients to divide larger files into chunks and send each chunk separately, the result is a more robust process that allows failed chunks to be resent. The following actions must be used by the client to manage the chunked upload process.

-

Uploads collection

Initiate chunked upload
POST/projects/{id}/uploads

This is the first step in uploading a large file. An upload objects is created along with a composite status object that can be polled by client agents to track the progress of the chunked upload.

-
-

Permission: create_file

-
-
-
-

Request Properties

-
-
-
    -
  • name (string, required) - The name of the client file to upload.
  • -
  • content_type (string, optional) - Valid content type per media types.
  • -
  • size (number, required) - The size in bytes of entire file (computed by client).
  • -
-
-

Response Properties

-
-
-
    -
  • chunks (object) - The chunks the client has requested to upload.
  • -
  • storage_location (object) - Object that contains target storage details.
  • -
  • status (object) - Object used to track status of overall file upload.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/projects/d5ae02a4-b9e6-473d-87c4-66f4c881ae7a/uploads
URI Parameters
HideShow
id
string (required) Example: d5ae02a4-b9e6-473d-87c4-66f4c881ae7a

Globally unique id of the project.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "content_type": "application/octet-stream",
-  "size": 30024000
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "content_type": "application/octet-stream",
-  "size": 30024000,
-  "hashes": [],
-  "chunks": [],
-  "storage_provider": {
-    "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-    "name": "duke_oit_swift",
-    "description": "Duke OIT Storage"
-  },
-  "status": {
-    "initiated_on": "2015-07-10T13:00:00Z",
-    "completed_on": null,
-    "error_on": null,
-    "error_message": null
-  },
-  "audit": {}
-}

List chunked uploads
GET/projects/{id}/uploads

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/d5ae02a4-b9e6-473d-87c4-66f4c881ae7a/uploads
URI Parameters
HideShow
id
string (required) Example: d5ae02a4-b9e6-473d-87c4-66f4c881ae7a

Globally unique id of the project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "project": {
-        "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-      },
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "content_type": "application/octet-stream",
-      "hashes": [],
-      "chunks": [],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      },
-      "status": {
-        "initiated_on": "2015-07-10T13:00:00Z",
-        "completed_on": null,
-        "error_on": null,
-        "error_message": null
-      },
-      "audit": {}
-    }
-  ]
-}

Upload instance

View chunked upload
GET/uploads/{id}

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/uploads/666be35a-98e0-4c2e-9a17-7bc009f9bb23
URI Parameters
HideShow
id
string (required) Example: 666be35a-98e0-4c2e-9a17-7bc009f9bb23

The unique id of the upload.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "content_type": "application/octet-stream",
-  "size": 30024000,
-  "hashes": [],
-  "chunks": [
-    {
-      "number": 1,
-      "size": 10000,
-      "hash": {
-        "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-        "algorithm": "md5"
-      }
-    }
-  ],
-  "storage_provider": {
-    "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-    "name": "duke_oit_swift",
-    "description": "Duke OIT Storage"
-  },
-  "status": {
-    "initiated_on": "2015-07-10T13:00:00Z",
-    "completed_on": null,
-    "error_on": null,
-    "error_message": null
-  },
-  "audit": {}
-}

Get pre-signed chunk URL
PUT/uploads/{id}/chunks

Generates and returns a pre-signed URL that can be used by client to upload a file chunk to the storage provider. This step is repeated for each chunk. If the chunk uploads fails, the client must call this action again to get a new pre-signed URL for the chunk number, then retry the chunk upload.

-
-

Permission: create_file

-
-
-
-

Request Properties

-
-
-
    -
  • number (number, required) - The chunk number.
  • -
  • size (number, required) - The size of the chunk in bytes (computed by client).
  • -
  • hash.value (string, required) - The chunk hash (computed by client).
  • -
  • hash.algorithm (string, required) - The hash algorithm used (i.e. md5, sha256, sha1, etc.); this must be the default algorithm (i.e. chunk_hash_algorithm) supported by storage provider (see Storage Providers actions)
  • -
-
-

Response Properties

-
-
-
    -
  • http_verb (string) - The http verb to use for uploading the next chunk.
  • -
  • host (string) - The storage provider host.
  • -
  • url (string) - The pre-signed URL for uploading the chunk to the storage provider.
  • -
  • http_headers (object[ ]) - Array of headers (i.e. key/value pairs) that must be included in the client upload request.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/uploads/666be35a-98e0-4c2e-9a17-7bc009f9bb23/chunks
URI Parameters
HideShow
id
string (required) Example: 666be35a-98e0-4c2e-9a17-7bc009f9bb23

The unique id of the upload.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "number": 1,
-  "size": 5024000,
-  "hash": {
-    "value": "ey23df2207d99a74fbe169e3eba035e633b65d76",
-    "algorithm": "md5"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "http_verb": "PUT",
-  "host": "duke_data_service_prod.s3.amazonaws.com",
-  "url": "/666be35a-98e0-4c2e-9a17-7bc009f9bb23?partNumber=1&uploadId=EXAMPLEJZ6e0YupT2...&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN...",
-  "http_headers": [
-    {
-      "Content-Length": "5024000"
-    }
-  ]
-}

Complete chunked file upload
PUT/uploads/{id}/complete

This operation is called by the client after all file chunks have been successfully uploaded to the storage provider.

-
-

Permission: create_file

-
-
-
-

Properties

-
-
-
    -
  • hash.value (string, required) - The entire file hash (computed by client).
  • -
  • hash.algorithm (string, required) - The algorithm used by client to compute entire file hash (i.e. md5, sha256, sha1, etc.).
  • -
-
-

Rules

-
-
-
    -
  • If the storage provider requires the individual chunks to be assembled, such as Amazon S3, this operation will call the storage provider actions to assemble the parts into a single file object.
  • -
  • The reported hash.value must be a valid algorithm - supported/valid algorithms are: md5, sha256, and sha1.
  • -
  • The client hash for each chunk must equal the storage provider hash for the same chunk, or an upload error is reported.
  • -
  • The client reported file size (bytes) must equal the storage provider reported file size, or an upload error is reported.
  • -
  • If there are no errors, the upload_status.completed_on is set to the current timestamp.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/uploads/666be35a-98e0-4c2e-9a17-7bc009f9bb23/complete
URI Parameters
HideShow
id
string (required) Example: 666be35a-98e0-4c2e-9a17-7bc009f9bb23

The unique id of the upload.

-
Request
HideShow
Body
{
-  "hash": {
-    "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-    "algorithm": "md5"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "content_type": "application/octet-stream",
-  "size": 30024000,
-  "hashes": [
-    {
-      "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-      "algorithm": "md5",
-      "audit": {}
-    }
-  ],
-  "chunks": [
-    {
-      "number": 1,
-      "size": 5024000,
-      "hash": {
-        "value": "jw23df2207d99a74fbe169e3eba035e633b65d88",
-        "algorithm": "md5"
-      }
-    },
-    {
-      "number": 2,
-      "size": 5024000,
-      "hash": {
-        "value": "ry23df2207d99a74fbe169e3eba035e633b65dkq",
-        "algorithm": "md5"
-      }
-    }
-  ],
-  "storage_provider": {
-    "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-    "name": "duke_oit_swift",
-    "description": "Duke OIT Storage"
-  },
-  "status": {
-    "initiated_on": "2015-07-10T13:00:00Z",
-    "completed_on": "2015-07-10T13:00:00Z",
-    "error_on": null,
-    "error_message": null
-  },
-  "audit": {}
-}

Report upload hash
PUT/uploads/{id}/hashes

Report a hash (fingerprint) for the uploaded file.

-
-

Permission: update_file

-
-
-
-

Properties

-
-
-
    -
  • value (string, required) - The entire file hash (computed by client).
  • -
  • algorithm (string, required) - The algorithm used by client to compute entire file hash (i.e. md5, sha256, sha1, etc.).
  • -
-
-

Rules

-
-
-
    -
  • The reported value must be a valid algorithm - supported/valid algorithms are: md5, sha256, and sha1.
  • -
  • The upload must be in a completed state (i.e. upload_status.completed_on).
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/uploads/666be35a-98e0-4c2e-9a17-7bc009f9bb23/hashes
URI Parameters
HideShow
id
string (required) Example: 666be35a-98e0-4c2e-9a17-7bc009f9bb23

The unique id of the upload.

-
Request
HideShow
Body
{
-  "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-  "algorithm": "md5"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "content_type": "application/octet-stream",
-  "size": 30024000,
-  "hashes": [
-    {
-      "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-      "algorithm": "md5",
-      "audit": {}
-    }
-  ],
-  "chunks": [
-    {
-      "number": 1,
-      "size": 5024000,
-      "hash": {
-        "value": "jw23df2207d99a74fbe169e3eba035e633b65d88",
-        "algorithm": "md5"
-      }
-    },
-    {
-      "number": 2,
-      "size": 5024000,
-      "hash": {
-        "value": "ry23df2207d99a74fbe169e3eba035e633b65dkq",
-        "algorithm": "md5"
-      }
-    }
-  ],
-  "storage_provider": {
-    "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-    "name": "duke_oit_swift",
-    "description": "Duke OIT Storage"
-  },
-  "status": {
-    "initiated_on": "2015-07-10T13:00:00Z",
-    "completed_on": "2015-07-10T13:00:00Z",
-    "error_on": null,
-    "error_message": null
-  },
-  "audit": {}
-}

Files

A file resource represents a virtual container for a physical data file (i.e. upload) that is persisted in a storage backend supported by Duke Data Services (e.g. Duke OIT Swift Service).

-

Files collection

Create file
POST/files

Creates a file metadata resource; the client is responsible for the creation of this resource after confirming the associated physical file has been successfully uploaded to a storage provider (see Uploads actions).

-

Note: A file is a versionable resource; this action creates the initial version of a file. New file versions can be created (uploaded) via the /file/{id}/update action. Versions can be managed via the File Versions actions.

-
-

Permission: create_file

-
-
-
-

Properties

-
-
-
    -
  • parent.kind (string, required) - The kind of parent container for the file; this can be a project (i.e. dds-project) or a folder (i.e. dds-folder).
  • -
  • parent.id (string, required) - The unique id of the parent.
  • -
  • upload.id (string, required) - The unique id for an upload that completed successfully.
  • -
  • label (string, optional) - An optional version label for the file.
  • -
-
-

Rules

-
-
-
    -
  • The current user must be the user who uploaded the file.
  • -
  • The parent object (dds-project or dds-folder) must be associated with the same project that the upload is associated with.
  • -
  • The upload must be in a completed state (i.e. upload.completed_on != null).
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/files
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "parent": {
-    "kind": "dds-folder",
-    "id": "ad9115b8-1e4a-4399-b606-56622eb462e1"
-  },
-  "upload": {
-    "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23"
-  },
-  "label": "Initial raw data from device"
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file",
-  "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-      "name": "Sequencing Core"
-    }
-  ],
-  "is_deleted": false,
-  "current_version": {
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "version": 1,
-    "label": "Initial raw data from device",
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    }
-  },
-  "audit": {}
-}

File instance

View file
GET/files/{id}

-

Permission: view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file",
-  "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-      "name": "Sequencing Core"
-    }
-  ],
-  "is_deleted": false,
-  "current_version": {
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "version": 1,
-    "label": "Initial raw data from device",
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    }
-  },
-  "audit": {}
-}

Update file
PUT/files/{id}

Updates one or more file resource properties; if this action includes an upload.id property in the request, a new file version is created and associated to the file - this becomes the current_version of the file (see File Versions).

-

Note: Only the upload and label properties for the file are versioned; all other file properties and relationships, such as name, tags, metadata properties, etc. are not versioned, and they will not vary from version to version.

-
-

Permission: update_file

-
-
-
-

Properties

-
-
-
    -
  • upload.id (string, optional) - An optional unique id for an upload that completed successfully; if specified, a new file version is created.
  • -
  • label (string, optional) - An optional version label for the file.
  • -
-
-

Rules

-
-
-
    -
  • The current user must be the user who uploaded the file.
  • -
  • The upload must be in a completed state (i.e. upload.completed_on != null).
  • -
  • Only upload.id, label properties can be updated via this action.
  • -
  • New versions are assigned the next sequential version number. (see File Versions)
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "upload": {
-    "id": "422f8778-a62c-4918-8b1b-f398a041345a"
-  },
-  "label": "Post pairwise sequence alignment"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file",
-  "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e",
-      "name": "Sequencing Archive"
-    }
-  ],
-  "is_deleted": false,
-  "current_version": {
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "version": 2,
-    "label": "Post pairwise sequence alignment",
-    "upload": {
-      "id": "56a0431f-5a89-455a-aa2d-996ae9226601",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    }
-  },
-  "audit": {}
-}

Delete file
DELETE/files/{id}

-

Permission: delete_file

-
-
-
-

Rules

-
-
-
    -
  • This operation recursively deletes all the related file versions.
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Response  204

Get file download URL
GET/files/{id}/url

Generates and returns a storage provider specific pre-signed URL that client can use to download file; the download URL is for the current version of the specified file.

-

Note: This action returns URL to download current version of the file - to download a prior version see File Versions actions.

-
-

Permission: download_file

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111/url
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "http_verb": "GET",
-  "host": "swift.oit.duke.edu",
-  "url": "/v1/AUTH_dev/418da9e8-7d01-4761-982c-811d95ac6653/0618a1bc-5042-48d2-af66-ed171354bf6b?temp_url_sig=93b5c5a2c920f0d4962c391d932e4054ec76916c&temp_url_expires=1448918738",
-  "http_headers": []
-}

Move file
PUT/files/{id}/move

Move file to a different parent project or parent folder.

-
-

Permission: create_file

-
-
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111/move
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "parent": {
-    "kind": "dds-folder",
-    "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file",
-  "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e",
-      "name": "Sequencing Archive"
-    }
-  ],
-  "is_deleted": false,
-  "current_version": {
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "version": 2,
-    "label": "Post pairwise sequence alignment",
-    "upload": {
-      "id": "56a0431f-5a89-455a-aa2d-996ae9226601",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    }
-  },
-  "audit": {}
-}

Rename file
PUT/files/{id}/rename

Change the name of a file.

-
-

Permission: update_file

-
-
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111/rename
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file",
-  "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-  "parent": {
-    "kind": "dds-folder",
-    "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e"
-  },
-  "name": "RSEM_Normalized_PI3K_RNASeq_Matrix_V2.Rdata",
-  "project": {
-    "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-  },
-  "ancestors": [
-    {
-      "kind": "dds-project",
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-      "name": "Knockout Mouse Project (KOMP)"
-    },
-    {
-      "kind": "dds-folder",
-      "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e",
-      "name": "Sequencing Archive"
-    }
-  ],
-  "is_deleted": false,
-  "current_version": {
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "version": 2,
-    "label": "Post pairwise sequence alignment",
-    "upload": {
-      "id": "56a0431f-5a89-455a-aa2d-996ae9226601",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    }
-  },
-  "audit": {}
-}

File Versions

The actions herein are used to interact with prior versions of a file resource.

-

Note: Only the upload and label properties for the file are versioned; all other file properties and relationships, such as name, tags, etc. are not versioned, and they will not vary from version to version.

-

File Versions collection

List file versions
GET/files/{id}/versions

This action can be used to list all prior versions of a file, including the current version.

-
-

Permission: view_project

-
-
-
-

Rules

-
-
-
    -
  • File versions that have been deleted (i.e. "is_deleted": true) are included in this listing, but are immutable.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/files/777be35a-98e0-4c2e-9a17-7bc009f9b111/versions
URI Parameters
HideShow
id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the file.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-file-version",
-      "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-      "file": {
-        "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-        "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-        "project": {
-          "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-        }
-      },
-      "version": 1,
-      "label": "Initial raw data from device",
-      "is_deleted": false,
-      "upload": {
-        "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-        "size": 30024000,
-        "hashes": [
-          {
-            "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-            "algorithm": "md5",
-            "audit": {}
-          }
-        ],
-        "storage_provider": {
-          "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-          "name": "duke_oit_swift",
-          "description": "Duke OIT Storage"
-        }
-      },
-      "audit": {}
-    }
-  ]
-}

File Version instance

View file version
GET/file_versions/{id}

-

Permission view_project

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/file_versions/89ef1e77-1a0b-40a8-aaca-260d13987f2b
URI Parameters
HideShow
id
string (required) Example: 89ef1e77-1a0b-40a8-aaca-260d13987f2b

The unique id of the file version.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file-version",
-  "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-  "file": {
-    "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-    "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-    "project": {
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-    }
-  },
-  "version": 1,
-  "label": "Initial raw data from device",
-  "is_deleted": false,
-  "upload": {
-    "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-    "size": 30024000,
-    "hashes": [
-      {
-        "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-        "algorithm": "md5",
-        "audit": {}
-      }
-    ],
-    "storage_provider": {
-      "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-      "name": "duke_oit_swift",
-      "description": "Duke OIT Storage"
-    }
-  },
-  "audit": {}
-}

Update file version
PUT/file_versions/{id}

-

Permission: update_file

-
-
-
-

Rules

-
-
-
    -
  • Only the label property for a file version can be updated via this action.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/file_versions/89ef1e77-1a0b-40a8-aaca-260d13987f2b
URI Parameters
HideShow
id
string (required) Example: 89ef1e77-1a0b-40a8-aaca-260d13987f2b

The unique id of the file version.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "label": "Post pairwise sequence alignment (piecewise)"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file-version",
-  "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-  "file": {
-    "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-    "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-    "project": {
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-    }
-  },
-  "version": 1,
-  "label": "Post pairwise sequence alignment (piecewise)",
-  "is_deleted": false,
-  "upload": {
-    "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-    "size": 30024000,
-    "hashes": [
-      {
-        "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-        "algorithm": "md5",
-        "audit": {}
-      }
-    ],
-    "storage_provider": {
-      "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-      "name": "duke_oit_swift",
-      "description": "Duke OIT Storage"
-    }
-  },
-  "audit": {}
-}

Delete file version
DELETE/file_versions/{id}

-

Permission: delete_file

-
-
-
-

Rules

-
-
-
    -
  • The current file version cannot be deleted.
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/file_versions/89ef1e77-1a0b-40a8-aaca-260d13987f2b
URI Parameters
HideShow
id
string (required) Example: 89ef1e77-1a0b-40a8-aaca-260d13987f2b

The unique id of the file version.

-
Response  204

Get file version download URL
GET/file_versions/{id}/url

Generates and returns a storage provider specific pre-signed URL that client can use to download the file version.

-
-

Permission: download_file

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/file_versions/89ef1e77-1a0b-40a8-aaca-260d13987f2b/url
URI Parameters
HideShow
id
string (required) Example: 89ef1e77-1a0b-40a8-aaca-260d13987f2b

The unique id of the file version.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "http_verb": "GET",
-  "host": "swift.oit.duke.edu",
-  "url": "/v1/AUTH_dev/418da9e8-7d01-4761-982c-811d95ac6653/0618a1bc-5042-48d2-af66-ed171354bf6b?temp_url_sig=93b5c5a2c920f0d4962c391d932e4054ec76916c&temp_url_expires=1448918738",
-  "http_headers": []
-}

Promote file version
POST/file_versions/{id}/current

This action can be used to promote a prior file version to the current version. This actually mints a copy of the specified version and puts it on the top of the version stack.

-
-

Permission: update_file

-
-
-
-

Rules

-
-
-
    -
  • The current file version cannot be promoted.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/file_versions/89ef1e77-1a0b-40a8-aaca-260d13987f2b/current
URI Parameters
HideShow
id
string (required) Example: 89ef1e77-1a0b-40a8-aaca-260d13987f2b

The unique id of the file version to be promoted to the current version.

-
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-file-version",
-  "id": "66ed147e-2312-4974-999a-58ec77230182",
-  "file": {
-    "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-    "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-    "project": {
-      "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-    }
-  },
-  "version": 3,
-  "label": "Post pairwise sequence alignment (piecewise)",
-  "is_deleted": false,
-  "upload": {
-    "id": "56a0431f-5a89-455a-aa2d-996ae9226601",
-    "size": 30024000,
-    "hashes": [
-      {
-        "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-        "algorithm": "md5",
-        "audit": {}
-      }
-    ],
-    "storage_provider": {
-      "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-      "name": "duke_oit_swift",
-      "description": "Duke OIT Storage"
-    }
-  },
-  "audit": {}
-}

Search Children

Search for the children (i.e. folders and files) of a project or folder.

-

Search project children

Search project children
GET/projects/{id}/children{?name_contains,kind}

-

Permission: view_project

-
-
-
-

Rules

-
-
-
    -
  • Searches the immediate children of the project unless the name_contains parameter is specified; when specified, the name_contains parameter invokes a recursive search of the project hierarchy.
  • -
  • Folders/files that have been deleted (i.e. "is_deleted": true) are not included in search.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/children?name_contains=Sequencing&kind=dds-folder
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
name_contains
string (optional) Example: Sequencing

Returns children where their name contains the specified string.

-
kind
string (optional) Example: dds-folder

Returns children of the specified kind; supported kinds are dds-folder and dds-file.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-folder",
-      "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a",
-      "parent": {
-        "kind": "dds-folder",
-        "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-      },
-      "name": "Raw Data",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      },
-      "ancestors": [
-        {
-          "kind": "dds-project",
-          "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-          "name": "Knockout Mouse Project (KOMP)"
-        },
-        {
-          "kind": "dds-folder",
-          "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-          "name": "Sequencing Core"
-        }
-      ],
-      "is_deleted": false,
-      "audit": {}
-    },
-    {
-      "kind": "dds-file",
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "parent": {
-        "kind": "dds-folder",
-        "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e"
-      },
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-      },
-      "ancestors": [
-        {
-          "kind": "dds-project",
-          "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-          "name": "Knockout Mouse Project (KOMP)"
-        },
-        {
-          "kind": "dds-folder",
-          "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e",
-          "name": "Sequencing Archive"
-        }
-      ],
-      "is_deleted": false,
-      "current_version": {
-        "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "version": 1,
-        "label": "Initial raw data from device",
-        "upload": {
-          "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-          "size": 30024000,
-          "hashes": [
-            {
-              "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-              "algorithm": "md5",
-              "audit": {}
-            }
-          ],
-          "storage_provider": {
-            "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-            "name": "duke_oit_swift",
-            "description": "Duke OIT Storage"
-          }
-        }
-      },
-      "audit": {}
-    }
-  ]
-}

Search folder children

Search folder children
GET/folders/{id}/children{?name_contains,kind}

-

Permission: view_project

-
-
-
-

Rules

-
-
-
    -
  • Searches the immediate children of the folder unless the name_contains parameter is specified; when specified, the name_contains parameter invokes a recursive search of the folder hierarchy.
  • -
  • Folders/files that have been deleted (i.e. "is_deleted": true) are not included in search.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/folders/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/children?name_contains=Sequencing&kind=dds-folder
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the folder.

-
name_contains
string (optional) Example: Sequencing

Returns children where their name contains the specified string.

-
kind
string (optional) Example: dds-folder

Returns children of the specified kind; supported kinds are dds-folder and dds-file.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-folder",
-      "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a",
-      "parent": {
-        "kind": "dds-folder",
-        "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-      },
-      "name": "Raw Data",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      },
-      "ancestors": [
-        {
-          "kind": "dds-project",
-          "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-          "name": "Knockout Mouse Project (KOMP)"
-        },
-        {
-          "kind": "dds-folder",
-          "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-          "name": "Sequencing Core"
-        }
-      ],
-      "is_deleted": false,
-      "audit": {}
-    },
-    {
-      "kind": "dds-file",
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "parent": {
-        "kind": "dds-folder",
-        "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e"
-      },
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-      },
-      "ancestors": [
-        {
-          "kind": "dds-project",
-          "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-          "name": "Knockout Mouse Project (KOMP)"
-        },
-        {
-          "kind": "dds-folder",
-          "id": "2b91658a-2b0f-4ac6-83f5-287391610d0e",
-          "name": "Sequencing Archive"
-        }
-      ],
-      "is_deleted": false,
-      "current_version": {
-        "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "version": 1,
-        "label": "Initial raw data from device",
-        "upload": {
-          "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-          "size": 30024000,
-          "hashes": [
-            {
-              "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-              "algorithm": "md5",
-              "audit": {}
-            }
-          ],
-          "storage_provider": {
-            "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-            "name": "duke_oit_swift",
-            "description": "Duke OIT Storage"
-          }
-        }
-      },
-      "audit": {}
-    }
-  ]
-}

Provenance Activities

Represents the main record of provenance in DDS; it is analogous to Activity defined in the W3C Specification on Provenance. Activities are recorded/tracked by researchers and their Software Agents with the intent of maintaining comprehensive data provenance.

-

Note: Provenance relations to an activity, such as used and wasGeneratedBy are managed through the Provenance Relations API actions.

-

Activities collection

Create activity
POST/activities

-

Permission: authenticated

-
-
-
-

Properties

-
-
-
    -
  • name (string, required) - A short name for this activity.
  • -
  • description (string, optional) - A verbose description for this activity.
  • -
  • started_on (string, optional) - The time this activity was started; defaults to the current datetime if not specified.
  • -
  • ended_on (string, optional) - The time this activity ended.
  • -
-
-

Rules

-
-
-
    -
  • The ended_on time must be greater than or equal to the started_on time.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/activities
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "RF PI3-Kinase",
-  "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity"
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-activity",
-  "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-  "name": "RF PI3-Kinase",
-  "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-  "started_on": "2015-01-01T12:00:00Z",
-  "ended_on": null,
-  "is_deleted": false,
-  "audit": {}
-}

List activities
GET/activities

-

Permission:

-
-
-
    -
  • authenticated [scope: creator or visiblity to single entity that has a provenance relation to the activity]
  • -
-
-

Rules

-
-
-
    -
  • Activities that have been deleted (i.e. "is_deleted": true) are not included.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/activities
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-activity",
-      "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-      "name": "RF PI3-Kinase",
-      "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-      "started_on": "2015-01-01T12:00:00Z",
-      "ended_on": null,
-      "is_deleted": false,
-      "audit": {}
-    }
-  ]
-}

Activities instance

View activity
GET/activities/{id}

-

Permission:

-
-
-
    -
  • creator or visiblity to single entity that has a provenance relation to the activity
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/activities/a1ff02a4-b7e9-999d-87x1-66f4c881jka1
URI Parameters
HideShow
id
string (required) Example: a1ff02a4-b7e9-999d-87x1-66f4c881jka1

The unique id of the activity.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-activity",
-  "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-  "name": "RF PI3-Kinase",
-  "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-  "started_on": "2015-01-01T12:00:00Z",
-  "ended_on": null,
-  "is_deleted": false,
-  "audit": {}
-}

Update activity
PUT/activities/{id}

-

Permission: creator

-
-
-
-

Rules

-
-
-
    -
  • Only name, description, started_on, and ended_on properties may be updated via this action.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/activities/a1ff02a4-b7e9-999d-87x1-66f4c881jka1
URI Parameters
HideShow
id
string (required) Example: a1ff02a4-b7e9-999d-87x1-66f4c881jka1

The unique id of the activity.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "ended_on": "2015-01-01T14:30:00Z"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-activity",
-  "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-  "name": "RF PI3-Kinase",
-  "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-  "started_on": "2015-01-01T12:00:00Z",
-  "ended_on": "2015-01-01T14:30:00Z",
-  "is_deleted": false,
-  "audit": {}
-}

Delete activity
DELETE/activities/{id}

-

Permission: creator

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/activities/a1ff02a4-b7e9-999d-87x1-66f4c881jka1
URI Parameters
HideShow
id
string (required) Example: a1ff02a4-b7e9-999d-87x1-66f4c881jka1

The unique id of the activity.

-
Response  204

Provenance Relations

Represents provenance relations as defined in the W3C Specification on Provenance. Relations are recorded/tracked by researchers and their Software Agents with the intent of maintaining comprehensive data provenance.

-

Relations collection

Create used relation
POST/relations/used

-

Permission: creator of the activity and visibility to the used entity

-
-
-
-

Properties

-
-
-
    -
  • activity.id (string, required) - The activity that used the entity.
  • -
  • entity.kind (string, required) - The kind of entity that was used; this must be a file version (i.e. dds-file-version).
  • -
  • entity.id (string, required) - The unique id of the used entity.
  • -
-
-

Rules

-
-
-
    -
  • An entity (i.e. file_version) cannot be used and generated by the same activity (i.e. dds-activity).
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/relations/used
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "activity": {
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1"
-  },
-  "entity": {
-    "kind": "dds-file-version",
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b"
-  }
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-used",
-  "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-  "from": {
-    "kind": "dds-activity",
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-    "name": "RF PI3-Kinase",
-    "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-    "started_on": "2015-01-01T12:00:00Z",
-    "ended_on": "2015-01-01T14:30:00Z",
-    "is_deleted": false,
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-file-version",
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 1,
-    "label": "Post pairwise sequence alignment (piecewise)",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "audit": {}
-}

Create was generated by relation
POST/relations/was_generated_by

-

Permission: creator of the activity and update_file for the wasGeneratedBy entity

-
-
-
-

Properties

-
-
-
    -
  • entity.kind (string, required) - The kind of entity that was generated; this must be a file version (i.e. dds-file-version).
  • -
  • entity.id (string, required) - The unique id of the generated entity.
  • -
  • activity.id (string, required) - The activity that generated the entity.
  • -
-
-

Rules

-
-
-
    -
  • An entity (i.e. file_version) can be generated by one and only one activity (i.e. dds-activity).
  • -
  • An entity (i.e. file_version) cannot be used and generated by the same activity (i.e. dds-activity).
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/relations/was_generated_by
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "entity": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3"
-  },
-  "activity": {
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1"
-  }
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-was-generated-by",
-  "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95",
-  "from": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 2,
-    "label": "Alignment performed on raw data",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-activity",
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-    "name": "RF PI3-Kinase",
-    "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-    "started_on": "2015-01-01T12:00:00Z",
-    "ended_on": "2015-01-01T14:30:00Z",
-    "is_deleted": false,
-    "audit": {}
-  },
-  "audit": {}
-}

Create was derived from relation
POST/relations/was_derived_from

-

Permission: visibility to the used entity and update_file for the generated entity.

-
-
-
-

Properties

-
-
-
    -
  • generated_entity.kind (string, required) - The kind of entity generated by the derivation; this must be a file version (i.e. dds-file-version).
  • -
  • generated_entity.id (string, required) - The unique id of the generated entity.
  • -
  • used_entity.kind (string, required) - The kind of entity used by the derivation; this must be a file version (i.e. dds-file-version).
  • -
  • used_entity.id (string, required) - The unique id of the used entity.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/relations/was_derived_from
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "generated_entity": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3"
-  },
-  "used_entity": {
-    "kind": "dds-file-version",
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b"
-  }
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-was-derived-from",
-  "id": "6bf31123-b078-4655-ae4e-be599d52adc5",
-  "from": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 2,
-    "label": "Alignment performed on raw data",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-file-version",
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 1,
-    "label": "Initial raw data from device",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "audit": {}
-}

Create was invalidated by relation
POST/relations/was_invalidated_by

-

Permission: creator of the activity and delete_file for wasInvalidatedBy entity

-
-
-
-

Properties

-
-
-
    -
  • entity.kind (string, required) - The kind of entity that was invalidated; this must be a file version (i.e. dds-file-version).
  • -
  • entity.id (string, required) - The unique id of the invalidated entity.
  • -
  • activity.id (string, required) - The activity that invalidated the entity.
  • -
-
-

Rules

-
-
-
    -
  • The invalidated entity must be in a deleted state (i.e. "is_deleted": true).
  • -
  • An entity (i.e. file_version) can be invalidated by one and only one activity (i.e. dds-activity).
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/relations/was_invalidated_by
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "entity": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3"
-  },
-  "activity": {
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1"
-  }
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-was-generated-by",
-  "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95",
-  "from": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 2,
-    "label": "Alignment performed on raw data",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-activity",
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-    "name": "RF PI3-Kinase",
-    "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-    "started_on": "2015-01-01T12:00:00Z",
-    "ended_on": "2015-01-01T14:30:00Z",
-    "is_deleted": false,
-    "audit": {}
-  },
-  "audit": {}
-}

List provenance relations
GET/relations/{object_kind}/{object_id}

List the relations for a provenance node; this only lists direct relations for the node that are a single hop away.

-
-

Permission: visibility to the specified (starting) provenance node (i.e. object_kind, object_id) - which may be an activity or an entity

-
-
-
-

Rules

-
-
-
    -
  • Provenance relations that have been deleted (i.e. "is_deleted": true) are not included.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/relations/dds-activity/a1ff02a4-b7e9-999d-87x1-66f4c881jka1
URI Parameters
HideShow
object_kind
string (required) Example: dds-activity

The kind of provenance node; can be one of dds-activity or dds-file-version.

-
object_id
string (required) Example: a1ff02a4-b7e9-999d-87x1-66f4c881jka1

The unique id of the node.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-relation-used",
-      "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-      "from": {
-        "kind": "dds-activity",
-        "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "name": "RF PI3-Kinase",
-        "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-        "started_on": "2015-01-01T12:00:00Z",
-        "ended_on": "2015-01-01T14:30:00Z",
-        "is_deleted": false,
-        "audit": {}
-      },
-      "to": {
-        "kind": "dds-file-version",
-        "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "file": {
-          "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-          "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-          "project": {
-            "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-          }
-        },
-        "version": 1,
-        "label": "Post pairwise sequence alignment (piecewise)",
-        "is_deleted": false,
-        "upload": {
-          "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-          "size": 30024000,
-          "hashes": [
-            {
-              "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-              "algorithm": "md5",
-              "audit": {}
-            }
-          ],
-          "storage_provider": {
-            "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-            "name": "duke_oit_swift",
-            "description": "Duke OIT Storage"
-          }
-        },
-        "audit": {}
-      },
-      "audit": {}
-    }
-  ]
-}

Relation instance

View relation
GET/relations/{id}

-

Permission: visibility to a single node for the specified relation - which may be the activity or the entity

-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/relations/ac242faf-fba0-4293-a949-0b82ae7ba810
URI Parameters
HideShow
id
string (required) Example: ac242faf-fba0-4293-a949-0b82ae7ba810

The unique id of the provenance relation.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-used",
-  "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-  "from": {
-    "kind": "dds-activity",
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-    "name": "RF PI3-Kinase",
-    "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-    "started_on": "2015-01-01T12:00:00Z",
-    "ended_on": "2015-01-01T14:30:00Z",
-    "is_deleted": false,
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-file-version",
-    "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 1,
-    "label": "Post pairwise sequence alignment (piecewise)",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "audit": {}
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-was-associated-with",
-  "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-  "from": {
-    "kind": "dds-activity",
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-    "name": "RF PI3-Kinase",
-    "description": "Building a Random Forest as a heuristic for PI3-Kinase pathway activity",
-    "started_on": "2015-01-01T12:00:00Z",
-    "ended_on": "2015-01-01T14:30:00Z",
-    "is_deleted": false,
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-user",
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "first_name": "Matthew",
-    "last_name": "Gardner",
-    "full_name": "Matthew Gardner",
-    "email": "mrgardner01@duke.edu",
-    "auth_provider": {
-      "source": "duke_shibboleth",
-      "uid": "gardner100"
-    },
-    "last_login_on": "2015-01-01T12:00:00Z",
-    "audit": {}
-  },
-  "audit": {}
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-was-attributed-to",
-  "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-  "from": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 2,
-    "label": "Alignment performed on raw data",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-user",
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "first_name": "Matthew",
-    "last_name": "Gardner",
-    "full_name": "Matthew Gardner",
-    "email": "mrgardner01@duke.edu",
-    "auth_provider": {
-      "source": "duke_shibboleth",
-      "uid": "gardner100"
-    },
-    "last_login_on": "2015-01-01T12:00:00Z",
-    "audit": {}
-  },
-  "audit": {}
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "kind": "dds-relation-was-attributed-to",
-  "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-  "from": {
-    "kind": "dds-file-version",
-    "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-    "file": {
-      "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-      "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      }
-    },
-    "version": 2,
-    "label": "Alignment performed on raw data",
-    "is_deleted": false,
-    "upload": {
-      "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-      "size": 30024000,
-      "hashes": [
-        {
-          "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-          "algorithm": "md5",
-          "audit": {}
-        }
-      ],
-      "storage_provider": {
-        "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-        "name": "duke_oit_swift",
-        "description": "Duke OIT Storage"
-      }
-    },
-    "audit": {}
-  },
-  "to": {
-    "kind": "dds-software-agent",
-    "id": "9a4c28a2-ec18-40ed-b75c-3bf5b309715f",
-    "name": "Sample pipeline agent",
-    "description": null,
-    "repo_url": null,
-    "is_deleted": false,
-    "audit": {}
-  },
-  "audit": {}
-}

Delete relation
DELETE/relations/{id}

-

Permission: creator

-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/relations/ac242faf-fba0-4293-a949-0b82ae7ba810
URI Parameters
HideShow
id
string (required) Example: ac242faf-fba0-4293-a949-0b82ae7ba810

The unique id of the provenance relation.

-
Response  204

Search Provenance

The Provenance Relations API actions allows users and software agents to record the use and production of entities (i.e. files, file versions, etc.) by research activities, which may be influenced in various ways by agents. The resulting provenace chain is organized as a graph structure. The search API can be used by client applications to extract the provenace graph in a JSON data format that can be transformed to a visual representation.

-

Note: The provenance graph structure is stored in a Neo4J database and ubiquitous JavaScript libraries can be used for graph rendering.

-

Search Provenance

Search Provenance
POST/search/provenance

Given a starting node, returns a graph structure for the provenance chain. This structure is based on the Neo4J JSON graph format.

-
-

Permission: visibility to the specified (starting) provenance node (i.e. start_node.kind, start_node.id) - which may be an activity or an entity

-
-
-
-

Rules:

-
-
-
    -
  • If the user does not have visibilty to a node in the resulting graph, the properties attribute for that node will be a partial resource containing: kind, id, and is_deleted.
  • -
-
-

Properties

-
-
-
    -
  • start_node.kind (string, required) - The kind of provenance node; can be one of dds-activity or dds-file-version.
  • -
  • start_node.id (string, required) - The unique id of the node.
  • -
  • max_hops (number, optional) - The max number of hops (degree of node separation) to traverse from the starting node; defaults to infinity.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/search/provenance
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "start_node": {
-    "kind": "dds-activity",
-    "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1"
-  }
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "graph": {
-    "nodes": [
-      {
-        "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "labels": [
-          "Activity"
-        ],
-        "properties": {
-          "kind": "dds-activity",
-          "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-          "name": "RF PI3-Kinase",
-          "is_deleted": false,
-          "audit": {}
-        }
-      },
-      {
-        "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "labels": [
-          "File Version"
-        ],
-        "properties": {
-          "kind": "dds-file-version",
-          "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-          "file": {
-            "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-            "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata"
-          },
-          "version": 1,
-          "label": "Initial raw data from device",
-          "is_deleted": false,
-          "audit": {}
-        }
-      },
-      {
-        "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-        "labels": [
-          "File Version"
-        ],
-        "properties": {
-          "kind": "dds-file-version",
-          "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-          "file": {
-            "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-            "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata"
-          },
-          "version": 2,
-          "label": "Alignment performed on raw data",
-          "is_deleted": false,
-          "audit": {}
-        }
-      }
-    ],
-    "relationships": [
-      {
-        "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-        "type": "used",
-        "start_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "end_node": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "properties": {
-          "kind": "dds-relation-used",
-          "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-          "audit": {}
-        }
-      },
-      {
-        "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95",
-        "type": "wasGeneratedBy",
-        "start_node": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-        "end_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "properties": {
-          "kind": "dds-relation-was-generated-by",
-          "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95",
-          "audit": {}
-        }
-      }
-    ]
-  }
-}

NOT_IMPLEMENTED_NEW Search Provenance wasGeneratedBy

NOT_IMPLEMENTED_NEW Search Provenance wasGeneratedBy
POST/search/provenance/origin

This is a targeted query that navigates “up” the provenance chain for a file version to see how it was generated (i.e. by what activity) and from what source file versions. Given a list of file versions, this action perform the following query for each File Version:

-
    -
  1. -

    Gets all related wasDerivedFrom file versions (if they exist).

    -
  2. -
  3. -

    Gets the generating activity (if it exists).

    -
  4. -
  5. -

    For the generating activity, gets the list of wasGeneratedBy and used file versions.

    -
  6. -
-

A graph structure of the unique nodes and relationships is returned.

-
-

Rules:

-
-
-
    -
  • All of the provided file versions must exist or a validation error is returned.
  • -
  • If a file version does not have a generating activity, then only the file version node is returned.
  • -
  • If the user does not have visibilty to a node in the resulting graph, the properties attribute for that node will be a partial resource containing: kind, id, and is_deleted.
  • -
-
-

Properties

-
-
-
    -
  • file_versions (object[ ], required) - The list of file versions (i.e. dds-file-version)
  • -
  • file_versions[ ].id (string, required) - The unique file version id.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/search/provenance/origin
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "file_versions": [
-    {
-      "id": "1b80a313-97cf-482d-8d17-9b911bf815b3"
-    }
-  ]
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "graph": {
-    "nodes": [
-      {
-        "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "labels": [
-          "Activity"
-        ],
-        "properties": {
-          "kind": "dds-activity",
-          "id": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-          "name": "RF PI3-Kinase",
-          "is_deleted": false,
-          "audit": {}
-        }
-      },
-      {
-        "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "labels": [
-          "File Version"
-        ],
-        "properties": {
-          "kind": "dds-file-version",
-          "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-          "file": {
-            "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-            "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata"
-          },
-          "version": 1,
-          "label": "Initial raw data from device",
-          "is_deleted": false,
-          "audit": {}
-        }
-      },
-      {
-        "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-        "labels": [
-          "File Version"
-        ],
-        "properties": {
-          "kind": "dds-file-version",
-          "id": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-          "file": {
-            "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111",
-            "name": "RSEM_Normalized_PI3K_RNASeq_Matrix.Rdata"
-          },
-          "version": 2,
-          "label": "Alignment performed on raw data",
-          "is_deleted": false,
-          "audit": {}
-        }
-      }
-    ],
-    "relationships": [
-      {
-        "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-        "type": "used",
-        "start_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "end_node": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "properties": {
-          "kind": "dds-relation-used",
-          "id": "ac242faf-fba0-4293-a949-0b82ae7ba810",
-          "audit": {}
-        }
-      },
-      {
-        "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95",
-        "type": "wasGeneratedBy",
-        "start_node": "1b80a313-97cf-482d-8d17-9b911bf815b3",
-        "end_node": "a1ff02a4-b7e9-999d-87x1-66f4c881jka1",
-        "properties": {
-          "kind": "dds-relation-was-generated-by",
-          "id": "372f25e1-01b0-4b8d-9524-e26dd573cc95",
-          "audit": {}
-        }
-      }
-    ]
-  }
-}

Tags

A tag is a label (i.e. word or phrase) that can be associated to an object to facilitate classification and searching.

-

Note: Tags are composite metadata that become part of the tagged resource - they do not live in a global namespace. Only tagging of files (i.e. dds-file) is currently supported.

-

Tags collection

Create object tag
POST/tags/{object_kind}/{object_id}

-

Permission: update_file when tagged object is file (dds-file)

-
-
-
-

Properties

-
-
-
    -
  • label (string, required) - The textual tag content.
  • -
-
-

Rules:

-
-
-
    -
  • The specified label must not already exist for the (object.kind, object.id), the label comparison is case-insensitive.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/tags/dds-file/777be35a-98e0-4c2e-9a17-7bc009f9b111
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the object.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "label": "SMRT sequencing"
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "66211c4e-a49e-42d7-9793-87989d56e1e3",
-  "object": {
-    "kind": "dds-file",
-    "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111"
-  },
-  "label": "SMRT sequencing",
-  "audit": {}
-}

List object tags
GET/tags/{object_kind}/{object_id}

-

Permission: view_project when tagged object is file (dds-file)

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/tags/dds-file/777be35a-98e0-4c2e-9a17-7bc009f9b111
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the object.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "66211c4e-a49e-42d7-9793-87989d56e1e3",
-      "object": {
-        "kind": "dds-file",
-        "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111"
-      },
-      "label": "SMRT sequencing",
-      "audit": {}
-    }
-  ]
-}

Append a list of object tags
POST/tags/{object_kind}/{object_id}/append

Append a list of tags to an object.

-
-

Permission: update_file when tagged object is file (dds-file)

-
-
-
-

Properties

-
-
-
    -
  • tags (object[], required) - An array of tags to apply to the object; object structure is as follows:
  • -
  • label (string, required) - The textual tag content.
  • -
-
-

Rules:

-
-
-
    -
  • If the object has an exisiting tag with the specified label, the label is ignored and a tag is not appended (i.e. created); the label comparison is case-insensitive.
  • -
  • The request must specify at least one label.
  • -
  • The response only contains the list of tags that were appended (i.e. created).
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/tags/dds-file/777be35a-98e0-4c2e-9a17-7bc009f9b111/append
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: 777be35a-98e0-4c2e-9a17-7bc009f9b111

The unique id of the object.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "tags": [
-    {
-      "label": "SMRT sequencing"
-    }
-  ]
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "66211c4e-a49e-42d7-9793-87989d56e1e3",
-      "object": {
-        "kind": "dds-file",
-        "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111"
-      },
-      "label": "SMRT sequencing",
-      "audit": {}
-    }
-  ]
-}

List tag labels
GET/tags/labels{?object_kind,label_contains}

Get a list of the distinct tag label values visible to the current user.

-

Note: Intent of this action is to allow Web and native UX apps to render tag clouds and enable auto-complete widgets.

-
-

Permission: authenticated [scope: view_project when tagged object is file (dds-file)]

-
-
-
-

Rules:

-
-
-
    -
  • The returned tags are sorted in most recently used (i.e. last_used_on) order.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/tags/labels?object_kind=dds-file&label_contains=sequen
URI Parameters
HideShow
object_kind
string (optional) Example: dds-file

Restricts search scope to tags for this kind of object.

-
label_contains
string (optional) Example: sequen

If provided, searches for tags that contain this text fragment.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "label": "SMRT sequencing",
-      "count": 47,
-      "last_used_on": "2015-01-01T12:10:00Z"
-    },
-    {
-      "label": "Polony sequencing",
-      "count": 21,
-      "last_used_on": "2015-01-01T12:05:00Z"
-    },
-    {
-      "label": "DNA nanoball sequencing",
-      "count": 13,
-      "last_used_on": "2015-01-01T12:00:00Z"
-    }
-  ]
-}

Tag instance

View tag
GET/tags/{id}

-

Permission: view_project when tagged object is file (dds-file)

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/tags/66211c4e-a49e-42d7-9793-87989d56e1e3
URI Parameters
HideShow
id
string (required) Example: 66211c4e-a49e-42d7-9793-87989d56e1e3

The unique id of the tag.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "66211c4e-a49e-42d7-9793-87989d56e1e3",
-  "object": {
-    "kind": "dds-file",
-    "id": "777be35a-98e0-4c2e-9a17-7bc009f9b111"
-  },
-  "label": "SMRT sequencing",
-  "audit": {}
-}

Delete tag
DELETE/tags/{id}

-

Permission: update_file when tagged object is file (dds-file)

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/tags/66211c4e-a49e-42d7-9793-87989d56e1e3
URI Parameters
HideShow
id
string (required) Example: 66211c4e-a49e-42d7-9793-87989d56e1e3

The unique id of the tag.

-
Response  204

Metadata

The metadata actions allow researchers to define, store, and associate custom attributes with their digital assets (e.g. activities, files, etc.). Unlike Tags, which are just textual labels, metadata are structured key:value pairs. For example, an experiment (i.e. represented as a provenance Activity) may have the following metadata properties: [{"assay": "ChIP-seq"}, {"organism": "Mus Musculus"}, {"biosample_type": "tissue"}].

-

Metadata must be defined and captured in the context of a metadata template. Templates allow related keys (i.e. properties) to be grouped together. For example, a template named seq_platform_info may contain properties that describe the characteristics of the sequencing platform. In addition, templates enforce data type (i.e. string, integer, etc.) integrity for the contained keys, so that clients are type aware when referencing key values from a search or data processing perspective. Metatdata templates are global in scope and visible to all users.

-

Metadata Templates collection

Create metadata template
POST/templates

-

Permission: authenticated

-
-
-
-

Properties

-
-
-
    -
  • name (string, required) - The unique name of the template; the name must meet the following criteria: -
      -
    • contain only alphanumerics and underscores
    • -
    • no whitespace
    • -
    • maximum of 60 characters
    • -
    -
  • -
  • label (string, required) - A short display label for the template.
  • -
  • description (string, optional) - A verbose description of the template.
  • -
-
-

Rules:

-
-
-
    -
  • The template name must be unique in the global context.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/templates
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "name": "sequencing_file_info",
-  "label": "Sequencing File Info",
-  "description": "Extended attributes for sequencing output files."
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "168f3f51-6800-403a-973d-78b23c08049b",
-  "name": "sequencing_file_info",
-  "label": "Sequencing File Info",
-  "description": "Extended attributes for sequencing output files.",
-  "audit": {}
-}

List metadata templates
GET/templates{?name_contains}

List all of the global metadata templates.

-
-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/templates?name_contains=Sequencing
URI Parameters
HideShow
name_contains
string (optional) Example: Sequencing

Returns templates in which name contains the specified string.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "168f3f51-6800-403a-973d-78b23c08049b",
-      "name": "sequencing_file_info",
-      "label": "Sequencing File Info",
-      "description": "Extended attributes for sequencing output files.",
-      "audit": {}
-    }
-  ]
-}

Metadata Template instance

View metadata template
GET/templates/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/templates/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "168f3f51-6800-403a-973d-78b23c08049b",
-  "name": "sequencing_file_info",
-  "label": "Sequencing File Info",
-  "description": "Extended attributes for sequencing output files (raw and processed).",
-  "audit": {}
-}

Update metadata template
PUT/templates/{id}

-

Permission: creator or system_admin

-
-
-
-

Rules

-
-
-
    -
  • The name cannot be updated if the template has been associated to one or more DDS objects.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/templates/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "description": "Extended attributes for sequencing output files (raw and processed)."
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "168f3f51-6800-403a-973d-78b23c08049b",
-  "name": "sequencing_file_info",
-  "label": "Sequencing File Info",
-  "description": "Extended attributes for sequencing output files (raw and processed).",
-  "audit": {}
-}

Delete metadata template
DELETE/templates/{id}

-

Permission: creator or system_admin

-
-
-
-

Rules

-
-
-
    -
  • The template cannot be deleted if it has been associated to one or more DDS objects.
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/templates/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Response  204

Metadata Properties collection

Create metadata property
POST/templates/{id}/properties

-

Permission: template creator or system_admin

-
-
-
-

Properties

-
-
-
    -
  • key (string, required) - The unique key for the property; the key must meet the following criteria: -
      -
    • contain only alphanumerics and underscores
    • -
    • no whitespace
    • -
    • maximum of 60 characters
    • -
    -
  • -
  • label (string, required) - A short display label for the property.
  • -
  • description (string, required) - A verbose description of the property.
  • -
  • type (string, required) - The datatype of the key’s value; currenty only the Elasticsearch core datatypes are supported: Elasticsearch Core Datatypes.
  • -
-
-

Rules:

-
-
-
    -
  • The property key must be unique within the context of the template.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/templates/168f3f51-6800-403a-973d-78b23c08049b/properties
URI Parameters
HideShow
id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "key": "output_type",
-  "label": "Output Type",
-  "description": "The type of data in the sequencing output file.",
-  "type": "string"
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-  "template": {
-    "id": "168f3f51-6800-403a-973d-78b23c08049b",
-    "name": "sequencing_file_info"
-  },
-  "key": "output_type",
-  "label": "Output Type",
-  "description": "The type of data in the sequencing output file.",
-  "type": "string",
-  "audit": {}
-}

List metadata properties
GET/templates/{id}/properties

List metadata template properties.

-
-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/templates/168f3f51-6800-403a-973d-78b23c08049b/properties
URI Parameters
HideShow
id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-      "template": {
-        "id": "168f3f51-6800-403a-973d-78b23c08049b",
-        "name": "sequencing_file_info"
-      },
-      "key": "output_type",
-      "label": "Output Type",
-      "description": "The type of data in the sequencing output file.",
-      "type": "string",
-      "audit": {}
-    }
-  ]
-}

Metadata Property instance

View metadata property
GET/template_properties/{id}

-

Permission: authenticated

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/template_properties/48d34c8f-4284-4327-9ca6-7a9145a1c957
URI Parameters
HideShow
id
string (required) Example: 48d34c8f-4284-4327-9ca6-7a9145a1c957

The unique id of the template property.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-  "template": {
-    "id": "168f3f51-6800-403a-973d-78b23c08049b",
-    "name": "sequencing_file_info"
-  },
-  "key": "output_type",
-  "label": "Output Type",
-  "description": "The type of data in the sequencing output file. (alignments, peaks, signal)",
-  "type": "string",
-  "audit": {}
-}

Update metadata property
PUT/template_properties/{id}

-

Permission: creator or system_admin

-
-
-
-

Rules

-
-
-
    -
  • The key or type cannot be updated if the template property has been associated to one or more DDS objects.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/template_properties/48d34c8f-4284-4327-9ca6-7a9145a1c957
URI Parameters
HideShow
id
string (required) Example: 48d34c8f-4284-4327-9ca6-7a9145a1c957

The unique id of the template property.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "description": "The type of data in the sequencing output file. (alignments, peaks, signal)"
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-  "template": {
-    "id": "168f3f51-6800-403a-973d-78b23c08049b",
-    "name": "sequencing_file_info"
-  },
-  "key": "output_type",
-  "label": "Output Type",
-  "description": "The type of data in the sequencing output file. (alignments, peaks, signal)",
-  "type": "string",
-  "audit": {}
-}

Delete metadata property
DELETE/template_properties/{id}

-

Permission: creator or system_admin

-
-
-
-

Rules

-
-
-
    -
  • The template property cannot be deleted if it is assigned to one or more DDS objects.
  • -
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/template_properties/48d34c8f-4284-4327-9ca6-7a9145a1c957
URI Parameters
HideShow
id
string (required) Example: 48d34c8f-4284-4327-9ca6-7a9145a1c957

The unique id of the template property.

-
Response  204

Object Metadata instance

Create object metadata
POST/meta/{object_kind}/{object_id}/{template_id}

Used to create a metadata template instance for a corresponding DDS object (i.e. dds-file). When creating metadata, only values that adhere to the metadata template schema will be accepted.

-
-

Permission: update_file when annotated object is file (dds-file)

-
-
-
-

Properties

-
-
-
    -
  • properties (object[ ], required) - A list of the key:value pairs to set for the template instance.
  • -
  • properties[ ].key (string, required) - The property key to set.
  • -
  • properties[ ].value (any, required) - The key value.
  • -
-
-

Rules:

-
-
-
    -
  • All specified key:values must adhere to the metadata template schema or a validation error will be returned.
  • -
  • If the template instance already exists for the DDS object, a validation (unique conflict) error will be returned and the update method should be used.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/meta/dds-file/b80a2679-f6bf-46da-acaa-b7a4582b1eda/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: b80a2679-f6bf-46da-acaa-b7a4582b1eda

The unique id of the object.

-
template_id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "properties": [
-    {
-      "key": "output_type",
-      "value": "alignments"
-    }
-  ]
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "object": {
-    "kind": "dds-file",
-    "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda"
-  },
-  "template": {
-    "id": "168f3f51-6800-403a-973d-78b23c08049b",
-    "name": "sequencing_file_info"
-  },
-  "properties": [
-    {
-      "template_property": {
-        "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-        "key": "output_type"
-      },
-      "value": "alignments"
-    }
-  ]
-}

View object metadata
GET/meta/{object_kind}/{object_id}/{template_id}

Used to retrieve the metadata template instance for a corresponding DDS object.

-
-

Permission: authenticated [scope: view_project when annotated object is file (dds-file)]

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/meta/dds-file/b80a2679-f6bf-46da-acaa-b7a4582b1eda/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: b80a2679-f6bf-46da-acaa-b7a4582b1eda

The unique id of the object.

-
template_id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "object": {
-    "kind": "dds-file",
-    "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda"
-  },
-  "template": {
-    "id": "168f3f51-6800-403a-973d-78b23c08049b",
-    "name": "sequencing_file_info"
-  },
-  "properties": [
-    {
-      "template_property": {
-        "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-        "key": "output_type"
-      },
-      "value": "alignments"
-    }
-  ]
-}

Update object metadata
PUT/meta/{object_kind}/{object_id}/{template_id}

Used to update a metadata template instance for a corresponding DDS object (i.e. dds-file). When updating metadata, only values that adhere to the metadata template schema will be accepted.

-
-

Permission: update_file when annotated object is file (dds-file)

-
-
-
-

Properties

-
-
-
    -
  • properties (object[ ], required) - A list of the key:value pairs to set for the template instance.
  • -
  • properties[ ].key (string, required) - The property key to set.
  • -
  • properties[ ].value (any, required) - The key value.
  • -
-
-

Rules:

-
-
-
    -
  • All specified key:values must adhere to the metadata template schema or a validation error will be returned.
  • -
  • If the specified key already exists, the value is updated, otherwise it is appended to the template instance.
  • -
  • If the template instance specified does not exist, a validation error will be returned and the create method should be used.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/meta/dds-file/b80a2679-f6bf-46da-acaa-b7a4582b1eda/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: b80a2679-f6bf-46da-acaa-b7a4582b1eda

The unique id of the object.

-
template_id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "properties": [
-    {
-      "key": "output_type",
-      "value": "peaks"
-    }
-  ]
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "object": {
-    "kind": "dds-file",
-    "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda"
-  },
-  "template": {
-    "id": "168f3f51-6800-403a-973d-78b23c08049b",
-    "name": "sequencing_file_info"
-  },
-  "properties": [
-    {
-      "template_property": {
-        "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-        "key": "output_type"
-      },
-      "value": "peaks"
-    }
-  ]
-}

Delete object metadata
DELETE/meta/{object_kind}/{object_id}/{template_id}

Used to delete the metadata template instance.

-
-

Permission: update_file when annotated object is file (dds-file)

-
-
-

Example URI

DELETE https://apidev.dataservice.duke.edu/api/v1/meta/dds-file/b80a2679-f6bf-46da-acaa-b7a4582b1eda/168f3f51-6800-403a-973d-78b23c08049b
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: b80a2679-f6bf-46da-acaa-b7a4582b1eda

The unique id of the object.

-
template_id
string (required) Example: 168f3f51-6800-403a-973d-78b23c08049b

The unique id of the template.

-
Response  204

View All Object Metadata

View All Object Metadata
GET/meta/{object_kind}/{object_id}

Used to retrieve all metadata associated with a DDS object, optionally find a template instance by name.

-
-

Permission: authenticated [scope: view_project when annotated object is file (dds-file)]

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/meta/dds-file/b80a2679-f6bf-46da-acaa-b7a4582b1eda
URI Parameters
HideShow
object_kind
string (required) Example: dds-file

The kind of object.

-
object_id
string (required) Example: b80a2679-f6bf-46da-acaa-b7a4582b1eda

The unique id of the object.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "object": {
-        "kind": "dds-file",
-        "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda"
-      },
-      "template": {
-        "id": "168f3f51-6800-403a-973d-78b23c08049b",
-        "name": "sequencing_file_info"
-      },
-      "properties": [
-        {
-          "template_property": {
-            "id": "48d34c8f-4284-4327-9ca6-7a9145a1c957",
-            "key": "output_type"
-          },
-          "value": "alignments"
-        }
-      ]
-    }
-  ]
-}

Search Objects

The search action can be used to find specific DDS objects (e.g. folders, files, etc.). The DDS platform leverages Elasticsearch to perform document based searches. All queries must be specified in Elasticsearch Query DSL.

-

Note: Only search for DDS folders and files (i.e. dds-folder, dds-file) is currently supported. These objects are replicated to Elasticsearch as indexed documents. The objects (i.e. documents) are extended with a tags and meta property when stored in Elaticsearch. These properties have composite metadata to facilitate search. See response payload for concrete example format of these properties.

-

Deprecation: The Search Children actions will be deprecated once this action has been implemented.

-

Search Objects

Search Objects
POST/search

Search for DDS objects (i.e. Elasticsearch documents).

-
-

Permission: authenticated [scope: view_project for objects of kind (dds-folder, dds-file)]

-
-
-
-

Properties

-
-
-
    -
  • include_kinds (string[ ], required) - The kind of objects (i.e. Elasticsearch document types) to include in the search; can include folders and/or files (i.e. dds-folder, dds-file).
  • -
  • search_query (object, required) - The Elasticsearch query criteria (i.e. Query DSL).
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/search
Request
HideShow
Headers
Content-Type: application/json
Body
{
-    "include_kinds": ["dds-file"],
-    "search_query": {
-        "query": {
-            "match" : {
-                "_all" : "SMRT sequencing"
-        }
-    }
-}
-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "kind": "dds-file",
-      "id": "b80a2679-f6bf-46da-acaa-b7a4582b1eda",
-      "parent": {
-        "kind": "dds-folder",
-        "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy"
-      },
-      "name": "ENCFF000SJR.bam",
-      "project": {
-        "id": "d5ae02a4-b9e6-473d-87c4-66f4c881ae7a"
-      },
-      "ancestors": [
-        {
-          "kind": "dds-project",
-          "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1",
-          "name": "Knockout Mouse Project (KOMP)"
-        },
-        {
-          "kind": "dds-folder",
-          "id": "552be8c5-209d-4e3b-afaf-cb66686ffbyy",
-          "name": "Sequencing Core"
-        }
-      ],
-      "is_deleted": false,
-      "current_version": {
-        "id": "89ef1e77-1a0b-40a8-aaca-260d13987f2b",
-        "version": 1,
-        "label": "Processed sequence data",
-        "upload": {
-          "id": "666be35a-98e0-4c2e-9a17-7bc009f9bb23",
-          "size": 30024000,
-          "hashes": [
-            {
-              "value": "cf23df2207d99a74fbe169e3eba035e633b65d94",
-              "algorithm": "md5",
-              "audit": {}
-            }
-          ],
-          "storage_provider": {
-            "id": "g5579f73-0558-4f96-afc7-9d251e65bv33",
-            "name": "duke_oit_swift",
-            "description": "Duke OIT Storage"
-          }
-        }
-      },
-      "audit": {},
-      "tags": [
-        "SMRT sequencing",
-        "GCB lab"
-      ],
-      "meta": [
-        {
-          "sequencing_file_info": {
-            "output_type": "alignments",
-            "mapping_assembly": "hg19"
-          }
-        }
-      ]
-    }
-  ]
-}

Project Transfer

Proposed endpoints to meet the needs of the GCB project transfer workflow
-The Project Transfer actions can be used by research core facilities to formally transfer ownership of a project to a researcher (customer). These endpoints support the transfer workflow and retain a record of the transfer history.

-

Project Transfer collection

NOT_IMPLEMENTED_NEW Initiate a project transfer
POST/projects/{id}/transfers

Initiates a project transfer from the current owner (i.e. project_admin) to a new owner or list of owners.

-
-

Permission: manage_project_permissions

-
-
-
-

Request Properties

-
-
-
    -
  • to_users (object[ ], required) - The list of users to transfer project ownership to.
  • -
  • to_users[ ].id (string, required) - The unique id of a user.
  • -
-
-

Response Properties

-
-
-
    -
  • from_user (object) - The user who initiated the project transfer.
  • -
  • status (string) - The current status of the project transfer; defaults to pending.
  • -
  • status_comment (string) - An optional comment that can be provided when status transfers to a terminal state.
  • -
-
-

Rules:

-
-
-
    -
  • There must be no existing transfers for the project in a pending state.
  • -
-

Example URI

POST https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/transfers
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "to_users": [
-    {
-      "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712"
-    }
-  ]
-}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "from_user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "to_users": [
-    {
-      "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-      "username": "cbrandon01",
-      "full_name": "Chad Brandon"
-    }
-  ],
-  "status": "pending",
-  "status_comment": null,
-  "audit": {}
-}

NOT_IMPLEMENTED_NEW List project transfers
GET/projects/{id}/transfers

-

Permission: authenticated [scope: manage_project_permissions, transfer initiator (i.e. from_user), or a transfer recipient (i.e. in to_users)]

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/projects/ca29f7df-33ca-46dd-a015-92c46fdb6fd1/transfers
URI Parameters
HideShow
id
string (required) Example: ca29f7df-33ca-46dd-a015-92c46fdb6fd1

The unique id of the project.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      },
-      "from_user": {
-        "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-        "username": "mrgardner01",
-        "full_name": "Matthew Gardner"
-      },
-      "to_users": [
-        {
-          "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-          "username": "cbrandon01",
-          "full_name": "Chad Brandon"
-        }
-      ],
-      "status": "pending",
-      "status_comment": null,
-      "audit": {}
-    }
-  ]
-}

Project Transfer instance

NOT_IMPLEMENTED_NEW View a project transfer
GET/project_transfers/{id}

-

Permission: manage_project_permissions, transfer initiator (i.e. from_user), or a transfer recipient (i.e. in to_users)

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/project_transfers/be8ac3c5-84e9-4969-8308-21cd5456946d
URI Parameters
HideShow
id
string (required) Example: be8ac3c5-84e9-4969-8308-21cd5456946d

The unique id of the project transfer.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "from_user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "to_users": [
-    {
-      "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-      "username": "cbrandon01",
-      "full_name": "Chad Brandon"
-    }
-  ],
-  "status": "pending",
-  "status_comment": null,
-  "audit": {}
-}

NOT_IMPLEMENTED_NEW Accept a project transfer
PUT/project_transfers/{id}/accept

Accept a pending project transfer.

-
-

Permission: transfer recipient (i.e. in to_users)]

-
-
-
-

Properties

-
-
-
    -
  • status_comment (string, optional) - An optional comment that can be provided.
  • -
-
-

Rules:

-
-
-
    -
  • The project transfer must be in a pending state.
  • -
  • All exisiting permissions for the project are removed, project_viewer is granted to the transfer initiater (i.e. from_user), and project_admin is granted to the list of recipients (i.e. to_users)
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/project_transfers/be8ac3c5-84e9-4969-8308-21cd5456946d/accept
URI Parameters
HideShow
id
string (required) Example: be8ac3c5-84e9-4969-8308-21cd5456946d

The unique id of the project transfer.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "status_comment": "This data looks great..."
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "from_user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "to_users": [
-    {
-      "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-      "username": "cbrandon01",
-      "full_name": "Chad Brandon"
-    }
-  ],
-  "status": "accepted",
-  "status_comment": "This data looks great...",
-  "audit": {}
-}

NOT_IMPLEMENTED_NEW Reject a project transfer
PUT/project_transfers/{id}/reject

Reject a pending project transfer.

-
-

Permission: transfer recipient (i.e. in to_users)]

-
-
-
-

Properties

-
-
-
    -
  • status_comment (string, optional) - An optional comment that can be provided.
  • -
-
-

Rules:

-
-
-
    -
  • The project transfer must be in a pending state.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/project_transfers/be8ac3c5-84e9-4969-8308-21cd5456946d/reject
URI Parameters
HideShow
id
string (required) Example: be8ac3c5-84e9-4969-8308-21cd5456946d

The unique id of the project transfer.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "status_comment": "Missing alignment files..."
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "from_user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "to_users": [
-    {
-      "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-      "username": "cbrandon01",
-      "full_name": "Chad Brandon"
-    }
-  ],
-  "status": "rejected",
-  "status_comment": "Missing alignment files...",
-  "audit": {}
-}

NOT_IMPLEMENTED_NEW Cancel a project transfer
PUT/project_transfers/{id}/cancel

Cancel a pending project transfer.

-
-

Permission: manage_project_permissions

-
-
-
-

Properties

-
-
-
    -
  • status_comment (string, optional) - An optional comment that can be provided.
  • -
-
-

Rules:

-
-
-
    -
  • The project transfer must be in a pending state.
  • -
-

Example URI

PUT https://apidev.dataservice.duke.edu/api/v1/project_transfers/be8ac3c5-84e9-4969-8308-21cd5456946d/cancel
URI Parameters
HideShow
id
string (required) Example: be8ac3c5-84e9-4969-8308-21cd5456946d

The unique id of the project transfer.

-
Request
HideShow
Headers
Content-Type: application/json
Body
{
-  "status_comment": "Sent to the wrong PI..."
-}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-  "project": {
-    "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-  },
-  "from_user": {
-    "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-    "username": "mrgardner01",
-    "full_name": "Matthew Gardner"
-  },
-  "to_users": [
-    {
-      "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-      "username": "cbrandon01",
-      "full_name": "Chad Brandon"
-    }
-  ],
-  "status": "canceled",
-  "status_comment": "Sent to the wrong PI...",
-  "audit": {}
-}

View All Project Transfers

NOT_IMPLEMENTED_NEW View All Project Transfers
GET/project_transfers{?status}

Used to retrieve all project transfers visible to the current user, optionally filtered by status.

-
-

Permission: authenticated [scope: manage_project_permissions, transfer initiator (i.e. from_user), or a transfer recipient (i.e. in to_users)]

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/project_transfers?status=pending
URI Parameters
HideShow
status
string (optional) Example: pending

The status of the project transfer; can be one of pending,accepted, or canceled.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "be8ac3c5-84e9-4969-8308-21cd5456946d",
-      "project": {
-        "id": "ca29f7df-33ca-46dd-a015-92c46fdb6fd1"
-      },
-      "from_user": {
-        "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-        "username": "mrgardner01",
-        "full_name": "Matthew Gardner"
-      },
-      "to_users": [
-        {
-          "id": "7bbf009d-c26e-401e-a9d5-0faa99b9b712",
-          "username": "cbrandon01",
-          "full_name": "Chad Brandon"
-        }
-      ],
-      "status": "pending",
-      "status_comment": null,
-      "audit": {}
-    }
-  ]
-}

Authentication Providers

Represents the authentication providers (services) that are supported by DDS.

-

Authentication Providers collection

NOT_IMPLEMENTED_NEW List authentication providers
GET/auth_providers

-

Permission: public

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/auth_providers
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c",
-      "name": "duke",
-      "description": "Duke Authentication Service"
-    }
-  ]
-}

Authentication Provider instance

NOT_IMPLEMENTED_NEW View authentication provider
GET/auth_providers/{id}

-

Permission: public

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/auth_providers/3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c
URI Parameters
HideShow
id
string (required) Example: 3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c

The unique id of the authentication provider.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c",
-  "name": "duke",
-  "description": "Duke Authentication Service"
-}

NOT_IMPLEMENTED_NEW Get All Authentication Provider Affiliates
GET/auth_providers/{id}/affiliates{?full_name_contains}

Get a list of affiliates (potential users), for a supported authentication provider.

-
-

Permission: public

-
-
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/auth_providers/3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c/affiliates?full_name_contains=gardner
URI Parameters
HideShow
id
string (required) Example: 3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c

The unique id of the authentication provider.

-
full_name_contains
string (optional) Example: gardner

Returns affiliates where their full name contains the specified string.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "results": [
-    {
-      "uid": "mrgardner01",
-      "first_name": "Matthew",
-      "last_name": "Gardner",
-      "full_name": "Matthew Gardner",
-      "email": "mrgardner01@duke.edu",
-      "auth_provider": {
-        "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c",
-        "name": "duke"
-      }
-    }
-  ]
-}

NOT_IMPLEMENTED_NEW View User by Auth Provider ID
GET/auth_providers/{id}/affiliates/{uid}/dds_user

Transform an institutional affiliates UID, such as a Duke NetID, to a DDS specific user identity; can be used by clients prior to calling DDS APIs that require a DDS user in the request payload.

-
-

Permission: authenticated

-
-
-
-

Rules:

-
-
-
    -
  • If the id and uid are valid and a corresponding DDS user does not exist, the affiliate is registered as DDS user and returned.
  • -
-

Example URI

GET https://apidev.dataservice.duke.edu/api/v1/auth_providers/duke/affiliates/gardner001/dds_user
URI Parameters
HideShow
id
string (required) Example: duke

The id of an authentication provider (service) supported by the DDS application.

-
uid
string (required) Example: gardner001

The unique uid (user id) in the context of the specified auth provider.

-
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
-  "id": "c1179f73-0558-4f96-afc7-9d251e65b7bb",
-  "username": "mrgardner01",
-  "first_name": "Matthew",
-  "last_name": "Gardner",
-  "full_name": "Matthew Gardner",
-  "email": "mrgardner01@duke.edu",
-  "auth_provider": {
-    "id": "3f2cb4ea-dc03-4e2e-90a8-ca26f04ec62c",
-    "name": "duke",
-    "affiliate": {
-      "uid": "mrgardner01"
-    }
-  },
-  "last_login_on": "2015-01-01T12:00:00Z",
-  "audit": {}
-}

Generated by aglio on 17 Oct 2016

\ No newline at end of file diff --git a/app/views/swaggerui/index.html.erb b/app/views/swaggerui/index.html.erb index 994902e0a..ed809f6e8 100644 --- a/app/views/swaggerui/index.html.erb +++ b/app/views/swaggerui/index.html.erb @@ -48,32 +48,56 @@ } else if (window.location.href.indexOf('#access_token') > 0){ $('#login').hide(); - var parts = window.location.hash.split('&'); - var access_token = parts[0].split('=')[1]; - validateAccessToken(access_token).then( + var hashParams = new URLSearchParams(window.location.hash); + //we store the service_id in the state for the round-trip + //URLSearchParams doesnt really handle the first param after the # correctly + getApiToken(hashParams.get('state'), hashParams.get('#access_token')).then( function(data) { - signed_token = data['signed_info']; - getApiToken(signed_token).then( - function(data) { - api_token = data['api_token']; - window.localStorage.api_token = api_token; - $('#login').hide(); - addApiKeyAuthorization(); - window.location.replace("#"); - }, - handleInvalidSignedToken - ); + api_token = data['api_token']; + window.localStorage.api_token = api_token; + $('#login').hide(); + addApiKeyAuthorization(); + window.location.replace("#"); }, - handleInvalidAccessToken + handleInvalidSignedToken ); } else { + getLoginChoices().then( + populateLoginChoices, + handleAjaxError + ); $('#login').show(); } + function getLoginChoices() { + return $.ajax({ + type: 'GET', + url: '/api/v1/auth_providers', + contentType: 'application/json', + dataType: 'json' + }) + } + + function populateLoginChoices(data) { + var authLogin = ''; + $( authLogin ).insertBefore($('#UseAuthToken')) + } + function handleLogout() { window.localStorage.removeItem('api_token'); $('#current_user_info').hide(); + getLoginChoices().then( + populateLoginChoices, + handleAjaxError + ); $('#login').show(); removeApiKeyAuthorization(); } @@ -115,15 +139,6 @@ $('#current_user_info').show(); } - function validateAccessToken(access_token) { - return $.ajax({ - type: 'GET', - url: "<%= @auth_service.base_uri -%>/api/v1/token_info?access_token="+access_token, - contentType: 'application/json', - dataType: 'json' - }) - } - function handleInvalidAccessToken(jqXHR, status, err) { if ('console' in window) { console.log(jqXHR.responseText); @@ -145,10 +160,10 @@ } }; - function getApiToken(signed_token) { + function getApiToken(service_id, signed_token) { return $.ajax({ type: 'GET', - url: '/api/v1/user/api_token?access_token='+signed_token, + url: '/api/v1/user/api_token?access_token='+signed_token+'&authentication_service_id='+service_id, contentType: 'application/json', dataType: 'json' }) @@ -212,7 +227,6 @@