From 311a251f245d19885517f746bfa1161d18df2cad Mon Sep 17 00:00:00 2001
From: Eric James <eric.james@yale.edu>
Date: Thu, 21 Apr 2016 17:04:58 -0400
Subject: [PATCH 1/4] initial CAS scaffolding

---
 Gemfile                                      |  2 ++
 app/controllers/users/sessions_controller.rb | 33 ++++++++++++++++++++
 app/views/_user_util_links.html.erb          |  4 +--
 app/views/modules/_user_management.html.erb  |  2 +-
 config/initializers/omniauth.rb              |  8 +++++
 config/routes.rb                             | 13 ++++++--
 db/schema.rb                                 |  6 ++--
 7 files changed, 59 insertions(+), 9 deletions(-)
 create mode 100644 config/initializers/omniauth.rb

diff --git a/Gemfile b/Gemfile
index 1c84a426ad..87cbb14fac 100644
--- a/Gemfile
+++ b/Gemfile
@@ -79,6 +79,8 @@
   gem 'equivalent-xml'
   gem 'net-ldap'
 
+  gem 'omniauth-cas'
+
   group :assets, :production do
     gem 'coffee-rails'
     gem 'uglifier', '>= 1.0.3'
diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb
index 62972d473b..24c547e01a 100644
--- a/app/controllers/users/sessions_controller.rb
+++ b/app/controllers/users/sessions_controller.rb
@@ -27,4 +27,37 @@ def destroy
     flash[:success] = flash[:notice]
     flash[:notice] = nil
   end
+
+  def login
+    logger.info "in omniauth callback after logging in"
+    
+    params[:provider] ? provider = params[:provider] : provider = ""
+    user_info = getExtraFromLDAP(request.env["omniauth.auth"].uid)
+    user_info["mail"] ? email = user_info["mail"][0] : email = ""
+    user_info["uid"] ? uid = user_info["uid"][0] : uid = ""
+    logger.info "provider: #{provider}"
+    logger.info "email: #{email}"
+    logger.info "uid: #{uid}"
+    redirect_to root_path
+  end
+
+  def logout
+    logger.info "logging out of cas"
+    redirect_to 'https://secure.its.yale.edu/cas/logout'
+  end
+
+  protected
+
+  def getExtraFromLDAP(netid)
+    begin
+      require 'net/ldap'
+      ldap = Net::LDAP.new( :host =>"directory.yale.edu" , :port =>"389" )
+      f = Net::LDAP::Filter.eq('uid', netid)
+      b = 'ou=People,o=yale.edu'
+      p = ldap.search(:base => b, :filter => f, :return_result => true).first
+    rescue Exception => e
+      return
+    end
+    return p
+  end
 end
diff --git a/app/views/_user_util_links.html.erb b/app/views/_user_util_links.html.erb
index 4ea6074637..82c732dc06 100644
--- a/app/views/_user_util_links.html.erb
+++ b/app/views/_user_util_links.html.erb
@@ -35,9 +35,9 @@ Unless required by applicable law or agreed to in writing, software distributed
     </li>
     <% end %>
     <li class="divider desktop-hidden" />
-    <%= link_to_if user_signed_in?, 'Sign out', destroy_user_session_path do %>
+    <%= link_to_if user_signed_in?, 'Sign out', "users/sign_out" do %>
     <%# Fallback if the test above fails %>
-    <%= link_to 'Sign in', new_user_session_path %>
+    <%= link_to 'Sign in', "users/auth/cas" %>
     <% end %>
   </ul>
 </div>
diff --git a/app/views/modules/_user_management.html.erb b/app/views/modules/_user_management.html.erb
index ee10e57d68..c2cd33aeb9 100644
--- a/app/views/modules/_user_management.html.erb
+++ b/app/views/modules/_user_management.html.erb
@@ -17,5 +17,5 @@ Unless required by applicable law or agreed to in writing, software distributed
     <% if user_signed_in? %>
       <%= user_key %> <%= link_to t('auth.sign_out'), destroy_user_session_path %>
     <% else %>
-      <%= link_to t('auth.sign_in'), new_user_session_path %>
+      <%= link_to t('auth.sign_in'), "users/auth/cas" %>
     <% end %>
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
new file mode 100644
index 0000000000..06c4433eed
--- /dev/null
+++ b/config/initializers/omniauth.rb
@@ -0,0 +1,8 @@
+Rails.application.config.middleware.use OmniAuth::Builder do
+  provider :cas, 
+   host: 'secure.its.yale.edu',
+   login_url: '/cas/login',
+   service_validate_url: '/cas/serviceValidate',
+   disable_ssl_verification: true,
+   logout_url: '/cas/logout'
+end
diff --git a/config/routes.rb b/config/routes.rb
index 38e8e6ccf0..c591c5d043 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -20,11 +20,18 @@
 
   root :to => "catalog#index"
 
-  devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }, format: false
+  #devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }, format: false
+  #devise_scope :user do 
+  #  match '/users/sign_in', :to => "users/sessions#new", :as => :new_user_session, via: [:get]
+  #  match '/users/sign_out', :to => "users/sessions#destroy", :as => :destroy_user_session, via: [:get]
+  #end
+
+  devise_for :users
   devise_scope :user do 
-    match '/users/sign_in', :to => "users/sessions#new", :as => :new_user_session, via: [:get]
-    match '/users/sign_out', :to => "users/sessions#destroy", :as => :destroy_user_session, via: [:get]
+    match 'users/auth/:provider/callback', :to => "users/sessions#login", via: [:get]
+    match '/users/sign_out', :to => "users/sessions#logout", via: [:get]
   end
+
   match "/authorize", to: 'derivatives#authorize', via: [:get, :post]
   match "/authorize/:path", to: 'derivatives#authorize', via: [:get, :post]
   match "/autocomplete", to: 'object#autocomplete', via: [:get]
diff --git a/db/schema.rb b/db/schema.rb
index da1831013e..77645d3b09 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20150625121750) do
+ActiveRecord::Schema.define(version: 20150824155143) do
 
   create_table "bookmarks", force: true do |t|
     t.integer  "user_id",       null: false
@@ -82,8 +82,8 @@
   add_index "searches", ["user_id"], name: "index_searches_on_user_id"
 
   create_table "sessions", force: true do |t|
-    t.string   "session_id", null: false
-    t.text     "data"
+    t.string   "session_id",                  null: false
+    t.text     "data",       limit: 16777215
     t.datetime "created_at"
     t.datetime "updated_at"
   end

From e90f3e9aa0a36568cf1e9bd22ebd9b4e63d30398 Mon Sep 17 00:00:00 2001
From: Eric James <eric.james@yale.edu>
Date: Mon, 25 Apr 2016 14:52:32 -0400
Subject: [PATCH 2/4] finish cas login

---
 app/controllers/users/providers_controller.rb | 80 +++++++++++++++++++
 app/views/_user_util_links.html.erb           |  2 +-
 config/routes.rb                              |  4 +-
 3 files changed, 83 insertions(+), 3 deletions(-)
 create mode 100644 app/controllers/users/providers_controller.rb

diff --git a/app/controllers/users/providers_controller.rb b/app/controllers/users/providers_controller.rb
new file mode 100644
index 0000000000..d99dd9369d
--- /dev/null
+++ b/app/controllers/users/providers_controller.rb
@@ -0,0 +1,80 @@
+# Copyright 2011-2015, The Trustees of Indiana University and Northwestern
+#   University.  Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+# 
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software distributed 
+#   under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+#   CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+#   specific language governing permissions and limitations under the License.
+# ---  END LICENSE_HEADER BLOCK  ---
+
+class Users::ProvidersController < ApplicationController
+
+  def login
+    logger.info "in omniauth callback after logging in"
+    
+    #4/25/16 current implemented provider is "CAS" 
+    params[:provider] ? provider = params[:provider] : provider = ""
+    user_info = getExtraFromLDAP(request.env["omniauth.auth"].uid)
+    user_info["mail"] ? email = user_info["mail"][0] : email = ""
+    user_info["uid"] ? username = user_info["uid"][0] : username = ""
+    logger.info "provider: #{provider}"
+    logger.info "email: #{email}"
+    logger.info "username: #{username}"
+
+    if provider.present? == false || email.present? == false || username.present? == false
+      logger.error "missing key info - provider, email, username"
+      flash[:error] = "Error retrieving user information"
+      redirect_to root_path and return
+    end
+    #service = Service.find_by_provider_uid(provider,uid)
+    user = User.where(provider: provider,username: username)
+    if user.empty? == false
+      logger.info "signing in as user #{user.inspect}"
+      if user[0].email != email
+        logger.info "email from ldap #{email} doesn't match email in this app #{user[0].email}, update."
+        user.email = email
+        user.save!
+      end
+      flash[:notice] = "Signed in successfully via #{provider.upcase} as #{username} with email #{email}."
+      sign_in_and_redirect(user[0]) and return
+    else
+      logger.info "no user found, creating #{provider.upcase} user #{username} email #{email}"
+      user = User.new(:username => username, :provider => provider, :email => email)
+      user.save!
+      flash[:notice] = "Sign in via #{provider.upcase} has been added to your account #{username} with email #{email}."
+      sign_in_and_redirect(user) and return
+    end
+    logger.error "Something went wrong on login."
+    flash[:error] = "Something went wrong on login.  Contact administrator"    
+    redirect_to root_path and return
+  end
+
+  def logout
+    logger.info "logging out of cas"
+    sign_out(current_user)
+    redirect_to 'https://secure.its.yale.edu/cas/logout'
+  end
+
+  protected
+
+  def getExtraFromLDAP(netid)
+    begin
+      require 'net/ldap'
+      ldap = Net::LDAP.new( :host =>"directory.yale.edu" , :port =>"389" )
+      f = Net::LDAP::Filter.eq('uid', netid)
+      b = 'ou=People,o=yale.edu'
+      p = ldap.search(:base => b, :filter => f, :return_result => true).first
+    rescue Exception => e
+      return
+    end
+    return p
+  end
+
+  private
+
+end
diff --git a/app/views/_user_util_links.html.erb b/app/views/_user_util_links.html.erb
index 82c732dc06..b159b55d48 100644
--- a/app/views/_user_util_links.html.erb
+++ b/app/views/_user_util_links.html.erb
@@ -35,7 +35,7 @@ Unless required by applicable law or agreed to in writing, software distributed
     </li>
     <% end %>
     <li class="divider desktop-hidden" />
-    <%= link_to_if user_signed_in?, 'Sign out', "users/sign_out" do %>
+    <%= link_to_if user_signed_in?, 'Sign out', destroy_user_session_path do %>
     <%# Fallback if the test above fails %>
     <%= link_to 'Sign in', "users/auth/cas" %>
     <% end %>
diff --git a/config/routes.rb b/config/routes.rb
index c591c5d043..49269f9366 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -28,8 +28,8 @@
 
   devise_for :users
   devise_scope :user do 
-    match 'users/auth/:provider/callback', :to => "users/sessions#login", via: [:get]
-    match '/users/sign_out', :to => "users/sessions#logout", via: [:get]
+    match 'users/auth/:provider/callback', :to => "users/providers#login", via: [:get]
+    match '/users/sign_out', :to => "users/providers#logout", :as => :destroy_user_session, via: [:get]
   end
 
   match "/authorize", to: 'derivatives#authorize', via: [:get, :post]

From db6a51180b92e902dbea17f0e26d6fdddb814c60 Mon Sep 17 00:00:00 2001
From: Eric James <eric.james@yale.edu>
Date: Mon, 25 Apr 2016 15:03:12 -0400
Subject: [PATCH 3/4] remove changes to sessions controller

---
 app/controllers/users/sessions_controller.rb | 33 --------------------
 1 file changed, 33 deletions(-)

diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb
index 24c547e01a..62972d473b 100644
--- a/app/controllers/users/sessions_controller.rb
+++ b/app/controllers/users/sessions_controller.rb
@@ -27,37 +27,4 @@ def destroy
     flash[:success] = flash[:notice]
     flash[:notice] = nil
   end
-
-  def login
-    logger.info "in omniauth callback after logging in"
-    
-    params[:provider] ? provider = params[:provider] : provider = ""
-    user_info = getExtraFromLDAP(request.env["omniauth.auth"].uid)
-    user_info["mail"] ? email = user_info["mail"][0] : email = ""
-    user_info["uid"] ? uid = user_info["uid"][0] : uid = ""
-    logger.info "provider: #{provider}"
-    logger.info "email: #{email}"
-    logger.info "uid: #{uid}"
-    redirect_to root_path
-  end
-
-  def logout
-    logger.info "logging out of cas"
-    redirect_to 'https://secure.its.yale.edu/cas/logout'
-  end
-
-  protected
-
-  def getExtraFromLDAP(netid)
-    begin
-      require 'net/ldap'
-      ldap = Net::LDAP.new( :host =>"directory.yale.edu" , :port =>"389" )
-      f = Net::LDAP::Filter.eq('uid', netid)
-      b = 'ou=People,o=yale.edu'
-      p = ldap.search(:base => b, :filter => f, :return_result => true).first
-    rescue Exception => e
-      return
-    end
-    return p
-  end
 end

From f6e4b25297fb8be48d71470a629672b3d6dc53a5 Mon Sep 17 00:00:00 2001
From: Eric James <eric.james@yale.edu>
Date: Mon, 25 Apr 2016 15:48:52 -0400
Subject: [PATCH 4/4] more bug cleanup and test skeleton

---
 app/controllers/users/providers_controller.rb |  4 +-
 app/views/modules/_user_management.html.erb   |  2 +-
 .../users/providers_controller_spec.rb        | 37 +++++++++++++++++++
 3 files changed, 40 insertions(+), 3 deletions(-)
 create mode 100644 spec/controllers/users/providers_controller_spec.rb

diff --git a/app/controllers/users/providers_controller.rb b/app/controllers/users/providers_controller.rb
index d99dd9369d..5db49d8b0f 100644
--- a/app/controllers/users/providers_controller.rb
+++ b/app/controllers/users/providers_controller.rb
@@ -37,8 +37,8 @@ def login
       logger.info "signing in as user #{user.inspect}"
       if user[0].email != email
         logger.info "email from ldap #{email} doesn't match email in this app #{user[0].email}, update."
-        user.email = email
-        user.save!
+        user[0].email = email
+        user[0].save!
       end
       flash[:notice] = "Signed in successfully via #{provider.upcase} as #{username} with email #{email}."
       sign_in_and_redirect(user[0]) and return
diff --git a/app/views/modules/_user_management.html.erb b/app/views/modules/_user_management.html.erb
index c2cd33aeb9..283ae46b7b 100644
--- a/app/views/modules/_user_management.html.erb
+++ b/app/views/modules/_user_management.html.erb
@@ -15,7 +15,7 @@ Unless required by applicable law or agreed to in writing, software distributed
 %>
 <%# The containers for the links need to be defined by the calling partial %>
     <% if user_signed_in? %>
-      <%= user_key %> <%= link_to t('auth.sign_out'), destroy_user_session_path %>
+      <%= user_key %> <%= "  #{current_user.email}" %><%= link_to t('auth.sign_out'), destroy_user_session_path %>
     <% else %>
       <%= link_to t('auth.sign_in'), "users/auth/cas" %>
     <% end %>
diff --git a/spec/controllers/users/providers_controller_spec.rb b/spec/controllers/users/providers_controller_spec.rb
new file mode 100644
index 0000000000..e8ffe70d84
--- /dev/null
+++ b/spec/controllers/users/providers_controller_spec.rb
@@ -0,0 +1,37 @@
+# Copyright 2011-2015, The Trustees of Indiana University and Northwestern
+#   University.  Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+# 
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software distributed 
+#   under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+#   CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+#   specific language governing permissions and limitations under the License.
+# ---  END LICENSE_HEADER BLOCK  ---
+
+require 'spec_helper'
+
+describe Users::ProvidersController do
+  describe "#login" do
+    describe "as an authenticated user" do
+      it "should flash error if provider is missing" do
+      end
+      it "should flash error if email missing" do
+      end
+      it "should flash error if username missing" do
+      end
+      it "should login new user with new provider and username, with email" do
+      end
+      it "should login existing user if provider and username exist and same email" do
+      end
+      it "should login existing user if provider and username exist and change email if email changed" do
+      end
+      it "currently 4-25-16 should have only have one provider that is cas" do
+      end
+    end
+  end
+
+end