ccls-calnet_authenticated 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +59 -0
- data/generators/calnet_authenticated/USAGE +15 -0
- data/generators/calnet_authenticated/calnet_authenticated_generator.rb +118 -0
- data/generators/calnet_authenticated/templates/autotest_calnet_authenticated.rb +3 -0
- data/generators/calnet_authenticated/templates/calnet_authenticated.rake +6 -0
- data/generators/calnet_authenticated/templates/controllers/sessions_controller.rb +8 -0
- data/generators/calnet_authenticated/templates/controllers/users_controller.rb +40 -0
- data/generators/calnet_authenticated/templates/functional/sessions_controller_test.rb +68 -0
- data/generators/calnet_authenticated/templates/functional/users_controller_test.rb +94 -0
- data/generators/calnet_authenticated/templates/migration.rb +41 -0
- data/generators/calnet_authenticated/templates/views/users/_form.html.erb +27 -0
- data/generators/calnet_authenticated/templates/views/users/edit.html.erb +1 -0
- data/generators/calnet_authenticated/templates/views/users/index.html.erb +26 -0
- data/generators/calnet_authenticated/templates/views/users/menu.js.erb +4 -0
- data/generators/calnet_authenticated/templates/views/users/new.html.erb +1 -0
- data/generators/calnet_authenticated/templates/views/users/show.html.erb +19 -0
- data/lib/calnet_authenticated.rb +83 -0
- data/lib/calnet_authenticated/autotest.rb +54 -0
- data/lib/calnet_authenticated/calnet_user.rb +89 -0
- data/lib/calnet_authenticated/controller.rb +94 -0
- data/lib/calnet_authenticated/test_helper.rb +100 -0
- data/lib/calnet_authenticated/test_tasks.rb +42 -0
- data/lib/ccls-calnet_authenticated.rb +1 -0
- data/rails/init.rb +4 -0
- data/test/unit/calnet/user_test.rb +137 -0
- metadata +222 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
<% stylesheets('user') %>
|
2
|
+
|
3
|
+
<% form_for @user do |form| %>
|
4
|
+
<%= form.error_messages %>
|
5
|
+
<% if params[:token] %>
|
6
|
+
<%= hidden_field_tag :token, params[:token] %>
|
7
|
+
<% end %>
|
8
|
+
<div>
|
9
|
+
<%= form.label :username, "Username" %>
|
10
|
+
<%= form.text_field :username %>
|
11
|
+
</div>
|
12
|
+
<div>
|
13
|
+
<%= form.label :email, "Email" %>
|
14
|
+
<%= form.text_field :email %>
|
15
|
+
</div>
|
16
|
+
<div>
|
17
|
+
<%= form.label :password, "Password" %>
|
18
|
+
<%= form.password_field :password %>
|
19
|
+
</div>
|
20
|
+
<div>
|
21
|
+
<%= form.label :password_confirmation, "Password confirmation" %>
|
22
|
+
<%= form.password_field :password_confirmation %>
|
23
|
+
</div>
|
24
|
+
<p>
|
25
|
+
<%= form.submit "Submit" %>
|
26
|
+
</p>
|
27
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'form' %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<% stylesheets('users') %>
|
2
|
+
<h4>Users:</h4>
|
3
|
+
<% unless @users.empty? %>
|
4
|
+
<table id='users'><tbody>
|
5
|
+
<% @users.each do |user| %>
|
6
|
+
<tr class='<%=user.role_names.join(' ')-%> user row'>
|
7
|
+
<td class='gravatar'>
|
8
|
+
<%#= link_to( image_tag(user.gravatar_url), "http://gravatar.com", :target => 'new' )%>
|
9
|
+
</td>
|
10
|
+
<td class='username'>
|
11
|
+
<%= link_to user.displayname, user_path(user) -%>
|
12
|
+
</td>
|
13
|
+
<td class='role_name'>
|
14
|
+
<% user.role_names.each do |role_name| %>
|
15
|
+
<%= link_to role_name, users_path( :role_name => role_name ) -%>
|
16
|
+
<% end %>
|
17
|
+
</td>
|
18
|
+
<td class='manage'>
|
19
|
+
<%= destroy_link_to( 'Destroy', user_path(user) ) %>
|
20
|
+
</td>
|
21
|
+
</tr>
|
22
|
+
<% end %>
|
23
|
+
</tbody></table><!-- id='users' -->
|
24
|
+
<% else %>
|
25
|
+
Sorry, no users yet.
|
26
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'form' %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% stylesheets('user') %>
|
2
|
+
|
3
|
+
<fieldset id='user'>
|
4
|
+
<legend><%= @user.sn %></legend>
|
5
|
+
|
6
|
+
<div class='person'><dl>
|
7
|
+
<% %w( displayname mail uid ).each do |key| -%>
|
8
|
+
<dt><%= key -%></dt>
|
9
|
+
<dd><%= @user.attributes[key] -%></dd>
|
10
|
+
<% end -%>
|
11
|
+
</dl>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div id='roles'>
|
15
|
+
<%#= link_to( image_tag(@user.gravatar_url), "http://gravatar.com", :target => 'new' )%>
|
16
|
+
<%= user_roles() %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
</fieldset>
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support'
|
3
|
+
require 'action_controller'
|
4
|
+
|
5
|
+
gem 'ccls-common_lib'
|
6
|
+
require 'common_lib'
|
7
|
+
|
8
|
+
gem 'rubycas-client', '>= 2.2.1'
|
9
|
+
require 'rubycas-client'
|
10
|
+
|
11
|
+
require 'casclient'
|
12
|
+
require 'casclient/frameworks/rails/filter'
|
13
|
+
|
14
|
+
gem 'ucb_ldap', '>= 1.4.2'
|
15
|
+
require 'ucb_ldap'
|
16
|
+
|
17
|
+
gem 'ccls-simply_authorized'
|
18
|
+
require 'simply_authorized'
|
19
|
+
|
20
|
+
gem 'ryanb-acts-as-list'
|
21
|
+
require 'acts_as_list'
|
22
|
+
|
23
|
+
# Don't know if I use CalnetAuthenticated namespace anymore
|
24
|
+
# It is used in functional test names
|
25
|
+
module CalnetAuthenticated
|
26
|
+
# predefine namespace
|
27
|
+
end
|
28
|
+
module Calnet
|
29
|
+
# predefine namespace
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'calnet_authenticated/calnet_user'
|
33
|
+
require 'calnet_authenticated/controller'
|
34
|
+
|
35
|
+
# I don't think that this is needed
|
36
|
+
# Apparently it is. I don't quite understand
|
37
|
+
# why my ccls_engine doesn't.
|
38
|
+
#%w{models controllers}.each do |dir|
|
39
|
+
# path = File.expand_path(File.join(File.dirname(__FILE__), '../app', dir))
|
40
|
+
# ActiveSupport::Dependencies.autoload_paths << path
|
41
|
+
# ActiveSupport::Dependencies.autoload_once_paths << path
|
42
|
+
#end
|
43
|
+
|
44
|
+
# I don't think this is needed
|
45
|
+
#
|
46
|
+
# Why do I need this for calnet_authenticated,
|
47
|
+
# but not for authorized or photos or ...
|
48
|
+
#
|
49
|
+
# I think that it depends on whether the gem is
|
50
|
+
# explictly added to the configuration with config.gem
|
51
|
+
# or just a dependency with a require.
|
52
|
+
# Since buffler and clic and engine only have config.gem ccls_engine,
|
53
|
+
# we need to be explicit, which is probably better anyway.
|
54
|
+
#ActionController::Routing::Routes.add_configuration_file(
|
55
|
+
# File.expand_path(
|
56
|
+
# File.join(
|
57
|
+
# File.dirname(__FILE__), '../config/routes.rb')))
|
58
|
+
|
59
|
+
HTML::WhiteListSanitizer.allowed_attributes.merge(%w(
|
60
|
+
id class style
|
61
|
+
))
|
62
|
+
|
63
|
+
if defined?(Rails) && Rails.env == 'test' && Rails.class_variable_defined?("@@configuration")
|
64
|
+
require 'active_support/test_case'
|
65
|
+
require 'calnet_authenticated/test_helper'
|
66
|
+
require 'factory_girl'
|
67
|
+
end
|
68
|
+
|
69
|
+
#ActionController::Base.view_paths <<
|
70
|
+
# File.expand_path(
|
71
|
+
# File.join(
|
72
|
+
# File.dirname(__FILE__), '../app/views'))
|
73
|
+
|
74
|
+
# I don't use paperclip anymore, especially not here.
|
75
|
+
# gem 'paperclip'
|
76
|
+
# require 'paperclip'
|
77
|
+
# if defined? ::Paperclip::Glue
|
78
|
+
# ActiveRecord::Base.send(:include, ::Paperclip::Glue)
|
79
|
+
# else
|
80
|
+
# # older versions did not have "Glue"
|
81
|
+
# ActiveRecord::Base.send(:include, ::Paperclip)
|
82
|
+
# end
|
83
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Autotest::Rails
|
2
|
+
|
3
|
+
#
|
4
|
+
# Need both the mapping and the extra files
|
5
|
+
#
|
6
|
+
def run_with_calnet_authenticated
|
7
|
+
add_exception %r%config/%
|
8
|
+
add_exception %r%versions/%
|
9
|
+
add_exception %r%\.git/%
|
10
|
+
self.extra_files << File.expand_path(File.join(
|
11
|
+
File.dirname(__FILE__),'/../../test/unit/calnet/'))
|
12
|
+
|
13
|
+
# self.extra_files << File.expand_path(File.join(
|
14
|
+
# File.dirname(__FILE__),'/../../test/functional/calnet/'))
|
15
|
+
|
16
|
+
# add_mapping(
|
17
|
+
# %r{^#{File.expand_path(File.join(File.dirname(__FILE__),'/../../test/'))}/(unit|functional)/calnet/.*_test\.rb$}
|
18
|
+
# ) do |filename, _|
|
19
|
+
# filename
|
20
|
+
# end
|
21
|
+
|
22
|
+
add_mapping(
|
23
|
+
%r{^#{File.expand_path(File.join(File.dirname(__FILE__),'/../../test/'))}/unit/calnet/.*_test\.rb$}
|
24
|
+
) do |filename, _|
|
25
|
+
filename
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# This stops the ...
|
30
|
+
#
|
31
|
+
# Unable to map class Ccls::IdentifierTest to a file
|
32
|
+
# Unable to map class Ccls::SubjectTest to a file
|
33
|
+
#
|
34
|
+
# By default autotest is expecting all the namespaces to end with Test
|
35
|
+
# ie. CclsTest::IdentifierTest
|
36
|
+
# Could have renamed the dir, I suppose.
|
37
|
+
#
|
38
|
+
Dir[File.join(File.dirname(__FILE__),'/../../test/unit/**/*rb')].each do |f|
|
39
|
+
# the condition isn't as important as grabbing "calnet/test_file_name.rb" for camelcasing
|
40
|
+
if f =~ /test\/unit\/(calnet\/.*)\.rb/
|
41
|
+
self.extra_class_map[$1.camelcase] = File.expand_path(f)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# Dir[File.join(File.dirname(__FILE__),'/../../test/functional/**/*rb')].each do |f|
|
45
|
+
# if f =~ /test\/functional\/(calnet\/.*)\.rb/
|
46
|
+
# self.extra_class_map[$1.camelcase] = File.expand_path(f)
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
|
50
|
+
run_without_calnet_authenticated
|
51
|
+
end
|
52
|
+
alias_method_chain :run, :calnet_authenticated
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# == requires
|
2
|
+
# * uid (unique)
|
3
|
+
#
|
4
|
+
# == accessible attributes
|
5
|
+
# * sn
|
6
|
+
# * displayname
|
7
|
+
# * mail
|
8
|
+
# * telephonenumber
|
9
|
+
class Calnet::User < ActiveRecord::Base
|
10
|
+
self.abstract_class = true
|
11
|
+
|
12
|
+
def self.search(options={})
|
13
|
+
conditions = {}
|
14
|
+
includes = joins = []
|
15
|
+
if !options[:role_name].blank?
|
16
|
+
includes = [:roles]
|
17
|
+
if Role.all.collect(&:name).include?(options[:role_name])
|
18
|
+
joins = [:roles]
|
19
|
+
conditions = ["roles.name = ?",options[:role_name]]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
self.all(
|
23
|
+
:joins => joins,
|
24
|
+
:include => includes,
|
25
|
+
:conditions => conditions )
|
26
|
+
end
|
27
|
+
|
28
|
+
# Find or Create a user from a given uid, and then
|
29
|
+
# proceed to update the user's information from the
|
30
|
+
# UCB::LDAP::Person.find_by_uid(uid) response.
|
31
|
+
#
|
32
|
+
# Returns: user
|
33
|
+
def self.find_create_and_update_by_uid(uid)
|
34
|
+
user = self.find_or_create_by_uid(uid)
|
35
|
+
person = UCB::LDAP::Person.find_by_uid(uid)
|
36
|
+
user.update_attributes!({
|
37
|
+
:displayname => person.displayname,
|
38
|
+
:sn => person.sn.first,
|
39
|
+
:mail => person.mail.first || '',
|
40
|
+
:telephonenumber => person.telephonenumber.first
|
41
|
+
}) unless person.nil?
|
42
|
+
user
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
displayname
|
47
|
+
end
|
48
|
+
|
49
|
+
# this has been included above
|
50
|
+
# ucb_authenticated
|
51
|
+
|
52
|
+
# defined in plugin/engine ...
|
53
|
+
#
|
54
|
+
# def may_administrate?(*args)
|
55
|
+
# (self.role_names & ['superuser','administrator']).length > 0
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# def may_read?(*args)
|
59
|
+
# (self.role_names &
|
60
|
+
# ['superuser','administrator','editor','interviewer','reader']
|
61
|
+
# ).length > 0
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# def may_edit?(*args)
|
65
|
+
# (self.role_names &
|
66
|
+
# ['superuser','administrator','editor']
|
67
|
+
# ).length > 0
|
68
|
+
# end
|
69
|
+
|
70
|
+
def self.inherited(subclass)
|
71
|
+
|
72
|
+
subclass.class_eval do
|
73
|
+
# for some reason is nil which causes problems
|
74
|
+
self.default_scoping = []
|
75
|
+
|
76
|
+
validates_presence_of :uid
|
77
|
+
validates_uniqueness_of :uid
|
78
|
+
|
79
|
+
# include the many may_*? for use in the controllers
|
80
|
+
authorized
|
81
|
+
|
82
|
+
alias_method :may_create?, :may_edit?
|
83
|
+
alias_method :may_update?, :may_edit?
|
84
|
+
alias_method :may_destroy?, :may_edit?
|
85
|
+
|
86
|
+
end # class_eval
|
87
|
+
end # inherited()
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
|
3
|
+
# Further info regarding UCB's CAS setup can be found at
|
4
|
+
# https://calnet.berkeley.edu/developers/developerResources/cas/CASAppSetup.html#firstLevelServers
|
5
|
+
|
6
|
+
module Calnet::Controller
|
7
|
+
|
8
|
+
# Setup the CASClient and add the cas_filter before_filter
|
9
|
+
# to all application_controller requests. This can be
|
10
|
+
# overridden or "skipped" in any controller, particularly
|
11
|
+
# those that are passive and will use the cas_gateway_filter
|
12
|
+
# instead.
|
13
|
+
def self.included(base)
|
14
|
+
base_server_url = ( RAILS_ENV == "production" ) ?
|
15
|
+
"https://auth.berkeley.edu" :
|
16
|
+
"https://auth-test.berkeley.edu"
|
17
|
+
|
18
|
+
CASClient::Frameworks::Rails::Filter.configure(
|
19
|
+
:username_session_key => :calnetuid,
|
20
|
+
:cas_base_url => "#{base_server_url}/cas/"
|
21
|
+
)
|
22
|
+
|
23
|
+
base.helper_method :current_user, :logged_in?
|
24
|
+
|
25
|
+
base.extend(ClassMethods)
|
26
|
+
base.send(:include, InstanceMethods)
|
27
|
+
|
28
|
+
base.class_eval do
|
29
|
+
class << self
|
30
|
+
alias_method_chain :inherited, :calnet_before_filter
|
31
|
+
end
|
32
|
+
@@calnet_controller_loaded = true
|
33
|
+
# try to stop any possiblity of duplicating self in chain
|
34
|
+
end unless base.class_variable_defined?("@@calnet_controller_loaded")
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def inherited_with_calnet_before_filter(base)
|
42
|
+
identifier = 'inherited_calnet_authenticated_login_required'
|
43
|
+
unless filter_chain.select(&:before?).map(&:identifier
|
44
|
+
).include?(identifier)
|
45
|
+
before_filter :login_required,
|
46
|
+
:identifier => identifier
|
47
|
+
end
|
48
|
+
inherited_without_calnet_before_filter(base)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
module InstanceMethods
|
54
|
+
|
55
|
+
def logged_in?
|
56
|
+
!current_user.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
# Force the user to be have an SSO session open.
|
60
|
+
def current_user_required
|
61
|
+
# Have to add ".filter(self)" when not in before_filter line.
|
62
|
+
CASClient::Frameworks::Rails::Filter.filter(self)
|
63
|
+
end
|
64
|
+
alias_method :login_required, :current_user_required
|
65
|
+
|
66
|
+
def current_user
|
67
|
+
load 'user.rb' unless defined?(User)
|
68
|
+
@current_user ||= if( session && session[:calnetuid] )
|
69
|
+
# if the user model hasn't been loaded yet
|
70
|
+
# this will return nil and fail.
|
71
|
+
User.find_create_and_update_by_uid(session[:calnetuid])
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# This will allow the user to view the page without authentication
|
78
|
+
# but will process CAS authentication data if the user already
|
79
|
+
# has an SSO session open. This is potentially useful if you
|
80
|
+
# don't store a copy of the user info locally. Otherwise,
|
81
|
+
# not so much.
|
82
|
+
#
|
83
|
+
# Not using, so commented out so not to affect code coverage output.
|
84
|
+
#
|
85
|
+
# def cas_gateway_filter
|
86
|
+
# # Have to add ".filter(self)" when not in before_filter line.
|
87
|
+
# CASClient::Frameworks::Rails::GatewayFilter.filter(self)
|
88
|
+
# @login_url = CASClient::Frameworks::Rails::Filter.login_url(self)
|
89
|
+
# end
|
90
|
+
|
91
|
+
end # InstanceMethods
|
92
|
+
|
93
|
+
end # Calnet::Controller
|
94
|
+
ActionController::Base.send(:include,Calnet::Controller)
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module CalnetAuthenticated::TestHelper
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
def login_as( user=nil )
|
8
|
+
uid = ( user.is_a?(User) ) ? user.uid : user
|
9
|
+
if !uid.blank?
|
10
|
+
@request.session[:calnetuid] = uid
|
11
|
+
stub_ucb_ldap_person()
|
12
|
+
User.find_create_and_update_by_uid(uid)
|
13
|
+
|
14
|
+
CASClient::Frameworks::Rails::Filter.stubs(
|
15
|
+
:filter).returns(true)
|
16
|
+
# No longer using the GatewayFilter stuff.
|
17
|
+
# CASClient::Frameworks::Rails::GatewayFilter.stubs(
|
18
|
+
# :filter).returns(true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
alias :login :login_as
|
22
|
+
alias :log_in :login_as
|
23
|
+
|
24
|
+
|
25
|
+
def stub_ucb_ldap_person(options={})
|
26
|
+
UCB::LDAP::Person.stubs(:find_by_uid).returns(
|
27
|
+
UCB::LDAP::Person.new({
|
28
|
+
:sn => ["Wendt"],
|
29
|
+
:displayname => ["Mr. Jake Wendt, BA"],
|
30
|
+
:telephonenumber => ["+1 510 642-9749"],
|
31
|
+
:mail => []
|
32
|
+
})
|
33
|
+
)
|
34
|
+
# Load schema locally for offline testing.
|
35
|
+
# This will generate this warning...
|
36
|
+
# Warning: schema loading from file
|
37
|
+
# from ucb_ldap-1.3.2/lib/ucb_ldap_schema.rb
|
38
|
+
# Comment this out to get the schema from Cal.
|
39
|
+
# This will generate this warning...
|
40
|
+
# warning: peer certificate won't be verified in this SSL session
|
41
|
+
UCB::LDAP::Schema.stubs(
|
42
|
+
:load_attributes_from_url).raises(StandardError)
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_redirected_to_login
|
46
|
+
assert_response :redirect
|
47
|
+
assert_match "https://auth-test.berkeley.edu/cas/login",
|
48
|
+
@response.redirected_to
|
49
|
+
end
|
50
|
+
|
51
|
+
def assert_redirected_to_logout
|
52
|
+
assert_response :redirect
|
53
|
+
assert_match "https://auth-test.berkeley.edu/cas/logout",
|
54
|
+
@response.redirected_to
|
55
|
+
end
|
56
|
+
|
57
|
+
def assert_logged_in
|
58
|
+
assert_not_nil session[:calnetuid]
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_not_logged_in
|
62
|
+
assert_nil session[:calnetuid]
|
63
|
+
end
|
64
|
+
|
65
|
+
module ClassMethods
|
66
|
+
|
67
|
+
def site_administrators
|
68
|
+
@site_administrators ||= %w( superuser administrator )
|
69
|
+
end
|
70
|
+
|
71
|
+
def non_site_administrators
|
72
|
+
@non_site_administrators ||= ( all_test_roles - site_administrators )
|
73
|
+
end
|
74
|
+
|
75
|
+
def site_editors
|
76
|
+
@site_editors ||= %w( superuser administrator editor )
|
77
|
+
end
|
78
|
+
|
79
|
+
def non_site_editors
|
80
|
+
@non_site_editors ||= ( all_test_roles - site_editors )
|
81
|
+
end
|
82
|
+
|
83
|
+
def site_readers
|
84
|
+
@site_readers ||= %w( superuser administrator editor interviewer reader )
|
85
|
+
end
|
86
|
+
|
87
|
+
def non_site_readers
|
88
|
+
@non_site_readers ||= ( all_test_roles - site_readers )
|
89
|
+
end
|
90
|
+
|
91
|
+
def all_test_roles
|
92
|
+
@all_test_roles = %w( superuser administrator editor interviewer reader active_user )
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end # module CalnetAuthenticated::TestHelper
|
97
|
+
|
98
|
+
require 'active_support'
|
99
|
+
require 'active_support/test_case'
|
100
|
+
ActiveSupport::TestCase.send(:include,CalnetAuthenticated::TestHelper)
|