coalescing_panda 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Rakefile +28 -0
  2. data/app/assets/javascripts/coalescing_panda/application.js +15 -0
  3. data/app/assets/javascripts/coalescing_panda/coalescing_panda/oauth2.js +2 -0
  4. data/app/assets/javascripts/coalescing_panda/oauth2.js.coffee +8 -0
  5. data/app/assets/stylesheets/coalescing_panda/application.css +13 -0
  6. data/app/assets/stylesheets/coalescing_panda/coalescing_panda/oauth2.css +4 -0
  7. data/app/assets/stylesheets/coalescing_panda/oauth2.css +4 -0
  8. data/app/controllers/coalescing_panda/application_controller.rb +4 -0
  9. data/app/controllers/coalescing_panda/lti_controller.rb +32 -0
  10. data/app/controllers/coalescing_panda/oauth2_controller.rb +34 -0
  11. data/app/models/coalescing_panda/canvas_api_auth.rb +6 -0
  12. data/app/models/coalescing_panda/lti_account.rb +23 -0
  13. data/app/models/coalescing_panda/lti_nonce.rb +12 -0
  14. data/app/views/coalescing_panda/oauth2/oauth2.html.haml +10 -0
  15. data/app/views/coalescing_panda/oauth2/redirect.html.haml +5 -0
  16. data/app/views/layouts/coalescing_panda/application.html.erb +14 -0
  17. data/config/routes.rb +4 -0
  18. data/db/migrate/20131114150001_create_coalescing_panda_canvas_api_auths.rb +10 -0
  19. data/db/migrate/20131118211442_create_coalescing_panda_lti_accounts.rb +14 -0
  20. data/db/migrate/20131119165343_create_coalescing_panda_lti_nonces.rb +9 -0
  21. data/lib/coalescing_panda/controller_helpers.rb +61 -0
  22. data/lib/coalescing_panda/engine.rb +17 -0
  23. data/lib/coalescing_panda/route_helpers.rb +28 -0
  24. data/lib/coalescing_panda/version.rb +3 -0
  25. data/lib/coalescing_panda.rb +31 -0
  26. data/lib/tasks/coalescing_panda_tasks.rake +4 -0
  27. data/spec/controllers/coalescing_panda/lti_controller_spec.rb +42 -0
  28. data/spec/controllers/coalescing_panda/oauth2_controller_spec.rb +22 -0
  29. data/spec/dummy/README.rdoc +28 -0
  30. data/spec/dummy/Rakefile +6 -0
  31. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  32. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  34. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  35. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  36. data/spec/dummy/bin/bundle +3 -0
  37. data/spec/dummy/bin/rails +4 -0
  38. data/spec/dummy/bin/rake +4 -0
  39. data/spec/dummy/config/application.rb +23 -0
  40. data/spec/dummy/config/boot.rb +5 -0
  41. data/spec/dummy/config/database.yml +25 -0
  42. data/spec/dummy/config/environment.rb +5 -0
  43. data/spec/dummy/config/environments/development.rb +29 -0
  44. data/spec/dummy/config/environments/production.rb +80 -0
  45. data/spec/dummy/config/environments/test.rb +36 -0
  46. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  47. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  48. data/spec/dummy/config/initializers/inflections.rb +16 -0
  49. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  50. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  51. data/spec/dummy/config/initializers/session_store.rb +3 -0
  52. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/spec/dummy/config/locales/en.yml +23 -0
  54. data/spec/dummy/config/routes.rb +5 -0
  55. data/spec/dummy/config.ru +4 -0
  56. data/spec/dummy/db/development.sqlite3 +0 -0
  57. data/spec/dummy/db/schema.rb +24 -0
  58. data/spec/dummy/db/test.sqlite3 +0 -0
  59. data/spec/dummy/log/development.log +9 -0
  60. data/spec/dummy/log/test.log +2084 -0
  61. data/spec/dummy/public/404.html +58 -0
  62. data/spec/dummy/public/422.html +58 -0
  63. data/spec/dummy/public/500.html +57 -0
  64. data/spec/dummy/public/favicon.ico +0 -0
  65. data/spec/models/coalescing_panda/canvas_api_auth_spec.rb +11 -0
  66. data/spec/spec_helper.rb +50 -0
  67. metadata +312 -0
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'CoalescingPanda'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rspec/core/rake_task'
25
+
26
+ RSpec::Core::RakeTask.new(:spec)
27
+
28
+ task :default => :spec
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,8 @@
1
+ $ ->
2
+ canvasAuth = (url) ->
3
+ newwindow = window.open(url, "name", "width=700,height=500")
4
+ newwindow.focus() if window.focus
5
+ false
6
+
7
+ $('#oauth_btn').bind 'click', (event) ->
8
+ canvasAuth($("input[name='canvas_oauth_url']").val())
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ module CoalescingPanda
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,32 @@
1
+ require_dependency "coalescing_panda/application_controller"
2
+
3
+ module CoalescingPanda
4
+ class LtiController < ApplicationController
5
+
6
+ def lti_config
7
+ lti_options = CoalescingPanda.lti_options
8
+ lti_nav = CoalescingPanda.lti_paths
9
+ platform = 'canvas.instructure.com'
10
+ host = "#{request.scheme}://#{request.host_with_port}"
11
+ tc = IMS::LTI::ToolConfig.new(:title => lti_options[:title], :launch_url => (lti_options[:launch_url])|| 'ABC')
12
+ tc.set_ext_param(platform, :domain, request.host)
13
+ tc.set_ext_param(platform, :privacy_level, 'public')
14
+ lti_nav.each do |k, v|
15
+ tc.set_ext_param(platform, "#{k.to_s}_navigation".to_sym, ext_params(v) )
16
+ end
17
+
18
+ #strip the launch url
19
+ xml = tc.to_xml.sub( /<blti:launch_url>.*<\/blti:launch_url>/, '') if lti_options[:launch_url].blank?
20
+ render :xml => xml
21
+ end
22
+
23
+ private
24
+
25
+ def ext_params(options)
26
+ url = options.delete(:url)
27
+ options[:url] = main_app.send(url+'_url')
28
+ options
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ require_dependency "coalescing_panda/application_controller"
2
+
3
+ module CoalescingPanda
4
+ class Oauth2Controller < ApplicationController
5
+
6
+ def oauth2
7
+ end
8
+
9
+ def redirect
10
+ unless params[:error]
11
+ lti_account = LtiAccount.find_by_key(params[:key])
12
+ client_id = lti_account.oauth2_client_id
13
+ client_key = lti_account.oauth2_client_key
14
+ user_id = params[:user_id]
15
+ api_domain = params[:api_domain]
16
+ client = Bearcat::Client.new(prefix: oauth2_protocol+'://'+api_domain)
17
+ token = client.retrieve_token(client_id, coalescing_panda.oauth2_redirect_url, client_key, params['code'])
18
+ CanvasApiAuth.where('user_id = ? and api_domain = ?', user_id, api_domain).first_or_create do |auth|
19
+ auth.api_token = token
20
+ auth.user_id = user_id
21
+ auth.api_domain = api_domain
22
+ end
23
+ end
24
+ end
25
+
26
+
27
+ private
28
+
29
+ def oauth2_protocol
30
+ ENV['OAUTH_PROTOCOL'] || 'https'
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ module CoalescingPanda
2
+ class CanvasApiAuth < ActiveRecord::Base
3
+ validates :user_id, :api_domain, presence: true
4
+ validates :user_id, uniqueness: {scope: :api_domain}
5
+ end
6
+ end
@@ -0,0 +1,23 @@
1
+ module CoalescingPanda
2
+ class LtiAccount < ActiveRecord::Base
3
+ validates :name, :key, uniqueness: true
4
+ validates :name, :key, :secret, presence: true
5
+ has_many :coalescing_panda_lti_nonces,
6
+ :foreign_key => :coalescing_panda_lti_account_id,
7
+ :class_name => 'CoalescingPanda::LtiNonce'
8
+
9
+ def validate_nonce(nonce, timestamp)
10
+ cleanup_nonce
11
+ if timestamp > 15.minutes.ago
12
+ coalescing_panda_lti_nonces.create(nonce:nonce, timestamp:timestamp).persisted?
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def cleanup_nonce
19
+ coalescing_panda_lti_nonces.where('timestamp > ?', 15.minutes.ago).delete_all
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module CoalescingPanda
2
+ class LtiNonce < ActiveRecord::Base
3
+ validates :coalescing_panda_lti_account, :nonce, :timestamp, :presence => true
4
+ validates :nonce, uniqueness: {scope: :coalescing_panda_lti_account}
5
+ belongs_to :coalescing_panda_lti_account, :class_name => 'CoalescingPanda::LtiAccount'
6
+ end
7
+
8
+ def cleanup
9
+ CoalescingPanda::LtiNonce.where("coalescing_panda_lti_account_id = ? AND timestamp < ?", b.coalescing_panda_lti_account.id, 15.minutes.ago )
10
+ end
11
+
12
+ end
@@ -0,0 +1,10 @@
1
+ %input{type: 'hidden', value: "#{@canvas_url}", name: :canvas_oauth_url}
2
+ %form.oauth2
3
+ %h2 Canvas Authentication Required
4
+ %button.btn-canvas#oauth_btn Authenticate
5
+
6
+ %form{id: 'lti_form', action: "#{request.original_url}", method: 'post'}
7
+ - @lti_params.each do |k,v|
8
+ %input{:type =>"hidden", :value=>"#{v}", :name=>"#{k}"}
9
+
10
+ = javascript_include_tag "coalescing_panda/oauth2"
@@ -0,0 +1,5 @@
1
+ :javascript
2
+ $(document).ready( function() {
3
+ window.opener.document.forms["lti_form"].submit();
4
+ window.close();
5
+ } );
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>CoalescingPanda</title>
5
+ <%= stylesheet_link_tag "coalescing_panda/application", media: "all" %>
6
+ <%= javascript_include_tag "coalescing_panda/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ CoalescingPanda::Engine.routes.draw do
2
+ get '/oauth2/redirect' => 'oauth2#redirect'
3
+ get '/config' => 'lti#lti_config'
4
+ end
@@ -0,0 +1,10 @@
1
+ class CreateCoalescingPandaCanvasApiAuths < ActiveRecord::Migration
2
+ def change
3
+ create_table :coalescing_panda_canvas_api_auths do |t|
4
+ t.string :user_id
5
+ t.string :api_domain
6
+ t.string :api_token
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ class CreateCoalescingPandaLtiAccounts < ActiveRecord::Migration
2
+ def change
3
+ create_table :coalescing_panda_lti_accounts do |t|
4
+ t.string :name
5
+ t.string :key
6
+ t.string :secret
7
+ t.string :oauth2_client_id
8
+ t.string :oauth2_client_key
9
+
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ class CreateCoalescingPandaLtiNonces < ActiveRecord::Migration
2
+ def change
3
+ create_table :coalescing_panda_lti_nonces do |t|
4
+ t.belongs_to :coalescing_panda_lti_account
5
+ t.string :nonce
6
+ t.datetime :timestamp
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,61 @@
1
+ module CoalescingPanda
2
+ module ControllerHelpers
3
+
4
+ def canvas_oauth2
5
+ user_id = params['user_id']
6
+ api_domain = params['custom_canvas_api_domain']
7
+
8
+ if token = CanvasApiAuth.where('user_id = ? and api_domain = ?', user_id, api_domain).pluck(:api_token).first
9
+ @client = Bearcat::Client.new(token: token, prefix: ENV['OAUTH_PROTOCOL']+'://'+api_domain)
10
+ else
11
+ client_id = ENV['OAUTH_CLIENT_ID']
12
+ client = Bearcat::Client.new(prefix: 'http://'+api_domain)
13
+ @lti_params = params.to_hash
14
+ @canvas_url = client.auth_redirect_url(client_id,
15
+ coalescing_panda.oauth2_redirect_url({key: params['oauth_consumer_key'],
16
+ user_id: user_id, api_domain: api_domain}))
17
+ #delete the added params so the original oauth sig still works
18
+ @lti_params.delete('action')
19
+ @lti_params.delete('controller')
20
+ render 'coalescing_panda/oauth2/oauth2'
21
+ end
22
+ end
23
+
24
+ def lti_authorize!(*roles)
25
+ authorized = false
26
+ if @lti_account = params['oauth_consumer_key'] && LtiAccount.find_by_key(params['oauth_consumer_key'])
27
+ @tp = IMS::LTI::ToolProvider.new(@lti_account.key, @lti_account.secret, params)
28
+ authorized = @tp.valid_request?(request)
29
+ end
30
+ authorized = authorized && (roles == 0 || (roles && lti_roles).count > 1)
31
+ authorized = authorized && @lti_account.validate_nonce(params['oauth_nonce'], DateTime.strptime(params['oauth_timestamp'],'%s'))
32
+ if !authorized
33
+ render :text => 'Invalid Credentials, please contact your Administrator.', :status => :unauthorized
34
+ end
35
+ end
36
+
37
+ def lti_roles
38
+ @lti_roles ||= params['roles'].split(',').map { |role|
39
+ case role.downcase.strip
40
+ when 'admin'
41
+ :admin
42
+ when 'urn:lti:instrole:ims/lis/administrator'
43
+ :admin
44
+ when 'learner'
45
+ :student
46
+ when 'instructor'
47
+ :teacher
48
+ when 'urn:lti:role:ims/lis/teachingassistant'
49
+ :ta
50
+ when 'contentdeveloper'
51
+ :designer
52
+ when 'urn:lti:instrole:ims/lis/observer'
53
+ :observer
54
+ else
55
+ :none
56
+ end
57
+ }.uniq
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ module CoalescingPanda
2
+ class Engine < ::Rails::Engine
3
+ config.autoload_paths += Dir["#{config.root}/lib/**/"]
4
+ isolate_namespace CoalescingPanda
5
+
6
+ initializer 'coalescing_panda.app_controller' do |app|
7
+ OAUTH_10_SUPPORT = true
8
+ ActiveSupport.on_load(:action_controller) do
9
+ include CoalescingPanda::ControllerHelpers
10
+ end
11
+ end
12
+
13
+ initializer 'cloaescing_panda.route_helper' do |route|
14
+ ActionDispatch::Routing::Mapper.send :include, CoalescingPanda::RouteHelpers
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ module CoalescingPanda
2
+ module RouteHelpers
3
+ def lti_nav(nav, *rest, &block)
4
+ base_path = Rails.application.routes.named_routes[:coalescing_panda].path.spec
5
+ raise LtiNavigationInUse.new('CoalescingPanda must be mounted before defining lti_nav routes') if base_path.blank?
6
+ valid_options = [:course, :user, :account, :editor, :external_tool]
7
+ if rest.empty? && nav.is_a?(Hash)
8
+ options = nav
9
+ nav, to = options.find {|name, _value| valid_options.include? name}
10
+ options[:to] = to
11
+ options.delete(nav)
12
+ else
13
+ options = rest.pop || {}
14
+ end
15
+ lti_options = options.delete(:lti_options) || {}
16
+ path = "#{base_path}/#{nav.to_s}"
17
+ lti_options[:url] = path.split('/').reject(&:empty?).join('_')
18
+ CoalescingPanda::lti_navigation(nav, lti_options)
19
+ post path, options, &block
20
+ end
21
+
22
+ def lti_mount(app, options = nil)
23
+ CoalescingPanda.lti_options = options && options.delete(:lti_options)
24
+ mount(app, options)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module CoalescingPanda
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,31 @@
1
+ require "coalescing_panda/engine" if defined?(Rails)
2
+ require 'ims/lti'
3
+ require 'bearcat'
4
+ require 'oauth/request_proxy/rack_request'
5
+
6
+ module CoalescingPanda
7
+ class LtiNavigationInUse < StandardError;end
8
+ class NotMounted < StandardError;end
9
+
10
+ @@lti_navigation = {}
11
+ @@lti_options
12
+
13
+ def self.lti_options= lti_options
14
+ @@lti_options = lti_options
15
+ end
16
+
17
+ def self.lti_options
18
+ @@lti_options.deep_dup
19
+ end
20
+
21
+ def self.lti_navigation(navigation, options)
22
+ raise LtiNavigationInUse.new("#{navigation} can only be defined once") if @@lti_navigation.has_key?(navigation)
23
+ @@lti_navigation[navigation] = options
24
+ end
25
+
26
+ def self.lti_paths
27
+ @@lti_navigation.deep_dup
28
+ end
29
+
30
+ end
31
+
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :coalescing_panda do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe CoalescingPanda::LtiController do
4
+ routes { CoalescingPanda::Engine.routes }
5
+
6
+ describe '#lti_config' do
7
+
8
+ it 'generates lti xml config'do
9
+ controller.main_app.stub(:test_action_url) {'foo'}
10
+ get(:lti_config)
11
+ xml = Nokogiri::XML(response.body)
12
+ xml.at_xpath('//blti:title').text.should == 'LTI Tool'
13
+ xml.at_xpath('//lticm:property[@name="domain"]').text.should_not == nil
14
+ xml.at_xpath('//lticm:property[@name="privacy_level"]').text.should == 'public'
15
+ end
16
+
17
+ it 'generates lti nav config' do
18
+ controller.main_app.stub(:test_action_url) {'foo'}
19
+ CoalescingPanda.lti_navigation(:account, {
20
+ url: 'test_action',
21
+ text: 'My Title',
22
+ enabled: false
23
+ })
24
+ get(:lti_config)
25
+ xml = Nokogiri::XML(response.body)
26
+ account_nav = xml.at_xpath('//lticm:options[@name="account_navigation"]')
27
+ account_nav.at_xpath('lticm:property[@name="enabled"]').text.should == 'false'
28
+ account_nav.at_xpath('lticm:property[@name="text"]').text.should == 'My Title'
29
+ account_nav.at_xpath('lticm:property[@name="url"]').text.should == 'foo'
30
+ end
31
+
32
+ end
33
+
34
+
35
+ it 'get the url, from the action string' do
36
+ controller.main_app.stub(:test_action_url) {'foo'}
37
+ options = controller.send(:ext_params, {url:'test_action'})
38
+ options[:url].should == 'foo'
39
+ end
40
+
41
+
42
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe CoalescingPanda::Oauth2Controller do
4
+ routes { CoalescingPanda::Engine.routes }
5
+
6
+ describe "#redirect" do
7
+ it 'creates a token in the db' do
8
+ ENV['OAUTH_PROTOCOL'] = 'http'
9
+ Bearcat::Client.any_instance.stub(retrieve_token: 'foobar')
10
+ get :redirect, {user_id: 1, api_domain:'foo.com', code:'bar'}
11
+ auth = CoalescingPanda::CanvasApiAuth.find_by_user_id_and_api_domain(1, 'foo.com')
12
+ auth.should_not == nil
13
+ end
14
+
15
+ it "doesn't create a token in the db" do
16
+ get :redirect, {error: 'your face'}
17
+ CoalescingPanda::CanvasApiAuth.all.count.should == 0
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Dummy::Application.load_tasks
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
6
+ <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ Bundler.require(*Rails.groups)
6
+ require "coalescing_panda"
7
+
8
+ module Dummy
9
+ class Application < Rails::Application
10
+ # Settings in config/environments/* take precedence over those specified here.
11
+ # Application configuration should go into files in config/initializers
12
+ # -- all .rb files in that directory are automatically loaded.
13
+
14
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
15
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
16
+ # config.time_zone = 'Central Time (US & Canada)'
17
+
18
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
19
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
20
+ # config.i18n.default_locale = :de
21
+ end
22
+ end
23
+
@@ -0,0 +1,5 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)