boar 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.travis-gemfile +13 -0
- data/.travis.yml +10 -0
- data/.yardopts +1 -0
- data/Gemfile +20 -0
- data/README.md +19 -0
- data/Rakefile +11 -0
- data/app/controllers/boar/application_controller.rb +16 -0
- data/app/controllers/boar/downloads_controller.rb +17 -0
- data/app/controllers/boar/pages_controller.rb +13 -0
- data/app/models/boar/handlers/authentication.rb +38 -0
- data/app/models/boar/handlers/downloads/base.rb +56 -0
- data/app/models/boar/handlers/downloads/box_net.rb +67 -0
- data/app/models/boar/handlers/downloads/dropbox.rb +59 -0
- data/app/models/boar/handlers/downloads/google_drive.rb +48 -0
- data/app/models/boar/handlers/downloads/local.rb +34 -0
- data/app/models/boar/handlers/downloads/remote.rb +24 -0
- data/app/models/boar/handlers/downloads/s3.rb +54 -0
- data/app/models/boar/handlers/downloads/sky_drive.rb +45 -0
- data/app/models/boar/handlers/generic.rb +25 -0
- data/app/models/boar/handlers/hosts.rb +28 -0
- data/app/models/boar/handlers/locale.rb +25 -0
- data/app/models/boar/handlers/path_mapper.rb +15 -0
- data/app/models/boar/handlers/root.rb +25 -0
- data/app/models/boar/handlers/views.rb +25 -0
- data/app/models/boar/services/downloads.rb +118 -0
- data/app/models/boar/services/generic.rb +78 -0
- data/app/models/boar/services/pages.rb +62 -0
- data/app/models/boar/utils/basic.rb +27 -0
- data/boar.gemspec +41 -0
- data/lib/boar.rb +31 -0
- data/lib/boar/configuration.rb +77 -0
- data/lib/boar/engine.rb +16 -0
- data/lib/boar/exceptions.rb +46 -0
- data/lib/boar/providers/base.rb +28 -0
- data/lib/boar/providers/box_net.rb +27 -0
- data/lib/boar/providers/dropbox.rb +26 -0
- data/lib/boar/providers/google_drive.rb +87 -0
- data/lib/boar/providers/sky_drive.rb +80 -0
- data/lib/boar/router.rb +68 -0
- data/lib/boar/version.rb +25 -0
- data/lib/tasks/boar.rake +102 -0
- data/spec/boar/controllers/application_controller_spec.rb +11 -0
- data/spec/boar/controllers/pages_controller_spec.rb +11 -0
- data/spec/boar/routes_spec.rb +11 -0
- data/spec/boar_spec.rb +7 -0
- data/spec/coverage_helper.rb +17 -0
- data/spec/spec_helper.rb +15 -0
- metadata +264 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 759e561d17ff3e059f0e8f8168de927341984d3dfa4020b403486b17060bc798
|
4
|
+
data.tar.gz: bb5914f410422e6b258634c7399f775061608d09e5503736a1b7cfafbcf336cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d5f27c144af8fec2209df0506c8244c3c70d55e221b0955d4a652b8906252df8035882f3f4c3fdbd0c191a3323246ef7f7a445032033db306528e32445dfe59d
|
7
|
+
data.tar.gz: 9ff81b0da89b289602f0ea589ce4a862de2c09bce1e603ceb1d70ee2d8e46d6d749a8426bc13fbcaae44b56d41a1ab38f2e1dfc2e371df2b72ecd42253a1fe26
|
data/.gitignore
ADDED
data/.travis-gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
source "http://rubygems.org"
|
8
|
+
|
9
|
+
gemspec
|
10
|
+
|
11
|
+
# Testing
|
12
|
+
gem "rspec", "~> 2.12.0"
|
13
|
+
gem "rake", "~> 10.0.3"
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-m markdown
|
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
source "http://rubygems.org"
|
8
|
+
|
9
|
+
gemspec
|
10
|
+
|
11
|
+
# Testing
|
12
|
+
gem "rspec", "~> 2.13.0"
|
13
|
+
gem "rake", "~> 10.0.3"
|
14
|
+
|
15
|
+
# Documentation
|
16
|
+
gem "simplecov", ">= 0.7.1"
|
17
|
+
gem "pry", ">= 0"
|
18
|
+
gem "yard", ">= 0.8.5"
|
19
|
+
gem "kramdown", ">= 1.0.1"
|
20
|
+
gem "github-markup", ">= 0.7.5"
|
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# boar
|
2
|
+
|
3
|
+
## END OF DEVELOPMENT NOTICE - This gem has been discontinued
|
4
|
+
|
5
|
+
## Contributing to boar
|
6
|
+
|
7
|
+
- Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
+
- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
+
- Fork the project.
|
10
|
+
- Start a feature/bugfix branch.
|
11
|
+
- Commit and push until you are happy with your contribution.
|
12
|
+
- Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
- Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
## Copyright
|
16
|
+
|
17
|
+
Copyright (C) 2013 and above Shogun (shogun_panda@me.com).
|
18
|
+
|
19
|
+
Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
require "bundler/gem_tasks"
|
8
|
+
require "rspec/core/rake_task"
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new("spec")
|
11
|
+
RSpec::Core::RakeTask.new("spec:coverage") { |t| t.ruby_opts = "-r./spec/coverage_helper" }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
class ApplicationController < ActionController::Base
|
9
|
+
attr_reader :boar_options
|
10
|
+
before_filter :setup_boar_options
|
11
|
+
|
12
|
+
def setup_boar_options
|
13
|
+
@boar_options ||= params.delete(:boar_options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
class DownloadsController < ApplicationController
|
9
|
+
def main
|
10
|
+
Boar::Services::Downloads.new(self).run(:downloads)
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
Boar::Services::Downloads.new(self).run(:update)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
class PagesController < ApplicationController
|
9
|
+
def main
|
10
|
+
Boar::Services::Pages.new(self).run(:main)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
module Handlers
|
9
|
+
class Authentication < Boar::Handlers::Generic
|
10
|
+
def call(*args)
|
11
|
+
# Get path
|
12
|
+
path = args[0]
|
13
|
+
|
14
|
+
if self.required_for?(path) then
|
15
|
+
self.authenticating_for?(path) ? self.authenticate_for(path) : self.request_authentication_for(path)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def required_for?(_ = nil)
|
20
|
+
false # By default we don't require authentication
|
21
|
+
end
|
22
|
+
|
23
|
+
def authenticating_for?(_ = nil)
|
24
|
+
false # By default we're not authentication
|
25
|
+
end
|
26
|
+
|
27
|
+
def request_authentication_for(_ = nil)
|
28
|
+
# Render the view for authentication
|
29
|
+
@service.controller.render(@service.handler_for(:views).call(:authentication))
|
30
|
+
end
|
31
|
+
|
32
|
+
def authenticate_for(_ = nil)
|
33
|
+
# By default we are authenticating
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
module Handlers
|
9
|
+
module Downloads
|
10
|
+
class Base < Boar::Handlers::Generic
|
11
|
+
attr_reader :options, :provider_options
|
12
|
+
|
13
|
+
def initialize(service, options)
|
14
|
+
super(service)
|
15
|
+
|
16
|
+
@options = ensure_hash(options)
|
17
|
+
|
18
|
+
# Get the configuration for the provider
|
19
|
+
@provider_options = ensure_hash(@options[:providers]).fetch(self.class_key, {}).deep_symbolize_keys
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO: Create something Elephas.use for the remote implementations
|
23
|
+
def call(_, _, _, _)
|
24
|
+
raise Boar::Exceptions::UnImplemented.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def class_key
|
28
|
+
self.class.name.demodulize.underscore
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_credentials
|
32
|
+
self.credentials_params[:single]
|
33
|
+
end
|
34
|
+
|
35
|
+
def credentials_params
|
36
|
+
host = @service.handler_for(:hosts).call(@service.controller.request)
|
37
|
+
path = self.interpolate(@configuration.credentials_file, {root: Rails.root, request: @service.controller.request, controller: @service.controller})
|
38
|
+
all = YAML.load_file(path)
|
39
|
+
name = self.class_key
|
40
|
+
|
41
|
+
{single: HashWithIndifferentAccess.new(all.fetch(host).fetch(name)), path: path, all: all, host: host, provider: self, name: name }
|
42
|
+
end
|
43
|
+
|
44
|
+
def update_credentials(credentials, params = nil)
|
45
|
+
params ||= self.credentials_params
|
46
|
+
params[:all][params[:host]][params[:name]] = params[:single].merge(credentials).to_hash
|
47
|
+
open(params[:path], "w") {|f| f.write(params[:all].to_yaml) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def finalize_path(path, match_data)
|
51
|
+
path.gsub(/\\(\d+)/) { |m| match_data[$1.to_i] }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
module Handlers
|
9
|
+
module Downloads
|
10
|
+
class BoxNet < Base
|
11
|
+
def initialize(service, options)
|
12
|
+
super(service, options)
|
13
|
+
configuration = self.load_credentials
|
14
|
+
|
15
|
+
# Open the session and refresh the token
|
16
|
+
@session = RubyBox::Session.new({client_id: configuration[:client_id], client_secret: configuration[:client_secret], access_token: configuration[:access_token]})
|
17
|
+
token = @session.refresh_token(configuration[:refresh_token])
|
18
|
+
|
19
|
+
# Save the token and schedule an update to avoid expiration
|
20
|
+
self.update_credentials({access_token: token.token, refresh_token: token.refresh_token})
|
21
|
+
# TODO: Reschedule token refreshing after 13 days
|
22
|
+
|
23
|
+
@client = RubyBox::Client.new(@session)
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(path, entry, skip_cache, _, _)
|
27
|
+
# Read the URL from Redis
|
28
|
+
key = @configuration.backend_key("downloads:box_net[#{path}]", self, @service.controller.request)
|
29
|
+
url = @configuration.backend.get(key)
|
30
|
+
|
31
|
+
if skip_cache || url.blank? then
|
32
|
+
begin
|
33
|
+
# Get the file
|
34
|
+
file = @client.file(entry[:path])
|
35
|
+
raise Boar::Exceptions::NotFound if file.nil?
|
36
|
+
|
37
|
+
# Create the shared link
|
38
|
+
shared_link = create_shared_link(file)
|
39
|
+
raise Boar::Exceptions::NotFound if shared_link.nil?
|
40
|
+
url = entry["disposition"] == "inline" ? shared_link["url"] : shared_link["download_url"]
|
41
|
+
|
42
|
+
# Save the URL
|
43
|
+
@configuration.backend.set(key, url) if url.present?
|
44
|
+
rescue => e
|
45
|
+
raise Boar::Exceptions::ServerError.new("[#{e.class}] #{e.message}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Redirect to the final URL
|
50
|
+
@service.controller.redirect_to(url)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def create_shared_link(file)
|
55
|
+
begin
|
56
|
+
api_uri = URI.parse("#{RubyBox::API_URL}/files/#{file.id}")
|
57
|
+
request = Net::HTTP::Put.new(api_uri.path, {"Content-Type" => 'application/json'})
|
58
|
+
request.body = JSON.dump({shared_link: {access: "open"}})
|
59
|
+
@session.request(api_uri, request).fetch("shared_link")
|
60
|
+
rescue
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
module Handlers
|
9
|
+
module Downloads
|
10
|
+
class Dropbox < Base
|
11
|
+
def initialize(service, options)
|
12
|
+
super(service, options)
|
13
|
+
|
14
|
+
@session = ::DropboxSession.deserialize(load_credentials[:session])
|
15
|
+
@root = @provider_options.fetch(:root, "dropbox").to_sym
|
16
|
+
@client = ::DropboxClient.new(@session, @root)
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(path, entry, skip_cache, _, _)
|
20
|
+
# Read the URL from Redis
|
21
|
+
key = @configuration.backend_key("downloads:dropbox[#{path}]", self, @service.controller.request)
|
22
|
+
url = @configuration.backend.get(key)
|
23
|
+
|
24
|
+
if skip_cache || url.blank? then
|
25
|
+
begin
|
26
|
+
attachment = entry[:disposition] != "inline"
|
27
|
+
share = attachment ? self.direct_shares(entry[:path]) : @client.shares(entry[:path])
|
28
|
+
|
29
|
+
url = share["url"] + (attachment ? "?dl=1" : "")
|
30
|
+
expire = DateTime.parse(share["expires"], "%a, %d %b %Y %T %Z")
|
31
|
+
|
32
|
+
# Save the URL
|
33
|
+
if url.present? then
|
34
|
+
@configuration.backend.set(key, url)
|
35
|
+
@configuration.backend.expire(key, expire.to_i)
|
36
|
+
end
|
37
|
+
rescue => e
|
38
|
+
if e.message =~ /Path .+ not found/ then
|
39
|
+
raise Boar::Exceptions::NotFound.new(path)
|
40
|
+
else
|
41
|
+
raise e
|
42
|
+
raise Boar::Exceptions::ServerError.new("[#{e.class}] #{e.message}")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Redirect to the final URL
|
48
|
+
@service.controller.redirect_to(url)
|
49
|
+
end
|
50
|
+
|
51
|
+
def direct_shares(path)
|
52
|
+
# Get the public URL - We don't use Dropbox shares method directly because we have to pass a parameter
|
53
|
+
response = @session.do_get@client.build_url("/shares/#{@root}#{@client.format_path(path)}?short_url=false")
|
54
|
+
@client.parse_response(response)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
module Handlers
|
9
|
+
module Downloads
|
10
|
+
class GoogleDrive < Base
|
11
|
+
def initialize(service, options)
|
12
|
+
super(service, options)
|
13
|
+
configuration = self.load_credentials
|
14
|
+
@client = Boar::Providers::GoogleDrive.authorized_client(configuration)
|
15
|
+
@api = @client.discovered_api('drive', 'v2')
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(path, entry, skip_cache, _, _)
|
19
|
+
# Read the URL from Redis
|
20
|
+
key = @configuration.backend_key("downloads:google_drive[#{path}]", self, @service.controller.request)
|
21
|
+
url = @configuration.backend.get(key)
|
22
|
+
|
23
|
+
if skip_cache || url.blank? then
|
24
|
+
begin
|
25
|
+
# Get the file
|
26
|
+
result = @client.execute(api_method: @api.files.get, parameters: {"fileId" => entry[:id]})
|
27
|
+
raise Boar::Exceptions::NotFound if result.status == 404
|
28
|
+
|
29
|
+
# Get the share link
|
30
|
+
file = result.data
|
31
|
+
url = file.web_content_link || file.alternate_link
|
32
|
+
url = file.alternate_link if entry["disposition"] == "inline"
|
33
|
+
raise Boar::Exceptions::NotFound if url.blank?
|
34
|
+
|
35
|
+
# Save the URL
|
36
|
+
@configuration.backend.set(key, url) if url.present?
|
37
|
+
rescue => e
|
38
|
+
raise Boar::Exceptions::ServerError.new("[#{e.class}] #{e.message}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Redirect to the final URL
|
43
|
+
@service.controller.redirect_to(url)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the boar gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Boar
|
8
|
+
module Handlers
|
9
|
+
module Downloads
|
10
|
+
class Local < Base
|
11
|
+
def initialize(service, options)
|
12
|
+
super(service, options)
|
13
|
+
|
14
|
+
# Normalize the root
|
15
|
+
@root = self.get_option(options, :directory, Rails.application.config.boar.downloads_directory)
|
16
|
+
@root = self.interpolate(@root, {root: Rails.root, request: @service.controller.request, controller: @controller})
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(path, entry, _, _, _)
|
20
|
+
# Get the full path
|
21
|
+
file = Pathname.new(@root) + path
|
22
|
+
raise Boar::Exceptions::NotFound.new(path) if !file.exist?
|
23
|
+
|
24
|
+
# Check MIME and whether the disposition is inline or not
|
25
|
+
type = MIME::Types.type_for(file.to_s).first.content_type
|
26
|
+
disposition = (entry[:disposition].ensure_string == "inline") ? "inline" : "attachment"
|
27
|
+
|
28
|
+
# Serve the file
|
29
|
+
@service.download_file(file, disposition: disposition, type: type)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|