openstax_connect 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +70 -0
- data/Rakefile +49 -0
- data/app/algorithms/openstax/connect/search_users.rb +47 -0
- data/app/assets/javascripts/openstax/connect/application.js +15 -0
- data/app/assets/javascripts/openstax/connect/sessions.js +2 -0
- data/app/assets/stylesheets/openstax/connect/application.css +13 -0
- data/app/assets/stylesheets/openstax/connect/dev.css.scss +31 -0
- data/app/assets/stylesheets/openstax/connect/sessions.css +4 -0
- data/app/controllers/openstax/connect/application_controller.rb +9 -0
- data/app/controllers/openstax/connect/dev/dev_controller.rb +16 -0
- data/app/controllers/openstax/connect/dev/sessions_controller.rb +21 -0
- data/app/controllers/openstax/connect/dev/users_controller.rb +28 -0
- data/app/controllers/openstax/connect/sessions_controller.rb +44 -0
- data/app/handlers/openstax/connect/dev/users_create.rb +31 -0
- data/app/handlers/openstax/connect/dev/users_generate.rb +36 -0
- data/app/handlers/openstax/connect/dev/users_search.rb +64 -0
- data/app/handlers/openstax/connect/sessions_omniauth_authenticated.rb +35 -0
- data/app/helpers/openstax/connect/application_helper.rb +20 -0
- data/app/helpers/openstax/connect/sessions_helper.rb +4 -0
- data/app/models/anonymous_user.rb +40 -0
- data/app/models/user.rb +21 -0
- data/app/views/layouts/openstax/connect/application.html.erb +14 -0
- data/app/views/openstax/connect/dev/users/index.html.erb +31 -0
- data/app/views/openstax/connect/dev/users/search.js.erb +21 -0
- data/app/views/openstax/connect/sessions/create.html.erb +10 -0
- data/app/views/openstax/connect/shared/_attention.html.erb +3 -0
- data/app/views/openstax/connect/users/_action_create_form.html.erb +9 -0
- data/app/views/openstax/connect/users/_action_dialog.html.erb +10 -0
- data/app/views/openstax/connect/users/_action_list.html.erb +33 -0
- data/app/views/openstax/connect/users/_action_search.html.erb +25 -0
- data/app/views/openstax/connect/users/action_search.js.erb +8 -0
- data/config/initializers/02_extend_builtins.rb +48 -0
- data/config/routes.rb +32 -0
- data/db/migrate/20130729213800_create_users.rb +9 -0
- data/db/migrate/20130909215452_add_fields_to_user.rb +11 -0
- data/lib/omniauth/strategies/openstax.rb +28 -0
- data/lib/openstax/connect/action_list.rb +40 -0
- data/lib/openstax/connect/engine.rb +34 -0
- data/lib/openstax/connect/route_helper.rb +34 -0
- data/lib/openstax/connect/utilities.rb +12 -0
- data/lib/openstax/connect/version.rb +5 -0
- data/lib/openstax_connect.rb +72 -0
- data/lib/tasks/connect-rails_tasks.rake +4 -0
- metadata +191 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
<% handler_errors.each do |error| %>
|
3
|
+
<%= error.translate %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= osu_section_block "Register a new user" do %>
|
7
|
+
|
8
|
+
|
9
|
+
<%= lev_form_for :register, url: dev_users_create_path do |f| %>
|
10
|
+
|
11
|
+
First name <%= f.text_field :first_name %><br/>
|
12
|
+
Last name <%= f.text_field :last_name %><br/>
|
13
|
+
Username <%= f.text_field :username %><br/>
|
14
|
+
Admin? <%= f.check_box :is_administrator %><br/>
|
15
|
+
|
16
|
+
<%= submit_tag 'Register' %>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<%= osu_section_block "Generate new users" do %>
|
22
|
+
<%= lev_form_for :generate, url: dev_users_generate_path do |f| %>
|
23
|
+
Generate <%= f.text_field :count, style: 'width:30px' %> user(s) <%= submit_tag 'Do it now!' %>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<%= osu_section_block "Login as an existing user" do %>
|
28
|
+
|
29
|
+
<%= render 'openstax/connect/users/action_search', action_search_path: dev_users_search_path %>
|
30
|
+
|
31
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
<%= render template: 'openstax/connect/users/action_search',
|
3
|
+
locals: {
|
4
|
+
users: @results[:users],
|
5
|
+
list: OpenStax::Connect::ActionList.new(
|
6
|
+
headings: ['First Name', 'Last Name', 'Username', ''],
|
7
|
+
widths: ['25%', '25%', '25%', '25%'],
|
8
|
+
data_procs:
|
9
|
+
[
|
10
|
+
Proc.new { |user| user.first_name },
|
11
|
+
Proc.new { |user| user.last_name },
|
12
|
+
Proc.new { |user| user.username },
|
13
|
+
Proc.new { |user|
|
14
|
+
link_to 'Sign in as',
|
15
|
+
sessions_become_path(:user_id => user.id),
|
16
|
+
method: :post
|
17
|
+
}
|
18
|
+
]
|
19
|
+
)
|
20
|
+
}
|
21
|
+
%>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%# Copyright 2011-2012 Rice University. Licensed under the Affero General Public
|
2
|
+
License version 3 or later. See the COPYRIGHT file for details. %>
|
3
|
+
|
4
|
+
<%# Callers must supply a 'user' local variable %>
|
5
|
+
|
6
|
+
<%= form_for target, :method => :post, :remote => true do |f| %>
|
7
|
+
<%= f.hidden_field :user_id, :value => user.id %>
|
8
|
+
<%= f.submit "Add", :onclick => please_wait_js %>
|
9
|
+
<% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%# Copyright 2011-2012 Rice University. Licensed under the Affero General Public
|
2
|
+
License version 3 or later. See the COPYRIGHT file for details. %>
|
3
|
+
|
4
|
+
<div id="user_action_dialog" style="display:none" title="<%= @action_dialog_title %>">
|
5
|
+
<div id="user_action_dialog_errors"></div>
|
6
|
+
|
7
|
+
<%= render :partial => 'users/action_search',
|
8
|
+
:locals => { :action_search_path => @action_search_path } %>
|
9
|
+
|
10
|
+
</div>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%# Copyright 2011-2012 Rice University. Licensed under the Affero General Public
|
2
|
+
License version 3 or later. See the COPYRIGHT file for details. %>
|
3
|
+
|
4
|
+
<%
|
5
|
+
users ||= []
|
6
|
+
%>
|
7
|
+
|
8
|
+
<% if list.num_columns > 0 %>
|
9
|
+
<table class="list" width="100%">
|
10
|
+
<% if list.has_headings? %>
|
11
|
+
<tr>
|
12
|
+
<% for ii in 0..list.num_columns - 1 %>
|
13
|
+
<th><%= list.get_heading(ii) %></th>
|
14
|
+
<% end %>
|
15
|
+
</tr>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% if users.empty? %>
|
19
|
+
<tr>
|
20
|
+
<td colspan="<%= list.num_columns %>">No results</td>
|
21
|
+
</tr>
|
22
|
+
<% else %>
|
23
|
+
<% users.all.each_with_index do |user, uu| %>
|
24
|
+
<tr>
|
25
|
+
<% for cc in 0..list.num_columns - 1 %>
|
26
|
+
<% width = uu == 0 ? list.get_width(cc) : nil %>
|
27
|
+
<td <%= "width=#{width}" if width %>><%= list.get_data(cc, user) %></td>
|
28
|
+
<% end %>
|
29
|
+
</tr>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
</table>
|
33
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<%# Copyright 2011-2012 Rice University. Licensed under the Affero General Public
|
2
|
+
License version 3 or later. See the COPYRIGHT file for details. %>
|
3
|
+
|
4
|
+
<%
|
5
|
+
# Clients of this partial must supply the following variables:
|
6
|
+
# action_search_path
|
7
|
+
%>
|
8
|
+
|
9
|
+
<div id="action-search-errors"></div>
|
10
|
+
|
11
|
+
<%= lev_form_for :search,
|
12
|
+
url: action_search_path,
|
13
|
+
id: 'action_search_form',
|
14
|
+
remote: true do |f| %>
|
15
|
+
|
16
|
+
Search for
|
17
|
+
<%= f.text_field :search_terms, style: 'width:300px' %>
|
18
|
+
in
|
19
|
+
<%= f.select :search_type, options_for_select(['Any', 'Name', 'Username']) %>
|
20
|
+
|
21
|
+
<%= submit_tag 'Search' %>
|
22
|
+
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<div id="action-search-results-list"></div>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class ActionController::Base
|
2
|
+
# References:
|
3
|
+
# http://railscasts.com/episodes/356-dangers-of-session-hijacking
|
4
|
+
|
5
|
+
# Always return an object
|
6
|
+
def current_user
|
7
|
+
if !request.ssl? || cookies.signed[:secure_user_id] == "secure#{session[:user_id]}"
|
8
|
+
@current_user ||= AnonymousUser.instance
|
9
|
+
|
10
|
+
if @current_user.is_anonymous? && session[:user_id]
|
11
|
+
# Use current_user= to clear out bad state if any
|
12
|
+
self.current_user = User.where(id: session[:user_id]).first
|
13
|
+
end
|
14
|
+
|
15
|
+
@current_user
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_user=(user)
|
20
|
+
@current_user = user || AnonymousUser.instance
|
21
|
+
if user.is_anonymous?
|
22
|
+
session[:user_id] = nil
|
23
|
+
cookies.delete(:secure_user_id)
|
24
|
+
else
|
25
|
+
session[:user_id] = user.id
|
26
|
+
cookies.signed[:secure_user_id] = {secure: true, value: "secure#{user.id}"}
|
27
|
+
end
|
28
|
+
@current_user
|
29
|
+
end
|
30
|
+
|
31
|
+
def sign_in(user)
|
32
|
+
self.current_user = user
|
33
|
+
end
|
34
|
+
|
35
|
+
def sign_out!
|
36
|
+
self.current_user = AnonymousUser.instance
|
37
|
+
end
|
38
|
+
|
39
|
+
def signed_in?
|
40
|
+
!current_user.is_anonymous?
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
helper_method :current_user, :current_user=, :signed_in?
|
46
|
+
|
47
|
+
end
|
48
|
+
|
data/config/routes.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
OpenStax::Connect::Engine.routes.draw do
|
2
|
+
match '/auth/openstax/callback', to: 'sessions#omniauth_authenticated' #omniauth route
|
3
|
+
get '/auth/openstax', :as => 'openstax_login'
|
4
|
+
get 'sessions/new', :as => 'login'
|
5
|
+
post 'sessions/become'
|
6
|
+
|
7
|
+
# See https://github.com/plataformatec/devise/commit/f3385e96abf50e80d2ae282e1fb9bdad87a83d3c
|
8
|
+
match 'sessions/destroy', :as => 'logout', :via => OpenStax::Connect.configuration.logout_via
|
9
|
+
|
10
|
+
if OpenStax::Connect.configuration.enable_stubbing?
|
11
|
+
namespace :dev do
|
12
|
+
# get 'sessions/new'
|
13
|
+
# post 'sessions/create'
|
14
|
+
# post 'sessions/search'
|
15
|
+
get 'users', to: 'users#index'
|
16
|
+
post 'users/create'
|
17
|
+
post 'users/generate'
|
18
|
+
post 'users/search'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
module OpenStax
|
25
|
+
module Connect
|
26
|
+
hh = Engine.routes.url_helpers
|
27
|
+
|
28
|
+
RouteHelper.register_path(:login, hh.openstax_login_path) { hh.dev_users_path }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddFieldsToUser < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :users, :first_name, :string
|
4
|
+
add_column :users, :last_name, :string
|
5
|
+
add_column :users, :username, :string
|
6
|
+
add_column :users, :is_administrator, :boolean, :default => false
|
7
|
+
|
8
|
+
add_index :users, :openstax_uid, :unique => true
|
9
|
+
add_index :users, :username, :unique => true
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'omniauth'
|
2
|
+
require 'omniauth-oauth2'
|
3
|
+
|
4
|
+
module OmniAuth
|
5
|
+
module Strategies
|
6
|
+
class Openstax < OAuth2
|
7
|
+
option :name, "openstax"
|
8
|
+
|
9
|
+
option :client_options, {
|
10
|
+
:site => OpenStax::Connect.configuration.openstax_services_url,
|
11
|
+
:authorize_url => "/oauth/authorize"
|
12
|
+
}
|
13
|
+
|
14
|
+
uid { raw_info["uid"] }
|
15
|
+
|
16
|
+
info do
|
17
|
+
{
|
18
|
+
:username => raw_info["username"]
|
19
|
+
# and anything else you want to return to your API consumers
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def raw_info
|
24
|
+
@raw_info ||= access_token.get('/api/v1/me.json').parsed
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module OpenStax::Connect
|
2
|
+
class ActionList
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
@options = options
|
6
|
+
|
7
|
+
raise IllegalArgument, "must supply data procs" if options[:data_procs].nil?
|
8
|
+
|
9
|
+
if options[:headings].present? && options[:data_procs].size != options[:headings].size
|
10
|
+
raise IllegalArgument, "if you supply headings, you must supply one for each column"
|
11
|
+
end
|
12
|
+
|
13
|
+
if options[:widths].present? && options[:data_procs].size != options[:widths].size
|
14
|
+
raise IllegalArgument, "if you supply widths, you must supply one for each column"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def num_columns
|
20
|
+
@options[:data_procs].size
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_headings?
|
24
|
+
@options[:headings].present?
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_heading(column)
|
28
|
+
@options[:headings].nil? ? nil : @options[:headings][column]
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_width(column)
|
32
|
+
@options[:widths].nil? ? nil : @options[:widths][column]
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_data(column, *args)
|
36
|
+
@options[:data_procs][column].call(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
2
|
+
inflect.acronym 'OpenStax'
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'omniauth'
|
6
|
+
require 'squeel'
|
7
|
+
|
8
|
+
module OpenStax
|
9
|
+
module Connect
|
10
|
+
class Engine < ::Rails::Engine
|
11
|
+
isolate_namespace OpenStax::Connect
|
12
|
+
|
13
|
+
config.autoload_paths << File.expand_path("../../../app/algorithms", __FILE__)
|
14
|
+
config.autoload_paths << File.expand_path("../../../app/handlers", __FILE__)
|
15
|
+
|
16
|
+
config.generators do |g|
|
17
|
+
g.test_framework :rspec, :view_specs => false
|
18
|
+
end
|
19
|
+
|
20
|
+
# Doesn't work to put this omniauth code in an engine initializer, instead:
|
21
|
+
# https://gist.github.com/pablomarti/5243118
|
22
|
+
middleware.use ::OmniAuth::Builder do
|
23
|
+
provider :openstax,
|
24
|
+
OpenStax::Connect.configuration.openstax_application_id,
|
25
|
+
OpenStax::Connect.configuration.openstax_application_secret
|
26
|
+
end
|
27
|
+
|
28
|
+
config.after_initialize do
|
29
|
+
# The omniauth strategy requires values given during application init
|
30
|
+
require "omniauth/strategies/openstax"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module OpenStax
|
4
|
+
module Connect
|
5
|
+
class RouteHelper
|
6
|
+
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
# Registers a path against a canonical name. An optional
|
10
|
+
# block can be provided to give the stubbed path
|
11
|
+
def self.register_path(canonical_name, path, &block)
|
12
|
+
instance.paths[canonical_name] = path
|
13
|
+
if block.present? && OpenStax::Connect.configuration.enable_stubbing?
|
14
|
+
instance.stubbed_paths[canonical_name] = block.call
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get_path(canonical_name)
|
19
|
+
OpenStax::Connect.configuration.enable_stubbing? ?
|
20
|
+
instance.stubbed_paths[canonical_name] :
|
21
|
+
instance.paths[canonical_name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
self.paths = {}
|
26
|
+
self.stubbed_paths = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :paths
|
30
|
+
attr_accessor :stubbed_paths
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module OpenStax
|
2
|
+
module Connect
|
3
|
+
|
4
|
+
class SecurityTransgression < StandardError; end
|
5
|
+
class AbstractMethodCalled < StandardError; end
|
6
|
+
class NotYetImplemented < StandardError; end
|
7
|
+
class IllegalArgument < StandardError; end
|
8
|
+
class IllegalState < StandardError; end
|
9
|
+
class IllegalOperation < StandardError; end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "openstax/connect/engine"
|
2
|
+
require "openstax/connect/version"
|
3
|
+
require "openstax/connect/utilities"
|
4
|
+
require "openstax/connect/route_helper"
|
5
|
+
require "openstax/connect/action_list"
|
6
|
+
|
7
|
+
module OpenStax
|
8
|
+
module Connect
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
###########################################################################
|
13
|
+
#
|
14
|
+
# Configuration machinery.
|
15
|
+
#
|
16
|
+
# To configure OpenStax Utilities, put the following code in your applications
|
17
|
+
# initialization logic (eg. in the config/initializers in a Rails app)
|
18
|
+
#
|
19
|
+
# OpenStax::Connect.configure do |config|
|
20
|
+
# config.<parameter name> = <parameter value>
|
21
|
+
# ...
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# Set enable_stubbing to true iff you want this engine to fake all
|
25
|
+
# interaction with the services site.
|
26
|
+
#
|
27
|
+
|
28
|
+
def configure
|
29
|
+
yield configuration
|
30
|
+
end
|
31
|
+
|
32
|
+
def configuration
|
33
|
+
@configuration ||= Configuration.new
|
34
|
+
end
|
35
|
+
|
36
|
+
class Configuration
|
37
|
+
attr_accessor :openstax_application_id
|
38
|
+
attr_accessor :openstax_application_secret
|
39
|
+
attr_accessor :enable_stubbing
|
40
|
+
attr_reader :openstax_services_url
|
41
|
+
attr_accessor :logout_via
|
42
|
+
attr_accessor :default_errors_partial
|
43
|
+
attr_accessor :default_errors_html_id
|
44
|
+
attr_accessor :default_errors_added_trigger
|
45
|
+
|
46
|
+
def openstax_services_url=(url)
|
47
|
+
url.gsub!(/https|http/,'https') if !(url =~ /localhost/)
|
48
|
+
url = url + "/" if url[url.size-1] != '/'
|
49
|
+
@openstax_services_url = url
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@openstax_application_id = 'SET ME!'
|
54
|
+
@openstax_application_secret = 'SET ME!'
|
55
|
+
@openstax_services_url = 'https://services.openstax.org/'
|
56
|
+
@enable_stubbing = true
|
57
|
+
@logout_via = :get
|
58
|
+
@default_errors_partial = 'openstax/connect/shared/attention'
|
59
|
+
@default_errors_html_id = 'openstax-connect-attention'
|
60
|
+
@default_errors_added_trigger = 'openstax-connect-errors-added'
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
def enable_stubbing?
|
65
|
+
!Rails.env.production? && enable_stubbing
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|