UCB Rails User
A Rails engine that provides authentication and user management for UCB Rails apps. By adding this engine to your app, you get:
- a full User model which can be customized by host apps
- login and logout via CAS
- automatic creation of user records following CAS authentication
- controller filters that block access to resources unless user is logged in
- a default home page that reflects user's login status
- admin screens for updating and deleting user records
This engine also includes the Datatables JQuery plug-in, which is used in the user management screens. Host apps can make use of this as well.
Prerequisites
- Ruby >= 2.3
- Rails >= 5.1
Older versions may work as well, but they haven't been tested.
Installation
The easiest way to use this is to generate a new app with the ucb_rails command-line tool, which has this engine integrated as a gem and automates most of the steps below for you.
But if you need to add this to an already-existing app, do the following:
- Add the required gems to your Gemfile:
gem "ucb_rails_user", github: "ucb-ist-eas/ucb_rails_user"
gem "ucb_ldap", github: "ucb-ist-eas/ucb-ldap"
gem "rails_view_helpers", github: "ucb-ist-eas/rails_view_helpers", branch: "rails5"
then run bundler
to install them:
bundle install
- Create a file named
config.yml
in theconfig
directory, and copy this into it:
ldap:
username: LDAP_USERNAME
password: LDAP_PASSWORD
Replace LDAP_USERNAME
and LDAP_PASSWORD
with the proper credentials - you can get these from another developer.
IMPORTANT Be sure to add config/config.yml
to your .gitignore
so that the username and password are not saved to source control.
- Add this line to your host app's
ApplicationController:
include UcbRailsUser::Concerns::ControllerMethods
Copy this initializer file into your host app's
config/initializer
directory.Setup a root path in
config/routes.rb
, if you haven't already. You can use the default home page provided by this gem, if you like:
root to: UcbRailsUser::HomeController.action(:index)
- Copy the migrations for the
User
model from the engine into your host app, and run them:
bin/rails railties:install:migrations
bin/rake db:migrate
- Update your assets files
In application.css
add this line:
*= require ucb_rails_user/main
And in application.js
add this line:
//= require ucb_rails_user/scripts
- Restart your host app as usual
You should be able to access the following routes:
/
: if you're usingUcbRailsUser::HomeController#index
as your home page, you should see a simple screen showing your login status/login
: this should redirect you to the main CAS login page/logout
: this should log you out of CAS and redirect you back to the host app/admin/users
: this should display the user management screen, if your user account has thesuperuser
flag set; otherwise, you'll see a 401 page/admin/users/toggle_superuser
: in dev mode, you can use this url to turn the superuser flag of your account on and off
Routing
The config/routes.rb file will show you the routes that this engine provides out of the box. But if necessary, you can override these routes in your host app.
For example, if the admin screens for your app are under the /backend
path rather than /admin,
you can rewrite the route in your host app like this:
resources :users, controller: "ucb_rails_user/users", path: "backend/users", as: :backend_users
Controller Methods
If you followed the setup instructions above, your ApplicationController
should be including UcbRails::Concerns::ControllerMethods.
This provides a number of utility methods you can use in your controllers:
current_user
: returns theUser
instance for the currently logged-in user, ornil
if user is not logged incurrent_ldap_person
: returns theUCB::LDAP::Person
instance for the currently logged-in user, ornil
if user is not logged inlogged_in?
: returns true if the user is logged insuperuser?
: returns true if the current user has the superuser flag set to trueensure_authenticated_user
: returns a 401 error if the user is not logged inensure_admin_user
: returns a 401 error if the user is not a superuser
current_user
, current_ldap_person
, logged_in?
and superuser?
are all helper methods, so you can use them in views as well as controllers.
ensure_authenticated_user
is set as a before_filter
so by default, all pages will require a login (except the HomeController
included in this gem).
To make a page available to a non-logged-in user, add this line to your controller:
skip_before_action :ensure_authenticated_user
UsersController
uses ensure_admin_user
as a before_filter
Testing Support
This engine comes with a few features to help with testing.
The UcbRailsUser::UserSessionManager::TestSessionManager
is a specialized session manager designed for test cases. It overrides the login
method to lookup the given uid
in the users
table of the database. As long as the user record already exists, the login
method will return successfully.
There is also a UcbRailsUser::SpecHelpers
module that provides some support methods. Specifically, the login_user
method can be used in request or integration specs to perform the behind-the-scenes work needed to login a given user. This method is implemented according to the omniauth gem documentation.
To add the testing support, add the following lines to your spec_helper.rb
or rails_helper.rb
file:
# add this line
require 'ucb_rails_user/spec_helpers'
# then, somewhere in this block...
RSpec.configure do |config|
...
# ...add these lines
config.include UcbRailsUser::SpecHelpers
UcbRailsUser.config do |config|
config.user_session_manager = "UcbRailsUser::UserSessionManager::TestSessionManager"
end
Then, from within any request or integration spec, you should be able to do this:
it "should do some neato feature" do
user = create(:user) # assumes you've added FactoryBot or similiar
login_user(user)
end
and the user should now be logged in.
Overriding Model And Controller Behavior
The host app can add or override behavior of the User
model and UserController
as needed. We've followed the conventions suggested in the Rails guide to make this as easy as possible.
To add to the User
model, create a file named app/models/user.rb
in your host app, and add the following code:
class User < ApplicationRecord
include UcbRailsUser::UserConcerns
# add your code here
end
Similarly, to override UserController,
add app/controllers/ucb_rails/user_controller.rg
and add the following:
class UcbRailsUser::UsersController < ApplicationController
include UcbRailsUser::Concerns::UsersController
# add your code here
end
Overriding The Default Home Page
If you're using the HomeController
provided by this engine for your home page, you can change the views that are used for the logged in and not logged in states.
- create the directory
app/views/ucb_rails_user/home
- inside that directory, create two files:
logged_in.html.haml
not_logged_in.html.haml
One of those two views will render when the user hits the home page, depending on whether or not they're currently logged in.