poto 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +4 -0
  5. data/.travis.yml +3 -0
  6. data/CODE_OF_CONDUCT.md +49 -0
  7. data/Dockerfile +21 -0
  8. data/Gemfile +14 -0
  9. data/LICENSE.txt +21 -0
  10. data/Procfile +1 -0
  11. data/README.md +97 -0
  12. data/Rakefile +10 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/docker-compose.yml +16 -0
  16. data/exe/poto-aws-s3 +29 -0
  17. data/exe/poto-google-cloud-storage +34 -0
  18. data/lib/poto.rb +11 -0
  19. data/lib/poto/api.rb +62 -0
  20. data/lib/poto/app.rb +11 -0
  21. data/lib/poto/ext/open_uri.rb +7 -0
  22. data/lib/poto/file_repository/aws/s3.rb +32 -0
  23. data/lib/poto/file_repository/aws/s3/client.rb +33 -0
  24. data/lib/poto/file_repository/aws/s3/file_collection_mapper.rb +36 -0
  25. data/lib/poto/file_repository/aws/s3/file_mapper.rb +37 -0
  26. data/lib/poto/file_repository/dsl.rb +25 -0
  27. data/lib/poto/file_repository/file.rb +5 -0
  28. data/lib/poto/file_repository/file_collection.rb +5 -0
  29. data/lib/poto/file_repository/google/cloud/storage.rb +34 -0
  30. data/lib/poto/file_repository/google/cloud/storage/file_collection_mapper.rb +37 -0
  31. data/lib/poto/file_repository/google/cloud/storage/file_mapper.rb +39 -0
  32. data/lib/poto/file_repository/proxy.rb +27 -0
  33. data/lib/poto/image_proxy.rb +45 -0
  34. data/lib/poto/representers/file_collection_representer.rb +22 -0
  35. data/lib/poto/representers/file_representer.rb +19 -0
  36. data/lib/poto/services/download.rb +24 -0
  37. data/lib/poto/services/file_cache.rb +28 -0
  38. data/lib/poto/services/resize.rb +23 -0
  39. data/lib/poto/version.rb +3 -0
  40. data/poto.gemspec +40 -0
  41. data/public/ajax-loader.gif +0 -0
  42. data/public/index.html +150 -0
  43. metadata +244 -0
@@ -0,0 +1,11 @@
1
+ require 'sinatra'
2
+
3
+ module Poto
4
+ class App < Sinatra::Base
5
+ set :public_folder, File.join(File.dirname(__FILE__), '..', '..', 'public')
6
+
7
+ get('/') do
8
+ File.read(File.join('public', 'index.html'))
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module OpenURI
2
+ class << self
3
+ def redirectable?(*)
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,32 @@
1
+ require 'base64'
2
+ require 'poto/file_repository/aws/s3/client'
3
+ require 'poto/file_repository/aws/s3/file_collection_mapper'
4
+
5
+ module Poto
6
+ module FileRepository
7
+ module AWS
8
+ class S3
9
+ attr_reader :bucket, :client
10
+
11
+ def initialize(bucket:, client: Client.new(bucket))
12
+ @bucket = bucket
13
+ @client = client
14
+ end
15
+
16
+ def url(id)
17
+ client.url(id)
18
+ end
19
+
20
+ def all(prefix:, page:, per_page:)
21
+ objects = client.objects(
22
+ page: page,
23
+ per_page: per_page,
24
+ prefix: prefix
25
+ )
26
+
27
+ FileCollectionMapper.new(objects).call
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ require 'aws-sdk'
2
+
3
+ module Poto
4
+ module FileRepository
5
+ module AWS
6
+ class S3
7
+ class Client
8
+ attr_reader :bucket
9
+
10
+ def initialize(bucket)
11
+ @bucket = bucket
12
+ end
13
+
14
+ def objects(prefix:, page:, per_page:)
15
+ Aws::S3::Client.new.list_objects(
16
+ bucket: bucket,
17
+ marker: page,
18
+ max_keys: per_page,
19
+ prefix: prefix
20
+ )
21
+ end
22
+
23
+ def url(key)
24
+ Aws::S3::Object.new(
25
+ bucket,
26
+ key
27
+ ).presigned_url(:get, expires_in: 3600)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'poto/file_repository/aws/s3/file_mapper'
2
+ require 'poto/file_repository/file_collection'
3
+
4
+ module Poto
5
+ module FileRepository
6
+ module AWS
7
+ class S3
8
+ class FileCollectionMapper
9
+ attr_reader :objects
10
+
11
+ def initialize(objects)
12
+ @objects = objects
13
+ end
14
+
15
+ def call
16
+ FileCollection.new(files, page, next_page)
17
+ end
18
+
19
+ private
20
+
21
+ def files
22
+ objects.contents.map { |object| FileMapper.new(object).call }
23
+ end
24
+
25
+ def page
26
+ objects.marker
27
+ end
28
+
29
+ def next_page
30
+ files.last.try(:name)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ require 'base64'
2
+
3
+ require 'poto/file_repository/file'
4
+
5
+ module Poto
6
+ module FileRepository
7
+ module AWS
8
+ class S3
9
+ class FileMapper
10
+ attr_reader :object
11
+
12
+ def initialize(object)
13
+ @object = object
14
+ end
15
+
16
+ def call
17
+ File.new(id, name, size)
18
+ end
19
+
20
+ private
21
+
22
+ def name
23
+ object.key
24
+ end
25
+
26
+ def size
27
+ object.size
28
+ end
29
+
30
+ def id
31
+ object.key
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ module Poto
2
+ module FileRepository
3
+ class Proxy
4
+ module DSL
5
+ module ClassMethods
6
+ def option(name)
7
+ define_method(name) do |value|
8
+ tap do
9
+ options[name] = value
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+
19
+ def options
20
+ @__options ||= {}
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Poto
2
+ module FileRepository
3
+ File = Struct.new('File', :id, :name, :size)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Poto
2
+ module FileRepository
3
+ FileCollection = Struct.new('FileCollection', :files, :page, :next_page)
4
+ end
5
+ end
@@ -0,0 +1,34 @@
1
+ require 'base64'
2
+ require 'google/cloud/storage'
3
+
4
+ require 'poto/file_repository/google/cloud/storage/file_collection_mapper'
5
+
6
+ module Poto
7
+ module FileRepository
8
+ module Google
9
+ module Cloud
10
+ class Storage
11
+ attr_reader :client
12
+
13
+ def initialize(client:)
14
+ @client = client
15
+ end
16
+
17
+ def url(id)
18
+ client.file(id).signed_url
19
+ end
20
+
21
+ def all(prefix:, page:, per_page:)
22
+ files = client.files(
23
+ prefix: prefix,
24
+ token: page,
25
+ max: per_page
26
+ )
27
+
28
+ FileCollectionMapper.new(files, page).call
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require 'base64'
2
+
3
+ require 'poto/file_repository/file_collection'
4
+ require 'poto/file_repository/google/cloud/storage/file_mapper'
5
+
6
+ module Poto
7
+ module FileRepository
8
+ module Google
9
+ module Cloud
10
+ class Storage
11
+ class FileCollectionMapper
12
+ attr_reader :page
13
+
14
+ def initialize(files, page)
15
+ @files = files
16
+ @page = page
17
+ end
18
+
19
+ def call
20
+ FileCollection.new(files, page, next_page)
21
+ end
22
+
23
+ private
24
+
25
+ def files
26
+ @files.map { |file| FileMapper.new(file).call }
27
+ end
28
+
29
+ def next_page
30
+ @files.token
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ require 'base64'
2
+
3
+ require 'poto/file_repository/file'
4
+
5
+ module Poto
6
+ module FileRepository
7
+ module Google
8
+ module Cloud
9
+ class Storage
10
+ class FileMapper
11
+ attr_reader :file
12
+
13
+ def initialize(file)
14
+ @file = file
15
+ end
16
+
17
+ def call
18
+ File.new(id, name, size)
19
+ end
20
+
21
+ private
22
+
23
+ def name
24
+ file.name
25
+ end
26
+
27
+ def size
28
+ file.size
29
+ end
30
+
31
+ def id
32
+ file.name
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ require 'poto/file_repository/dsl'
2
+
3
+ module Poto
4
+ module FileRepository
5
+ class Proxy
6
+ include DSL
7
+
8
+ option :per_page
9
+ option :page
10
+ option :prefix
11
+
12
+ attr_reader :backend
13
+
14
+ def initialize(backend)
15
+ @backend = backend
16
+ end
17
+
18
+ def url(id)
19
+ backend.url(id)
20
+ end
21
+
22
+ def all
23
+ backend.all(options)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ require 'sinatra'
2
+ require 'tmpdir'
3
+
4
+ require 'poto/services/download'
5
+ require 'poto/services/file_cache'
6
+ require 'poto/services/resize'
7
+
8
+ module Poto
9
+ class ImageProxy < Sinatra::Base
10
+ set :cache_path, Dir.tmpdir
11
+
12
+ helpers do
13
+ def src
14
+ URI(params['src'].gsub(%r{\A\/\/}, 'http://'))
15
+ end
16
+
17
+ def width
18
+ params['width'].to_i
19
+ end
20
+
21
+ def height
22
+ params['height'].to_i
23
+ end
24
+
25
+ def cache(key, &set)
26
+ Services::FileCache.new(path: settings.cache_path).cache(key, &set)
27
+ end
28
+
29
+ def download(uri)
30
+ Services::Download.new(file: Tempfile.new(settings.cache_path), uri: uri).call
31
+ end
32
+
33
+ def resize(path, height, width)
34
+ Services::Resize.new(path: path, height: height, width: width).call
35
+ end
36
+ end
37
+
38
+ get('/') do
39
+ src_path = cache(src.path) { download(src) }
40
+ dst_path = cache("#{src_path}#{width}x#{height}") { resize(src_path, height, width) }
41
+
42
+ send_file(dst_path)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ require 'roar/representer'
2
+ require 'roar/json'
3
+ require 'roar/json/hal'
4
+ require 'poto/representers/file_representer'
5
+
6
+ module Poto
7
+ module FileCollectionRepresenter
8
+ include Roar::JSON::HAL
9
+ include Roar::Hypermedia
10
+ include Grape::Roar::Representer
11
+
12
+ collection :files, extend: FileRepresenter, embedded: true
13
+
14
+ link :self do |opts, helpers = opts[:env]['api.endpoint']|
15
+ helpers.url_for opts, '/files', page: helpers.page
16
+ end
17
+
18
+ link :next do |opts, helpers = opts[:env]['api.endpoint']|
19
+ helpers.url_for opts, '/files', page: next_page, per_page: helpers.per_page if next_page
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ require 'base64'
2
+ require 'roar/representer'
3
+ require 'roar/json'
4
+ require 'roar/json/hal'
5
+
6
+ module Poto
7
+ module FileRepresenter
8
+ include Roar::JSON::HAL
9
+ include Roar::Hypermedia
10
+ include Grape::Roar::Representer
11
+
12
+ property :name
13
+ property :size
14
+
15
+ link :file do |opts, helpers = opts[:env]['api.endpoint']|
16
+ helpers.url_for opts, '/files/' + Base64.urlsafe_encode64(id)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'open-uri'
2
+ require 'poto/ext/open_uri'
3
+
4
+ module Poto
5
+ module Services
6
+ class Download
7
+ attr_reader :file, :uri
8
+
9
+ def initialize(file:, uri:)
10
+ @file = file
11
+ @uri = uri
12
+ end
13
+
14
+ def call
15
+ open(uri) do |src|
16
+ file.write(src.read)
17
+ end
18
+
19
+ file.close
20
+ file.path
21
+ end
22
+ end
23
+ end
24
+ end