REST Api
Sharry is provided as a REST server and a web application client. The REST Api is specified using openapi 3.0 and it’s static documentation can be seen here.
The “raw” openapi.yml
specification file can be found
here.
The calls are divided into 4 categories:
/open/*
: no authentication is required to access/sec/*
: an authenticated user is required/alias/*
: these routes are allowed with a valid alias id given as headerSharry-Alias
/admin/*
: an authenticated user that is admin is required
Authentication works by logging in with username/password (or an
oauth2 flow) that generates a token that has to be sent with every
request to a secured and admin route. It is possible to sent it via a
Cookie
header or the special Sharry-Auth
header.
Files can be uploaded using different methods. There is an endpoint that can take all files and meta data from one single request. For more reliable uploads, the server implements the tus protocol that allows to resume failed or paused uploads.
Authentication
The unprotected route /open/auth/login
can be used to login with
account name and password. The response contains a token that can be
used for accessing protected routes. The token is only valid for a
restricted time which can be configured (default is 5 minutes).
New tokens can be generated using an existing valid token and the
protected route /sec/auth/session
. This will return the same
response as above, giving a new token.
This token can be added to requests in two ways: as a cookie header or
a “normal” http header. If a cookie header is used, the cookie name
must be sharry_auth
and a custom header must be named
Sharry-Auth
.
Live Api
Besides the statically generated documentation at this site, the rest
server provides a openapi generated documenation, that allows playing
around with the api. It requires a running sharry rest server. If it
is deployed at http://localhost:9090
, then check this url:
http://localhost:909/api/doc
Examples
Login with username/password
$ curl -d'{"account":"eike", "password":"test"}' http://localhost:9090/api/v2/open/auth/login
Output:
{"id":"6ExuF2eYpvd-hFPyEk4jAdy-aGiyyyDRk3q-nHkAE6kjViU","user":"eike","admin":false,"success":true,"message":"Login successful","token":"1577122333196-NkV4dUYyZVlwdmQtaEZQeUVrNGpBZHktYUdpeXl5RFJrM3EtbkhrQUU2a2pWaVUvZWlrZS9mYWxzZQ==-$2a$10$t5OpvGG8/t0.Dw2CO3RSN.-Lnow8nTb4t9nVMBkJEJbaRwABGY=","validMs":300000}
The token
must be used with subsequent requests. It is valid for 5 minutes.
Get a new token
$ curl -XPOST -H 'Sharry-Auth: 1577122333196-NkV4dUYyZVlwdmQtaEZQeUVrNGpBZHktYUdpeXl5RFJrM3EtbkhrQUU2a2pWaVUvZWlrZS9mYWxzZQ==-$2a$10$t5OpvGG8/t0.Dw2CO3RSN.-Lnow8nTb4t9nVMBkJEJbaRwABGY=' http://localhost:9090/api/v2/sec/auth/session
Output:
{"id":"6ExuF2eYpvd-hFPyEk4jAdy-aGiyyyDRk3q-nHkAE6kjViU","user":"eike","admin":false,"success":true,"message":"Login successful","token":"1577122497189-NkV4dUYyZVlwdmQtaEZQeUVrNGpBZHktYUdpeXl5RFJrM3EtbkhrQUU2a2pWaVUvZWlrZS9mYWxzZQ==-$2a$10$9/VNIq8e3YxHKTLyE0JwbO-bI0CpZnEsmfhDHxsjwhe7qzQaSY=","validMs":300000}
Get your shares
$ curl -XGET -H 'Sharry-Auth: 1577122333196-NkV4dUYyZVlwdmQtaEZQeUVrNGpBZHktYUdpeXl5RFJrM3EtbkhrQUU2a2pWaVUvZWlrZS9mYWxzZQ==-$2a$10$t5OpvGG8/t0.Dw2CO3RSN.-Lnow8nTb4t9nVMBkJEJbaRwABGY=' http://localhost:9090/api/v2/sec/share/search
Output:
{"items":[{"id":"7wNPzKepw4g-gKgSfQ376tJ-HSifxLc33r5-xY8FigeF7wG","name":null,"aliasName":null,"validity":172800000,"maxViews":30,"password":false,"created":1577102005295,"files":
1,"size":199640,"published":null},{"id":"44EPQPe7Lo2-KnUCp3kiQNg-dJ4oxiAQ5Lh-etMiDwe5KD3","name":null,"aliasName":null,"validity":172800000,"maxViews":30,"password":false,"created
":1577101969643,"files":1,"size":192886,"published":null}]}
Create an alias page
$ curl -XPOST -H 'Sharry-Auth: 1577122785983-NkV4dUYyZVlwdmQtaEZQeUVrNGpBZHktYUdpeXl5RFJrM3EtbkhrQUU2a2pWaVUvZWlrZS9mYWxzZQ==-$2a$10$kceo1M6cRNpMpptb0F67uO-sZurk/s03VHuzpxLGhT+AUF4TjU=' -d'{"name":"test alias","validity": 172800000, "enabled":true,"members":[]}' http://localhost:9090/api/v2/sec/alias
Output:
{"success":true,"message":"Alias successfully created.","id":"HfHViHEN5EM-E6jmgmw1W3H-KVUR2KanbEd-EGvDeZR2RPV"}
Upload a file to the new alias page
Using the id, upload files via multipart/form-data
requests. You can
upload multiple files at once.
$ curl -XPOST -F file=@P1020416.JPG -F file=@P1020422.JPG -H 'Sharry-Alias: HfHViHEN5EM-E6jmgmw1W3H-KVUR2KanbEd-EGvDeZR2RPV' http://localhost:9090/api/v2/alias/upload
Output:
{"success":true,"message":"Share created.","id":"8P7GzxmLGjF-F7K4kXAhe8j-6AhLrQuFJGb-i54TTRZ3xn8"}
Get Details about the share
This requires authenticated users, of course. The | jq
pipes the
one-line json output through a program that formats it.
$ curl -H'Sharry-Auth: 1577132299230-NkV4dUYyZVlwdmQtaEZQeUVrNGpBZHktYUdpeXl5RFJrM3EtbkhrQUU2a2pWaVUvZWlrZS9mYWxzZQ==-$2a$10$jFhOEGYktHb8yiLF5mhHjO-CvDL2MniUH+RQv8dTSWPwhSUeIw=' http://localhost:9090/api/v2/sec/share/8P7GzxmLGjF-F7K4kXAhe8j-6AhLrQuFJGb-i54TTRZ3xn8 | jq
Output:
{
"id": "8P7GzxmLGjF-F7K4kXAhe8j-6AhLrQuFJGb-i54TTRZ3xn8",
"name": null,
"aliasId": "HfHViHEN5EM-E6jmgmw1W3H-KVUR2KanbEd-EGvDeZR2RPV",
"aliasName": "test alias",
"validity": 172800000,
"maxViews": 30,
"password": false,
"descriptionRaw": null,
"description": null,
"created": 1577132473544,
"publishInfo": null,
"files": [
{
"id": "6QcXQ9qeSQb-VYF2p9M23XT-bMPRFkmtsPK-ejjJUns3Ymk",
"filename": "P1020416.JPG",
"size": 2829079,
"mimetype": "image/jpeg",
"checksum": "8ffe8da9d49b7e6590b78362ed0acd4156f4bccaa724c710560a57bd3c54d74d",
"storedSize": 2829079
},
{
"id": "Eur8FJj4uxL-q9NYVBqYi1L-jnsEFKPwCYQ-6Z81iazysjD",
"filename": "P1020422.JPG",
"size": 3692609,
"mimetype": "image/jpeg",
"checksum": "424bcfa141f61a73269466102ee1a826f1fae31a847a5861500fc4cbdfb1732f",
"storedSize": 3692609
}
]
}
The output contains the two files that have been uploaded. Also
interesting is the storedSize
property. This indicates how many
bytes really reached the server. The size
property uses the value as
advertised by the uploader. If storedSize
does not equal size
then
the file is not fully uploaded.