Compare commits
19 Commits
02820203f0
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
92b3b14107
|
|||
|
5efab8b733
|
|||
|
2772463196
|
|||
|
f0d6e6c2c4
|
|||
|
8bcf3854c2
|
|||
|
771ff97cfe
|
|||
| 3512c0f7c9 | |||
| aff383b99b | |||
|
6455f24ab0
|
|||
|
bf14785404
|
|||
| 8b6f201a0b | |||
|
209fcca5ea
|
|||
|
589dcf7fa2
|
|||
|
91cadbf228
|
|||
|
d09c6e7a39
|
|||
| 93fd1ecd5f | |||
|
024f516a9d
|
|||
|
96417e3884
|
|||
|
b7ff3e7d42
|
16
.drone.yml
Normal file
16
.drone.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: specs
|
||||
image: ruby
|
||||
environment:
|
||||
REDIS_HOST: redis
|
||||
commands:
|
||||
- cp config.yml.erb.example config.yml.erb
|
||||
- bundle install --jobs=3 --retry=3
|
||||
- bundle exec rake test
|
||||
|
||||
services:
|
||||
- name: redis
|
||||
image: redis
|
||||
33
.github/workflows/ruby.yml
vendored
33
.github/workflows/ruby.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
ruby-version: ['2.7', '3.0', '3.1']
|
||||
redis-version: [6, 7]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version }}
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
- name: Start Redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
redis-version: ${{ matrix.redis-version }}
|
||||
- name: Configure
|
||||
run: cp config.yml.erb.example config.yml.erb
|
||||
- name: Run tests
|
||||
run: bundle exec rake test
|
||||
@@ -1,8 +1,7 @@
|
||||
# FROM ruby:3.1.4
|
||||
FROM ruby:2.7.8
|
||||
FROM ruby:3.1.4
|
||||
|
||||
WORKDIR /liquorcabinet
|
||||
ENV RACK_ENV=staging
|
||||
ENV RACK_ENV=production
|
||||
|
||||
COPY Gemfile Gemfile.lock /liquorcabinet/
|
||||
RUN bundle install
|
||||
|
||||
4
Gemfile
4
Gemfile
@@ -6,9 +6,8 @@ gem "activesupport", "~> 6.1.0"
|
||||
gem "redis", "~> 4.6.0"
|
||||
gem "rest-client", "~> 2.1.0"
|
||||
gem "aws-sigv4", "~> 1.0.0"
|
||||
# Remove require when we can update to 3.0, which sets the new storage
|
||||
# format to columnar by default. Increases performance
|
||||
gem "mime-types"
|
||||
gem "rainbows"
|
||||
|
||||
group :test do
|
||||
gem 'rake'
|
||||
@@ -20,6 +19,5 @@ group :test do
|
||||
end
|
||||
|
||||
group :staging, :production do
|
||||
gem "rainbows"
|
||||
gem "sentry-raven", require: false
|
||||
end
|
||||
|
||||
40
README.md
40
README.md
@@ -1,21 +1,55 @@
|
||||
[](https://github.com/5apps/liquor-cabinet/actions/workflows/ruby.yml)
|
||||
[](https://drone.kosmos.org/5apps/liquor-cabinet)
|
||||
|
||||
# Liquor Cabinet
|
||||
|
||||
Liquor Cabinet is where Frank stores all his stuff. It's a
|
||||
[remoteStorage](https://remotestorage.io) HTTP API, based on Sinatra. The
|
||||
metadata and OAuth tokens are stored in Redis, and documents can be stored in
|
||||
anything that supports the storage API of either Openstack Swift or Amazon S3.
|
||||
metadata and OAuth tokens are stored in Redis, and
|
||||
documents/files can be stored in anything that supports
|
||||
the S3 object storage API.
|
||||
|
||||
Liquor Cabinet only implements the storage API part of the remoteStorage
|
||||
protocol, but does not include the Webfinger and OAuth parts. It is meant to be
|
||||
added to existing systems and user accounts, so you will have to add your own
|
||||
OAuth dialog for remoteStorage authorizations and persist the tokens in Redis.
|
||||
|
||||
There is an [open-source accounts management
|
||||
app](https://gitea.kosmos.org/kosmos/akkounts/) by the Kosmos project, which
|
||||
comes with a built-in remoteStorage dashboard and is compatible with Liquor
|
||||
Cabinet.
|
||||
|
||||
If you have any questions about this program, please [post to the RS
|
||||
forums](https://community.remotestorage.io/c/server-development), and we'll
|
||||
gladly answer them.
|
||||
|
||||
## System requirements
|
||||
|
||||
* [Ruby](https://www.ruby-lang.org/en/) and [Bundler](https://bundler.io/)
|
||||
* [Redis](https://redis.io/)
|
||||
* S3-compatible object storage (e.g. [Garage](https://garagehq.deuxfleurs.fr/)
|
||||
or [MinIO](https://min.io/) for self-hosting)
|
||||
|
||||
## Setup
|
||||
|
||||
1. Check the `config.yml.erb.example` file. Either copy it to `config.yml.erb`
|
||||
and use the enviroment variables it contains, or create/deploy your own
|
||||
config YAML file with custom values.
|
||||
2. Install dependencies: `bundle install`
|
||||
|
||||
## Development
|
||||
|
||||
Running the test suite:
|
||||
|
||||
bundle exec rake test
|
||||
|
||||
Running the app:
|
||||
|
||||
bundle exec rainbows
|
||||
|
||||
## Deployment
|
||||
|
||||
_TODO document options_
|
||||
|
||||
## Contributing
|
||||
|
||||
We love pull requests. If you want to submit a patch:
|
||||
|
||||
@@ -2,11 +2,11 @@ development: &defaults
|
||||
maintenance: false
|
||||
redis:
|
||||
host: <%= ENV["REDIS_HOST"] || "localhost" %>
|
||||
port: <%= ENV["REDIS_PORT"] || "6379" %>
|
||||
db: <%= ENV["REDIS_DB"] || 0 %>
|
||||
port: <%= ENV["REDIS_PORT"] || 6379 %>
|
||||
db: <%= ENV["REDIS_DB"] || 1 %>
|
||||
s3: &s3_defaults
|
||||
endpoint: <%= ENV["S3_ENDPOINT"] || "http://127.0.0.1:9000" %>
|
||||
region: <%= ENV["S3_REGION"] %>
|
||||
region: <%= ENV["S3_REGION"] || "us-east-1" %>
|
||||
access_key_id: <%= ENV["S3_ACCESS_KEY"] || "minioadmin" %>
|
||||
secret_key_id: <%= ENV["S3_SECRET_KEY"] || "minioadmin" %>
|
||||
bucket: <%= ENV["S3_BUCKET"] || "rs-development" %>
|
||||
|
||||
@@ -431,9 +431,9 @@ module RemoteStorage
|
||||
end
|
||||
end
|
||||
|
||||
def escape(url)
|
||||
def escape(str)
|
||||
# We want spaces to turn into %20 and slashes to stay slashes
|
||||
CGI::escape(url).gsub('+', '%20').gsub('%2F', '/')
|
||||
CGI::escape(str).gsub('+', '%20').gsub('%2F', '/')
|
||||
end
|
||||
|
||||
def redis
|
||||
|
||||
@@ -15,7 +15,8 @@ module RemoteStorage
|
||||
service: 's3',
|
||||
region: settings.s3["region"],
|
||||
access_key_id: settings.s3["access_key_id"].to_s,
|
||||
secret_access_key: settings.s3["secret_key_id"].to_s
|
||||
secret_access_key: settings.s3["secret_key_id"].to_s,
|
||||
uri_escape_path: false
|
||||
)
|
||||
end
|
||||
|
||||
@@ -29,6 +30,8 @@ module RemoteStorage
|
||||
headers = { "Content-Type" => content_type }
|
||||
auth_headers = auth_headers_for("PUT", url, headers, data)
|
||||
|
||||
# TODO check if put was successful, e.g. it's returning a 413 directly
|
||||
# if the back-end does, too (missing CORS headers in that case)
|
||||
res = RestClient.put(url, data, headers.merge(auth_headers))
|
||||
|
||||
return [
|
||||
@@ -36,10 +39,6 @@ module RemoteStorage
|
||||
timestamp_for(res.headers[:date]) # S3 does not return a Last-Modified response header on PUTs
|
||||
]
|
||||
end
|
||||
|
||||
rescue RestClient::Forbidden => ex
|
||||
puts ex.response.to_s
|
||||
raise ex
|
||||
end
|
||||
|
||||
def do_get_request(url, &block)
|
||||
@@ -53,14 +52,14 @@ module RemoteStorage
|
||||
|
||||
def do_head_request(url, &block)
|
||||
deal_with_unauthorized_requests do
|
||||
auth_headers = auth_headers_for("HEAD", url, {})
|
||||
auth_headers = auth_headers_for("HEAD", url)
|
||||
RestClient.head(url, auth_headers, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def do_delete_request(url)
|
||||
deal_with_unauthorized_requests do
|
||||
auth_headers = auth_headers_for("DELETE", url, {})
|
||||
auth_headers = auth_headers_for("DELETE", url)
|
||||
RestClient.delete(url, auth_headers)
|
||||
end
|
||||
end
|
||||
@@ -79,19 +78,13 @@ module RemoteStorage
|
||||
return found
|
||||
end
|
||||
|
||||
def auth_headers_for(http_method, url, headers, data = nil)
|
||||
def auth_headers_for(http_method, url, headers = {}, data = nil)
|
||||
signature = s3_signer.sign_request(
|
||||
http_method: http_method, url: url, headers: headers, body: data
|
||||
)
|
||||
|
||||
puts signature.headers.inspect
|
||||
signature.headers
|
||||
end
|
||||
|
||||
def uri_escape(s)
|
||||
CGI.escape(s).gsub('%5B', '[').gsub('%5D', ']')
|
||||
end
|
||||
|
||||
def base_url
|
||||
@base_url ||= settings.s3["endpoint"]
|
||||
end
|
||||
|
||||
@@ -64,7 +64,7 @@ class LiquorCabinet < Sinatra::Base
|
||||
headers 'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'GET, PUT, DELETE',
|
||||
'Access-Control-Allow-Headers' => 'Authorization, Content-Type, Origin, If-Match, If-None-Match, Range',
|
||||
'Access-Control-Expose-Headers' => 'ETag, Content-Length, Content-Range',
|
||||
'Access-Control-Expose-Headers' => 'ETag, Content-Length, Content-Range, Content-Type',
|
||||
'Accept-Ranges' => 'bytes'
|
||||
headers['Access-Control-Allow-Origin'] = env["HTTP_ORIGIN"] if env["HTTP_ORIGIN"]
|
||||
headers['Cache-Control'] = 'no-cache'
|
||||
|
||||
11
run-dev.sh
11
run-dev.sh
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
RACK_ENV=staging \
|
||||
REDIS_HOST=localhost \
|
||||
REDIS_PORT=6379 \
|
||||
REDIS_DB=1 \
|
||||
S3_ENDPOINT='http://localhost:9000' \
|
||||
S3_ACCESS_KEY='dev-key' \
|
||||
S3_SECRET_KEY='123456789' \
|
||||
S3_BUCKET=remotestorage \
|
||||
bundle exec rainbows --listen localhost:4567
|
||||
Reference in New Issue
Block a user