openstax_connect 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +70 -0
  3. data/Rakefile +49 -0
  4. data/app/algorithms/openstax/connect/search_users.rb +47 -0
  5. data/app/assets/javascripts/openstax/connect/application.js +15 -0
  6. data/app/assets/javascripts/openstax/connect/sessions.js +2 -0
  7. data/app/assets/stylesheets/openstax/connect/application.css +13 -0
  8. data/app/assets/stylesheets/openstax/connect/dev.css.scss +31 -0
  9. data/app/assets/stylesheets/openstax/connect/sessions.css +4 -0
  10. data/app/controllers/openstax/connect/application_controller.rb +9 -0
  11. data/app/controllers/openstax/connect/dev/dev_controller.rb +16 -0
  12. data/app/controllers/openstax/connect/dev/sessions_controller.rb +21 -0
  13. data/app/controllers/openstax/connect/dev/users_controller.rb +28 -0
  14. data/app/controllers/openstax/connect/sessions_controller.rb +44 -0
  15. data/app/handlers/openstax/connect/dev/users_create.rb +31 -0
  16. data/app/handlers/openstax/connect/dev/users_generate.rb +36 -0
  17. data/app/handlers/openstax/connect/dev/users_search.rb +64 -0
  18. data/app/handlers/openstax/connect/sessions_omniauth_authenticated.rb +35 -0
  19. data/app/helpers/openstax/connect/application_helper.rb +20 -0
  20. data/app/helpers/openstax/connect/sessions_helper.rb +4 -0
  21. data/app/models/anonymous_user.rb +40 -0
  22. data/app/models/user.rb +21 -0
  23. data/app/views/layouts/openstax/connect/application.html.erb +14 -0
  24. data/app/views/openstax/connect/dev/users/index.html.erb +31 -0
  25. data/app/views/openstax/connect/dev/users/search.js.erb +21 -0
  26. data/app/views/openstax/connect/sessions/create.html.erb +10 -0
  27. data/app/views/openstax/connect/shared/_attention.html.erb +3 -0
  28. data/app/views/openstax/connect/users/_action_create_form.html.erb +9 -0
  29. data/app/views/openstax/connect/users/_action_dialog.html.erb +10 -0
  30. data/app/views/openstax/connect/users/_action_list.html.erb +33 -0
  31. data/app/views/openstax/connect/users/_action_search.html.erb +25 -0
  32. data/app/views/openstax/connect/users/action_search.js.erb +8 -0
  33. data/config/initializers/02_extend_builtins.rb +48 -0
  34. data/config/routes.rb +32 -0
  35. data/db/migrate/20130729213800_create_users.rb +9 -0
  36. data/db/migrate/20130909215452_add_fields_to_user.rb +11 -0
  37. data/lib/omniauth/strategies/openstax.rb +28 -0
  38. data/lib/openstax/connect/action_list.rb +40 -0
  39. data/lib/openstax/connect/engine.rb +34 -0
  40. data/lib/openstax/connect/route_helper.rb +34 -0
  41. data/lib/openstax/connect/utilities.rb +12 -0
  42. data/lib/openstax/connect/version.rb +5 -0
  43. data/lib/openstax_connect.rb +72 -0
  44. data/lib/tasks/connect-rails_tasks.rake +4 -0
  45. 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,10 @@
1
+ <h1>Sessions#create</h1>
2
+ <p>Find me in app/views/openstax/connect/sessions/create.html.erb</p>
3
+
4
+ <hr/>
5
+
6
+ <%= request.env['omniauth.auth'] %>
7
+
8
+ <hr/>
9
+
10
+ <%= session.inspect %>
@@ -0,0 +1,3 @@
1
+ <% handler_errors.each do |error| %>
2
+ <%= error.translate %>
3
+ <% end %>
@@ -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,8 @@
1
+ <%= unless_errors errors_html_id: (errors_html_id ||= 'action-search-errors') do %>
2
+ <% contents = render 'openstax/connect/users/action_list',
3
+ users: users,
4
+ list: list %>
5
+
6
+ $("#action-search-results-list").html("<%= j(contents) %>");
7
+ <% end %>
8
+
@@ -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,9 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.integer :openstax_uid
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -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,5 @@
1
+ module OpenStax
2
+ module Connect
3
+ VERSION = "0.0.1"
4
+ end
5
+ 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
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :connect-rails do
3
+ # # Task goes here
4
+ # end