Merge pull request #321 from warpc/270-user_control

[Refs #270] Admin user control (include ban, protect from mass assigment)
This commit is contained in:
Vladimir Sharshov 2012-03-22 08:41:07 -07:00
commit 09a3d46303
26 changed files with 280 additions and 156 deletions

View File

@ -622,6 +622,22 @@ div.rightlist textarea.resizable {
resize: both; resize: both;
} }
table.tablesorter.list-users th.th1 {
width: 150px;
}
table.tablesorter.list-users th.th2 {
width: 100px;
}
table.tablesorter.list-users th.th3 {
width: 200px;
}
table.tablesorter.list-users th.th4 {
width: 50px;
}
div.admin-role { div.admin-role {
padding-right: 10px; padding-right: 10px;
} }

View File

@ -0,0 +1,70 @@
# -*- encoding : utf-8 -*-
class Admin::UsersController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource :except => :create
authorize_resource :only => :create
def index
@filter = params[:filter] || 'all'
end
def new
end
def create
@user = User.new params[:user]
@user.role = params[:role]
@user.uname = params[:uname]
if @user.save
flash[:notice] = t('flash.user.saved')
redirect_to users_path
else
flash[:error] = t('flash.user.save_error')
render :action => :new
end
end
def profile
end
def update
@user.role = params[:role]
if @user.update_without_password(params[:user])
if @user.avatar && params[:delete_avatar] == '1'
@user.avatar = nil
@user.save
end
flash[:notice] = t('flash.user.saved')
redirect_to users_path#edit_user_path(@user)
else
flash[:error] = t('flash.user.save_error')
flash[:warning] = @user.errors.full_messages.join('. ')
render(:action => :profile)
end
end
def destroy
@user.destroy
flash[:notice] = t("flash.user.destroyed")
redirect_to users_path
end
def list
colName = ['users.name', 'users.uname', 'users.email']
sort_col = params[:iSortCol_0] || 0
sort_dir = params[:sSortDir_0]=="asc" ? 'asc' : 'desc'
order = "#{colName[sort_col.to_i]} #{sort_dir}"
@users = @users.paginate(:page => (params[:iDisplayStart].to_i/params[:iDisplayLength].to_i).to_i + 1, :per_page => params[:iDisplayLength])
@total_users = @users.count
if !params[:sSearch].blank? && search = "%#{params[:sSearch]}%"
@users = @users.where('users.name ILIKE ? or users.uname ILIKE ? or users.email ILIKE ?', search, search, search)
end
@filter = params[:filter] || 'all'
@users = @users.send(@filter) if ['real', 'admin', 'banned'].include? @filter
@total_user = @users.count
@users = @users.order(order)
render :partial =>'users_ajax', :layout => false
end
end

View File

@ -12,7 +12,7 @@ class ApplicationController < ActionController::Base
helper_method :get_owner helper_method :get_owner
rescue_from CanCan::AccessDenied do |exception| rescue_from CanCan::AccessDenied do |exception|
redirect_to forbidden_url, :alert => t('flash.exception_message')#:alert => exception.message redirect_to forbidden_url, :alert => t("flash.exception_message")
end end
protected protected

View File

@ -2,57 +2,27 @@
class UsersController < ApplicationController class UsersController < ApplicationController
before_filter :authenticate_user! before_filter :authenticate_user!
load_and_authorize_resource load_and_authorize_resource :only => :show
before_filter :set_current_user, :only => [:profile, :update, :private]
autocomplete :user, :uname autocomplete :user, :uname
def index
@user = User.scoped
if !params[:filter].blank? && !params[:filter][:email].blank?
@users = @users.where(:email => params[:filter][:email])
@email = params[:filter][:email]
end
@users = @users.paginate(:page => params[:user_page])
@action_url = users_path
end
def show def show
@groups = @user.groups.uniq @groups = @user.groups.uniq
@platforms = @user.platforms.paginate(:page => params[:platform_page], :per_page => 10) @platforms = @user.platforms.paginate(:page => params[:platform_page], :per_page => 10)
@projects = @user.projects.paginate(:page => params[:project_page], :per_page => 10) @projects = @user.projects.paginate(:page => params[:project_page], :per_page => 10)
end end
def new
@user = User.new
end
def profile def profile
@user ||= current_user
end
def create
@user = User.new params[:user]
if @user.save
flash[:notice] = t('flash.user.saved')
redirect_to users_path
else
flash[:error] = t('flash.user.save_error')
render :action => :new
end
end end
def update def update
if params[:user][:role] && current_user.admin?
@user.role = params[:user][:role]
params[:user].delete(:role)
end
@user ||= current_user
if @user.update_without_password(params[:user]) if @user.update_without_password(params[:user])
if @user.avatar && params[:delete_avatar] == '1' if @user.avatar && params[:delete_avatar] == '1'
@user.avatar = nil @user.avatar = nil
@user.save @user.save
end end
flash[:notice] = t('flash.user.saved') flash[:notice] = t('flash.user.saved')
redirect_to @user == current_user ? edit_profile_path : edit_user_path(@user) redirect_to edit_profile_path
else else
flash[:error] = t('flash.user.save_error') flash[:error] = t('flash.user.save_error')
flash[:warning] = @user.errors.full_messages.join('. ') flash[:warning] = @user.errors.full_messages.join('. ')
@ -73,10 +43,10 @@ class UsersController < ApplicationController
end end
end end
def destroy protected
@user.destroy
flash[:notice] = t("flash.user.destroyed") def set_current_user
redirect_to users_path @user = current_user
end end
end end

View File

@ -25,7 +25,7 @@ class Group < ActiveRecord::Base
attr_accessible :description attr_accessible :description
attr_readonly :own_projects_count attr_readonly :own_projects_count
delegate :ssh_key, :email, :to => :owner delegate :email, :to => :owner
after_create :add_owner_to_members after_create :add_owner_to_members

View File

@ -1,6 +1,6 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class User < ActiveRecord::Base class User < ActiveRecord::Base
ROLES = ['admin'] ROLES = ['', 'admin', 'banned']
LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']] LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']]
LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last) LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last)
MAX_AVATAR_SIZE = 5.megabyte MAX_AVATAR_SIZE = 5.megabyte
@ -43,14 +43,16 @@ class User < ActiveRecord::Base
validates :role, :inclusion => {:in => ROLES}, :allow_blank => true validates :role, :inclusion => {:in => ROLES}, :allow_blank => true
validates :language, :inclusion => {:in => LANGUAGES}, :allow_blank => true validates :language, :inclusion => {:in => LANGUAGES}, :allow_blank => true
attr_accessible :email, :password, :password_confirmation, :current_password, :remember_me, :login, :name, :ssh_key, :uname, :language, attr_accessible :email, :password, :password_confirmation, :current_password, :remember_me, :login, :name, :language,
:site, :company, :professional_experience, :location, :avatar :site, :company, :professional_experience, :location, :avatar
attr_readonly :uname, :own_projects_count attr_readonly :uname, :own_projects_count
attr_readonly :uname
attr_accessor :login attr_accessor :login
scope :search_order, order("CHAR_LENGTH(uname) ASC") scope :search_order, order("CHAR_LENGTH(uname) ASC")
scope :search, lambda {|q| where("uname ILIKE ?", "%#{q}%")} scope :search, lambda {|q| where("uname ILIKE ?", "%#{q}%")}
scope :banned, where(:role => 'banned')
scope :admin, where(:role => 'admin')
scope :real, where(:role => ['', nil])
after_create lambda { self.create_notifier } after_create lambda { self.create_notifier }
@ -66,6 +68,10 @@ class User < ActiveRecord::Base
new_record? new_record?
end end
def access_locked?
role == 'banned'
end
def fullname def fullname
return "#{uname} (#{name})" return "#{uname} (#{name})"
end end

View File

@ -0,0 +1,9 @@
- content_for :sidebar do
.bordered.nopadding
%h3= t("layout.users.filter_header")
%table
- t('layout.users.users_filter').each_key do |base|
%tr
%td.width18=radio_button_tag :myradio, base, @filter.to_sym == base, {:id => 'users_filter', :class => 'niceRadio', :name => 'filter'}
%td.width135=t("layout.users.users_filter.#{base}")
.both

View File

@ -0,0 +1,19 @@
{
"sEcho": <%=h params[:sEcho].to_i || -1 %>,
"iTotalRecords": <%= @total_users %>,
"iTotalDisplayRecords": <%= @total_user %>,
"aaData": [
<% @users.each do |user| %>
[
"<%= user.name %>",
"<%= user.uname %>",
"<%= user.email %>",
"<span style='<%=user.access_locked? ? 'background: #FEDEDE' : ''%>'><%= user.role %></span>",
"<%= j raw [(link_to t('layout.show'), user_path(user) if can? :read, user),
(link_to t('layout.edit'), edit_user_path(user) if can? :edit, user),
(link_to t('layout.delete'), delete_user_path(user), :method => :delete, :confirm => t('layout.users.confirm_delete') if can? :destroy, user)
].compact.join('&nbsp;|&nbsp;') %>"
]<%= user == @users.last ? '' : ',' %>
<% end %>
]
}

View File

@ -0,0 +1,34 @@
%h3.fix= t("layout.users.list_header")
- if can? :create, User.new
= link_to t("layout.users.new"), new_user_path, :class => 'button'
- columns = [{:type => 'html'}, {:type => 'html'}, {:type => 'html'}, {:type => 'html', :sortable => false, :searchable => false}, {:type => nil, :sortable => false, :searchable => false, :class => 'buttons'}]
= raw datatable(columns, {:sort_by => "[0, 'asc']", :processing => t("layout.processing"),
:pagination_labels => {:previous => t("datatables.previous_label"), :next => t("datatables.next_label")},
:empty_label => t("datatables.empty_label"),
:info_label => t("datatables.info_label"),
:info_empty_label => t("datatables.info_empty_label"),
:filtered_label => t("datatables.filtered_label"),
:table_dom_id => 'datatable',
:auto_width => 'false',
:ajax_source => "#{url_for :controller => 'admin/users', :action => :list}",
:additional_data => {:filter => "' + $('#users_filter[type=\"radio\"]:checked').val() + '"} })
%table#datatable.tablesorter.list-users{:cellspacing => 0, :cellpadding => 0}
%thead
%tr
%th.th1= t("activerecord.attributes.user.name")
%th.th2= t("activerecord.attributes.user.uname")
%th.th3= t("activerecord.attributes.user.email")
%th.th4= t("activerecord.attributes.user.role")
%th.last &nbsp;
%tbody
%br
= render :partial => 'admin/users/sidebar'
= render 'admin/submenu'
:javascript
$('#users_filter[type="radio"]').live('change', function(){
$('#datatable').dataTable().fnDraw();
});

View File

@ -0,0 +1,10 @@
.block
.content
%h2.title= t("layout.users.new_header")
.inner
= form_for @user, :url => users_path, :html => { :class => :form } do |f|
= render :partial => "users/form", :locals => {:f => f}
- content_for :sidebar do
.bordered.nopadding
= render 'admin/submenu'

View File

@ -0,0 +1,16 @@
%h3.fix.bpadding10= @user.uname
= form_for @user, :url => update_user_path(@user), :html => { :class => :form } do |f|
= render :partial => "users/form", :locals => {:f => f}
.notify
%p= t('layout.users.public_data_edit_warning')
.notify
%p= t('layout.users.avatar_notice')
:javascript
$('article .right').addClass('middlepadding');
= render 'admin/submenu'
- content_for :sidebar do
.bordered.nopadding

View File

@ -7,15 +7,17 @@
.logo .logo
/ Page / Page
%article %article
- is_error = (flash.try(:first).try(:first) == :alert && flash.try(:first).try(:last) == t('devise.failure.invalid')) # Trash - if flash.try(:first).try(:first) == :alert && [t('devise.failure.invalid'), t('devise.failure.locked')].include?(flash.try(:first).try(:last))
- error = flash.first.last
- error ||= false
- login = t('devise.sessions.login'); password = t('devise.sessions.password') - login = t('devise.sessions.login'); password = t('devise.sessions.password')
=hidden_field_tag :login_default, login =hidden_field_tag :login_default, login
=hidden_field_tag :password_default, password =hidden_field_tag :password_default, password
= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "form login" }) do |f| = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "form login" }) do |f|
%h1= title t("layout.sessions.sign_in_header") %h1= title t("layout.sessions.sign_in_header")
= f.text_field :login, :class => "registartion-input #{is_error ? "registartion-input-error" : ''}", :value => login = f.text_field :login, :class => "registartion-input #{error ? "registartion-input-error" : ''}", :value => login
%br/ %br/
= f.password_field :password, :class => "registartion-input #{is_error ? "registartion-input-error" : ''}", :value => password = f.password_field :password, :class => "registartion-input #{error ? "registartion-input-error" : ''}", :value => password
%br/ %br/
.registration .registration
.remember .remember
@ -30,4 +32,4 @@
.forgot .forgot
.password .password
%p= link_to t("layout.devise.shared_links.forgot_password"), new_password_path(resource_name) %p= link_to t("layout.devise.shared_links.forgot_password"), new_password_path(resource_name)
=showDeviseHintError(:login_error, is_error ? t('devise.failure.invalid') : false) =showDeviseHintError(:login_error, error)

View File

@ -18,4 +18,4 @@
.actions-bar.wat-cf .actions-bar.wat-cf
.actions= will_paginate .actions= will_paginate
= render 'admins/submenu' = render 'admin/submenu'

View File

@ -1,6 +1,6 @@
%ul %ul
- (collection = t which_menu).each do |base, title| - (collection = t which_menu).each do |base, title|
- if can? :index, base.to_s.classify.constantize - if can? :index, base.to_s.classify.constantize
%li= link_to title, send(:"#{base}_path"), :class => [].tap{|c| c << 'active' if params[:controller] == base.to_s}.join(' ') %li= link_to title, send(:"#{base}_path"), :class => controller_name == base.to_s ? 'active' : ''
- if current_user.admin? && which_menu == 'top_menu' - if current_user.admin? && which_menu == 'top_menu'
%li= link_to 'Admin', users_path, :class => t('admins_menu').has_key?(params[:controller].to_sym) ? 'active' : '' %li= link_to 'Admin', users_path, :class => t('admins_menu').has_key?(controller_name.to_sym) ? 'active' : ''

View File

@ -1,3 +1,23 @@
- if current_user.admin?
.leftlist
= f.label :role, t("activerecord.attributes.user.role"), :class => :label
.rightlist
= f.select :role, User::ROLES, {}, {:name => 'role'}
- if @user.new_record?
.leftlist
= f.label :uname, t("activerecord.attributes.user.uname")
.rightlist
= f.text_field :uname, :name => 'uname'
.leftlist
= f.label :password, t("activerecord.attributes.user.password")
.rightlist
= f.password_field :password
.both
.leftlist
= f.label :password_confirmation, t("activerecord.attributes.user.password_confirm")
.rightlist
= f.password_field :password_confirmation
.both
.leftlist .leftlist
= f.label :name, t("activerecord.attributes.user.name") = f.label :name, t("activerecord.attributes.user.name")
.rightlist .rightlist

View File

@ -5,7 +5,7 @@
.admin-preferences .admin-preferences
%ul %ul
- if can? :edit, @user - if can? :edit, @user
%li{:class => (act == :edit && :users == contr) ? 'active' : ''} %li{:class => (act == :profile && :users == contr) ? 'active' : ''}
= link_to t("layout.users.profile"), @user == current_user ? edit_profile_path : edit_user_path(@user) = link_to t("layout.users.profile"), @user == current_user ? edit_profile_path : edit_user_path(@user)
- if can? :private, @user - if can? :private, @user
%li{:class => (act == :private && contr == :users) ? 'active' : ''} %li{:class => (act == :private && contr == :users) ? 'active' : ''}

View File

@ -1,39 +0,0 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first.active= link_to t("layout.users.list"), users_path
%li= link_to t("layout.users.new"), new_user_path
%li= link_to t("layout.users.register_requests"), register_requests_path if can? :read, RegisterRequest
.content
%h2.title
= t("layout.users.list_header")
.inner
= render :partial => "users/filter", :action_url => @action_url
.inner
%table.table
%tr
%th.first ID
%th= t("activerecord.attributes.user.name")
%th= t("activerecord.attributes.user.uname")
%th= t("activerecord.attributes.user.email")
%th= t("activerecord.attributes.user.role")
%th.last &nbsp;
- @users.each do |user|
%tr{:class => cycle("odd", "even")}
%td= user.id
%td= link_to user.name, user_path(user)
%td= link_to user.uname, user_path(user)
%td= user.email
%td= user.role
%td.last
- if can? :read, user
= link_to t("layout.show"), user_path(user)
\|
- if can? :edit, user
#{link_to t("layout.edit"), edit_user_path(user)}
\|
- if can? :destroy, user
#{link_to t("layout.delete"), user_path(user), :method => :delete, :confirm => t("layout.users.confirm_delete")}
.actions-bar.wat-cf
.actions= will_paginate @users, :param_name => :user_page
= render 'admins/submenu'

View File

@ -1,12 +0,0 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first= link_to t("layout.users.list"), users_path
%li.active= link_to t("layout.users.new"), new_user_path
.content
%h2.title= t("layout.users.new_header")
.inner
= form_for @user, :url => users_path, :html => { :class => :form } do |f|
= render :partial => "form", :locals => {:f => f}
- content_for :sidebar, render('sidebar')

View File

@ -1,12 +1,7 @@
%h3.fix.bpadding10= @user.uname %h3.fix.bpadding10= @user.uname
= form_for @user, :url => user_path(@user), :html => { :class => :form } do |f| = form_for @user, :url => user_path(@user), :html => { :class => :form } do |f|
- if current_user.admin? = render :partial => "users/form", :locals => {:f => f}
.leftlist
= f.label :role, t("activerecord.attributes.user.role"), :class => :label
.rightlist
= f.select :role, User::ROLES, :include_blank => true
= render :partial => "form", :locals => {:f => f}
.notify .notify
%p= t('layout.users.public_data_edit_warning') %p= t('layout.users.public_data_edit_warning')

View File

@ -1,7 +1,7 @@
.left .left
= image_tag avatar_url(@user, :big) = image_tag avatar_url(@user, :big)
%br %br
= link_to t("layout.users.settings"), edit_user_path(@user), :class => 'button width81' if can? :edit, @user = link_to t("layout.users.settings"), current_user == @user ? edit_profile_path : edit_user_path(@user), :class => 'button width81' if can? :edit, @user
.left .left
%h3= @user.uname %h3= @user.uname
= @user.name = @user.name

View File

@ -25,6 +25,11 @@ en:
avatar_notice: Without uploaded avatar will be used avatar from gravar web service. avatar_notice: Without uploaded avatar will be used avatar from gravar web service.
delete_avatar: Delete avatar delete_avatar: Delete avatar
avatar_with_size: Avatar (less than %{max}) avatar_with_size: Avatar (less than %{max})
users_filter:
all: All
admin: Admins
real: Real
banned: Banned
activerecord: activerecord:
attributes: attributes:

View File

@ -22,9 +22,14 @@ ru:
delete_header: Удалить аккаунт delete_header: Удалить аккаунт
delete_warning: Внимание! Удаленный аккаунт восстановлению не подлежит. delete_warning: Внимание! Удаленный аккаунт восстановлению не подлежит.
private_settings_header: Изменение пароля private_settings_header: Изменение пароля
avatar_notice: При отсутствии загруженной аватарки будет использована Ваша аватарка на сервисе gravatar. avatar_notice: При отсутствии загруженного аватара будет использован Ваш аватар на сервисе gravatar.
delete_avatar: Удалить аватар delete_avatar: Удалить аватар
avatar_with_size: Аватар (менее %{max}) avatar_with_size: Аватар (менее %{max})
users_filter:
all: Все
admin: Админы
real: Обычные
banned: Забаненные
activerecord: activerecord:
attributes: attributes:

View File

@ -5,14 +5,19 @@ Rosa::Application.routes.draw do
devise_scope :user do devise_scope :user do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru' get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
get '/user' => 'users#profile', :as => 'edit_profile' get '/user' => 'users#profile', :as => :edit_profile
put '/user' => 'users#update', :as => 'update_profile' put '/user' => 'users#update', :as => :update_profile
get '/users/:id/edit' => 'users#profile', :as => 'edit_user' get '/users' => 'admin/users#index', :as => :users
put '/users/:id/edit' => 'users#update', :as => 'update_user' get '/users/new' => 'admin/users#new', :as => :new_user
get '/users/list' => 'admin/users#list', :as => :users_list
post '/users' => 'admin/users#create', :as => :create_user
get '/users/:id/edit' => 'admin/users#profile', :as => :edit_user
put '/users/:id/edit' => 'admin/users#update', :as => :update_user
delete '/users/:id/delete' => 'admin/users#destroy', :as => :delete_user
end end
devise_for :users, :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'} devise_for :users, :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'}
resources :users do resources :users, :only => [:show, :profile, :update] do
resources :groups, :only => [:new, :create, :index] resources :groups, :only => [:new, :create, :index]
collection do collection do
resources :register_requests, :only => [:index, :new, :create, :show_message, :approve, :reject] do resources :register_requests, :only => [:index, :new, :create, :show_message, :approve, :reject] do
@ -27,6 +32,7 @@ Rosa::Application.routes.draw do
namespace :settings do namespace :settings do
resource :notifier, :only => [:show, :update] resource :notifier, :only => [:show, :update]
end end
resources :platforms, :only => [:new, :create]
end end
match 'users/:id/settings/private' => 'users#private', :as => :user_private_settings, :via => :get match 'users/:id/settings/private' => 'users#private', :as => :user_private_settings, :via => :get
match 'users/:id/settings/private' => 'users#private', :as => :user_private_settings, :via => :put match 'users/:id/settings/private' => 'users#private', :as => :user_private_settings, :via => :put
@ -182,14 +188,14 @@ Rosa::Application.routes.draw do
delete :remove delete :remove
end end
end end
end
resources :users, :groups do
resources :platforms, :only => [:new, :create] resources :platforms, :only => [:new, :create]
# resources :repositories, :only => [:new, :create]
end end
# resources :users, :groups do
# resources :platforms, :only => [:new, :create]
# resources :repositories, :only => [:new, :create]
# end
resources :activity_feeds, :only => [:index] resources :activity_feeds, :only => [:index]
resources :search, :only => [:index] resources :search, :only => [:index]

View File

@ -12,7 +12,7 @@ module Grack
return render_not_found if project.blank? return render_not_found if project.blank?
return ::Rack::Auth::Basic.new(@app) do |u, p| return ::Rack::Auth::Basic.new(@app) do |u, p|
user = User.find_for_database_authentication(:login => u) and user.valid_password?(p) and user = User.find_for_database_authentication(:login => u) and !user.access_locked? and user.valid_password?(p) and
ability = ::Ability.new(user) and ability.can?(action, project) # project.members.include?(user) ability = ::Ability.new(user) and ability.can?(action, project) # project.members.include?(user)
end.call(env) unless project.public? and read? # need auth end.call(env) unless project.public? and read? # need auth
end end

View File

@ -1,52 +1,30 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
require 'spec_helper' require 'spec_helper'
shared_examples_for 'user with users list viewer rights' do
it 'should be able to perform index action' do
get :index
response.should render_template(:index)
end
it 'should assigns 5 users without filter params' do
get :index
assigns[:users].count.should == 5
end
it 'should find one user' do
get :index, :filter => {:email => "user1@nonexistanceserver.com"}
assigns[:users].size == 1
end
it 'should find user with searchable email' do
get :index, :filter => {:email => "user1@nonexistanceserver.com"}
assigns[:users].first.email.should == "user1@nonexistanceserver.com"
end
end
describe UsersController do describe UsersController do
before(:each) do before(:each) do
stub_rsync_methods stub_rsync_methods
@simple_user = Factory(:user) @simple_user = Factory(:user)
@other_user = Factory(:user)
@admin = Factory(:admin) @admin = Factory(:admin)
%w[user1 user2 user3].each do |uname| %w[user1 user2 user3].each do |uname|
Factory(:user, :uname => uname, :email => "#{ uname }@nonexistanceserver.com") Factory(:user, :uname => uname, :email => "#{ uname }@nonexistanceserver.com")
end end
end @update_params = {:email => 'new_email@test.com'}
context 'for global admin' do
before(:each) do
set_session_for(@admin)
end
it_should_behave_like 'user with users list viewer rights'
end end
context 'for guest' do context 'for guest' do
it 'should not be able to perform index action' do it 'should not be able to view profile' do
get :index get :profile
response.should redirect_to(new_user_session_path) response.should redirect_to(new_user_session_path)
end end
it 'should not be able to update other profile' do
get :update, {:id => @other_user.id}.merge(@update_params)
response.should redirect_to(new_user_session_path)
@other_user.reload.email.should_not == @update_params[:email]
end
end end
context 'for simple user' do context 'for simple user' do
@ -54,9 +32,23 @@ describe UsersController do
set_session_for(@simple_user) set_session_for(@simple_user)
end end
it 'should not be able to perform index action' do it 'should be able to view profile' do
get :index get :profile
response.should redirect_to(forbidden_path) response.code.should eq('200')
end
context 'with mass assignment' do
it 'should not be able to update uname' do
@simple_user.should_not allow_mass_assignment_of :uname
end
it 'should not be able to update role' do
@simple_user.should_not allow_mass_assignment_of :role
end
it 'should not be able to update other user' do
@simple_user.should_not allow_mass_assignment_of :id
end
end end
end end
end end