286 lines
6.5 KiB
Markdown
286 lines
6.5 KiB
Markdown
|
|
# Collection Sharing
|
|
|
|
Static collection sharing without permissions filter using soft-links (Unix-only) is supported since storage type `multifilesystem` was implemented, see (Wiki: Sharing Collections)[https://github.com/Kozea/Radicale/wiki/Sharing-Collections]
|
|
|
|
With 3.7.0 a major extension was implemented using internal mapping configuration stored in a database and a management API.
|
|
|
|
## Sharing Configuration Store
|
|
|
|
Types of supported sharing configuration:
|
|
|
|
* csv (_>= 3.7.0_)
|
|
* files (_>= 3.7.0_)
|
|
|
|
### Sharing Configuration Entry Data
|
|
|
|
* `ShareType`: type of share
|
|
* `token`: token-based share (do not require user authentication)
|
|
* `map`: map-based share (requires user authentication)
|
|
* `PathOrToken`: token or "virtual" collection, has to be unique (PRIMARY KEY)
|
|
* `PathMapped`: target collection
|
|
* `Owner`: owner of the share
|
|
* `User`: user of the share
|
|
* `Permissions`: effective permission of the share
|
|
* `EnabledByOwner`: control by owner
|
|
* `EnabledByUser`: control by user
|
|
* `HiddenByOwner`: control by owner
|
|
* `HiddenByUser`: control by user
|
|
* `TimestampCreated`: unixtime of creation
|
|
* `TimestampUpdated`: unixtime of last update
|
|
|
|
`Enabled*`: owner AND user have to enable a share to become usable
|
|
|
|
`Hidden*`: owner AND user have to disable a share to become visible in PROPFIND
|
|
|
|
### Sharing Configuration Entry Storage
|
|
|
|
#### CSV
|
|
|
|
(_>= 3.7.0_)
|
|
|
|
One CSV file containing one row per sharing config, separated by `,` and containing header with columns from above.
|
|
|
|
#### Files
|
|
|
|
(_>= 3.7.0_)
|
|
|
|
File-based configuration store is using encoded `PathOrToken` as filename for each config. File contains the data stored as "dict" in binary Python "pickle" format (same is also used for item cache files).
|
|
|
|
## Sharing Access
|
|
|
|
### Sharing Access via Maps
|
|
|
|
(_>= 3.7.0_)
|
|
|
|
Map-based sharing can be accessed as usual after authentication and authorization.
|
|
|
|
#### Workflow
|
|
|
|
* create map as owner
|
|
* enable map as owner (can be combined with "create")
|
|
* enable map as user (explicit required to avoid sudden available share)
|
|
|
|
In case share should be visible using PROPFIND
|
|
|
|
* unhide map as owner (can be combined with "create")
|
|
* unhide map as user (explicit required to avoid sudden visible share)
|
|
|
|
|
|
### Sharing Access via Tokens
|
|
|
|
(_>= 3.7.0_)
|
|
|
|
Token-based sharing can be accessed after retrieving the token via
|
|
|
|
Token-URI: `/.token/<Token>`
|
|
|
|
#### Workflow
|
|
|
|
* create token as owner
|
|
* enable token as owner (can be combined with "create")
|
|
* handover URI with token to client
|
|
|
|
|
|
## Sharing Configuration Management API
|
|
|
|
### Sharing Configuration Management API version 1
|
|
|
|
(_>= 3.7.0_)
|
|
|
|
Type: POST API
|
|
|
|
Base-URI: `/.sharing/v1/<ShareType>/<Hook>`
|
|
|
|
See also test cases in `radicale/tests/test_sharing.py`
|
|
|
|
#### Data Format
|
|
|
|
##### Input Data Format
|
|
|
|
Parsing be controlled by `CONTENT_TYPE`
|
|
|
|
* application/x-www-form-urlencoded (_>= 3.7.0_)
|
|
* application/json (_>= 3.7.0_)
|
|
|
|
##### Output Data Format
|
|
|
|
Can be selected by `HTTP_ACCEPT`
|
|
|
|
* text/plain (_>= 3.7.0_)
|
|
* text/csv (_>= 3.7.0_) - only for "list"
|
|
* application/json (_>= 3.7.0_)
|
|
|
|
##### Accepted Input Data Fields
|
|
|
|
* `PathOrToken`: token or "virtual" collection
|
|
* `PathMapped`: target collection
|
|
* `Owner`: owner of the share
|
|
* `User`: user of the share
|
|
* `Permissions`: effective permission of the share
|
|
* `Enabled`: owner/user selected by authentication
|
|
* `Hidden`: owner/user selected by authentication
|
|
|
|
#### API Hooks
|
|
|
|
##### API Hook "info"
|
|
|
|
Shows what kind of ShareTypes are supported
|
|
|
|
* Example: TEXT
|
|
|
|
```
|
|
curl -u user:pass -H "accept: text/plain" -d "" http://localhost:5232/.sharing/v1/all/info
|
|
ApiVersion=1
|
|
Status=success
|
|
FeatureEnabledCollectionByMap=True
|
|
PermittedCreateCollectionByMap=True
|
|
FeatureEnabledCollectionByToken=True
|
|
PermittedCreateCollectionByToken=True
|
|
```
|
|
|
|
* Example: JSON
|
|
|
|
```
|
|
curl -u user:pass --silent -H "accept: application/json" -d "" http://localhost:5232/.sharing/v1/all/info | jq
|
|
{
|
|
"ApiVersion": 1,
|
|
"Status": "success",
|
|
"FeatureEnabledCollectionByMap": true,
|
|
"PermittedCreateCollectionByMap": true,
|
|
"FeatureEnabledCollectionByToken": true,
|
|
"PermittedCreateCollectionByToken": true
|
|
}
|
|
```
|
|
|
|
|
|
##### API Hook "*/create"
|
|
|
|
Create a share
|
|
|
|
###### API Hook "token/create"
|
|
|
|
* Input
|
|
|
|
| Parameter | Mandatory | Default |
|
|
| - | - | - |
|
|
| PathMapped | yes | |
|
|
| Permissions | no | r
|
|
|
|
* Output
|
|
|
|
| Parameter | Value |
|
|
| - | - |
|
|
| PathOrToken | (autogenerated token) |
|
|
|
|
* Example: TEXT
|
|
|
|
```
|
|
curl -u user:pass -d "PathMapped=/user/testcalendar1/" http://localhost:5232/.sharing/v1/token/create
|
|
ApiVersion=1
|
|
Status=success
|
|
PathOrToken=v1/VQR7AmsVRi2ZlFj_JwGpFx-ES5Goyku-gP_YkLh1zUw=
|
|
```
|
|
|
|
|
|
###### API Hook "map/create"
|
|
|
|
* Input
|
|
|
|
| Parameter | Mandatory | Default |
|
|
| - | - | - |
|
|
| PathOrToken | yes | |
|
|
| PathMapped | yes | |
|
|
| Permissions | no | r
|
|
| User | yes | |
|
|
|
|
* Output: result status
|
|
|
|
* Example: TEXT
|
|
|
|
```
|
|
curl -u owner:pass -d "PathOrToken=/user/cal1-from-owner/" -d "PathMapped=/owner/cal1/" -d "User=user" http://localhost:5232/.sharing/v1/map/create
|
|
ApiVersion=1
|
|
Status=success
|
|
```
|
|
|
|
|
|
##### API Hook "*/list"
|
|
|
|
List shares (optional with filter)
|
|
|
|
* Input
|
|
|
|
| Parameter | Mandatory | Default |
|
|
| - | - | - |
|
|
| PathMapped | no | (all) |
|
|
| Owner | no | (owned ones) |
|
|
| User | no | (filtered) |
|
|
|
|
* Output: plain/csv/json
|
|
|
|
* Example: CSV
|
|
|
|
```
|
|
curl -H "accept: text/csv" -u owner:pass -d "" http://localhost:5232/.sharing/v1/map/list
|
|
ShareType,PathOrToken,PathMapped,Owner,User,Permissions,EnabledByOwner,EnabledByUser,HiddenByOwner,HiddenByUser,TimestampCreated,TimestampUpdated
|
|
map,/user/cal1-from-owner/,/owner/cal1/,owner,user,r,False,False,True,True,1771962120,1771962120
|
|
```
|
|
|
|
|
|
##### API Hook "*/delete"
|
|
|
|
Delete a share selected by `PathOrToken`
|
|
|
|
* Input
|
|
|
|
| Parameter | Mandatory | Default |
|
|
| - | - | - |
|
|
| PathOrToken | yes | |
|
|
|
|
* Output: result status
|
|
|
|
##### API Hook "*/update"
|
|
|
|
Update a share selected by `PathOrToken`
|
|
|
|
* Input
|
|
|
|
| Parameter | Mandatory | Default |
|
|
| - | - | - |
|
|
| PathOrToken | yes | n/a |
|
|
| PathMapped | no | |
|
|
| User | no | |
|
|
|
|
* Output: result status
|
|
|
|
##### API Hooks "*/(enable|disable|hide|unhide)"
|
|
|
|
Enable|disable|hide|unhide a share selected by `PathOrToken`
|
|
|
|
* Input
|
|
|
|
| Parameter | Mandatory | Default |
|
|
| - | - | - |
|
|
| PathOrToken | yes | n/a |
|
|
|
|
* Output: result status
|
|
|
|
* Example: TEXT (enable)
|
|
|
|
```
|
|
curl -u owner:pass -d "PathOrToken=/user/cal1-from-owner/" -d "PathMapped=/owner/cal1/" -d "User=user" http://localhost:5232/.sharing/v1/map/enable
|
|
ApiVersion=1
|
|
Status=success
|
|
```
|
|
|
|
* Example: JSON (unhide)
|
|
|
|
```
|
|
curl -u owner:pass -d '{"PathOrToken": "/user/cal1-from-owner/", "PathMapped": "/owner/cal1/", "User": "user"} http://localhost:5232/.sharing/v1/map/unhide
|
|
ApiVersion=1
|
|
Status=success
|
|
```
|
|
|
|
|