openstax_accounts 1.0.0 → 2.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 (66) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +89 -58
  3. data/app/controllers/openstax/accounts/application_controller.rb +3 -12
  4. data/app/controllers/openstax/accounts/dev/accounts_controller.rb +19 -0
  5. data/app/controllers/openstax/accounts/dev/base_controller.rb +2 -8
  6. data/app/controllers/openstax/accounts/sessions_controller.rb +31 -19
  7. data/app/handlers/openstax/accounts/dev/{users_index.rb → accounts_index.rb} +4 -4
  8. data/app/handlers/openstax/accounts/sessions_callback.rb +43 -0
  9. data/app/models/openstax/accounts/{user.rb → account.rb} +7 -22
  10. data/app/models/openstax/accounts/anonymous_account.rb +24 -0
  11. data/app/models/openstax/accounts/application_account.rb +7 -0
  12. data/app/representers/openstax/accounts/api/v1/{user_representer.rb → account_representer.rb} +1 -1
  13. data/app/representers/openstax/accounts/api/v1/{user_search_representer.rb → account_search_representer.rb} +7 -6
  14. data/app/representers/openstax/accounts/api/v1/{application_user_representer.rb → application_account_representer.rb} +5 -4
  15. data/app/representers/openstax/accounts/api/v1/application_account_search_representer.rb +20 -0
  16. data/app/representers/openstax/accounts/api/v1/{application_users_representer.rb → application_accounts_representer.rb} +3 -3
  17. data/app/routines/openstax/accounts/dev/{search_users.rb → search_accounts.rb} +5 -5
  18. data/app/routines/openstax/accounts/{search_users.rb → search_accounts.rb} +55 -46
  19. data/app/routines/openstax/accounts/sync_accounts.rb +47 -0
  20. data/app/views/openstax/accounts/dev/{users → accounts}/_search_results.html.erb +13 -13
  21. data/app/views/openstax/accounts/dev/{users/login.html.erb → accounts/index.html.erb} +3 -3
  22. data/app/views/openstax/accounts/dev/{users → accounts}/index.js.erb +1 -1
  23. data/app/views/openstax/accounts/shared/{users → accounts}/_index.html.erb +4 -1
  24. data/config/initializers/action_interceptor.rb +14 -0
  25. data/config/routes.rb +18 -15
  26. data/db/migrate/0_create_openstax_accounts_accounts.rb +22 -0
  27. data/lib/generators/openstax/accounts/schedule/USAGE +1 -1
  28. data/lib/generators/openstax/accounts/schedule/templates/schedule.rb +1 -1
  29. data/lib/openstax/accounts/current_user_manager.rb +74 -65
  30. data/lib/openstax/accounts/default_account_user_mapper.rb +15 -0
  31. data/lib/openstax/accounts/engine.rb +2 -0
  32. data/lib/openstax/accounts/extend_builtins.rb +37 -0
  33. data/lib/openstax/accounts/version.rb +1 -1
  34. data/lib/openstax_accounts.rb +46 -25
  35. data/spec/controllers/openstax/accounts/dev/accounts_controller_spec.rb +21 -0
  36. data/spec/controllers/openstax/accounts/sessions_controller_spec.rb +12 -9
  37. data/spec/dummy/app/controllers/api/application_users_controller.rb +0 -4
  38. data/spec/dummy/app/controllers/api/users_controller.rb +7 -0
  39. data/spec/dummy/app/models/anonymous_user.rb +48 -0
  40. data/spec/dummy/app/models/user.rb +26 -0
  41. data/spec/dummy/config/initializers/openstax_accounts.rb +3 -2
  42. data/spec/dummy/config/routes.rb +5 -3
  43. data/spec/dummy/db/migrate/1_create_users.rb +11 -0
  44. data/spec/dummy/db/schema.rb +18 -6
  45. data/spec/factories/openstax_accounts_account.rb +6 -0
  46. data/spec/lib/openstax/accounts/current_user_manager_spec.rb +151 -0
  47. data/spec/lib/openstax_accounts_spec.rb +16 -9
  48. data/spec/models/openstax/accounts/account_spec.rb +9 -0
  49. data/spec/models/openstax/accounts/anonymous_account_spec.rb +9 -0
  50. data/spec/routines/openstax/accounts/{search_users_spec.rb → search_accounts_spec.rb} +38 -38
  51. metadata +87 -50
  52. data/app/controllers/openstax/accounts/dev/users_controller.rb +0 -22
  53. data/app/handlers/openstax/accounts/sessions_omniauth_authenticated.rb +0 -48
  54. data/app/models/openstax/accounts/application_user.rb +0 -7
  55. data/app/representers/openstax/accounts/api/v1/application_user_search_representer.rb +0 -19
  56. data/app/routines/openstax/accounts/dev/create_user.rb +0 -37
  57. data/app/routines/openstax/accounts/sync_users.rb +0 -44
  58. data/config/initializers/extend_builtins.rb +0 -42
  59. data/db/migrate/0_create_openstax_accounts_users.rb +0 -18
  60. data/lib/openstax/accounts/action_list.rb +0 -42
  61. data/lib/openstax/accounts/route_helper.rb +0 -34
  62. data/lib/openstax/accounts/user_provider.rb +0 -15
  63. data/spec/controllers/openstax/accounts/dev/users_controller_spec.rb +0 -21
  64. data/spec/factories/openstax_accounts_user.rb +0 -6
  65. data/spec/models/openstax/accounts/user_spec.rb +0 -13
  66. data/spec/routines/openstax/accounts/dev/create_user_spec.rb +0 -26
@@ -1,10 +1,10 @@
1
- # Routine for searching for users
1
+ # Routine for searching for accounts
2
2
  #
3
3
  # Caller provides a query and some options. The query follows the rules of
4
4
  # https://github.com/bruce/keyword_search , e.g.:
5
5
  #
6
- # "username:jps,richb" --> returns the "jps" and "richb" users
7
- # "name:John" --> returns Users with first, last, or full name
6
+ # "username:jps,richb" --> returns the "jps" and "richb" accounts
7
+ # "name:John" --> returns accounts with first, last, or full name
8
8
  # starting with "John"
9
9
  #
10
10
  # Query terms can be combined, e.g. "username:jp first_name:john"
@@ -21,15 +21,15 @@
21
21
  #
22
22
  # Finally, you can also specify a maximum allowed number of results:
23
23
  #
24
- # :max_matching_users -- the max number of results allowed (default: 10)
24
+ # :max_matching_accounts -- the max number of results allowed (default: 10)
25
25
  #
26
26
  # This routine will return an empty relation if the number of results exceeds
27
- # max_matching_users. You can tell that this happened because the result will
28
- # have a non-zero num_matching_users.
27
+ # max_matching_accounts. You can tell that this situation happened when
28
+ # the result has an empty accounts array, but a non-zero num_matching_accounts.
29
29
 
30
30
  module OpenStax
31
31
  module Accounts
32
- class SearchUsers
32
+ class SearchAccounts
33
33
 
34
34
  lev_routine transaction: :no_transaction
35
35
 
@@ -45,60 +45,65 @@ module OpenStax
45
45
  KeywordSearch.search(query).values_at('email', :default).compact.any?
46
46
  # Delegate to Accounts
47
47
 
48
- response = OpenStax::Accounts.application_users_index(query)
48
+ response = OpenStax::Accounts.search_application_accounts(query)
49
49
 
50
- user_search = OpenStruct.new
51
- search_rep = OpenStax::Accounts::Api::V1::UserSearchRepresenter.new(user_search)
50
+
51
+ search = OpenStruct.new
52
+ search_rep = OpenStax::Accounts::Api::V1::AccountSearchRepresenter.new(search)
52
53
  search_rep.from_json(response.body)
53
54
 
54
55
  # Need to query local database in order to obtain ID's (primary keys)
55
- outputs[:users] = OpenStax::Accounts::User.where{
56
- openstax_uid.in user_search.users.collect{ |u| u.openstax_uid }
57
- }
58
- outputs[:query] = user_search.q
59
- outputs[:per_page] = user_search.per_page
60
- outputs[:page] = user_search.page
61
- outputs[:order_by] = user_search.order_by
62
- outputs[:num_matching_users] = user_search.num_matching_users
56
+ outputs[:accounts] = OpenStax::Accounts::Account.where {
57
+ openstax_uid.in search.accounts.collect{ |u| u.openstax_uid }
58
+ }
59
+ outputs[:query] = search.q
60
+ outputs[:per_page] = search.per_page
61
+ outputs[:page] = search.page
62
+ outputs[:order_by] = search.order_by
63
+ outputs[:num_matching_accounts] = search.num_matching_accounts
63
64
 
64
65
  else
65
66
 
66
67
  # Local search
67
- users = OpenStax::Accounts::User.scoped
68
+ accounts = OpenStax::Accounts::Account.scoped
68
69
 
69
70
  KeywordSearch.search(query) do |with|
70
71
 
71
72
  with.default_keyword :any
72
73
 
73
74
  with.keyword :username do |usernames|
74
- users = users.where{username.like_any my{prep_usernames(usernames)}}
75
+ accounts = accounts.where{username
76
+ .like_any my{prep_usernames(usernames)}}
75
77
  end
76
78
 
77
79
  with.keyword :first_name do |first_names|
78
- users = users.where{lower(first_name).like_any my{prep_names(first_names)}}
80
+ accounts = accounts.where{lower(first_name)
81
+ .like_any my{prep_names(first_names)}}
79
82
  end
80
83
 
81
84
  with.keyword :last_name do |last_names|
82
- users = users.where{lower(last_name).like_any my{prep_names(last_names)}}
85
+ accounts = accounts.where{lower(last_name)
86
+ .like_any my{prep_names(last_names)}}
83
87
  end
84
88
 
85
89
  with.keyword :full_name do |full_names|
86
- users = users.where{lower(full_name).like_any my{prep_names(full_names)}}
90
+ accounts = accounts.where{lower(full_name)
91
+ .like_any my{prep_names(full_names)}}
87
92
  end
88
93
 
89
94
  with.keyword :name do |names|
90
95
  names = prep_names(names)
91
- users = users.where{ (lower(full_name).like_any names) |
92
- (lower(last_name).like_any names) |
93
- (lower(first_name).like_any names) }
96
+ accounts = accounts.where{ (lower(full_name).like_any names) |
97
+ (lower(last_name).like_any names) |
98
+ (lower(first_name).like_any names) }
94
99
  end
95
100
 
96
101
  with.keyword :id do |ids|
97
- users = users.where{openstax_uid.in ids}
102
+ accounts = accounts.where{openstax_uid.in ids}
98
103
  end
99
104
 
100
105
  with.keyword :email do |emails|
101
- users = OpenStax::Accounts::User.where('0=1')
106
+ accounts = OpenStax::Accounts::Account.where('0=1')
102
107
  end
103
108
 
104
109
  # Rerun the queries above for 'any' terms (which are ones without a
@@ -107,13 +112,13 @@ module OpenStax
107
112
  with.keyword :any do |terms|
108
113
  names = prep_names(terms)
109
114
 
110
- users = users.where{
111
- ( lower(username).like_any my{prep_usernames(terms)}) |
112
- (lower(first_name).like_any names) |
113
- (lower(last_name).like_any names) |
114
- (lower(full_name).like_any names) |
115
- (id.in terms)
116
- }
115
+ accounts = accounts.where{
116
+ ( lower(username).like_any my{prep_usernames(terms)}) |
117
+ (lower(first_name).like_any names) |
118
+ (lower(last_name).like_any names) |
119
+ (lower(full_name).like_any names) |
120
+ (id.in terms)
121
+ }
117
122
  end
118
123
 
119
124
  end
@@ -123,14 +128,15 @@ module OpenStax
123
128
  page = options[:page] || 0
124
129
  per_page = options[:per_page] || 20
125
130
 
126
- users = users.limit(per_page).offset(per_page*page)
131
+ accounts = accounts.limit(per_page).offset(per_page*page)
127
132
 
128
133
  #
129
134
  # Ordering
130
135
  #
131
136
 
132
137
  # Parse the input
133
- order_bys = (options[:order_by] || 'username').split(',').collect{|ob| ob.strip.split(' ')}
138
+ order_bys = (options[:order_by] || 'username').split(',')
139
+ .collect{|ob| ob.strip.split(' ')}
134
140
 
135
141
  # Toss out bad input, provide default direction
136
142
  order_bys = order_bys.collect do |order_by|
@@ -151,25 +157,26 @@ module OpenStax
151
157
 
152
158
  # Make the ordering call
153
159
  order_bys.each do |order_by|
154
- users = users.order(order_by)
160
+ accounts = accounts.order(order_by)
155
161
  end
156
162
 
157
163
  # Translate to routine outputs
158
164
 
159
- outputs[:users] = users
165
+ outputs[:accounts] = accounts
160
166
  outputs[:query] = query
161
167
  outputs[:per_page] = per_page
162
168
  outputs[:page] = page
163
- outputs[:order_by] = order_bys.join(', ') # convert back to one string
164
- outputs[:num_matching_users] = users.except(:offset, :limit, :order).count
169
+ outputs[:order_by] = order_bys.join(', ') # Convert back to String
170
+ outputs[:num_matching_accounts] = accounts
171
+ .except(:offset, :limit, :order).count
165
172
 
166
173
  end
167
174
 
168
175
  # Return no results if query exceeds maximum allowed number of matches
169
- max_users = options[:max_matching_users] || \
170
- OpenStax::Accounts.configuration.max_matching_users
171
- outputs[:users] = OpenStax::Accounts::User.where('0=1') \
172
- if outputs[:num_matching_users] > max_users
176
+ max_accounts = options[:max_matching_accounts] || \
177
+ OpenStax::Accounts.configuration.max_matching_accounts
178
+ outputs[:accounts] = OpenStax::Accounts::Account.where('0=1') \
179
+ if outputs[:num_matching_accounts] > max_accounts
173
180
 
174
181
  end
175
182
 
@@ -180,7 +187,9 @@ module OpenStax
180
187
  end
181
188
 
182
189
  def prep_usernames(usernames)
183
- usernames.collect{|username| username.gsub(OpenStax::Accounts::User::USERNAME_DISCARDED_CHAR_REGEX, '').downcase + '%'}
190
+ usernames.collect{|username| username.gsub(
191
+ OpenStax::Accounts::Account::USERNAME_DISCARDED_CHAR_REGEX, '')
192
+ .downcase + '%'}
184
193
  end
185
194
 
186
195
  end
@@ -0,0 +1,47 @@
1
+ # Routine for getting account updates from the Accounts server
2
+ #
3
+ # Should be scheduled to run regularly
4
+
5
+ module OpenStax
6
+ module Accounts
7
+
8
+ class SyncAccounts
9
+
10
+ SYNC_ATTRIBUTES = ['username', 'first_name', 'last_name',
11
+ 'full_name', 'title']
12
+
13
+ lev_routine transaction: :no_transaction
14
+
15
+ protected
16
+
17
+ def exec(options={})
18
+
19
+ return if OpenStax::Accounts.configuration.enable_stubbing?
20
+
21
+ response = OpenStax::Accounts.get_application_account_updates
22
+
23
+ app_accounts = []
24
+ app_accounts_rep = OpenStax::Accounts::Api::V1::ApplicationAccountsRepresenter
25
+ .new(app_accounts)
26
+ app_accounts_rep.from_json(response.body)
27
+
28
+ return if app_accounts.empty?
29
+
30
+ app_accounts_hash = {}
31
+ app_accounts.each do |app_account|
32
+ account = OpenStax::Accounts::Account.where(
33
+ :openstax_uid => app_account.account.openstax_uid).first
34
+ account.syncing_with_accounts = true
35
+ next unless account.update_attributes(
36
+ app_account.account.attributes.slice(*SYNC_ATTRIBUTES))
37
+ app_accounts_hash[app_account.id] = app_account.unread_updates
38
+ end
39
+
40
+ OpenStax::Accounts.mark_updates_as_read(app_accounts_hash)
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -1,13 +1,13 @@
1
1
  <%
2
2
  page = @handler_result.outputs[:page]
3
- num_users = @handler_result.outputs[:num_matching_users]
3
+ num_accounts = @handler_result.outputs[:num_matching_accounts]
4
4
  per_page = @handler_result.outputs[:per_page]
5
- pages = (num_users * 1.0 / per_page).ceil
6
- users = @handler_result.outputs[:users]
5
+ pages = (num_accounts * 1.0 / per_page).ceil
6
+ accounts = @handler_result.outputs[:accounts]
7
7
  %>
8
8
 
9
9
  <div id='search-results-pagination'>
10
- <%= pluralize(num_users, 'user') %> found.
10
+ <%= pluralize(num_accounts, 'user') %> found.
11
11
 
12
12
  <% if pages > 0 %>
13
13
  Page:
@@ -25,25 +25,25 @@
25
25
  <% linked_page_numbers.each do |lpn| %>
26
26
  <%= link_to_unless lpn == page + 1,
27
27
  lpn,
28
- dev_users_path(search: {terms: @handler_result.outputs[:query], page: lpn-1, per_page: per_page}), remote: true %>
28
+ dev_accounts_path(search: {terms: @handler_result.outputs[:query], page: lpn-1, per_page: per_page}), remote: true %>
29
29
  <% end %>
30
30
  <% end %>
31
31
  </div>
32
32
 
33
33
  <%= osu.action_list(
34
- records: users,
34
+ records: accounts,
35
35
  list: {
36
36
  headings: ['Username', 'First Name', 'Last Name', ''],
37
37
  widths: ['25%', '25%', '25%', '25%'],
38
38
  data_procs:
39
39
  [
40
- Proc.new { |user| user.username },
41
- Proc.new { |user| user.first_name || '---' },
42
- Proc.new { |user| user.last_name || '---' },
43
- Proc.new { |user|
44
- link_to 'Sign in as',
45
- become_dev_user_path(user),
46
- method: :post
40
+ Proc.new { |account| account.username },
41
+ Proc.new { |account| account.first_name || '---' },
42
+ Proc.new { |account| account.last_name || '---' },
43
+ Proc.new { |account|
44
+ link_to 'Sign in as',
45
+ with_interceptor { become_dev_account_path(account) },
46
+ method: :post
47
47
  }
48
48
  ]
49
49
  }
@@ -9,9 +9,9 @@
9
9
  <p>You need to login, but we're not connected to the Accounts server.
10
10
  Search for a user below and click the sign in link next to him or her.</p>
11
11
 
12
- <%= render 'openstax/accounts/shared/users/index',
13
- :search_action_path => openstax_accounts.dev_users_path,
14
- :remote => true %>
12
+ <%= with_interceptor { render 'openstax/accounts/shared/accounts/index',
13
+ :search_action_path => openstax_accounts.dev_accounts_path,
14
+ :remote => true } %>
15
15
 
16
16
  <% end %>
17
17
 
@@ -1,3 +1,3 @@
1
1
  <%= unless_errors alerts_html_id: 'dialog-local-alerts' do %>
2
- $("#search-results-list").html("<%= j(render 'openstax/accounts/dev/users/search_results') %>");
2
+ $("#search-results-list").html("<%= j(render 'openstax/accounts/dev/accounts/search_results') %>");
3
3
  <% end %>
@@ -1,6 +1,8 @@
1
1
  <%
2
2
  # Clients of this partial can override the following variables:
3
3
  search_action_path ||= nil
4
+ results_list_id ||= 'search-results-list'
5
+ method ||= :post
4
6
  remote ||= false
5
7
  form_html ||= {id: 'search-form',
6
8
  class: 'form-inline'}
@@ -10,6 +12,7 @@
10
12
  <%= lev_form_for :search,
11
13
  url: search_action_path,
12
14
  remote: remote,
15
+ method: method,
13
16
  html: form_html do |f| %>
14
17
 
15
18
  Search for
@@ -21,4 +24,4 @@
21
24
 
22
25
  <% end %>
23
26
 
24
- <div id="search-results-list"></div>
27
+ <div id=<%= results_list_id %>></div>
@@ -0,0 +1,14 @@
1
+ ActionInterceptor.configure do
2
+
3
+ interceptor :authenticate_user! do
4
+ account = current_account
5
+
6
+ return if account && !account.is_anonymous?
7
+
8
+ respond_to do |format|
9
+ format.html { redirect_to registration_path }
10
+ format.json { head(:forbidden) }
11
+ end
12
+ end
13
+
14
+ end
data/config/routes.rb CHANGED
@@ -1,26 +1,29 @@
1
1
  OpenStax::Accounts::Engine.routes.draw do
2
- get '/auth/openstax/callback', to: 'sessions#omniauth_authenticated' #omniauth route
2
+
3
+ # Redirect here if we don't know what to do (theoretically should not happen)
4
+ root :to => 'sessions#new'
5
+
6
+ # Shortcut to OmniAuth route that redirects to the Accounts server
7
+ # This is provided by OmniAuth and is not in the SessionsController
3
8
  get '/auth/openstax', :as => 'openstax_login'
4
9
 
5
- get 'sessions/new', :as => 'login'
6
- # See https://github.com/plataformatec/devise/commit/f3385e96abf50e80d2ae282e1fb9bdad87a83d3c
7
- match 'sessions/destroy', :as => 'logout',
8
- :via => OpenStax::Accounts.configuration.logout_via
10
+ # OmniAuth local routes (SessionsController)
11
+ resource :session, :only => [], :path => '', :as => '' do
12
+ get 'callback', :path => 'auth/:provider/callback' # Authentication success
13
+ get 'failure', :path => 'auth/failure' # Authentication failure
14
+
15
+ get 'login', :to => :new # Redirects to /auth/openstax or stub
16
+ match 'logout', :to => :destroy, # Redirects to logout path or stub
17
+ :via => OpenStax::Accounts.configuration.logout_via
18
+ end
9
19
 
10
20
  if OpenStax::Accounts.configuration.enable_stubbing?
11
21
  namespace :dev do
12
- resources :users, :only => [:index] do
13
- collection do
14
- get 'login'
15
- post 'index'
16
- end
17
-
22
+ resources :accounts, :only => [:index] do
23
+ post 'index', :on => :collection
18
24
  post 'become', :on => :member
19
25
  end
20
26
  end
21
27
  end
22
- end
23
28
 
24
- hh = OpenStax::Accounts::Engine.routes.url_helpers
25
-
26
- OpenStax::Accounts::RouteHelper.register_path(:login, hh.openstax_login_path) { hh.login_dev_users_path }
29
+ end
@@ -0,0 +1,22 @@
1
+ class CreateOpenStaxAccountsAccounts < ActiveRecord::Migration
2
+ def change
3
+ create_table :openstax_accounts_accounts do |t|
4
+ t.integer :openstax_uid, :null => false
5
+ t.string :username, :null => false
6
+ t.string :access_token
7
+ t.string :first_name
8
+ t.string :last_name
9
+ t.string :full_name
10
+ t.string :title
11
+
12
+ t.timestamps
13
+ end
14
+
15
+ add_index :openstax_accounts_accounts, :openstax_uid, :unique => true
16
+ add_index :openstax_accounts_accounts, :username, :unique => true
17
+ add_index :openstax_accounts_accounts, :access_token, :unique => true
18
+ add_index :openstax_accounts_accounts, :first_name
19
+ add_index :openstax_accounts_accounts, :last_name
20
+ add_index :openstax_accounts_accounts, :full_name
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  Description:
2
- Creates a "whenever" task that checks for updates from Accounts.
2
+ Creates a "whenever" task that checks for updates from the Accounts server.
3
3
 
4
4
  Example:
5
5
  rails generate openstax:accounts:schedule
@@ -1,3 +1,3 @@
1
1
  every 5.minutes do
2
- runner "OpenStax::Accounts::SyncUsers.call"
2
+ runner "OpenStax::Accounts::SyncAccounts.call"
3
3
  end
@@ -2,102 +2,111 @@ module OpenStax
2
2
  module Accounts
3
3
  class CurrentUserManager
4
4
 
5
- # References:
6
- # http://railscasts.com/episodes/356-dangers-of-session-hijacking
7
-
8
5
  def initialize(request, session, cookies)
9
6
  @request = request
10
7
  @session = session
11
8
  @cookies = cookies
12
9
  end
13
10
 
14
- # Returns the current app user
11
+ # Returns the current account
12
+ def current_account
13
+ load_session
14
+ @current_account
15
+ end
16
+
17
+ # Returns the current user
15
18
  def current_user
16
- load_current_users
17
- @app_current_user
19
+ load_session
20
+ @current_user
18
21
  end
19
22
 
20
- # Signs in the given user; the argument can be either an accounts user or
21
- # an app user
22
- def sign_in(user)
23
- user.is_a?(User) ?
24
- self.accounts_current_user = user :
23
+ # Signs in the given user or account
24
+ def sign_in!(user)
25
+ user.is_a?(Account) ?
26
+ self.current_account = user :
25
27
  self.current_user = user
26
28
  end
27
29
 
28
- # Signs out the user
30
+ alias_method :sign_in, :sign_in!
31
+
32
+ # Signs out the currently signed in user
29
33
  def sign_out!
30
- sign_in(OpenStax::Accounts::User.anonymous)
34
+ self.current_account = AnonymousAccount.instance
31
35
  end
32
36
 
37
+ alias_method :sign_out, :sign_out!
38
+
33
39
  # Returns true iff there is a user signed in
34
40
  def signed_in?
35
- !accounts_current_user.is_anonymous?
41
+ !current_account.is_anonymous?
36
42
  end
37
43
 
38
- # Returns the current accounts user
39
- def accounts_current_user
40
- load_current_users
41
- @accounts_current_user
42
- end
43
-
44
- protected
45
-
46
- # If they are nil (unset), sets the current users based on the session state
47
- def load_current_users
48
- return if !@accounts_current_user.nil?
44
+ protected
49
45
 
50
- if @request.ssl? && @cookies.signed[:secure_user_id] != "secure#{@session[:user_id]}"
51
- sign_out! # hijacked
46
+ # Sets the session state based on the given account
47
+ def set_session(account)
48
+ if account.is_anonymous?
49
+ @session[:account_id] = nil
50
+ @cookies.delete(:secure_account_id)
52
51
  else
53
- # If there is a session user_id, load up that user, otherwise set the anonymous user.
54
-
55
- if @session[:user_id]
56
- @accounts_current_user = User.where(id: @session[:user_id]).first
57
-
58
- # It could happen (normally in development) that there is a session
59
- # user_id that doesn't map to a User in the db.
60
- # In such a case, sign_out! to reset the state
61
- if @accounts_current_user.nil?
62
- sign_out!
63
- return
64
- end
65
- else
66
- @accounts_current_user = User.anonymous
67
- end
68
-
69
- # Bring the app user inline with the accounts user
70
- @app_current_user = user_provider.accounts_user_to_app_user(@accounts_current_user)
52
+ @session[:account_id] = account.id
53
+ @cookies.signed[:secure_account_id] = { secure: true,
54
+ httponly: true, value: "secure#{account.id}" }
71
55
  end
72
56
  end
73
57
 
74
- # Sets (signs in) the provided app user.
75
- def current_user=(user)
76
- self.accounts_current_user = user_provider.app_user_to_accounts_user(user)
77
- @app_current_user
78
- end
79
-
80
- # Sets the current accounts user, updates the app user, and also updates
81
- # the session and cookie state.
82
- def accounts_current_user=(user)
83
- @accounts_current_user = user || User.anonymous
84
- @app_current_user = user_provider.accounts_user_to_app_user(@accounts_current_user)
58
+ # If not already loaded, sets the current user and current account
59
+ # based on the session state
60
+ def load_session
61
+ return unless @current_account.nil?
62
+
63
+ # Sign the user out to reset the session if the request is SSL
64
+ # and the signed secure ID doesn't match the unsecure ID
65
+ # http://railscasts.com/episodes/356-dangers-of-session-hijacking
66
+ if @request.ssl? && \
67
+ @cookies.signed[:secure_account_id] != "secure#{@session[:account_id]}"
68
+ sign_out!
69
+ return
70
+ end
85
71
 
86
- if @accounts_current_user.is_anonymous?
87
- @session[:user_id] = nil
88
- @cookies.delete(:secure_user_id)
72
+ # If there is a session account_id, load up that account,
73
+ # otherwise set the anonymous account.
74
+ if @session[:account_id]
75
+ @current_account = Account.where(id: @session[:account_id]).first
76
+
77
+ # It could happen (normally in development) that there is a session
78
+ # account_id that doesn't map to an Account in the db.
79
+ # In such a case, sign_out! to reset the state
80
+ if @current_account.nil?
81
+ sign_out!
82
+ return
83
+ end
89
84
  else
90
- @session[:user_id] = @accounts_current_user.id
91
- @cookies.signed[:secure_user_id] = {secure: true, value: "secure#{@accounts_current_user.id}"}
85
+ @current_account = AnonymousAccount.instance
92
86
  end
93
87
 
94
- @accounts_current_user
88
+ # Bring the user inline with the account
89
+ @current_user = account_user_mapper.account_to_user(@current_account)
90
+ end
91
+
92
+ # Sets the current account, updates the session and loads it
93
+ def current_account=(account)
94
+ set_session(account)
95
+ @current_user = account_user_mapper.account_to_user(account)
96
+ @current_account = account
97
+ end
98
+
99
+ # Sets (signs in) the provided user, as above
100
+ def current_user=(user)
101
+ @current_account = account_user_mapper.user_to_account(user)
102
+ set_session(@current_account)
103
+ @current_user = user
95
104
  end
96
105
 
97
- def user_provider
98
- OpenStax::Accounts.configuration.user_provider
106
+ def account_user_mapper
107
+ OpenStax::Accounts.configuration.account_user_mapper
99
108
  end
100
109
 
101
110
  end
102
111
  end
103
- end
112
+ end
@@ -0,0 +1,15 @@
1
+ module OpenStax
2
+ module Accounts
3
+ class DefaultAccountUserMapper
4
+
5
+ def self.account_to_user(account)
6
+ account
7
+ end
8
+
9
+ def self.user_to_account(user)
10
+ user
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -5,6 +5,8 @@ require 'roar/decorator'
5
5
  require 'roar/representer/json'
6
6
  require 'keyword_search'
7
7
  require 'squeel'
8
+ require 'action_interceptor'
9
+ require 'openstax/accounts/extend_builtins'
8
10
 
9
11
  ActiveSupport::Inflector.inflections do |inflect|
10
12
  inflect.acronym 'OpenStax'