Build
Storage
Files live in buckets inside your app. Each bucket has a read and a write policy, like a table, plus optional size and type limits. Uploads are one raw PUT.
Buckets
| Field | Values |
|---|---|
read | public, authenticated, owner, secret |
write | authenticated, owner, secret |
max_file_size | bytes, up to the 50 MB platform limit |
allowed_types | content types, wildcards allowed, for example ["image/*"] |
With owner, a signed-in user may only use keys that start with their user id and a slash, such as <user id>/avatar.png. The secret key may use any key.
Public avatars that only their owner can replace:
berth storage buckets create --app "$APP" avatars --read public --write owner --max-file-size 2000000Private documents for your server only, with a type allow list:
curl -sS -X POST https://api.atberth.com/v1/apps/$APP/storage/buckets \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"docs","read":"secret","write":"secret","allowed_types":["text/plain","application/pdf"]}'
berth storage buckets list --app "$APP"Upload
Upload is PUT /storage/objects/{bucket}/{key} with the raw file as the body. The Content-Type you send is stored and served back. A second PUT to the same key overwrites it.
Sign up a user and upload their avatar as them:
SESSION=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/signup \
-H "Authorization: Bearer $PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"ada@example.com","password":"correct horse battery"}')
ACCESS_TOKEN=$(echo "$SESSION" | jq -er .access_token)
USER_ID=$(echo "$SESSION" | jq -er .user.id)
echo 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==' | base64 -d > avatar.pngcurl -sS -X PUT https://api.atberth.com/v1/apps/$APP/storage/objects/avatars/$USER_ID/avatar.png \
-H "apikey: $PUBLISHABLE_KEY" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: image/png" \
--data-binary @avatar.pngOutside her own folder, the owner policy refuses with 403 policy_violation:
curl -sS -X PUT https://api.atberth.com/v1/apps/$APP/storage/objects/avatars/someone-else/avatar.png \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: image/png" \
--data-binary @avatar.pngFrom the CLI (secret key), the key defaults to the file name:
echo "Berth storage example" > readme.txt
berth storage upload --app "$APP" docs readme.txt
berth storage upload --app "$APP" docs readme.txt notes/readme.txt --content-type text/plainList
berth storage ls --app "$APP" docs --prefix notes/
curl -sS "https://api.atberth.com/v1/apps/$APP/storage/objects/avatars?prefix=$USER_ID/&limit=100" \
-H "Authorization: Bearer $SECRET_KEY"Download
A public bucket needs no key at all, so the URL can go straight into an image tag. Add ?download=1 to get an attachment.
curl -sS -o downloaded.png https://api.atberth.com/v1/apps/$APP/storage/objects/avatars/$USER_ID/avatar.png
file downloaded.pngberth storage download --app "$APP" docs readme.txt -o copy.txt
cat copy.txtSigned URLs
For a private bucket, hand out a link that works without a key until it expires. Anyone allowed to read the object may sign it.
SIGNED_URL=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/storage/sign/docs/readme.txt \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"expires_in":600}' | jq -er .url)
curl -sS "$SIGNED_URL"berth storage sign --app "$APP" docs readme.txt --expires 3600The link carries ?expires= and ?signature=. Changing either one breaks it.
Delete
berth storage rm --app "$APP" docs notes/readme.txt
curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/storage/objects/avatars/$USER_ID/avatar.png \
-H "Authorization: Bearer $ACCESS_TOKEN"A bucket must be empty before it can be deleted, unless you pass --force (?force=true), which deletes its files too.
berth storage buckets delete --app "$APP" docs --force
berth storage buckets delete --app "$APP" avatars