# Shared drives

Shared drives and their members: create, rename, hide and delete a drive, with each caller's access answered by its membership role.

Shared drives hold files that belong to a team rather than to one user, and every route answers a caller by its membership: `organizer`, `fileOrganizer`, `writer`, `commenter` or `reader`.

No scenario holds a shared drive, so create one, put a file in it and add a member. A member is a permission on the drive's id:

```bash
AUTH='Authorization: Bearer ya29.placeholder'
JSON='Content-Type: application/json'
DRIVE=$(curl -s -H "$AUTH" -H "$JSON" -d '{"name":"Studio team"}' "$RYSTIC_URL/drive/v3/drives?requestId=studio-1" | jq -r .id)
curl -s -H "$AUTH" "$RYSTIC_URL/drive/v3/drives/$DRIVE" | jq -c '{kind, name}'
# -> {"kind":"drive#drive","name":"Studio team"}
curl -s -H "$AUTH" -H "$JSON" -d "{\"name\":\"Brief.txt\",\"parents\":[\"$DRIVE\"]}" "$RYSTIC_URL/drive/v3/files?supportsAllDrives=true&fields=name,driveId" | jq -c '{name, inDrive: (.driveId == "'"$DRIVE"'")}'
# -> {"name":"Brief.txt","inDrive":true}
curl -s -H "$AUTH" -H "$JSON" -d '{"type":"user","role":"writer","emailAddress":"kit.alvarez@studio.example"}' "$RYSTIC_URL/drive/v3/files/$DRIVE/permissions?supportsAllDrives=true&fields=id,role" | jq -c .
# -> {"id":"10222233334444555567","role":"writer"}
curl -s -H "$AUTH" -H 'X-Rystic-Actor: 10222233334444555567' -X DELETE "$RYSTIC_URL/drive/v3/drives/$DRIVE" | jq -c '.error.errors[0].reason'
# -> "insufficientFilePermissions"
curl -s -H "$AUTH" -X DELETE "$RYSTIC_URL/drive/v3/drives/$DRIVE" | jq -c '.error.errors[0].reason'
# -> "cannotDeleteResourceWithChildren"
```

### Creating a drive

`drives.create` needs a `requestId`. A second create with the same `requestId` while that drive exists answers 409 `teamDriveAlreadyExists`, and the drive's creator is its organizer.

### Membership decides the answer

`drives.get`, `drives.list`, `drives.update`, `drives.hide`, `drives.unhide` and `drives.delete` answer by the caller's membership. Only an organizer renames or deletes a drive, and a drive deletes only once it holds no untrashed item: until then `drives.delete` answers 403 `cannotDeleteResourceWithChildren`.

On a drive's files, trash, move and share follow the caller's role too: a `reader` and a `commenter` are refused with 403 `insufficientFilePermissions`, a `writer` can share but neither move nor trash, and a `fileOrganizer` or `organizer` can do all three.

Right after a user is granted a role on a shared drive, Drive can refuse that user's `comments.create` on the drive's files with 403 `insufficientFilePermissions` for up to about two minutes, even while `files.get` already reports `canComment: true`. The simulator accepts the comment at once. Code that comments soon after a grant should retry that 403 with backoff for up to two minutes.

### Domain-admin access

`useDomainAdminAccess=true` is served on `drives.get`, `drives.list`, `drives.update` and `drives.delete`, and on `permissions.list`, `permissions.create`, `permissions.get`, `permissions.update` and `permissions.delete` with a shared drive's id as `fileId`. It opens the drive and its member list to a domain administrator who is not a member. It never opens the drive's contents: the administrator's `files.create` or upload into the drive answers 404 `notFound` and stores nothing, as on Drive, and on a file in the drive the flag grants nothing.

No scenario holds an administrator. Seed a user marked `"domainAdmin": true` and speak as it with `X-Rystic-Actor` ([Seeding state](https://www.rystic.ai/docs/simulators/google-drive.md#seeding-state)); no answer renders the mark:

```bash
curl -s -X POST "$RYSTIC_URL/_rystic/seed" -d '{"state_user": {"ada": {"permissionId": "ada", "displayName": "Ada Admin", "emailAddress": "ada@studio.example", "kind": "drive#user", "domainAdmin": true}}}'
curl -s -H "$AUTH" -H 'X-Rystic-Actor: ada' "$RYSTIC_URL/drive/v3/drives?useDomainAdminAccess=true" | jq -c '[.drives[].name]'
# -> ["Studio team"]
```

A caller who is not an administrator is judged as an administrator would be, even the drive's own organizer: `drives.delete` answers 403 `noManageTeamDriveAdministratorPrivilege`, `drives.list` 403 `noListTeamDrivesAdministratorPrivilege`, and `drives.get`, `drives.update` and `permissions.*` 404 `notFound`.

`drives.delete` with `allowItemDeletion=true` and the flag deletes a drive that still holds items; `allowItemDeletion=true` without the flag answers 403 `driveItemDeletionRequiresAdminAccess`. On Drive, a new drive can take up to about 10 seconds to become visible to the administrator, and the delay varies, so poll `drives.list` with the flag before reading or deleting it. The simulator shows it at once.

### Files and changes inside a drive

Name the drive's id in `parents` with `supportsAllDrives=true` to create a file in it. `files.list` refuses `includeItemsFromAllDrives` without `supportsAllDrives`, and `corpora=drive` with `driveId` lists one drive's items. The change feed takes a `driveId` too, and refuses it without `supportsAllDrives`, or for `changes.list` without `includeItemsFromAllDrives` as well. With `driveId`, both change routes answer 404 for an id that names no drive and 403 `teamDriveMembershipRequired` to a caller who is not a member ([Change feed](https://www.rystic.ai/docs/simulators/google-drive/features/change-feed.md)).

Where the simulator's answers differ from Drive's for shared drives, Limitations lists each one.

---

Source: https://www.rystic.ai/docs/simulators/google-drive/features/shared-drives · Markdown: https://www.rystic.ai/docs/simulators/google-drive/features/shared-drives.md
