user_plane 0.0.15

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 (205) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +30 -0
  4. data/app/assets/javascripts/user_plane/application.js +13 -0
  5. data/app/assets/stylesheets/user_plane/application.css +15 -0
  6. data/app/concerns/null_object_persistable.rb +62 -0
  7. data/app/controllers/user/confirm_email_addresses_controller.rb +17 -0
  8. data/app/controllers/user/details_controller.rb +48 -0
  9. data/app/controllers/user/invites_controller.rb +69 -0
  10. data/app/controllers/user/reset_passwords_controller.rb +50 -0
  11. data/app/controllers/user/sign_ins_controller.rb +53 -0
  12. data/app/controllers/user/sign_ups_controller.rb +47 -0
  13. data/app/controllers/user_plane/application_controller.rb +5 -0
  14. data/app/helpers/user_plane/application_helper.rb +4 -0
  15. data/app/mailers/user_plane/application_mailer.rb +8 -0
  16. data/app/mailers/user_plane/invite_mailer.rb +14 -0
  17. data/app/mailers/user_plane/verification_mailer.rb +25 -0
  18. data/app/models/session_manager.rb +100 -0
  19. data/app/models/user.rb +5 -0
  20. data/app/models/user/account.rb +26 -0
  21. data/app/models/user/confirm_email_address.rb +55 -0
  22. data/app/models/user/guest.rb +18 -0
  23. data/app/models/user/identities.rb +5 -0
  24. data/app/models/user/identities/email.rb +98 -0
  25. data/app/models/user/identities/email_verification.rb +70 -0
  26. data/app/models/user/identities/facebook.rb +5 -0
  27. data/app/models/user/identities/github.rb +5 -0
  28. data/app/models/user/identities/id_token.rb +7 -0
  29. data/app/models/user/identities/o_auth.rb +67 -0
  30. data/app/models/user/identities/o_auth_endpoint.rb +28 -0
  31. data/app/models/user/identities/twitter.rb +5 -0
  32. data/app/models/user/identity.rb +26 -0
  33. data/app/models/user/reset_password.rb +59 -0
  34. data/app/models/user/send_password_reset.rb +25 -0
  35. data/app/models/user/send_sign_up_invite.rb +27 -0
  36. data/app/models/user/sign_in.rb +42 -0
  37. data/app/models/user/sign_up.rb +47 -0
  38. data/app/models/user/sign_up_invites.rb +5 -0
  39. data/app/models/user/sign_up_invites/invite.rb +46 -0
  40. data/app/models/user/sign_up_invites/stack.rb +22 -0
  41. data/app/models/user/sign_up_with_invite.rb +45 -0
  42. data/app/models/user/suspension.rb +7 -0
  43. data/app/models/user/update_details.rb +103 -0
  44. data/app/views/layouts/user_plane/application.html.erb +14 -0
  45. data/app/views/user/details/edit.html.erb +37 -0
  46. data/app/views/user/invites/edit.html.erb +34 -0
  47. data/app/views/user/invites/new.html.erb +21 -0
  48. data/app/views/user/reset_passwords/edit.html.erb +26 -0
  49. data/app/views/user/reset_passwords/new.html.erb +21 -0
  50. data/app/views/user/sign_ins/new.html.erb +25 -0
  51. data/app/views/user/sign_ups/new.html.erb +33 -0
  52. data/app/views/user_plane/invite_mailer/invite.html.erb +2 -0
  53. data/app/views/user_plane/invite_mailer/invite.text.erb +3 -0
  54. data/app/views/user_plane/verification_mailer/address_verification.html.erb +2 -0
  55. data/app/views/user_plane/verification_mailer/address_verification.text.erb +4 -0
  56. data/app/views/user_plane/verification_mailer/password_reset.html.erb +2 -0
  57. data/app/views/user_plane/verification_mailer/password_reset.text.erb +4 -0
  58. data/config/initializers/inflections.rb +3 -0
  59. data/config/locales/en.yml +63 -0
  60. data/config/locales/it.yml +62 -0
  61. data/config/routes.rb +5 -0
  62. data/db/migrate/20121128143404_create_user_accounts.rb +11 -0
  63. data/db/migrate/20121226202553_create_user_identities_o_auths.rb +12 -0
  64. data/db/migrate/20121226203032_create_user_identities_emails.rb +13 -0
  65. data/db/migrate/20121227144617_create_user_identities_email_verifications.rb +15 -0
  66. data/db/migrate/20130113120152_create_user_identities_id_tokens.rb +12 -0
  67. data/db/migrate/20141025230304_create_user_sign_up_invites_stacks.rb +10 -0
  68. data/db/migrate/20141025230500_create_user_sign_up_invites_invites.rb +13 -0
  69. data/db/migrate/20141026230208_create_user_suspensions.rb +13 -0
  70. data/lib/generators/user_plane/view/details_generator.rb +22 -0
  71. data/lib/generators/user_plane/view/helpers.rb +68 -0
  72. data/lib/generators/user_plane/view/invites_generator.rb +23 -0
  73. data/lib/generators/user_plane/view/reset_passwords_generator.rb +22 -0
  74. data/lib/generators/user_plane/view/sign_ins_generator.rb +18 -0
  75. data/lib/generators/user_plane/view/sign_ups_generator.rb +22 -0
  76. data/lib/generators/user_plane/views_generator.rb +32 -0
  77. data/lib/tasks/user_plane_tasks.rake +4 -0
  78. data/lib/user_plane.rb +43 -0
  79. data/lib/user_plane/command.rb +24 -0
  80. data/lib/user_plane/engine.rb +27 -0
  81. data/lib/user_plane/fresh_validator.rb +9 -0
  82. data/lib/user_plane/omniauth.rb +50 -0
  83. data/lib/user_plane/redirect_to_sign_in.rb +22 -0
  84. data/lib/user_plane/route_concerns.rb +167 -0
  85. data/lib/user_plane/session_manager_concern.rb +9 -0
  86. data/lib/user_plane/signed_in_constraint.rb +11 -0
  87. data/lib/user_plane/token_segment.rb +52 -0
  88. data/lib/user_plane/version.rb +3 -0
  89. data/spec/controllers/user/confirm_email_addresses_controller_spec.rb +5 -0
  90. data/spec/controllers/user/details_controller_spec.rb +5 -0
  91. data/spec/controllers/user/invites_controller_spec.rb +19 -0
  92. data/spec/controllers/user/reset_passwords_controller_spec.rb +5 -0
  93. data/spec/controllers/user/sign_ins_controller_spec.rb +34 -0
  94. data/spec/controllers/user/sign_ups_controller_spec.rb +5 -0
  95. data/spec/dummy/README.rdoc +28 -0
  96. data/spec/dummy/Rakefile +6 -0
  97. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  98. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  99. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  100. data/spec/dummy/app/controllers/welcome_controller.rb +3 -0
  101. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  102. data/spec/dummy/app/views/layouts/application.html.erb +30 -0
  103. data/spec/dummy/app/views/welcome/index.html.erb +1 -0
  104. data/spec/dummy/bin/bundle +3 -0
  105. data/spec/dummy/bin/rails +4 -0
  106. data/spec/dummy/bin/rake +4 -0
  107. data/spec/dummy/config.ru +4 -0
  108. data/spec/dummy/config/application.rb +30 -0
  109. data/spec/dummy/config/boot.rb +5 -0
  110. data/spec/dummy/config/database.yml +49 -0
  111. data/spec/dummy/config/environment.rb +5 -0
  112. data/spec/dummy/config/environments/development.rb +37 -0
  113. data/spec/dummy/config/environments/production.rb +78 -0
  114. data/spec/dummy/config/environments/test.rb +39 -0
  115. data/spec/dummy/config/initializers/assets.rb +8 -0
  116. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  117. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  118. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  119. data/spec/dummy/config/initializers/inflections.rb +16 -0
  120. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  121. data/spec/dummy/config/initializers/session_store.rb +3 -0
  122. data/spec/dummy/config/initializers/user_plane.rb +5 -0
  123. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  124. data/spec/dummy/config/locales/en.yml +23 -0
  125. data/spec/dummy/config/routes.rb +43 -0
  126. data/spec/dummy/config/secrets.yml +22 -0
  127. data/spec/dummy/db/schema.rb +101 -0
  128. data/spec/dummy/log/development.log +0 -0
  129. data/spec/dummy/log/test.log +20185 -0
  130. data/spec/dummy/public/404.html +67 -0
  131. data/spec/dummy/public/422.html +67 -0
  132. data/spec/dummy/public/500.html +66 -0
  133. data/spec/dummy/public/favicon.ico +0 -0
  134. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/-pOuxJZhYk_qXqMNKgm23KfvzyUW71NynNLlcNBOubE.cache +0 -0
  135. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/3AV9ywHBH56Leqey5LeznxK9vu4HD8fF3zSTk4MiDJA.cache +1 -0
  136. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/5fzR1G0D8ukHkPkLXsUu6rP6qV82aIdx3hugKkDy6nM.cache +0 -0
  137. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/9bKtJ2lkHPqtboGfbyknZ1OyH4xYO-aml7U3qhv-3kk.cache +0 -0
  138. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/HjDmE9SFP2wimdNHU8Nff9cm3vFZ5soO1iw7Jdlb6z8.cache +0 -0
  139. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/J9j6OdatarYW7VzVCVttmGphOhJKL0QXasdheyrgsTE.cache +2 -0
  140. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/KqrOQSlg0Th0N3XXx-h4p5BVJCfN0D8rRLoA9VxvXrc.cache +1 -0
  141. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/UCB1W65KwVU8ttOY8jnPRDp8HyyYYEjeTwwPD6R4qy8.cache +1 -0
  142. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/YmMSaaBmIcNZWPVF9jXcGBi-kwEzMuxzwPT_Zrcj1Bo.cache +2 -0
  143. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/g3wU8ajFWb5ZLPvujEt5l9DesbFCiAwqjx1WQgwTtHA.cache +1 -0
  144. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/i5pp88VHKoqlxQJdgmQd_lkgX1-4em_uHqNDjQ4nyHA.cache +0 -0
  145. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/jL74yXjxf8cb6Olkjbw1C28MH_HbZe221l8AI6WVeH0.cache +3 -0
  146. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/puh7X4rfS3eDN9oHTXoQdAgqxivonrwAAdYZ4UB3GIg.cache +1 -0
  147. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/qxPWFIWnE6gOCY-SsdBJe7Cgm5D3YUwaEne78Y7XdRg.cache +1 -0
  148. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/rM9s67WgzKMZ1bRhUdA0yhPZDlyRE5a1kmdt7cS6m4c.cache +3 -0
  149. data/spec/dummy/tmp/cache/assets/test/sprockets/v3.0/rVoG8EHlrCOgY4ZkzOj64f0jiTcbteQ_SYNzq9RqY0I.cache +0 -0
  150. data/spec/fabricators/user_account_fabricator.rb +11 -0
  151. data/spec/fabricators/user_guest_fabricator.rb +2 -0
  152. data/spec/fabricators/user_identities_email_fabricator.rb +8 -0
  153. data/spec/fabricators/user_identities_email_verification_fabricator.rb +5 -0
  154. data/spec/fabricators/user_identities_id_token_fabricator.rb +2 -0
  155. data/spec/fabricators/user_sign_up_fabricator.rb +51 -0
  156. data/spec/fabricators/user_sign_up_invites_invite_fabricator.rb +3 -0
  157. data/spec/fabricators/user_sign_up_invites_stack_fabricator.rb +4 -0
  158. data/spec/fabricators/user_suspension_fabricator.rb +4 -0
  159. data/spec/fabricators/user_update_detail_fabricator.rb +2 -0
  160. data/spec/features/user_plane/user_plane_invites_spec.rb +31 -0
  161. data/spec/features/user_plane/user_plane_reset_passwords_spec.rb +31 -0
  162. data/spec/features/user_plane/user_plane_sign_ins_spec.rb +44 -0
  163. data/spec/features/user_plane/user_plane_signed_in_only_spec.rb +31 -0
  164. data/spec/features/user_plane/user_plane_update_details_spec.rb +43 -0
  165. data/spec/fixtures/user_plane/invite_mailer/invite +3 -0
  166. data/spec/fixtures/user_plane/verification_mailer/address_verification +3 -0
  167. data/spec/fixtures/user_plane/verification_mailer/password_reset +3 -0
  168. data/spec/lib/generators/views_generator_spec.rb +16 -0
  169. data/spec/lib/route_concerns_spec.rb +54 -0
  170. data/spec/mailers/previews/user_plane/invite_mailer_preview.rb +11 -0
  171. data/spec/mailers/previews/user_plane/verification_mailer_preview.rb +16 -0
  172. data/spec/mailers/user_plane/invite_mailer_spec.rb +25 -0
  173. data/spec/mailers/user_plane/verification_mailer_spec.rb +52 -0
  174. data/spec/models/session_manager_spec.rb +28 -0
  175. data/spec/models/user/account_spec.rb +26 -0
  176. data/spec/models/user/confirm_email_address_spec.rb +101 -0
  177. data/spec/models/user/guest_spec.rb +5 -0
  178. data/spec/models/user/identities/email_spec.rb +5 -0
  179. data/spec/models/user/identities/email_verification_spec.rb +42 -0
  180. data/spec/models/user/identities/facebook_spec.rb +5 -0
  181. data/spec/models/user/identities/github_spec.rb +5 -0
  182. data/spec/models/user/identities/id_token_spec.rb +5 -0
  183. data/spec/models/user/identities/o_auth_spec.rb +12 -0
  184. data/spec/models/user/identities/twitter_spec.rb +5 -0
  185. data/spec/models/user/reset_password_spec.rb +141 -0
  186. data/spec/models/user/send_password_reset_spec.rb +44 -0
  187. data/spec/models/user/send_sign_up_invite_spec.rb +30 -0
  188. data/spec/models/user/sign_in_spec.rb +31 -0
  189. data/spec/models/user/sign_up_invites/invite_spec.rb +13 -0
  190. data/spec/models/user/sign_up_invites/stack_spec.rb +21 -0
  191. data/spec/models/user/sign_up_spec.rb +58 -0
  192. data/spec/models/user/sign_up_with_invite_spec.rb +83 -0
  193. data/spec/models/user/suspension_spec.rb +5 -0
  194. data/spec/models/user/update_details_spec.rb +98 -0
  195. data/spec/routing/invites_spec.rb +49 -0
  196. data/spec/routing/reset_passwords_spec.rb +31 -0
  197. data/spec/routing/sign_ins_spec.rb +36 -0
  198. data/spec/routing/update_details_spec.rb +30 -0
  199. data/spec/shared_contexts/feature_helpers.rb +12 -0
  200. data/spec/shared_contexts/routing.rb +8 -0
  201. data/spec/shared_contexts/user.rb +67 -0
  202. data/spec/spec_helper.rb +38 -0
  203. data/spec/support/fabrication.rb +7 -0
  204. data/spec/support/omniauth.rb +4 -0
  205. metadata +770 -0
@@ -0,0 +1,50 @@
1
+ require 'omniauth'
2
+
3
+ module UserPlane
4
+ module OmniAuth
5
+
6
+ # Lets actiondispatch figure out the request path. Looks like request_path
7
+ # needs to return the callback path to generate the correct link
8
+ def self.request_path_criteria_for provider
9
+ lambda do |env|
10
+ path_parameters = env["action_dispatch.request.path_parameters"]
11
+ path_parameters[:action] == 'oauth_request' && UserPlane::OmniAuth.custom_path(env)
12
+ end
13
+ end
14
+
15
+ def self.callback_path_criteria_for provider
16
+ lambda do |env|
17
+ path_parameters = env["action_dispatch.request.path_parameters"]
18
+ path_parameters[:action] == 'oauth_callback'
19
+ end
20
+ end
21
+
22
+ def self.custom_path env
23
+ path_parameters = env["action_dispatch.request.path_parameters"]
24
+ custom_callback_path = path_parameters.merge(action: 'oauth_callback',
25
+ only_path: true)
26
+ env['action_dispatch.routes'].url_for custom_callback_path
27
+ end
28
+
29
+ # Configures the omniauth middleware for the application
30
+ def self.middleware &block
31
+ controllers = [User::SignInsController,
32
+ User::SignUpsController,
33
+ User::InvitesController]
34
+
35
+ controllers.each do |controller|
36
+ controller.middleware.use Builder, &block
37
+ end
38
+ end
39
+
40
+ # Wraps OmniAuth::Builder to provide custom callback urls driven by the routes
41
+ class Builder < ::OmniAuth::Builder
42
+ def provider(klass, *args, &block)
43
+ options = args.extract_options!
44
+ args << options.merge(request_path: UserPlane::OmniAuth.request_path_criteria_for(klass),
45
+ callback_path: UserPlane::OmniAuth.callback_path_criteria_for(klass))
46
+ super
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,22 @@
1
+ module UserPlane
2
+ class RedirectToSignIn
3
+ def initialize route_options={}
4
+ default_route = {controller: 'user/sign_ins', action: :new}
5
+ @sign_in_route = default_route.merge(route_options)
6
+ end
7
+
8
+ def call env
9
+ session_manager = SessionManager.new(env['rack.session'])
10
+
11
+ if session_manager.signed_in?
12
+ raise ActionController::RoutingError.new('Not Found')
13
+ end
14
+
15
+ request_path = "#{env['PATH_INFO']}?#{env['QUERY_STRING']}"
16
+ session_manager.remember_page(request_path)
17
+
18
+ sign_in_path = env['action_dispatch.routes'].path_for(@sign_in_route)
19
+ [301, {'Location' => sign_in_path}, ['Redirecting to the sign in page']]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,167 @@
1
+ module UserPlane
2
+ module RouteConcerns
3
+
4
+ DEFAULTS = {namespace: 'user', on: :collection}
5
+
6
+ mattr_accessor :signed_in_constraint do
7
+ -> (request) {SessionManager.new(request.session).signed_in?}
8
+ end
9
+
10
+ class AbstractConcern
11
+ attr_accessor :concern_options
12
+ attr_accessor :mapper
13
+
14
+ def initialize(options = {})
15
+ defaults = RouteConcerns::DEFAULTS.merge(options)
16
+ @namespace = defaults[:namespace]
17
+ @defaults = defaults.except(:namespace)
18
+ end
19
+
20
+ # Returns true if a particular concern exists
21
+ def exists? concern
22
+ mapper.instance_variable_get('@concerns').include?(concern)
23
+ end
24
+
25
+ # The abstract concern should be able to handle resources having a preferred
26
+ # collection/resource target.
27
+ def call(mapper, concern_options = {})
28
+ @mapper = mapper
29
+ @concern_options = concern_options
30
+
31
+ build
32
+ end
33
+
34
+ def options custom_route_options={}
35
+ resource_scope = mapper.send :resource_scope?
36
+
37
+ if resource_scope
38
+ @defaults.merge(@concern_options).merge(custom_route_options)
39
+ else
40
+ @defaults.merge(@concern_options).merge(custom_route_options).except(:on)
41
+ end
42
+ end
43
+ end
44
+
45
+ class AbstractNamespacedConcern < AbstractConcern
46
+ # The abstract concern should be able to handle resources having a preferred
47
+ # collection/resource target.
48
+ def call(mapper, concern_options = {})
49
+ @mapper = mapper
50
+ @concern_options = concern_options
51
+
52
+ mapper.namespace @namespace, path: '/' do
53
+ build
54
+ end
55
+ end
56
+ end
57
+
58
+ # Defines two resources:
59
+ # A session resource to sign a user in and out
60
+ # A details resource to let a user change the account's details
61
+ # It also defines an extra concern
62
+ # And a signed_in routing concern to ensure that child routes are accessible only
63
+ # to signed in users.
64
+ # It defines a route to edit the account details and one to sign in and sign out.
65
+ #
66
+ # To enforce being singed in to certain resources:
67
+ # resource :score, concern: :signed_in
68
+ #
69
+ # scope '/profile' concern: :signed_in do
70
+ # resource :score
71
+ # resource :buddies
72
+ # end
73
+ #
74
+ class Base < AbstractNamespacedConcern
75
+
76
+ attr_accessor :singed_in_constraint
77
+
78
+ def build
79
+ mapper.resource :sign_in, options(only: [:new, :create, :destroy]) do
80
+ if exists? :auth_endpoint
81
+ mapper.concerns :auth_endpoint, controller: :sign_ins
82
+ end
83
+ end
84
+
85
+ mapper.resource :details, options(only: [:edit, :update],
86
+ as: :update_details,
87
+ constraints: RouteConcerns.signed_in_constraint)
88
+ end
89
+ end
90
+
91
+ class SignUp < AbstractNamespacedConcern
92
+ def build
93
+ mapper.resource :sign_up, options(only: [:new, :create]) do
94
+ if exists? :auth_endpoint
95
+ mapper.concerns :auth_endpoint, controller: :sign_ups
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ # An alternative to the SignUp concern that provides routes to handle sign
102
+ # up via invites.
103
+ class Invites < AbstractNamespacedConcern
104
+
105
+ def initialize(defaults = {})
106
+ @users_can_send_invites = defaults.delete(:users_can_send_invites) || true
107
+ super
108
+ end
109
+
110
+ def build
111
+ sign_up_options = options(only: [:edit, :update],
112
+ path_names: {edit: 'redeem'},
113
+ as: :sign_up_with_invites,
114
+ param: :code)
115
+
116
+ mapper.resources :invites, sign_up_options do
117
+ if exists? :auth_endpoint
118
+ mapper.concerns :auth_endpoint, controller: :invites,
119
+ on: :member
120
+ end
121
+ end
122
+
123
+ if @users_can_send_invites
124
+ mapper.resources :invites, options(only: [:new, :create],
125
+ as: :send_sign_up_invites,
126
+ constraints: RouteConcerns.signed_in_constraint)
127
+ end
128
+ end
129
+ end
130
+
131
+ # Provides extra routes to manage email identities: password resets and email
132
+ # confirmations
133
+ class EmailIdentity < AbstractNamespacedConcern
134
+ def build
135
+ mapper.scope controller: :reset_passwords do
136
+ mapper.resources :reset_passwords, options(only: [:new, :create],
137
+ param: :code,
138
+ as: :send_password_resets)
139
+
140
+ mapper.resources :reset_passwords, options(only: [:edit, :update],
141
+ param: :code)
142
+ end
143
+
144
+ mapper.get '/confirm_email/:code', options(to: 'confirm_email_addresses#update',
145
+ as: :confirm_email_address)
146
+ end
147
+ end
148
+
149
+ class OAuthEndpoint < AbstractConcern
150
+
151
+ def build
152
+ controller = concern_options.delete(:controller) || 'sessions'
153
+
154
+ mapper.resources :auth, options(as: :o_auth_endpoint,
155
+ only: :edit,
156
+ path_names: {edit: 'callback'},
157
+ param: :provider,
158
+ to: "#{controller}#oauth_callback")
159
+ mapper.resources :auth, options(as: :o_auth_endpoint,
160
+ only: :show,
161
+ param: :provider,
162
+ to: "#{controller}#oauth_request")
163
+ end
164
+ end
165
+
166
+ end
167
+ end
@@ -0,0 +1,9 @@
1
+ module UserPlane
2
+ module SessionManagerConcern
3
+ extend ActiveSupport::Concern
4
+
5
+ def session_manager
6
+ @session_manager ||= SessionManager.new(session)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module UserPlane
2
+ # Prevents non signed in users to see specific routes
3
+ class SignedInConstraint
4
+
5
+ def matches?(request)
6
+ session = Session.new(request.session)
7
+ session.signed_in?
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_support/concern'
2
+
3
+ module TokenSegment
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+
8
+ def has_token(attribute, options={}, &block)
9
+ # Generates a random token on a given attirubte at creation time.
10
+ # optionally it can create it for every update of the record.
11
+
12
+ validates attribute, uniqueness: true
13
+
14
+ if life_span = options[:expires_in]
15
+ scope :stale, -> {unscoped.where('created_at <= ?', life_span.ago)}
16
+ scope :fresh, -> {where('created_at > ?', life_span.ago)}
17
+
18
+ define_method :stale? do
19
+ if new_record?
20
+ false
21
+ else
22
+ created_at <= life_span.ago
23
+ end
24
+ end
25
+ end
26
+
27
+ define_method :"regenerate_#{attribute}" do
28
+ if block_given?
29
+ make_token attribute, instance_eval(&block)
30
+ else
31
+ make_token attribute
32
+ end
33
+ end
34
+
35
+ if regenerate_on = options[:regenerate_on]
36
+ before_validation :"regenerate_#{attribute}", on: regenerate_on
37
+ else
38
+ before_validation :"regenerate_#{attribute}"
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ private
45
+
46
+ def make_token(attribute, token_string = nil)
47
+ string_to_hash = token_string || "#{self.class.name}-#{Time.now}-#{rand}-#{self.id}"
48
+ new_attributes = {attribute => Digest::SHA1.hexdigest(string_to_hash)}
49
+ self.assign_attributes new_attributes
50
+ end
51
+
52
+ end
@@ -0,0 +1,3 @@
1
+ module UserPlane
2
+ VERSION = "0.0.15"
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe User::ConfirmEmailAddressesController, type: :controller do
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe User::DetailsController, type: :controller do
4
+
5
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'shared_contexts/user'
3
+
4
+ describe User::InvitesController, type: :controller do
5
+ include_context 'user'
6
+ render_views
7
+
8
+ # TODO: report this bug. You can't reproduce every route without use_route
9
+ # because all params are stringified, but constraints can be symbols
10
+
11
+ it 'does serve an invite page' do
12
+ session_manager = SessionManager.new(session)
13
+ session_manager.identity = a_user.email
14
+
15
+ get :new
16
+ expect(response).to have_http_status(:ok)
17
+ end
18
+
19
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe User::ResetPasswordsController, type: :controller do
4
+
5
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'shared_contexts/user'
3
+
4
+ describe User::SignInsController, type: :controller do
5
+ include_context 'user'
6
+
7
+ let :session_manager do
8
+ double("session_manager")
9
+ end
10
+ before {allow(subject).to receive(:session_manager).and_return(session_manager)}
11
+
12
+ describe "signing in" do
13
+ it "updates the session with the correct credentials" do
14
+ expect(session_manager).to receive(:identity=).with(a_user.email)
15
+ expect(session_manager).to receive(:remember_page).with(nil)
16
+ expect(session_manager).to receive(:previous_page)
17
+
18
+ post :create, user_sign_in: {email: a_user.email.address, password: a_user.email.password}
19
+ end
20
+
21
+ it "does not log in with bad credentials" do
22
+ expect(session_manager).not_to receive(:identity=).with(a_user.email)
23
+ post :create, user_sign_in: {email: a_user.email.address, password: 'wrong password'}
24
+ end
25
+
26
+ end
27
+
28
+ describe "signing out" do
29
+ it "destroys the session" do
30
+ expect(session_manager).to receive(:sign_out)
31
+ get :destroy
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe User::SignUpsController, type: :controller do
4
+
5
+ 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
+ Rails.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 .