openstax_accounts 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +20 -0
- data/app/controllers/openstax/accounts/dev/base_controller.rb +19 -0
- data/app/controllers/openstax/accounts/dev/users_controller.rb +10 -9
- data/app/handlers/openstax/accounts/dev/users_index.rb +39 -0
- data/app/handlers/openstax/accounts/sessions_omniauth_authenticated.rb +2 -1
- data/app/models/openstax/accounts/application_user.rb +7 -0
- data/app/models/openstax/accounts/user.rb +15 -3
- data/app/representers/openstax/accounts/api/v1/application_user_representer.rb +5 -1
- data/app/representers/openstax/accounts/api/v1/application_user_search_representer.rb +19 -0
- data/app/representers/openstax/accounts/api/v1/application_users_representer.rb +16 -0
- data/app/representers/openstax/accounts/api/v1/user_representer.rb +2 -6
- data/app/routines/openstax/accounts/dev/create_user.rb +4 -4
- data/app/routines/openstax/accounts/dev/search_users.rb +27 -0
- data/app/routines/openstax/accounts/search_users.rb +174 -32
- data/app/routines/openstax/accounts/sync_users.rb +44 -0
- data/app/views/openstax/accounts/dev/users/_search_results.html.erb +50 -0
- data/app/views/openstax/accounts/dev/users/index.js.erb +3 -0
- data/app/views/openstax/accounts/dev/users/login.html.erb +6 -5
- data/app/views/openstax/accounts/shared/_attention.html.erb +1 -1
- data/app/views/openstax/accounts/shared/users/_index.html.erb +24 -0
- data/config/routes.rb +5 -4
- data/lib/generators/openstax/accounts/schedule/USAGE +8 -0
- data/lib/generators/openstax/accounts/schedule/schedule_generator.rb +18 -0
- data/lib/generators/openstax/accounts/schedule/templates/schedule.rb +3 -0
- data/lib/omniauth/strategies/openstax.rb +1 -1
- data/lib/openstax/accounts/engine.rb +2 -0
- data/lib/openstax/accounts/version.rb +1 -1
- data/lib/openstax_accounts.rb +69 -26
- data/spec/controllers/openstax/accounts/dev/users_controller_spec.rb +4 -3
- data/spec/dummy/app/controllers/api/application_users_controller.rb +12 -0
- data/spec/dummy/config/application.rb +3 -0
- data/spec/dummy/config/initializers/openstax_accounts.rb +1 -0
- data/spec/dummy/config/routes.rb +5 -4
- data/spec/lib/openstax_accounts_spec.rb +19 -11
- data/spec/routines/openstax/accounts/dev/create_user_spec.rb +26 -0
- data/spec/routines/openstax/accounts/search_users_spec.rb +129 -0
- metadata +47 -68
- data/app/controllers/openstax/accounts/dev/dev_controller.rb +0 -13
- data/app/handlers/openstax/accounts/dev/users_search.rb +0 -38
- data/app/representers/openstax/accounts/api/v1/contact_info_representer.rb +0 -23
- data/app/representers/openstax/accounts/api/v1/email_address_representer.rb +0 -9
- data/app/views/openstax/accounts/dev/users/search.js.erb +0 -21
- data/app/views/openstax/accounts/users/_action_create_form.html.erb +0 -9
- data/app/views/openstax/accounts/users/_action_dialog.html.erb +0 -10
- data/app/views/openstax/accounts/users/_action_list.html.erb +0 -33
- data/app/views/openstax/accounts/users/_action_search.html.erb +0 -25
- data/app/views/openstax/accounts/users/action_search.js.erb +0 -8
- data/spec/dummy/app/controllers/api/users_controller.rb +0 -7
@@ -0,0 +1,44 @@
|
|
1
|
+
# Routine for getting user updates from Accounts
|
2
|
+
#
|
3
|
+
# Should be scheduled to run regularly
|
4
|
+
|
5
|
+
module OpenStax
|
6
|
+
module Accounts
|
7
|
+
|
8
|
+
class SyncUsers
|
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.application_users_updates
|
22
|
+
|
23
|
+
app_users = []
|
24
|
+
app_users_rep = OpenStax::Accounts::Api::V1::ApplicationUsersRepresenter.new(app_users)
|
25
|
+
app_users_rep.from_json(response.body)
|
26
|
+
|
27
|
+
return if app_users.empty?
|
28
|
+
|
29
|
+
app_users_hash = {}
|
30
|
+
app_users.each do |app_user|
|
31
|
+
user = OpenStax::Accounts::User.where(:openstax_uid => app_user.user.openstax_uid).first
|
32
|
+
user.updating_from_accounts = true
|
33
|
+
next unless user.update_attributes(app_user.user.attributes.slice(*SYNC_ATTRIBUTES))
|
34
|
+
app_users_hash[app_user.id] = app_user.unread_updates
|
35
|
+
end
|
36
|
+
|
37
|
+
OpenStax::Accounts.application_users_updated(app_users_hash)
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<%
|
2
|
+
page = @handler_result.outputs[:page]
|
3
|
+
num_users = @handler_result.outputs[:num_matching_users]
|
4
|
+
per_page = @handler_result.outputs[:per_page]
|
5
|
+
pages = (num_users * 1.0 / per_page).ceil
|
6
|
+
users = @handler_result.outputs[:users]
|
7
|
+
%>
|
8
|
+
|
9
|
+
<div id='search-results-pagination'>
|
10
|
+
<%= pluralize(num_users, 'user') %> found.
|
11
|
+
|
12
|
+
<% if pages > 0 %>
|
13
|
+
Page:
|
14
|
+
|
15
|
+
<%
|
16
|
+
linked_page_numbers = [page+1]
|
17
|
+
linked_page_numbers.push(1)
|
18
|
+
linked_page_numbers.push(pages)
|
19
|
+
linked_page_numbers.push(page+1-1, page+1-2, page+1+1, page+1+2)
|
20
|
+
linked_page_numbers.reject!{|pp| pp < 1 || pp > pages}
|
21
|
+
linked_page_numbers.uniq!
|
22
|
+
linked_page_numbers.sort!
|
23
|
+
%>
|
24
|
+
|
25
|
+
<% linked_page_numbers.each do |lpn| %>
|
26
|
+
<%= link_to_unless lpn == page + 1,
|
27
|
+
lpn,
|
28
|
+
dev_users_path(search: {terms: @handler_result.outputs[:query], page: lpn-1, per_page: per_page}), remote: true %>
|
29
|
+
<% end %>
|
30
|
+
<% end %>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<%= osu.action_list(
|
34
|
+
records: users,
|
35
|
+
list: {
|
36
|
+
headings: ['Username', 'First Name', 'Last Name', ''],
|
37
|
+
widths: ['25%', '25%', '25%', '25%'],
|
38
|
+
data_procs:
|
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
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
) %>
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
<div class="openstax-accounts development-login">
|
3
2
|
|
4
3
|
<% handler_errors.each do |error| %>
|
@@ -7,11 +6,13 @@
|
|
7
6
|
|
8
7
|
<%= osu.section_block "Development Login" do %>
|
9
8
|
|
10
|
-
<p>You need to login, but we're not connected to the Accounts server.
|
11
|
-
|
9
|
+
<p>You need to login, but we're not connected to the Accounts server.
|
10
|
+
Search for a user below and click the sign in link next to him or her.</p>
|
12
11
|
|
13
|
-
<%= render 'openstax/accounts/users/
|
12
|
+
<%= render 'openstax/accounts/shared/users/index',
|
13
|
+
:search_action_path => openstax_accounts.dev_users_path,
|
14
|
+
:remote => true %>
|
14
15
|
|
15
16
|
<% end %>
|
16
17
|
|
17
|
-
</div>
|
18
|
+
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%
|
2
|
+
# Clients of this partial can override the following variables:
|
3
|
+
search_action_path ||= nil
|
4
|
+
remote ||= false
|
5
|
+
form_html ||= {id: 'search-form',
|
6
|
+
class: 'form-inline'}
|
7
|
+
search_types ||= ['Any', 'Username', 'Email']
|
8
|
+
%>
|
9
|
+
|
10
|
+
<%= lev_form_for :search,
|
11
|
+
url: search_action_path,
|
12
|
+
remote: remote,
|
13
|
+
html: form_html do |f| %>
|
14
|
+
|
15
|
+
Search for
|
16
|
+
<%= f.search_field :terms, style: 'width:300px' %>
|
17
|
+
in
|
18
|
+
<%= f.select :type, search_types, {}, {style: 'width: 150px'} %>
|
19
|
+
|
20
|
+
<%= f.submit 'Search', class: 'btn btn-primary' %>
|
21
|
+
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<div id="search-results-list"></div>
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
OpenStax::Accounts::Engine.routes.draw do
|
2
|
-
|
2
|
+
get '/auth/openstax/callback', to: 'sessions#omniauth_authenticated' #omniauth route
|
3
3
|
get '/auth/openstax', :as => 'openstax_login'
|
4
4
|
|
5
5
|
get 'sessions/new', :as => 'login'
|
@@ -9,12 +9,13 @@ OpenStax::Accounts::Engine.routes.draw do
|
|
9
9
|
|
10
10
|
if OpenStax::Accounts.configuration.enable_stubbing?
|
11
11
|
namespace :dev do
|
12
|
-
resources :users, :only => [] do
|
12
|
+
resources :users, :only => [:index] do
|
13
13
|
collection do
|
14
14
|
get 'login'
|
15
|
-
post '
|
16
|
-
post 'become'
|
15
|
+
post 'index'
|
17
16
|
end
|
17
|
+
|
18
|
+
post 'become', :on => :member
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Can't use OpenStax. See https://github.com/rails/rails/issues/13856
|
2
|
+
module Openstax
|
3
|
+
module Accounts
|
4
|
+
class ScheduleGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def generate_schedule
|
8
|
+
if File.exists?(File.expand_path('config/schedule.rb'))
|
9
|
+
File.open(File.expand_path('../templates/schedule.rb', __FILE__)) do |file|
|
10
|
+
append_file 'config/schedule.rb', file.read
|
11
|
+
end
|
12
|
+
else
|
13
|
+
copy_file 'schedule.rb', 'config/schedule.rb'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/openstax_accounts.rb
CHANGED
@@ -6,12 +6,14 @@ require 'openstax/accounts/user_provider'
|
|
6
6
|
require 'openstax/accounts/current_user_manager'
|
7
7
|
|
8
8
|
require 'openstax_utilities'
|
9
|
-
require 'uri'
|
10
9
|
require 'oauth2'
|
10
|
+
require 'uri'
|
11
11
|
|
12
12
|
module OpenStax
|
13
13
|
module Accounts
|
14
14
|
|
15
|
+
DEFAULT_API_VERSION = :v1
|
16
|
+
|
15
17
|
class << self
|
16
18
|
|
17
19
|
###########################################################################
|
@@ -27,9 +29,6 @@ module OpenStax
|
|
27
29
|
# ...
|
28
30
|
# end
|
29
31
|
#
|
30
|
-
# Set enable_stubbing to true iff you want this engine to fake all
|
31
|
-
# interaction with the accounts site.
|
32
|
-
#
|
33
32
|
|
34
33
|
def configure
|
35
34
|
yield configuration
|
@@ -40,26 +39,50 @@ module OpenStax
|
|
40
39
|
end
|
41
40
|
|
42
41
|
class Configuration
|
42
|
+
# openstax_accounts_url
|
43
|
+
# Base URL for OpenStax Accounts
|
44
|
+
attr_reader :openstax_accounts_url
|
45
|
+
|
46
|
+
# openstax_application_id
|
47
|
+
# OAuth client_id received from OpenStax Accounts
|
43
48
|
attr_accessor :openstax_application_id
|
49
|
+
|
50
|
+
# openstax_application_secret
|
51
|
+
# OAuth client_secret received from OpenStax Accounts
|
44
52
|
attr_accessor :openstax_application_secret
|
53
|
+
|
54
|
+
# enable_stubbing
|
55
|
+
# Set to true if you want this engine to fake all
|
56
|
+
# interaction with the accounts site.
|
45
57
|
attr_accessor :enable_stubbing
|
46
|
-
|
58
|
+
|
59
|
+
# logout_via
|
60
|
+
# HTTP method to accept for logout requests
|
47
61
|
attr_accessor :logout_via
|
62
|
+
|
48
63
|
attr_accessor :default_errors_partial
|
49
64
|
attr_accessor :default_errors_html_id
|
50
65
|
attr_accessor :default_errors_added_trigger
|
66
|
+
|
67
|
+
# security_transgression_exception
|
68
|
+
# Class to be used for security transgression exceptions
|
51
69
|
attr_accessor :security_transgression_exception
|
52
70
|
|
53
|
-
# See the "user_provider" discussion in the README
|
71
|
+
# See the "user_provider" discussion in the README
|
54
72
|
attr_accessor :user_provider
|
55
73
|
|
74
|
+
# The maximum number of users that can be returned in a call to SearchUsers
|
75
|
+
# If more would be returned, the result will be empty instead
|
76
|
+
# Can also be passed directly to SearchUsers
|
77
|
+
attr_accessor :max_matching_users
|
78
|
+
|
56
79
|
def openstax_accounts_url=(url)
|
57
80
|
url.gsub!(/https|http/,'https') if !(url =~ /localhost/)
|
58
81
|
url = url + "/" if url[url.size-1] != '/'
|
59
82
|
@openstax_accounts_url = url
|
60
83
|
end
|
61
84
|
|
62
|
-
def initialize
|
85
|
+
def initialize
|
63
86
|
@openstax_application_id = 'SET ME!'
|
64
87
|
@openstax_application_secret = 'SET ME!'
|
65
88
|
@openstax_accounts_url = 'https://accounts.openstax.org/'
|
@@ -70,6 +93,7 @@ module OpenStax
|
|
70
93
|
@default_errors_added_trigger = 'openstax-accounts-errors-added'
|
71
94
|
@security_transgression_exception = SecurityTransgression
|
72
95
|
@user_provider = OpenStax::Accounts::UserProvider
|
96
|
+
@max_matching_users = 10
|
73
97
|
super
|
74
98
|
end
|
75
99
|
|
@@ -96,43 +120,62 @@ module OpenStax
|
|
96
120
|
|
97
121
|
token_string = options.delete(:access_token)
|
98
122
|
token = token_string.blank? ? client.client_credentials.get_token :
|
99
|
-
|
123
|
+
OAuth2::AccessToken.new(client, token_string)
|
100
124
|
|
101
125
|
api_url = URI.join(configuration.openstax_accounts_url, 'api/', url)
|
102
126
|
|
103
127
|
token.request(http_method, api_url, options)
|
104
128
|
end
|
105
129
|
|
106
|
-
#
|
107
|
-
# and
|
108
|
-
#
|
130
|
+
# Performs an ApplicationUser search in Accounts for the configured app.
|
131
|
+
# Takes a query parameter and an optional API version parameter.
|
132
|
+
# API version currently defaults to :v1 (may change in the future).
|
109
133
|
# On failure, throws an Exception, just like api_call.
|
110
134
|
# On success, returns an OAuth2::Response object.
|
111
|
-
def
|
112
|
-
options = {:
|
135
|
+
def application_users_index(query, version = DEFAULT_API_VERSION)
|
136
|
+
options = {:params => {:q => query},
|
113
137
|
:api_version => version}
|
114
|
-
api_call(:
|
138
|
+
api_call(:get, 'application_users', options)
|
115
139
|
end
|
116
140
|
|
117
|
-
#
|
118
|
-
# Takes a query parameter and an optional API version parameter.
|
119
|
-
# API version currently defaults to :v1.
|
141
|
+
# Retrieves information about ApplicationUsers that have been recently updated.
|
120
142
|
# On failure, throws an Exception, just like api_call.
|
121
143
|
# On success, returns an OAuth2::Response object.
|
122
|
-
def
|
123
|
-
options = {:
|
124
|
-
|
125
|
-
|
144
|
+
def application_users_updates(version = DEFAULT_API_VERSION)
|
145
|
+
options = {:api_version => version}
|
146
|
+
api_call(:get, 'application_users/updates', options)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Marks ApplicationUser updates as "read".
|
150
|
+
# The app_users parameter is a hash that maps ApplicationUser
|
151
|
+
# openstax_uid's to the value of the last received unread_updates.
|
152
|
+
# On failure, throws an Exception, just like api_call.
|
153
|
+
# On success, returns an OAuth2::Response object.
|
154
|
+
def application_users_updated(app_users, version = DEFAULT_API_VERSION)
|
155
|
+
options = {:api_version => version,
|
156
|
+
:body => {:application_users => app_users}}
|
157
|
+
api_call(:put, 'application_users/updated', options)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Updates an OpenStax::Accounts::User in Accounts for the configured app.
|
161
|
+
# Also takes an optional API version parameter.
|
162
|
+
# API version currently defaults to :v1 (may change in the future).
|
163
|
+
# On failure, throws an Exception, just like api_call.
|
164
|
+
# On success, returns an OAuth2::Response object.
|
165
|
+
def user_update(user, version = DEFAULT_API_VERSION)
|
166
|
+
options = {:access_token => user.access_token,
|
167
|
+
:api_version => version,
|
168
|
+
:body => user.attributes.slice('username', 'first_name',
|
169
|
+
'last_name', 'full_name', 'title').to_json}
|
170
|
+
api_call(:put, 'user', options)
|
126
171
|
end
|
127
172
|
|
128
|
-
|
173
|
+
protected
|
129
174
|
|
130
175
|
def client
|
131
|
-
@client ||= OAuth2::Client.new(
|
132
|
-
configuration.openstax_application_id,
|
176
|
+
@client ||= OAuth2::Client.new(configuration.openstax_application_id,
|
133
177
|
configuration.openstax_application_secret,
|
134
|
-
:site => configuration.openstax_accounts_url
|
135
|
-
)
|
178
|
+
:site => configuration.openstax_accounts_url)
|
136
179
|
end
|
137
180
|
|
138
181
|
end
|
@@ -5,13 +5,14 @@ module OpenStax::Accounts
|
|
5
5
|
describe UsersController do
|
6
6
|
routes { OpenStax::Accounts::Engine.routes }
|
7
7
|
|
8
|
-
let!(:user) {
|
9
|
-
|
8
|
+
let!(:user) { user = FactoryGirl.create :openstax_accounts_user,
|
9
|
+
username: 'some_user',
|
10
|
+
openstax_uid: 10 }
|
10
11
|
|
11
12
|
it 'should allow users not in production to become other users' do
|
12
13
|
expect(controller.current_user).to eq(OpenStax::Accounts::User.anonymous)
|
13
14
|
expect(controller.current_user.is_anonymous?).to eq(true)
|
14
|
-
|
15
|
+
post :become, id: user.id
|
15
16
|
expect(controller.current_user).to eq(user)
|
16
17
|
expect(controller.current_user.is_anonymous?).to eq(false)
|
17
18
|
end
|