boar 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis-gemfile +13 -0
  4. data/.travis.yml +10 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +20 -0
  7. data/README.md +19 -0
  8. data/Rakefile +11 -0
  9. data/app/controllers/boar/application_controller.rb +16 -0
  10. data/app/controllers/boar/downloads_controller.rb +17 -0
  11. data/app/controllers/boar/pages_controller.rb +13 -0
  12. data/app/models/boar/handlers/authentication.rb +38 -0
  13. data/app/models/boar/handlers/downloads/base.rb +56 -0
  14. data/app/models/boar/handlers/downloads/box_net.rb +67 -0
  15. data/app/models/boar/handlers/downloads/dropbox.rb +59 -0
  16. data/app/models/boar/handlers/downloads/google_drive.rb +48 -0
  17. data/app/models/boar/handlers/downloads/local.rb +34 -0
  18. data/app/models/boar/handlers/downloads/remote.rb +24 -0
  19. data/app/models/boar/handlers/downloads/s3.rb +54 -0
  20. data/app/models/boar/handlers/downloads/sky_drive.rb +45 -0
  21. data/app/models/boar/handlers/generic.rb +25 -0
  22. data/app/models/boar/handlers/hosts.rb +28 -0
  23. data/app/models/boar/handlers/locale.rb +25 -0
  24. data/app/models/boar/handlers/path_mapper.rb +15 -0
  25. data/app/models/boar/handlers/root.rb +25 -0
  26. data/app/models/boar/handlers/views.rb +25 -0
  27. data/app/models/boar/services/downloads.rb +118 -0
  28. data/app/models/boar/services/generic.rb +78 -0
  29. data/app/models/boar/services/pages.rb +62 -0
  30. data/app/models/boar/utils/basic.rb +27 -0
  31. data/boar.gemspec +41 -0
  32. data/lib/boar.rb +31 -0
  33. data/lib/boar/configuration.rb +77 -0
  34. data/lib/boar/engine.rb +16 -0
  35. data/lib/boar/exceptions.rb +46 -0
  36. data/lib/boar/providers/base.rb +28 -0
  37. data/lib/boar/providers/box_net.rb +27 -0
  38. data/lib/boar/providers/dropbox.rb +26 -0
  39. data/lib/boar/providers/google_drive.rb +87 -0
  40. data/lib/boar/providers/sky_drive.rb +80 -0
  41. data/lib/boar/router.rb +68 -0
  42. data/lib/boar/version.rb +25 -0
  43. data/lib/tasks/boar.rake +102 -0
  44. data/spec/boar/controllers/application_controller_spec.rb +11 -0
  45. data/spec/boar/controllers/pages_controller_spec.rb +11 -0
  46. data/spec/boar/routes_spec.rb +11 -0
  47. data/spec/boar_spec.rb +7 -0
  48. data/spec/coverage_helper.rb +17 -0
  49. data/spec/spec_helper.rb +15 -0
  50. metadata +264 -0
@@ -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
@@ -0,0 +1,7 @@
1
+ Gemfile.lock
2
+ tester.rb
3
+ coverage/
4
+ pkg/
5
+ .idea/
6
+ .yardoc/
7
+ tester/
@@ -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"
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - jruby-19mode
6
+ - rbx-19mode
7
+ script: bundle exec rake spec
8
+ gemfile: .travis-gemfile
9
+ notifications:
10
+ email: false
@@ -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"
@@ -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.
@@ -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