Skip to content

Commit

Permalink
Add CAS login
Browse files Browse the repository at this point in the history
Closes #23
  • Loading branch information
tpendragon committed Jul 31, 2017
1 parent 61f6182 commit 83d1a24
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 15 deletions.
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ RSpec/VerifiedDoubles:
- 'spec/models/search_builder_spec.rb'
- 'spec/validators/viewing_hint_validator_spec.rb'
- 'spec/validators/viewing_direction_validator_spec.rb'
- 'spec/models/user_spec.rb'
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ gem 'devise'
gem 'hydra-head'
gem 'modernizr-rails'
gem 'normalize-rails'
gem 'omniauth-cas'
gem 'pul_metadata_services', github: 'pulibrary/pul_metadata_services', branch: 'master'
gem 'sidekiq'
gem 'string_rtl'
Expand Down
9 changes: 9 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ GEM
hamster (3.0.0)
concurrent-ruby (~> 1.0)
hashdiff (0.3.4)
hashie (3.5.6)
honeybadger (3.1.2)
httmultiparty (0.3.16)
httparty (>= 0.7.3)
Expand Down Expand Up @@ -412,6 +413,13 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
omniauth (1.6.1)
hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3)
omniauth-cas (1.1.1)
addressable (~> 2.3)
nokogiri (~> 1.5)
omniauth (~> 1.2)
open4 (1.3.4)
orm_adapter (0.5.0)
os (0.9.6)
Expand Down Expand Up @@ -674,6 +682,7 @@ DEPENDENCIES
listen
modernizr-rails
normalize-rails
omniauth-cas
pg
poltergeist
pry-byebug
Expand Down
6 changes: 6 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ class ApplicationController < ActionController::Base
layout 'application'

protect_from_forgery with: :exception

def guest_uid_authentication_key(key)
key &&= nil unless key.to_s =~ /^guest/
return key if key
"guest_" + guest_user_unique_suffix
end
end
10 changes: 10 additions & 0 deletions app/controllers/users/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def cas
# You need to implement the method below in your model (e.g. app/models/user.rb)
@user = User.from_omniauth(request.env["omniauth.auth"])

sign_in_and_redirect @user, event: :authentication # this will throw if @user is not activated
set_flash_message(:notice, :success, kind: "CAS") if is_navigational_format?
end
end
12 changes: 9 additions & 3 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@ class User < ApplicationRecord
# Connects this user object to Blacklights Bookmarks.
include Blacklight::User
include Hydra::User
def self.from_omniauth(access_token)
User.where(provider: access_token.provider, uid: access_token.uid).first_or_create do |user|
user.uid = access_token.uid
user.provider = access_token.provider
user.email = "#{access_token.uid}@princeton.edu"
end
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
devise :omniauthable, omniauth_providers: [:cas]

# Method added by Blacklight; Blacklight uses #to_s on your
# user class to get a user-displayable login/identifier for
# the account.
def to_s
email
uid
end

def admin?
Expand Down
7 changes: 4 additions & 3 deletions config/initializers/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [:email]
config.authentication_keys = [:uid]

# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
Expand All @@ -47,12 +47,12 @@
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [:email]
config.case_insensitive_keys = [:uid]

# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = [:email]
config.strip_whitespace_keys = [:uid]

# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
Expand Down Expand Up @@ -252,6 +252,7 @@
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :cas, host: 'fed.princeton.edu', url: 'https://fed.princeton.edu/cas'

# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
Expand Down
5 changes: 3 additions & 2 deletions config/role_map.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
development:
admin:
- admin@example.com
- admin
- tpend

test:
admin:
- admin@example.com
- admin

production:
# Add roles for users here.
6 changes: 5 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
end
end

devise_for :users
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }, skip: [:passwords, :registration]
devise_scope :user do
get 'sign_out', to: 'devise/sessions#destroy', as: :destroy_user_session
get 'users/auth/cas', to: 'users/omniauth_authorize#passthru', defaults: { provider: :cas }, as: "new_user_session"
end
concern :exportable, Blacklight::Routes::Exportable.new

resources :solr_documents, only: [:show], path: '/catalog', controller: 'catalog' do
Expand Down
9 changes: 9 additions & 0 deletions db/migrate/20170731174240_add_cas_to_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddCasToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :provider, :string
add_index :users, :provider
add_column :users, :uid, :string
add_index :users, :uid
end
end
6 changes: 5 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20170724192309) do
ActiveRecord::Schema.define(version: 20170731174240) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -74,8 +74,12 @@
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "guest", default: false
t.string "provider"
t.string "uid"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["provider"], name: "index_users_on_provider"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["uid"], name: "index_users_on_uid"
end

end
7 changes: 4 additions & 3 deletions spec/factories/user.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# frozen_string_literal: true
FactoryGirl.define do
factory :user do
sequence(:email) { |_n| "email-#{srand}@example.com" }
password 'a password'
password_confirmation 'a password'
sequence(:email) { |_n| "#{srand}@princeton.edu" }
sequence(:uid) { |_n| "#{srand}@princeton.edu" }
provider 'cas'
end
factory :admin, parent: :user do
email "admin@example.com"
uid 'admin'
end
end
13 changes: 13 additions & 0 deletions spec/features/root_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true
require 'rails_helper'

RSpec.describe "Home Page" do
let(:user) { FactoryGirl.create(:admin) }
before do
sign_in user
end

it "displays creation links for administrators" do
expect(page).to have_link "New Scanned Resource"
end
end
14 changes: 12 additions & 2 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
RSpec.describe User, type: :model do
subject(:user) { FactoryGirl.create(:user) }
describe "#to_s" do
it "returns the user's email" do
expect(user.to_s).to eq user.email
it "returns the user's NetID" do
expect(user.to_s).to eq user.uid
end
end
describe "#admin?" do
Expand All @@ -14,4 +14,14 @@
expect(user).to be_admin
end
end

describe ".from_omniauth" do
it "creates a user" do
token = double("token", provider: "cas", uid: "test")
user = described_class.from_omniauth(token)
expect(user).to be_persisted
expect(user.provider).to eq "cas"
expect(user.uid).to eq "test"
end
end
end
18 changes: 18 additions & 0 deletions spec/support/features/session_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Features
# Provides methods for login and logout within Feature Tests
module SessionHelpers
# Use this in feature tests
def sign_in(who = :user)
user = if who.instance_of?(User)
who.uid
else
FactoryGirl.create(:user).uid
end
OmniAuth.config.add_mock(:cas, uid: user)
visit user_cas_omniauth_authorize_path
end
end
end
RSpec.configure do |config|
config.include Features::SessionHelpers, type: :feature
end
8 changes: 8 additions & 0 deletions spec/support/reset_auth.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
OmniAuth.config.test_mode = true
RSpec.configure do |config|
config.before(:each) do
OmniAuth.config.mock_auth[:cas] = nil
Rails.application.env_config["devise.mapping"] = Devise.mappings[:user] # If using Devise
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter]
end
end

0 comments on commit 83d1a24

Please sign in to comment.