Administration and Restricting Access
| |
|
|
| |
Contents |
|
| |
|
|
Restricting access and activity is important to Role based sites. You will now add the ability to restrict access to certain parts of the site dependent upon which roles the user has been granted. You will also bootstrap an Admin (or Super User) account that will have the access ability to assign roles to other users.
Add Helper Methods
Add the following methods to app/controller/application_controller.rb
def current_user?
!session[:user_id].nil?
end
def logged_in
unless current_user?
flash[:error] = "Please Log In First"
redirect_to log_in_path
end
end
def admin?
current_user.role_ids.include?(Role.find_by_name("Admin").id)
end
def authorize
unless admin?
flash[:error] = "Unauthorized Access"
redirect_to root_url
false
end
end
Add these lines to same file to make the helper methods available to all controllers:
helper_method :current_user?
helper_method :admin?
helper_method :authorize
helper_method :logged_in
private
These methods basically return Boolean values that correspond to the method names. We will use these methods to determine, "Is there is a current user?", "Is the user the admin?", and "Is the user authorized to do this?".
The simple line "private" ensures these methods are private.
Restricting Access to Logged In Users
Add the before_filter line below to call a method before calling controller methods. This example shows how to restrict access to viewing and assigning roles to only users that are currently logged in.
Add the following line to the beginning of the class in app/controllers/roles_controller.rb:
before_filter :logged_in
Make sure you are logged out and navigate to http://localhost:3000/roles
. You should see the flash message that you must be logged in and redirected to the log in page.

Add Administrator Account
Add another rake task to bootstrap Admin and User roles to the database. The Admin role will grant users access to more restricted areas and methods. These tasks will also add an Admin account to the database. This account will be managed in a method User::authAdmin.
Add the following to lib/tasks/populate.rake:
task :all => [:AuthServiceURL, :AdminRoleID] do puts "All rake tasks performed" end task :Admin => :environment do admin = User.new admin.username = "admin" admin.cred = "not null" admin.firstname = "Site" admin.lastname = "Administrator" admin.password = "not_actual_password" #password must be present but is set in User:authAdmin if admin.save puts "Admin account saved successful" else puts "Admin account unsuccessful save" end end task :Role => :environment do addRole("Admin", "Site Administrator") addRole("User", "Normal User") end task :AdminRoleID => [:Role, :Admin] do role = Role.find_by_name("Admin") role.user_ids = role.user_ids << User.find_by_username("admin").id if role.save puts "Admin role assigned successful" else puts "Admin role unsuccessfully assigned" end end def addRole(name, description) role = Role.new role.name = name role.description = description if role.save puts name + " role save successful" else puts name + " role unsuccessful save" end end
Rake tasks follow dependency rules. The line :AdminRoleID => [:Role, :Admin] means the :Role and :Admin tasks will be called before :AdminRoleID task will run. Therefore, just run the :AdminRoleID task to run all of these tasks.

GridClient %> rake populate:AdminRoleID
You should see the following output:
Admin save successful User save successful Admin account saved successful Admin role assigned successful
| The ":all" task depends on both :AuthServiceURL and :AdminRoldID. Running this task will run all tasks in the populate.rake file. Any new tasks created can easily be added to the hash of dependencies of the :all task. |
Admin Credentials
The authAdmin method below will check the Admin account credentials at log in. Add the method to app/models/user.rb:
def self.authAdmin(password)
if password == "1234"
return find_by_username("admin")
end
end
| This is where the bootstrapped Admin account password is stored. This account is necessary because it will be the only account able to access and assign roles. Once another user is assigned the "Admin" role, this account can be deleted. However, only site administrators should have access to change this code. |
Replace the create method in app/controllers/sessions_controller.rb with the following:
def create
if params[:username] == "admin"
user = User.authAdmin(params[:password])
cred = nil
else
username = String.new(params[:username])
userCred = User.authUser(username.downcase, params[:password], params[:auth_service_url])
if !userCred.nil?
user = userCred.at(0)
if userCred.length > 1
cred = userCred.at(1)
end
end
end
if user
session[:user_id] = user.id
session[:globus] = cred
redirect_to roles_path, :notice => "Logged in!"
else
flash.now.alert = "Invalid username or password"
render "new"
end
end
Restricting Access
Open the file app/views/roles/index.html.erb and add the code just below the <h1>Listing Roles<h1> header:
<% if admin? %>
<td><%= link_to 'Assign Roles to Users', role_assign_path %></td>
<% end %>
<br></br>
This code will call the admin? method to check if the current user has the admin role assigned to them. If they do, then the link will be displayed.
Check this by starting the rails server, log in with the credentials:
Dorian username: admin Dorian password: 1234
Now, on the http://localhost:3000/roles
page, a link to "Assign Roles to Users" should be available.

Here you can see the two user accounts, admin and mark, and the roles assigned to each. Notice "mark" does not have the admin role.

Here is the roles index page when logged in with "mark". Notice there is no link to "Assign Roles to Users".

This is an good example of how to hide items in the view from users without proper access. This is good because a separate administration view is not needed, as admin options can just be added in line to the existing view. However, users can still access the assign roles page if they navigate to http://localhost:3000/role/assign
. The above code just hides the link on the page. To restrict which methods are available to users, add the following filter to class in app/controllers/roles_controller.rb
before_filter :authorize, :except => [:index]
This will restrict user's access to just the index location, http://localhost:3000/roles
. Any other attempts to access role pages or methods will redirected and will display the "Unauthorized Access" error message.

| To make more methods available to users, such as "show", just add more methods to the hash in the filter (ex. before_filter :authorize, :except => [:index, :show]). Remove the except option to restrict all methods in the controller. |
Be sure no unauthorized changes to roles will occur by adding the following filter to app/controllers/users_controller.rb:
before_filter :authorize, :except => [:new, :create, :index]





