openstax_accounts 0.3 → 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
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Mjc2YjE2MDk2NTlkODU2NWVkNjJhYjAzZjY2MzRiZmMxOTRmZDNkZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NzZmMzllNDRiODQ1MWVhMmRjMWNmYWYxYzc4ODUzZjNiMjkyZWFlNA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YzgxYzZkMjI5NDc5NTk3ZjQyOGFjMDVjYThiNDg4NDY2MTM1MWRlZTI4YTQ2
|
10
|
+
NDE2MzVkNDc4YzI1ODNkMDQ3ZWU0YjFkNmQxZmY5YWU2YTQzM2VmZjI4Zjk0
|
11
|
+
MWI1MzkyMzQ0NzA1MmQxMGZkYjFiZmRlOGI4NDczYzc5ZjVlMjc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODRkZDMzMDEwNGQwNTRhYjU5NzkwODU5YzljZGE4YzhiZWUwNDkzMzkwMWMx
|
14
|
+
ZmEwMmNlYTUzZDVjY2VhYzg5MWJiNzJkZjcwYjQ3MjVmZjE0ZTAwOGJjOWRl
|
15
|
+
MTE5ODIxN2NjYTY1MzFiZjI5NjNjMjE4ZTIwNTBlNzI5N2RlNDM=
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
accounts-rails
|
2
2
|
=============
|
3
3
|
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/openstax_accounts.svg)](http://badge.fury.io/rb/openstax_accounts)
|
5
|
+
[![Build Status](https://travis-ci.org/openstax/accounts-rails.svg?branch=master)](https://travis-ci.org/openstax/accounts-rails)
|
6
|
+
|
4
7
|
A rails engine for interfacing with OpenStax's accounts server.
|
5
8
|
|
6
9
|
Usage
|
@@ -75,6 +78,23 @@ Make sure to install the engine's migrations:
|
|
75
78
|
|
76
79
|
rake openstax_accounts:install:migrations
|
77
80
|
|
81
|
+
Syncing with Accounts
|
82
|
+
---------------------
|
83
|
+
|
84
|
+
OpenStax::Accounts requires your app to periodically sync user information with the Accounts server. The easiest way to do this is to use the "whenever" gem.
|
85
|
+
|
86
|
+
To create or append to the schedule.rb file, run the following command:
|
87
|
+
|
88
|
+
```sh
|
89
|
+
rails g openstax:accounts:schedule
|
90
|
+
```
|
91
|
+
|
92
|
+
Then, after installing the "whenever" gem, run the `whenever` command for instructions to set up your crontab:
|
93
|
+
|
94
|
+
```sh
|
95
|
+
whenever
|
96
|
+
```
|
97
|
+
|
78
98
|
Accounts API
|
79
99
|
------------
|
80
100
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module OpenStax
|
2
|
+
module Accounts
|
3
|
+
module Dev
|
4
|
+
class BaseController < OpenStax::Accounts::ApplicationController
|
5
|
+
|
6
|
+
before_filter Proc.new{
|
7
|
+
raise SecurityTransgression if Rails.env.production?
|
8
|
+
}
|
9
|
+
|
10
|
+
skip_before_filter :authenticate_user!
|
11
|
+
skip_before_filter :require_registration!
|
12
|
+
|
13
|
+
fine_print_skip_signatures :general_terms_of_use, :privacy_policy \
|
14
|
+
if respond_to?(:fine_print_skip_signatures)
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
module OpenStax
|
2
2
|
module Accounts
|
3
3
|
module Dev
|
4
|
-
class UsersController < OpenStax::Accounts::Dev::
|
5
|
-
|
6
|
-
def login; end
|
4
|
+
class UsersController < OpenStax::Accounts::Dev::BaseController
|
7
5
|
|
8
|
-
def
|
9
|
-
handle_with(
|
10
|
-
complete: lambda { render '
|
6
|
+
def index
|
7
|
+
handle_with(UsersIndex,
|
8
|
+
complete: lambda { render 'index' })
|
11
9
|
end
|
12
10
|
|
11
|
+
def login; end
|
12
|
+
|
13
13
|
def become
|
14
|
-
|
15
|
-
|
14
|
+
@user = User.find(params[:id])
|
15
|
+
sign_in(@user)
|
16
|
+
redirect_to return_url
|
16
17
|
end
|
17
18
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
21
|
-
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module OpenStax
|
2
|
+
module Accounts
|
3
|
+
module Dev
|
4
|
+
class UsersIndex
|
5
|
+
|
6
|
+
lev_handler transaction: :no_transaction
|
7
|
+
|
8
|
+
paramify :search do
|
9
|
+
attribute :terms, type: String
|
10
|
+
attribute :type, type: String
|
11
|
+
attribute :page, type: Integer
|
12
|
+
end
|
13
|
+
|
14
|
+
uses_routine OpenStax::Accounts::Dev::SearchUsers,
|
15
|
+
as: :search_users,
|
16
|
+
translations: { outputs: {type: :verbatim} }
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def authorized?
|
21
|
+
!Rails.env.production?
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle
|
25
|
+
case search_params.type
|
26
|
+
when 'Name'
|
27
|
+
query = "name:#{search_params.terms.gsub(/\s/,',')}"
|
28
|
+
when 'Username'
|
29
|
+
query = "username:#{search_params.terms.gsub(/\s/,',')}"
|
30
|
+
else
|
31
|
+
query = search_params.terms || ''
|
32
|
+
end
|
33
|
+
run(:search_users, query, page: search_params.page || 0)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,11 +2,17 @@ module OpenStax
|
|
2
2
|
module Accounts
|
3
3
|
class User < ActiveRecord::Base
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
USERNAME_DISCARDED_CHAR_REGEX = /[^A-Za-z\d_]/
|
6
|
+
USERNAME_MAX_LENGTH = 50
|
7
|
+
|
8
|
+
attr_accessor :updating_from_accounts
|
9
|
+
|
10
|
+
validates :username, uniqueness: true, presence: true
|
7
11
|
validates :openstax_uid, presence: true
|
8
12
|
|
9
|
-
|
13
|
+
attr_accessible :username, :first_name, :last_name, :full_name, :title
|
14
|
+
|
15
|
+
before_update :update_openstax_accounts
|
10
16
|
|
11
17
|
def name
|
12
18
|
(first_name || last_name) ? [first_name, last_name].compact.join(" ") : username
|
@@ -26,6 +32,12 @@ module OpenStax
|
|
26
32
|
@@anonymous ||= AnonymousUser.new
|
27
33
|
end
|
28
34
|
|
35
|
+
def update_openstax_accounts
|
36
|
+
return if updating_from_accounts || \
|
37
|
+
OpenStax::Accounts.configuration.enable_stubbing?
|
38
|
+
OpenStax::Accounts.user_update(self)
|
39
|
+
end
|
40
|
+
|
29
41
|
class AnonymousUser < User
|
30
42
|
before_save { false }
|
31
43
|
def initialize(attributes=nil)
|
@@ -11,7 +11,11 @@ module OpenStax
|
|
11
11
|
property :application_id,
|
12
12
|
type: Integer
|
13
13
|
|
14
|
-
property :
|
14
|
+
property :user,
|
15
|
+
class: OpenStax::Accounts::User,
|
16
|
+
decorator: UserRepresenter
|
17
|
+
|
18
|
+
property :unread_updates,
|
15
19
|
type: Integer
|
16
20
|
|
17
21
|
property :default_contact_info_id,
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module OpenStax
|
2
|
+
module Accounts
|
3
|
+
module Api
|
4
|
+
module V1
|
5
|
+
class ApplicationUserSearchRepresenter < UserSearchRepresenter
|
6
|
+
|
7
|
+
collection :application_users,
|
8
|
+
class: OpenStax::Accounts::ApplicationUser,
|
9
|
+
decorator: ApplicationUserRepresenter,
|
10
|
+
schema_info: {
|
11
|
+
description: "The ApplicationUsers associated with the matching Users",
|
12
|
+
minItems: 0
|
13
|
+
}
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'representable/json/collection'
|
2
|
+
|
3
|
+
module OpenStax
|
4
|
+
module Accounts
|
5
|
+
module Api
|
6
|
+
module V1
|
7
|
+
class ApplicationUsersRepresenter < Roar::Decorator
|
8
|
+
include Representable::JSON::Collection
|
9
|
+
|
10
|
+
items class: OpenStax::Accounts::ApplicationUser,
|
11
|
+
decorator: ApplicationUserRepresenter
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,7 +5,8 @@ module OpenStax
|
|
5
5
|
class UserRepresenter < Roar::Decorator
|
6
6
|
include Roar::Representer::JSON
|
7
7
|
|
8
|
-
property :
|
8
|
+
property :openstax_uid,
|
9
|
+
as: :id,
|
9
10
|
type: Integer
|
10
11
|
|
11
12
|
property :username,
|
@@ -23,11 +24,6 @@ module OpenStax
|
|
23
24
|
property :title,
|
24
25
|
type: String
|
25
26
|
|
26
|
-
# TODO: Not yet implemented in this gem
|
27
|
-
# collection :contact_infos,
|
28
|
-
# class: OpenStax::Accounts::ContactInfo,
|
29
|
-
# decorator: ContactInfoRepresenter
|
30
|
-
|
31
27
|
end
|
32
28
|
end
|
33
29
|
end
|
@@ -4,14 +4,14 @@ module OpenStax
|
|
4
4
|
class CreateUser
|
5
5
|
lev_routine
|
6
6
|
|
7
|
-
|
7
|
+
protected
|
8
8
|
|
9
9
|
def exec(inputs={})
|
10
10
|
|
11
11
|
username = inputs[:username]
|
12
12
|
|
13
13
|
if username.nil? || inputs[:ensure_no_errors]
|
14
|
-
loop do
|
14
|
+
loop do
|
15
15
|
break if !username.nil? && OpenStax::Accounts::User.where(username: username).none?
|
16
16
|
username = "#{inputs[:username] || 'user'}#{rand(1000000)}"
|
17
17
|
end
|
@@ -23,7 +23,7 @@ module OpenStax
|
|
23
23
|
user.username = username
|
24
24
|
user.openstax_uid = available_negative_openstax_uid
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
transfer_errors_from(outputs[:user], {type: :verbatim})
|
28
28
|
end
|
29
29
|
|
@@ -34,4 +34,4 @@ module OpenStax
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
|
-
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Routine for searching for users
|
2
|
+
#
|
3
|
+
# Caller provides a query and some options. The query follows the rules of
|
4
|
+
# https://github.com/bruce/keyword_search, e.g.:
|
5
|
+
#
|
6
|
+
# "username:jps,richb" --> returns the "jps" and "richb" users
|
7
|
+
# "name:John" --> returns Users with first, last, or full name starting with "John"
|
8
|
+
#
|
9
|
+
# Query terms can be combined, e.g. "username:jp first_name:john"
|
10
|
+
#
|
11
|
+
# There are currently two options to control query pagination:
|
12
|
+
#
|
13
|
+
# :per_page -- the max number of results to return (default: 20)
|
14
|
+
# :page -- the zero-indexed page to return (default: 0)
|
15
|
+
|
16
|
+
module OpenStax
|
17
|
+
module Accounts
|
18
|
+
module Dev
|
19
|
+
class SearchUsers < OpenStax::Accounts::SearchUsers
|
20
|
+
def exec(query, options={})
|
21
|
+
options = options.merge!(:max_matching_users => Float::INFINITY)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,47 +1,189 @@
|
|
1
|
-
|
1
|
+
# Routine for searching for users
|
2
|
+
#
|
3
|
+
# Caller provides a query and some options. The query follows the rules of
|
4
|
+
# https://github.com/bruce/keyword_search , e.g.:
|
5
|
+
#
|
6
|
+
# "username:jps,richb" --> returns the "jps" and "richb" users
|
7
|
+
# "name:John" --> returns Users with first, last, or full name
|
8
|
+
# starting with "John"
|
9
|
+
#
|
10
|
+
# Query terms can be combined, e.g. "username:jp first_name:john"
|
11
|
+
#
|
12
|
+
# There are currently two options to control query pagination:
|
13
|
+
#
|
14
|
+
# :per_page -- the max number of results to return per page (default: 20)
|
15
|
+
# :page -- the zero-indexed page to return (default: 0)
|
16
|
+
#
|
17
|
+
# There is also an option to control the ordering:
|
18
|
+
#
|
19
|
+
# :order_by -- comma-separated list of fields to sort by, with an optional
|
20
|
+
# space-separated sort direction (default: "username ASC")
|
21
|
+
#
|
22
|
+
# Finally, you can also specify a maximum allowed number of results:
|
23
|
+
#
|
24
|
+
# :max_matching_users -- the max number of results allowed (default: 10)
|
25
|
+
#
|
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.
|
2
29
|
|
3
30
|
module OpenStax
|
4
31
|
module Accounts
|
5
|
-
|
6
32
|
class SearchUsers
|
33
|
+
|
7
34
|
lev_routine transaction: :no_transaction
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
SORTABLE_FIELDS = ['username', 'first_name', 'last_name', 'id']
|
39
|
+
SORT_ASCENDING = 'ASC'
|
40
|
+
SORT_DESCENDING = 'DESC'
|
41
|
+
|
42
|
+
def exec(query, options={})
|
43
|
+
|
44
|
+
if !OpenStax::Accounts.configuration.enable_stubbing? &&\
|
45
|
+
KeywordSearch.search(query).values_at('email', :default).compact.any?
|
46
|
+
# Delegate to Accounts
|
47
|
+
|
48
|
+
response = OpenStax::Accounts.application_users_index(query)
|
49
|
+
|
50
|
+
user_search = OpenStruct.new
|
51
|
+
search_rep = OpenStax::Accounts::Api::V1::UserSearchRepresenter.new(user_search)
|
52
|
+
search_rep.from_json(response.body)
|
53
|
+
|
54
|
+
# 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
|
63
|
+
|
64
|
+
else
|
65
|
+
|
66
|
+
# Local search
|
67
|
+
users = OpenStax::Accounts::User.scoped
|
68
|
+
|
69
|
+
KeywordSearch.search(query) do |with|
|
70
|
+
|
71
|
+
with.default_keyword :any
|
72
|
+
|
73
|
+
with.keyword :username do |usernames|
|
74
|
+
users = users.where{username.like_any my{prep_usernames(usernames)}}
|
75
|
+
end
|
76
|
+
|
77
|
+
with.keyword :first_name do |first_names|
|
78
|
+
users = users.where{lower(first_name).like_any my{prep_names(first_names)}}
|
79
|
+
end
|
80
|
+
|
81
|
+
with.keyword :last_name do |last_names|
|
82
|
+
users = users.where{lower(last_name).like_any my{prep_names(last_names)}}
|
83
|
+
end
|
84
|
+
|
85
|
+
with.keyword :full_name do |full_names|
|
86
|
+
users = users.where{lower(full_name).like_any my{prep_names(full_names)}}
|
87
|
+
end
|
88
|
+
|
89
|
+
with.keyword :name do |names|
|
90
|
+
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) }
|
94
|
+
end
|
95
|
+
|
96
|
+
with.keyword :id do |ids|
|
97
|
+
users = users.where{openstax_uid.in ids}
|
98
|
+
end
|
99
|
+
|
100
|
+
with.keyword :email do |emails|
|
101
|
+
users = OpenStax::Accounts::User.where('0=1')
|
102
|
+
end
|
103
|
+
|
104
|
+
# Rerun the queries above for 'any' terms (which are ones without a
|
105
|
+
# prefix).
|
106
|
+
|
107
|
+
with.keyword :any do |terms|
|
108
|
+
names = prep_names(terms)
|
109
|
+
|
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
|
+
}
|
117
|
+
end
|
8
118
|
|
9
|
-
protected
|
10
|
-
|
11
|
-
def exec(terms, type=:any)
|
12
|
-
# Return empty results if no search terms
|
13
|
-
return User.where{id == nil}.where{id != nil} if terms.blank?
|
14
|
-
|
15
|
-
# Note: % is the wildcard. This allows the user to search
|
16
|
-
# for stuff that "begins with" but not "ends with".
|
17
|
-
case type
|
18
|
-
when :name
|
19
|
-
users = User.scoped
|
20
|
-
terms.gsub(/[%,]/, '').split.each do |t|
|
21
|
-
next if t.blank?
|
22
|
-
query = t + '%'
|
23
|
-
users = users.where{(first_name =~ query) | (last_name =~ query)}
|
24
119
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
120
|
+
|
121
|
+
# Pagination
|
122
|
+
|
123
|
+
page = options[:page] || 0
|
124
|
+
per_page = options[:per_page] || 20
|
125
|
+
|
126
|
+
users = users.limit(per_page).offset(per_page*page)
|
127
|
+
|
128
|
+
#
|
129
|
+
# Ordering
|
130
|
+
#
|
131
|
+
|
132
|
+
# Parse the input
|
133
|
+
order_bys = (options[:order_by] || 'username').split(',').collect{|ob| ob.strip.split(' ')}
|
134
|
+
|
135
|
+
# Toss out bad input, provide default direction
|
136
|
+
order_bys = order_bys.collect do |order_by|
|
137
|
+
field, direction = order_by
|
138
|
+
next if !SORTABLE_FIELDS.include?(field)
|
139
|
+
direction ||= SORT_ASCENDING
|
140
|
+
next if direction != SORT_ASCENDING && direction != SORT_DESCENDING
|
141
|
+
[field, direction]
|
36
142
|
end
|
37
|
-
|
38
|
-
|
143
|
+
|
144
|
+
order_bys.compact!
|
145
|
+
|
146
|
+
# Use a default sort if none provided
|
147
|
+
order_bys = ['username', SORT_ASCENDING] if order_bys.empty?
|
148
|
+
|
149
|
+
# Convert to query style
|
150
|
+
order_bys = order_bys.collect{|order_by| "#{order_by[0]} #{order_by[1]}"}
|
151
|
+
|
152
|
+
# Make the ordering call
|
153
|
+
order_bys.each do |order_by|
|
154
|
+
users = users.order(order_by)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Translate to routine outputs
|
158
|
+
|
159
|
+
outputs[:users] = users
|
160
|
+
outputs[:query] = query
|
161
|
+
outputs[:per_page] = per_page
|
162
|
+
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
|
165
|
+
|
39
166
|
end
|
40
167
|
|
41
|
-
|
168
|
+
# 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
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
# Downcase, and put a wildcard at the end.
|
177
|
+
# For the moment don't exclude characters.
|
178
|
+
def prep_names(names)
|
179
|
+
names.collect{|name| name.downcase + '%'}
|
180
|
+
end
|
181
|
+
|
182
|
+
def prep_usernames(usernames)
|
183
|
+
usernames.collect{|username| username.gsub(OpenStax::Accounts::User::USERNAME_DISCARDED_CHAR_REGEX, '').downcase + '%'}
|
42
184
|
end
|
43
185
|
|
44
186
|
end
|
45
187
|
|
46
188
|
end
|
47
|
-
end
|
189
|
+
end
|