fine_print 0.1.1 → 1.0.0

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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +74 -45
  3. data/Rakefile +9 -9
  4. data/app/assets/javascripts/application.js~ +16 -0
  5. data/app/assets/javascripts/fine_print/application.js +8 -2
  6. data/app/controllers/fine_print/application_controller.rb +9 -7
  7. data/app/controllers/fine_print/application_controller.rb~ +9 -7
  8. data/app/controllers/fine_print/contracts_controller.rb +79 -0
  9. data/app/controllers/fine_print/contracts_controller.rb~ +79 -0
  10. data/app/controllers/fine_print/home_controller.rb +1 -11
  11. data/app/controllers/fine_print/home_controller.rb~ +2 -11
  12. data/app/controllers/fine_print/signatures_controller.rb +14 -0
  13. data/app/controllers/fine_print/signatures_controller.rb~ +14 -0
  14. data/app/helpers/fine_print/application_helper.rb +7 -0
  15. data/app/helpers/fine_print/application_helper.rb~ +7 -0
  16. data/app/helpers/fine_print/contracts_helper.rb~ +7 -0
  17. data/app/models/fine_print/contract.rb +96 -0
  18. data/app/models/fine_print/contract.rb~ +100 -0
  19. data/app/models/fine_print/signature.rb +25 -0
  20. data/app/models/fine_print/signature.rb~ +25 -0
  21. data/app/views/fine_print/contracts/_form.html.erb +35 -0
  22. data/app/views/fine_print/contracts/_form.html.erb~ +35 -0
  23. data/app/views/fine_print/contracts/edit.html.erb +10 -0
  24. data/app/views/fine_print/contracts/index.html.erb +43 -0
  25. data/app/views/fine_print/contracts/index.html.erb~ +43 -0
  26. data/app/views/fine_print/contracts/new.html.erb +9 -0
  27. data/app/views/fine_print/contracts/new_version.html.erb +9 -0
  28. data/app/views/fine_print/contracts/show.html.erb +33 -0
  29. data/app/views/fine_print/contracts/show.html.erb~ +35 -0
  30. data/app/views/fine_print/home/index.html.erb +15 -6
  31. data/app/views/fine_print/home/index.html.erb~ +12 -4
  32. data/app/views/fine_print/signatures/index.html.erb +36 -0
  33. data/app/views/fine_print/signatures/index.html.erb~ +32 -0
  34. data/app/views/layouts/fine_print/application.html.erb +6 -0
  35. data/app/views/layouts/fine_print/application.html.erb~ +20 -0
  36. data/config/initializers/fine_print.rb +27 -44
  37. data/config/initializers/fine_print.rb~ +23 -40
  38. data/config/routes.rb +9 -3
  39. data/config/routes.rb~ +9 -4
  40. data/db/migrate/0_install_fine_print.rb +26 -0
  41. data/db/migrate/0_install_fine_print.rb~ +26 -0
  42. data/lib/fine_print/controller_additions.rb +69 -0
  43. data/lib/fine_print/controller_additions.rb~ +69 -0
  44. data/lib/fine_print/engine.rb +8 -0
  45. data/lib/fine_print/security_transgression.rb +1 -2
  46. data/lib/fine_print/utilities.rb~ +26 -0
  47. data/lib/fine_print/version.rb +1 -1
  48. data/lib/fine_print.rb +89 -42
  49. data/lib/fine_print.rb~ +89 -41
  50. data/lib/tasks/fine_print_tasks.rake +11 -8
  51. data/spec/controllers/contracts_controller_spec.rb +222 -0
  52. data/spec/controllers/contracts_controller_spec.rb~ +224 -0
  53. data/spec/controllers/home_controller_spec.rb +25 -0
  54. data/spec/controllers/home_controller_spec.rb~ +25 -0
  55. data/spec/controllers/signatures_controller_spec.rb +46 -0
  56. data/spec/controllers/signatures_controller_spec.rb~ +46 -0
  57. data/spec/dummy/README.md +1 -1
  58. data/spec/dummy/app/controllers/dummy_models_controller.rb +2 -0
  59. data/spec/dummy/app/controllers/dummy_models_controller.rb~ +29 -0
  60. data/spec/dummy/app/helpers/application_helper.rb +13 -0
  61. data/spec/dummy/app/models/dummy_user.rb +3 -0
  62. data/spec/dummy/app/models/dummy_user.rb~ +4 -0
  63. data/spec/dummy/app/models/user.rb~ +78 -0
  64. data/spec/dummy/config/application.rb +2 -2
  65. data/spec/dummy/config/application.rb~ +60 -0
  66. data/spec/dummy/config/initializers/fine_print.rb +36 -0
  67. data/spec/dummy/config/initializers/fine_print.rb~ +36 -0
  68. data/spec/dummy/config/initializers/session_store.rb +1 -1
  69. data/spec/dummy/config/initializers/session_store.rb~ +8 -0
  70. data/spec/dummy/config/initializers/wrap_parameters.rb +1 -1
  71. data/spec/dummy/config/initializers/wrap_parameters.rb~ +14 -0
  72. data/spec/dummy/config/routes.rb +1 -2
  73. data/spec/dummy/config/routes.rb~ +4 -0
  74. data/spec/dummy/db/development.sqlite3 +0 -0
  75. data/spec/dummy/db/migrate/1_create_dummy_users.rb +9 -0
  76. data/spec/dummy/db/migrate/1_create_dummy_users.rb~ +8 -0
  77. data/spec/dummy/db/schema.rb +20 -12
  78. data/spec/dummy/db/test.sqlite3 +0 -0
  79. data/spec/dummy/log/development.log +1635 -0
  80. data/spec/dummy/log/test.log +46188 -0
  81. data/spec/factories/contract.rb +25 -0
  82. data/spec/factories/contract.rb~ +26 -0
  83. data/spec/factories/dummy_user.rb +4 -0
  84. data/spec/factories/dummy_user.rb~ +6 -0
  85. data/spec/factories/signature.rb +6 -0
  86. data/spec/factories/signature.rb~ +8 -0
  87. data/spec/factories/user.rb~ +6 -0
  88. data/spec/fine_print_spec.rb~ +15 -4
  89. data/spec/lib/fine_print/controller_additions_spec.rb +20 -0
  90. data/spec/lib/fine_print/controller_additions_spec.rb~ +20 -0
  91. data/spec/lib/fine_print_spec.rb +47 -0
  92. data/spec/lib/fine_print_spec.rb~ +47 -0
  93. data/spec/models/contract_spec.rb +79 -0
  94. data/spec/models/contract_spec.rb~ +80 -0
  95. data/spec/models/signature_spec.rb +28 -0
  96. data/spec/models/signature_spec.rb~ +28 -0
  97. data/spec/spec_helper.rb +31 -0
  98. data/spec/spec_helper.rb~ +32 -0
  99. data/spec/test_helper.rb~ +15 -0
  100. metadata +153 -91
  101. data/app/assets/javascripts/fine_print/agreements.js +0 -19
  102. data/app/assets/javascripts/fine_print/agreements.js~ +0 -19
  103. data/app/assets/javascripts/fine_print/application.js~ +0 -5
  104. data/app/assets/javascripts/fine_print/dialog.js +0 -2
  105. data/app/assets/javascripts/fine_print/dialog.js~ +0 -2
  106. data/app/assets/javascripts/fine_print/user_agreements.js +0 -20
  107. data/app/assets/javascripts/fine_print/user_agreements.js~ +0 -20
  108. data/app/assets/stylesheets/fine_print/agreements.css +0 -11
  109. data/app/assets/stylesheets/fine_print/agreements.css~ +0 -11
  110. data/app/assets/stylesheets/fine_print/application.css~ +0 -60
  111. data/app/assets/stylesheets/fine_print/user_agreements.css~ +0 -3
  112. data/app/assets/stylesheets/scaffold.css~ +0 -56
  113. data/app/controllers/fine_print/agreements_controller.rb +0 -114
  114. data/app/controllers/fine_print/agreements_controller.rb~ +0 -113
  115. data/app/controllers/fine_print/user_agreements_controller.rb +0 -63
  116. data/app/controllers/fine_print/user_agreements_controller.rb~ +0 -63
  117. data/app/models/fine_print/agreement.rb +0 -50
  118. data/app/models/fine_print/agreement.rb~ +0 -50
  119. data/app/models/fine_print/user_agreement.rb +0 -19
  120. data/app/models/fine_print/user_agreement.rb~ +0 -21
  121. data/app/views/fine_print/agreements/_agreement.html.erb +0 -77
  122. data/app/views/fine_print/agreements/_agreement.html.erb~ +0 -77
  123. data/app/views/fine_print/agreements/_dialog.html.erb +0 -27
  124. data/app/views/fine_print/agreements/_dialog.html.erb~ +0 -27
  125. data/app/views/fine_print/agreements/_form.html.erb +0 -51
  126. data/app/views/fine_print/agreements/_form.html.erb~ +0 -51
  127. data/app/views/fine_print/agreements/edit.html.erb +0 -8
  128. data/app/views/fine_print/agreements/edit.html.erb~ +0 -8
  129. data/app/views/fine_print/agreements/index.html.erb +0 -32
  130. data/app/views/fine_print/agreements/index.html.erb~ +0 -32
  131. data/app/views/fine_print/agreements/new.html.erb +0 -7
  132. data/app/views/fine_print/agreements/new.html.erb~ +0 -7
  133. data/app/views/fine_print/agreements/new_version.html.erb +0 -7
  134. data/app/views/fine_print/agreements/new_version.html.erb~ +0 -7
  135. data/app/views/fine_print/agreements/show.html.erb +0 -15
  136. data/app/views/fine_print/agreements/show.html.erb~ +0 -14
  137. data/app/views/fine_print/user_agreements/cancel.js.erb +0 -1
  138. data/app/views/fine_print/user_agreements/cancel.js.erb~ +0 -2
  139. data/app/views/fine_print/user_agreements/create.js.erb +0 -2
  140. data/app/views/fine_print/user_agreements/create.js.erb~ +0 -2
  141. data/app/views/fine_print/user_agreements/index.html.erb +0 -25
  142. data/app/views/fine_print/user_agreements/index.html.erb~ +0 -25
  143. data/db/migrate/0_create_fine_print_agreements.rb~ +0 -22
  144. data/db/migrate/0_install.rb +0 -28
  145. data/db/migrate/0_install.rb~ +0 -28
  146. data/lib/fine_print/agreements_helper.rb +0 -13
  147. data/lib/fine_print/agreements_helper.rb~ +0 -11
  148. data/lib/fine_print/fine_print_agreement.rb +0 -26
  149. data/lib/fine_print/fine_print_agreement.rb~ +0 -26
  150. data/lib/fine_print/require_agreement.rb~ +0 -22
  151. data/lib/fine_print/security_transgression.rb~ +0 -3
  152. data/lib/fine_print/version.rb~ +0 -3
  153. data/lib/tasks/fine_print_tasks.rake~ +0 -42
  154. data/spec/dummy/README.md~ +0 -3
  155. data/spec/fine_print_spec.rb +0 -7
  156. data/spec/minitest_helper.rb +0 -12
@@ -1,53 +1,36 @@
1
1
  # Change the settings below to suit your needs
2
2
  # All settings are initially set to their default values
3
3
  FinePrint.configure do |config|
4
-
5
- # Engine Options (initializer only)
4
+ # Engine Configuration
6
5
 
7
6
  # Name of the ApplicationController helper method that returns the current user
8
- # Default: "current_user"
9
- config.current_user_method = "current_user"
7
+ # Default: 'current_user'
8
+ config.current_user_method = 'current_user'
10
9
 
11
10
  # Proc called with user as argument that should return true if and only if the user is an admin
12
11
  # Admins can create and edit agreements and terminate accepted agreements
13
12
  # Default: lambda { |user| false } (no admins)
14
13
  config.user_admin_proc = lambda { |user| false }
15
14
 
16
- # Path to redirect users to when an error occurs (e.g. permission denied on admin pages)
17
- # Default: "/"
18
- config.redirect_path = "/"
19
-
20
- # Path to link users to if they need to sign in
21
- # Set to nil to disable the link
22
- # Default: "/"
23
- config.sign_in_path = "/"
24
-
25
-
26
-
27
- # Agreement Options (initializer or inline)
15
+ # Proc that returns true if and only if the provided user is logged in
16
+ # In many systems, a non-logged-in user is represented by nil
17
+ # However, some systems use something like an AnonymousUser class to represent this state
18
+ # This proc is mostly used to help the developer realize that they should only be asking
19
+ # signed in users to sign contracts; without this, developers would get a cryptic SQL error
20
+ # Default: lambda { |user| !user.nil? }
21
+ config.user_signed_in_proc = lambda { |user| !user.nil? }
28
22
 
29
- # Message to be displayed to the user explaining that they need to accept an agreement
30
- # Set to nil to disable
31
- # Default: "You must accept the following agreement to proceed."
32
- config.agreement_notice = "You must accept the following agreement to proceed."
33
-
34
- # Path to redirect users to when an agreement is accepted and referer information is unavailable
35
- # Default: "/"
36
- config.accept_path = "/"
37
-
38
- # Path to redirect users to when an agreement is not accepted and referer information is unavailable
39
- # Default: "/"
40
- config.cancel_path = "/"
41
-
42
- # Whether to use referer information to redirect users after (not) accepting an agreement
43
- # Default: true
44
- config.use_referers = true
45
-
46
- # If set to true, modal jQuery UI dialogs will be used instead of redirecting the user to the agreement page
47
- # Note: users with javascript disabled will not even see the agreement and will be able to proceed without accepting it
48
- # if users are not supposed to ever see or interact with a certain page without accepting the agreement,
49
- # disable this option for that particular controller action
50
- # Default: false
51
- config.use_modal_dialogs = false
52
-
23
+ # Path to redirect users to when an error occurs (e.g. permission denied on admin pages)
24
+ # Default: '/'
25
+ config.redirect_path = '/'
26
+
27
+ # Signature (fine_print_get_signatures) Configuration
28
+
29
+ # Path to redirect users to when they need to agree to contract(s)
30
+ # A list of contract names that must be agreed to will be available in the 'contracts' parameter
31
+ # Your code doesn't have to deal with all of them at once, e.g. you can get
32
+ # the user to agree to the first one and then they'll just eventually be
33
+ # redirected back to this page with the remaining contract names
34
+ # Default: '/'
35
+ config.pose_contracts_path = '/'
53
36
  end
data/config/routes.rb CHANGED
@@ -1,7 +1,13 @@
1
1
  FinePrint::Engine.routes.draw do
2
- resources :agreements do
3
- get :new_version
2
+ resources :contracts do
3
+ member do
4
+ get :new_version
5
+ put :publish
6
+ put :unpublish
7
+ end
4
8
  end
5
- resources :user_agreements, :only => [:index, :create, :destroy]
9
+
10
+ resources :signatures, :only => [:index, :destroy]
11
+
6
12
  root :to => 'home#index'
7
13
  end
data/config/routes.rb~ CHANGED
@@ -1,7 +1,12 @@
1
1
  FinePrint::Engine.routes.draw do
2
- resources :agreements do
3
- get :new_version
2
+ resources :contracts do
3
+ member do
4
+ get :new_version, :on => :member
5
+ put :publish, :on => :member
6
+ put :unpublish, :on => :member
4
7
  end
5
- resources :user_agreements, :only => [:index, :create, :destroy]
6
- root :to => 'agreements#index'
8
+
9
+ resources :signatures, :only => [:index, :destroy]
10
+
11
+ root :to => 'home#index'
7
12
  end
@@ -0,0 +1,26 @@
1
+ class InstallFinePrint < ActiveRecord::Migration
2
+ def change
3
+ create_table :fine_print_contracts do |t|
4
+ t.string :name, :null => false
5
+ t.integer :version
6
+ t.string :title, :null => false
7
+ t.text :content, :null => false
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :fine_print_contracts, [:name, :version], :unique => true
13
+
14
+ create_table :fine_print_signatures do |t|
15
+ t.belongs_to :contract, :null => false
16
+ t.belongs_to :user, :polymorphic => true, :null => false
17
+
18
+ t.timestamps
19
+ end
20
+
21
+ add_index :fine_print_signatures, :contract_id
22
+ add_index :fine_print_signatures, [:user_id, :user_type, :contract_id],
23
+ :name => 'index_fine_print_s_on_u_id_and_u_type_and_c_id',
24
+ :unique => true
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ class InstallFinePrint < ActiveRecord::Migration
2
+ def change
3
+ create_table :fine_print_contracts do |t|
4
+ t.string :name, :null => false
5
+ t.integer :version
6
+ t.string :title, :null => false, :default => ''
7
+ t.text :content, :null => false, :default => ''
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :fine_print_contracts, [:name, :version], :unique => true
13
+
14
+ create_table :fine_print_signatures do |t|
15
+ t.belongs_to :contract, :null => false
16
+ t.belongs_to :user, :polymorphic => true, :null => false
17
+
18
+ t.timestamps
19
+ end
20
+
21
+ add_index :fine_print_signatures, :contract_id
22
+ add_index :fine_print_signatures, [:user_id, :user_type, :contract_id],
23
+ :name => 'index_fine_print_s_on_u_id_and_u_type_and_c_id',
24
+ :unique => true
25
+ end
26
+ end
@@ -0,0 +1,69 @@
1
+ module FinePrint
2
+ module ControllerAdditions
3
+ #
4
+ # Internally these methods think of contract names as strings, not symbols.
5
+ # Any names passed in as symbols are converted to strings.
6
+ #
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ def fine_print_skipped_contract_names
12
+ @fine_print_skipped_contract_names ||= []
13
+ end
14
+
15
+ # See the README
16
+ def fine_print_return
17
+ redirect_to session.delete(:fine_print_return_to) || root_path
18
+ end
19
+
20
+ module ClassMethods
21
+ # See the README
22
+ def fine_print_get_signatures(*args)
23
+ options = args.last.is_a?(Hash) ? args.pop : {}
24
+
25
+ filter_options = options.except(*FinePrint::SIGNATURE_OPTIONS)
26
+ fine_print_options = options.slice(*FinePrint::SIGNATURE_OPTIONS)
27
+
28
+ # Convert all names to string
29
+ names = args.collect{|n| n.to_s}
30
+
31
+ class_eval do
32
+ before_filter(filter_options) do |controller|
33
+ names_to_check = names - fine_print_skipped_contract_names
34
+
35
+ # Bail if nothing to do
36
+ return true if names_to_check.blank?
37
+
38
+ user = send FinePrint.current_user_method
39
+ FinePrint.raise_unless_signed_in(user)
40
+
41
+ unsigned_contract_names =
42
+ FinePrint.get_unsigned_contract_names(names_to_check, user)
43
+ return true if unsigned_contract_names.empty?
44
+
45
+ # http://stackoverflow.com/a/2165727/1664216
46
+ session[:fine_print_return_to] = "#{request.protocol}#{request.host_with_port}#{request.fullpath}"
47
+ # http://stackoverflow.com/a/6561953
48
+ path = fine_print_options[:pose_contracts_path] || FinePrint.pose_contracts_path
49
+ redirect_to path + (path.include?('?') ? '&' : '?') + {:terms => unsigned_contract_names}.to_query
50
+ end
51
+ end
52
+ end
53
+
54
+ # See the README
55
+ def fine_print_skip_signatures(*args)
56
+ options = args.last.is_a?(Hash) ? args.pop : {}
57
+ names = args.collect{|arg| arg.to_s}
58
+
59
+ class_eval do
60
+ prepend_before_filter(options) do |controller|
61
+ fine_print_skipped_contract_names.push(*names)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ ActionController::Base.send :include, FinePrint::ControllerAdditions
@@ -0,0 +1,69 @@
1
+ module FinePrint
2
+ module ControllerAdditions
3
+ #
4
+ # Internally these methods think of contract names as strings, not symbols.
5
+ # Any names passed in as symbols are converted to strings.
6
+ #
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ def fine_print_skipped_contract_names
12
+ @fine_print_skipped_contract_names ||= []
13
+ end
14
+
15
+ # See the README
16
+ def fine_print_return
17
+ redirect_to root_path
18
+ end
19
+
20
+ module ClassMethods
21
+ # See the README
22
+ def fine_print_get_signatures(*args)
23
+ options = args.last.is_a?(Hash) ? args.pop : {}
24
+
25
+ filter_options = options.except(*FinePrint::SIGNATURE_OPTIONS)
26
+ fine_print_options = options.slice(*FinePrint::SIGNATURE_OPTIONS)
27
+
28
+ # Convert all names to string
29
+ names = args.collect{|n| n.to_s}
30
+
31
+ class_eval do
32
+ before_filter(filter_options) do |controller|
33
+ names_to_check = names - fine_print_skipped_contract_names
34
+
35
+ # Bail if nothing to do
36
+ return true if names_to_check.blank?
37
+
38
+ user = send FinePrint.current_user_method
39
+ FinePrint.raise_unless_signed_in(user)
40
+
41
+ unsigned_contract_names =
42
+ FinePrint.get_unsigned_contract_names(names_to_check, user)
43
+ return true if unsigned_contract_names.empty?
44
+
45
+ # http://stackoverflow.com/a/2165727/1664216
46
+ session[:fine_print_return_to] = "#{request.protocol}#{request.host_with_port}#{request.fullpath}"
47
+ # http://stackoverflow.com/a/6561953
48
+ path = fine_print_options[:pose_contracts_path] || FinePrint.pose_contracts_path
49
+ redirect_to path + (path.include?('?') ? '&' : '?') + {:terms => unsigned_contract_names}.to_query
50
+ end
51
+ end
52
+ end
53
+
54
+ # See the README
55
+ def fine_print_skip_signatures(*args)
56
+ options = args.last.is_a?(Hash) ? args.pop : {}
57
+ names = args.collect{|arg| arg.to_s}
58
+
59
+ class_eval do
60
+ prepend_before_filter(options) do |controller|
61
+ fine_print_skipped_contract_names.push(*names)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ ActionController::Base.send :include, FinePrint::ControllerAdditions
@@ -1,5 +1,13 @@
1
1
  module FinePrint
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace FinePrint
4
+
5
+ # http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl
6
+ config.generators do |g|
7
+ g.test_framework :rspec, :fixture => false
8
+ g.fixture_replacement :factory_girl, :dir => 'spec/factories'
9
+ g.assets false
10
+ g.helper false
11
+ end
4
12
  end
5
13
  end
@@ -1,4 +1,3 @@
1
1
  module FinePrint
2
- class SecurityTransgression < StandardError
3
- end
2
+ class SecurityTransgression < StandardError; end
4
3
  end
@@ -0,0 +1,26 @@
1
+ module FinePrint
2
+ module Utilities
3
+ # Returns true iff the given user has signed any version of the given contract.
4
+ # contract -- can be a Contract object, its ID, or its name as a String or Symbol
5
+ def self.any_signed_contract_version?(contract, user)
6
+ contract = FinePrint::get_contract(contract)
7
+ !user.nil? &&
8
+ !Signature.joins(:contract)
9
+ .where(:contract => {:name => contract.name},
10
+ :user_type => user.class.name,
11
+ :user_id => user.id).first.nil?
12
+ end
13
+
14
+ # Returns the latest version of the named contract (since contracts don't have
15
+ # versions until they are published this only returns published contracts).
16
+ # If no such contract exists, returns nil.
17
+ # name -- can be a String or a Symbol
18
+ def self.latest_contract_named(name)
19
+ name = name.to_s
20
+ contract = Contract.where(:name => name).published.first
21
+ raise IllegalState, "Published version of #{name} not found" \
22
+ if contract.nil?
23
+ contract
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module FinePrint
2
- VERSION = "0.1.1"
2
+ VERSION = '1.0.0'
3
3
  end
data/lib/fine_print.rb CHANGED
@@ -1,69 +1,116 @@
1
- require "fine_print/engine"
2
- require "fine_print/fine_print_agreement"
1
+ require 'fine_print/engine'
2
+ require 'fine_print/security_transgression'
3
+ require 'fine_print/controller_additions'
3
4
 
4
5
  module FinePrint
5
- ASSET_FILES = %w(dialog.js)
6
-
7
6
  # Attributes
8
7
 
9
8
  # Can be set in initializer only
10
9
  ENGINE_OPTIONS = [
11
10
  :current_user_method,
12
11
  :user_admin_proc,
13
- :redirect_path,
14
- :sign_in_path
12
+ :user_signed_in_proc,
13
+ :pose_contracts_path,
14
+ :redirect_path
15
15
  ]
16
16
 
17
- # Can be set in initializer or passed as an option to fine_print_agreement
18
- AGREEMENT_OPTIONS = [
19
- :agreement_notice,
20
- :accept_path,
21
- :cancel_path,
22
- :use_referers,
23
- :use_modal_dialogs
17
+ # Can be set in initializer or passed as an option to fine_print_get_signatures
18
+ SIGNATURE_OPTIONS = [
19
+ :pose_contracts_path
24
20
  ]
25
21
 
26
- (ENGINE_OPTIONS + AGREEMENT_OPTIONS).each do |option|
22
+ (ENGINE_OPTIONS + SIGNATURE_OPTIONS).each do |option|
27
23
  mattr_accessor option
28
24
  end
29
-
30
- ActiveSupport.on_load(:before_initialize) do
31
- Rails.configuration.assets.precompile += ASSET_FILES
32
- end
33
25
 
34
26
  def self.configure
35
27
  yield self
36
28
  end
37
29
 
38
- def self.get_option(options, name)
39
- (!options.nil? && !options[name].nil?) ? options[name] : self.send(name)
30
+ # Gets a contract given either the contract's object, ID or name
31
+ # If given a name, it returns the latest published version of that contract
32
+ #
33
+ def self.get_contract(reference)
34
+ ref = Integer(reference) rescue reference
35
+ case ref
36
+ when Contract
37
+ ref
38
+ when Integer
39
+ Contract.find(ref)
40
+ when String
41
+ Contract.where(:name => ref).published.first
42
+ end
43
+ end
44
+
45
+ # Returns an array of names for the contracts whose latest published
46
+ # version the given user has not signed.
47
+ # - names -- an array of contract names
48
+ # - user -- the user in question
49
+ #
50
+ def self.get_unsigned_contract_names(names, user)
51
+ raise_unless_signed_in(user)
52
+ return [] if names.blank?
53
+ names_array = names.is_a?(Array) ? names.collect{|name| name.to_s} : [names.to_s]
54
+
55
+ signed_contracts = Contract
56
+ .joins(:signatures)
57
+ .where({:name => names_array,
58
+ :fine_print_signatures => {:user_id => user.id,
59
+ :user_type => user.class.name}}).latest
60
+ signed_contract_names = signed_contracts.collect{|c| c.name}
61
+
62
+ return names - signed_contract_names
40
63
  end
41
64
 
42
- def self.require_agreements(controller, names, options)
43
- user = controller.send current_user_method
44
- fine_print_dialog_agreements = []
45
- names.each do |name|
46
- agreement = Agreement.latest_ready(name)
47
- next if agreement.nil? || agreement.accepted_by?(user)
48
- if get_option(options, :use_modal_dialogs)
49
- fine_print_dialog_agreements << agreement
50
- else
51
- controller.session[:fine_print_accept_path] = options[:accept_path]
52
- controller.session[:fine_print_cancel_path] = options[:cancel_path]
53
- if get_option(options, :use_referers)
54
- controller.session[:fine_print_request_url] = controller.request.url
55
- controller.session[:fine_print_request_ref] = controller.request.referer
56
- end
57
- controller.redirect_to controller.fine_print.agreement_path(agreement),
58
- :notice => get_option(options, :agreement_notice)
59
- end
65
+ # Records that the given user has signed the given contract; the contract
66
+ # can be a Contract object, a contract ID, or a contract name (string)
67
+ #
68
+ def self.sign_contract(contract, user)
69
+ raise_unless_signed_in(user)
70
+ contract = get_contract(contract)
71
+ raise IllegalState, 'Contract not found' if contract.nil?
72
+
73
+ Signature.create do |signature|
74
+ signature.user = user
75
+ signature.contract = contract
60
76
  end
61
- controller.instance_variable_set(:@fine_print_dialog_agreements, fine_print_dialog_agreements)
62
- controller.instance_variable_set(:@fine_print_user, user)
63
- controller.instance_variable_set(:@fine_print_dialog_notice, get_option(options, :agreement_notice))
77
+ end
78
+
79
+ # Returns true iff the given user has signed the given contract; the contract
80
+ # can be a Contract object, a contract ID, or a contract name (string)
81
+ #
82
+ def self.signed_contract?(contract, user)
83
+ raise_unless_signed_in(user)
84
+ contract = get_contract(contract)
85
+
86
+ !contract.signatures.where(:user_id => user.id,
87
+ :user_type => user.class.name).first.nil?
88
+ end
89
+
90
+ # Returns true iff the given user has signed any version of the given contract.
91
+ # - contract -- can be a Contract object, its ID, or its name as a String or Symbol
92
+ def self.signed_any_contract_version?(contract, user)
93
+ raise_unless_signed_in(user)
94
+ contract = get_contract(contract)
95
+ !Signature.joins(:contract)
96
+ .where(:fine_print_contracts => {:name => contract.name},
97
+ :user_type => user.class.name,
98
+ :user_id => user.id).first.nil?
99
+ end
100
+
101
+ def self.is_signed_in?(user)
102
+ user_signed_in_proc.call(user)
64
103
  end
65
104
 
66
105
  def self.is_admin?(user)
67
- !user.nil? && user_admin_proc.call(user)
106
+ is_signed_in?(user) && user_admin_proc.call(user)
107
+ end
108
+
109
+ def self.raise_unless_signed_in(user)
110
+ raise IllegalState, 'User not signed in' unless is_signed_in?(user)
111
+ end
112
+
113
+ def self.raise_unless_admin(user)
114
+ raise SecurityTransgression unless is_admin?(user)
68
115
  end
69
116
  end