mirror of
https://github.com/projectsend/projectsend.git
synced 2026-10-03 12:54:18 +00:00
Document the folder endpoints
The OpenAPI document gains the seven folder operations; `ancestors` gets an explicit type so the schema says what it holds rather than Scramble's guess. The guide gets a Folders section, the folder abilities, the idempotent create under "Retries", and public folders under "Not in v1". The abilities table was split in two by a blank line, with the groups row left under the paragraph after it; both are back in the table.
This commit is contained in:
@@ -33,8 +33,7 @@ class FolderResource extends JsonResource
|
||||
$identity = app(ClientIdentityScope::class);
|
||||
$groupMorph = (new Group)->getMorphClass();
|
||||
|
||||
/** @var list<array{id: int, name: string}> $ancestors */
|
||||
$ancestors = $this->relationLoaded('trail') ? $this->getRelation('trail')->all() : [];
|
||||
$ancestors = $this->ancestors();
|
||||
|
||||
return [
|
||||
'id' => $this->id,
|
||||
@@ -65,4 +64,19 @@ class FolderResource extends JsonResource
|
||||
->all()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{id: int, name: string}>
|
||||
*/
|
||||
private function ancestors(): array
|
||||
{
|
||||
if (! $this->resource->relationLoaded('trail')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var list<array{id: int, name: string}> $trail */
|
||||
$trail = $this->resource->getRelation('trail')->all();
|
||||
|
||||
return $trail;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-4
@@ -80,6 +80,10 @@ list for your account.
|
||||
| `upload` | list files, upload |
|
||||
| `edit_files` / `edit_others_files` | read and edit file metadata, share files |
|
||||
| `delete_files` / `delete_others_files` | delete files |
|
||||
| `upload` / `edit_files` / `edit_others_files` | list and read folders |
|
||||
| `create_own_folders` | create folders (with `upload`, as on the web) |
|
||||
| `edit_files` / `edit_others_files` | rename, move and share folders |
|
||||
| `delete_files` / `delete_others_files` | delete folders |
|
||||
| `set_file_expiration_date` | set `expires_at` when editing |
|
||||
| `set_file_categories` | set `categories` when editing |
|
||||
| `limit_downloads` | set `download_limit` and `download_limit_scope` when editing |
|
||||
@@ -88,7 +92,7 @@ list for your account.
|
||||
| `manage_clients` | list clients |
|
||||
| `create_clients` / `edit_clients` / `delete_clients` | create, read and edit, delete clients; `edit_clients` also removes a client's two-factor authentication |
|
||||
| `manage_groups` | list groups |
|
||||
|
||||
| `create_groups` / `edit_groups` / `delete_groups` | create, read and edit (including membership), delete groups |
|
||||
| `moderate_comments` | list what is awaiting approval, and approve it |
|
||||
| `manage_users` | list staff accounts and the roles you may assign |
|
||||
| `create_users` / `edit_users` / `delete_users` | create, read and edit, delete staff accounts; `edit_users` also removes an account's two-factor authentication |
|
||||
@@ -99,10 +103,10 @@ a per-role permission, so the file abilities are the gate — the same question
|
||||
endpoint also lets an author remove their own within the editing window and that is not moderation;
|
||||
it additionally requires the token's owner to hold `moderate_comments`, checked live against the
|
||||
account rather than carried by the token.
|
||||
| `create_groups` / `edit_groups` / `delete_groups` | create, read and edit (including membership), delete groups |
|
||||
|
||||
Where an endpoint accepts several — `edit_files` *or* `edit_others_files` — holding either is enough,
|
||||
and which one applies to a given file depends on whether you uploaded it.
|
||||
and which one applies to a given file depends on whether you uploaded it. For a folder, it depends
|
||||
on whether you created it.
|
||||
|
||||
Every operation in the OpenAPI document names its own requirement.
|
||||
|
||||
@@ -359,6 +363,46 @@ two are narrowed to what your token may see: a counterpart outside your reach re
|
||||
|
||||
---
|
||||
|
||||
## Folders
|
||||
|
||||
`GET /folders` lists the folders you can see in the library, and polls like every other list.
|
||||
`parent_id=12` lists the folders directly inside folder 12, and `top_level=1` the folders at the top.
|
||||
|
||||
Each folder carries `parent_id`, and its place in the tree as `ancestors` (root first, as
|
||||
`{id, name}`) and as a display `path` such as `Clients / Acme / 2026`. Match on ids rather than on
|
||||
`path`: a folder's name may itself contain ` / `. If your token is limited to some clients, the
|
||||
trail starts at the first folder you can see.
|
||||
|
||||
Creating a folder:
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"Acme","parent_id":12}' \
|
||||
https://your-install.example.com/api/v1/folders
|
||||
```
|
||||
|
||||
A new folder answers `201`. If a folder with that name already exists in the same place, you get
|
||||
that folder back with a `200` instead, so a sync job can create a folder without looking first.
|
||||
|
||||
`PATCH /folders/{id}` takes `name`, `parent_id`, or both. `parent_id: null` moves the folder to the
|
||||
top. A folder moves with everything inside it, and cannot go into itself or one of its own
|
||||
subfolders.
|
||||
|
||||
**Deleting a folder that is not empty must be asked for.** `DELETE /folders/{id}` deletes an empty
|
||||
folder. A folder holding files or other folders answers `409` unless you send
|
||||
`content_action=cascade_delete`, which deletes it with every folder and file inside it, as the web
|
||||
screen does. There is no restore. The cascade is refused with `403` if the folder holds a file your
|
||||
token may not delete.
|
||||
|
||||
Sharing works as it does for a file, at `/folders/{id}/assignments`. A client a folder is shared
|
||||
with sees everything inside it, including what is added later.
|
||||
|
||||
A folder's `public` flag is reported but cannot be changed here: making a folder public publishes
|
||||
everything in it, and is done on the web.
|
||||
|
||||
---
|
||||
|
||||
## Staff accounts
|
||||
|
||||
`/users` manages the people who administer the installation, and the role assigned to each of them.
|
||||
@@ -443,7 +487,8 @@ sign-in — this un-sticks an account, it does not exempt one.
|
||||
|
||||
## Retries and duplicate requests
|
||||
|
||||
Assignments and group membership are idempotent. **Creating a file or a client is not** — a retried
|
||||
Assignments and group membership are idempotent, and so is creating a folder (see above).
|
||||
**Creating a file or a client is not** — a retried
|
||||
`POST` that actually succeeded the first time creates a second one. Until idempotency keys exist,
|
||||
check before retrying a create you are unsure about.
|
||||
|
||||
@@ -506,6 +551,7 @@ Recorded so they read as decisions rather than gaps:
|
||||
- **Webhooks.** Poll instead; see above.
|
||||
- **Idempotency keys.** See "Retries" above.
|
||||
- **Share links, notifications, thumbnails, settings.**
|
||||
- **Making a folder public**, or changing its public page. See "Folders" above.
|
||||
- **Creating and deleting roles.** `GET /roles` reads them and `role_id` assigns one; defining a
|
||||
role's permission set stays in the UI.
|
||||
|
||||
|
||||
+718
-1
@@ -2328,6 +2328,624 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/folders/{folder}/assignments": {
|
||||
"post": {
|
||||
"operationId": "folders.assignments.store",
|
||||
"description": "Sharing it again with the same client or group leaves one share.\n\nRequires a token with any of these abilities: `edit_files`, `edit_others_files`.",
|
||||
"summary": "Share a folder",
|
||||
"tags": [
|
||||
"FolderAssignments"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The folder ID",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "`FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/AuthorizationException"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/ModelNotFoundException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"operationId": "folders.assignments.destroy",
|
||||
"description": "Requires a token with any of these abilities: `edit_files`, `edit_others_files`.",
|
||||
"summary": "Stop sharing a folder",
|
||||
"tags": [
|
||||
"FolderAssignments"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The folder ID",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "`FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/AuthorizationException"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/ModelNotFoundException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/folders": {
|
||||
"get": {
|
||||
"operationId": "folders.index",
|
||||
"description": "Cursor paginated, like every list. Pass `updated_since` to poll for\nfolders created, renamed or moved since a point in time. `parent_id`\nlists the folders directly inside one folder, and `top_level=1` the\nfolders at the top of the library.\n\nMoving a folder updates the folder itself and every folder under it,\nso a poll sees the whole moved subtree.\n\nRequires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
|
||||
"summary": "List folders",
|
||||
"tags": [
|
||||
"Folders"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "updated_since",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"format": "date-time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "per_page",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"minimum": 1,
|
||||
"maximum": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "parent_id",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "top_level",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "search",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"maxLength": 255
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Paginated set of `FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"first": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"last": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"prev": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"next": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first",
|
||||
"last",
|
||||
"prev",
|
||||
"next"
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "Base path for paginator generated URLs."
|
||||
},
|
||||
"per_page": {
|
||||
"type": "integer",
|
||||
"description": "Number of items shown per page.",
|
||||
"minimum": 0
|
||||
},
|
||||
"next_cursor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The \"cursor\" that points to the next set of items."
|
||||
},
|
||||
"prev_cursor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The \"cursor\" that points to the previous set of items."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"per_page",
|
||||
"next_cursor",
|
||||
"prev_cursor"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data",
|
||||
"links",
|
||||
"meta"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/ValidationException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"operationId": "folders.store",
|
||||
"description": "At the top of the library, or inside `parent_id`. Requires the\n`create_own_folders` ability, and `upload` with it.\n\nIf a folder with the same name already exists in the same place, that\nfolder is returned with a 200 instead of a second one being made, so\nretrying a request is safe. A new folder answers 201.\n\nRequires a token with the ability: `create_own_folders`.",
|
||||
"summary": "Create a folder",
|
||||
"tags": [
|
||||
"Folders"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"parent_id": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "`FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"assignments"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "`FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"assignments"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "An error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "Error overview.",
|
||||
"examples": [
|
||||
""
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"message"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/ValidationException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/folders/{folder}": {
|
||||
"get": {
|
||||
"operationId": "folders.show",
|
||||
"description": "Requires a token with any of these abilities: `upload`, `edit_files`, `edit_others_files`.",
|
||||
"summary": "Show a folder, with the clients and groups it is shared with",
|
||||
"tags": [
|
||||
"Folders"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The folder ID",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "`FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"assignments"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/AuthorizationException"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/ModelNotFoundException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"operationId": "folders.update",
|
||||
"description": "Only the fields you send change. `parent_id: null` moves the folder to\nthe top of the library. A folder moves with everything inside it, and\ncannot be moved into itself or one of its own subfolders.\n\nRequires a token with any of these abilities: `edit_files`, `edit_others_files`.",
|
||||
"summary": "Rename or move a folder",
|
||||
"tags": [
|
||||
"Folders"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The folder ID",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"parent_id": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "`FolderResource`",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/FolderResource"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"assignments"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/AuthorizationException"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/ValidationException"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/ModelNotFoundException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"operationId": "folders.destroy",
|
||||
"description": "An empty folder is deleted straight away. A folder holding files or\nother folders answers 409 unless you send\n`content_action=cascade_delete`, which deletes the folder, every folder\nunder it and every file inside them, as the web screen does. There is\nno restore.\n\nA cascade is refused with 403 if the folder holds any file this token\nmay not delete itself.\n\nRequires a token with any of these abilities: `delete_files`, `delete_others_files`.",
|
||||
"summary": "Delete a folder",
|
||||
"tags": [
|
||||
"Folders"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The folder ID",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "content_action",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"cascade_delete",
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "An error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "Error overview.",
|
||||
"examples": [
|
||||
"This folder is not empty. Send content_action=cascade_delete to delete it with everything inside it."
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"message"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/AuthorizationException"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/ValidationException"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/ModelNotFoundException"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/AuthenticationException"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups/{group}/members": {
|
||||
"post": {
|
||||
"operationId": "groups.members.store",
|
||||
@@ -4189,17 +4807,25 @@
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"description": "GET /folders/{id} has the rest, its place in the tree included.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent_id": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name"
|
||||
"name",
|
||||
"parent_id"
|
||||
]
|
||||
},
|
||||
"uploaded_by": {
|
||||
@@ -4303,6 +4929,97 @@
|
||||
],
|
||||
"title": "FileResource"
|
||||
},
|
||||
"FolderResource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent_id": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"ancestors": {
|
||||
"type": "array",
|
||||
"description": "The folders above this one, root first, as far up as the\ncaller may see. Empty for a folder at the top of the library.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name"
|
||||
]
|
||||
}
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "The same trail as one string, this folder included:\n\"Clients / Acme / 2026\". For display; match on ids, since a\nfolder name may itself contain \" / \"."
|
||||
},
|
||||
"public": {
|
||||
"type": "boolean",
|
||||
"description": "Read-only here. Making a folder public publishes everything\ninside it, and is done on the web."
|
||||
},
|
||||
"created_at": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"updated_at": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"assignments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"group",
|
||||
"client"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"parent_id",
|
||||
"ancestors",
|
||||
"path",
|
||||
"public",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
],
|
||||
"title": "FolderResource"
|
||||
},
|
||||
"GroupResource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Reference in New Issue
Block a user