[PATCH conductor] Tasks 3387/3388 UI for user groups implementation
Scott Seago
sseago at redhat.com
Mon Jun 25 02:32:39 UTC 2012
On 06/22/2012 12:01 PM, Jozef Zigmund wrote:
> On Tuesday 19 June 2012 17:42:40 Scott Seago wrote:
>> UI for managing local user groups and for assigning group permissions.
>> When testing, note that after adding/removing a user from a group
>> the user must log out and in again to see the effects.
>> ---
>> aeolus-conductor.spec.in | 1 +
>> src/app/controllers/application_controller.rb | 7 +-
>> src/app/controllers/permissions_controller.rb | 12 +-
>> src/app/controllers/user_groups_controller.rb | 202
>> ++++++++++++++++++++ .../user_groups_helper.rb} |
>> 23 +--
>> src/app/models/common_filter_methods.rb | 8 +-
>> src/app/models/derived_permission.rb | 23 +++
>> src/app/models/entity.rb | 19 ++
>> src/app/models/permission.rb | 23 +++
>> src/app/models/user_group.rb | 12 ++
>> src/app/views/permissions/_form.html.haml | 23 ++-
>> src/app/views/permissions/_permissions.html.haml | 20 ++
>> src/app/views/user_groups/_form.html.haml | 26 +++
>> src/app/views/user_groups/_list.html.haml | 41 ++++
>> src/app/views/user_groups/add_members.html.haml | 25 +++
>> src/app/views/user_groups/edit.html.haml | 14 ++
>> src/app/views/user_groups/index.html.haml | 2 +
>> src/app/views/user_groups/new.html.haml | 13 ++
>> src/app/views/user_groups/show.html.haml | 71 +++++++
>> src/config/locales/en.yml | 62 ++++++-
>> src/config/routes.rb | 15 ++
>> .../step_definitions/user_group_steps.rb} | 26 ++-
>> src/features/support/paths.rb | 6 +
>> src/features/user_group.feature | 54 ++++++
>> .../controllers/user_groups_controller_spec.rb | 75 +++++++
>> src/spec/factories/permission.rb | 7 +
>> .../factories/user_group.rb} | 23 +--
>> src/spec/models/permission_spec.rb | 19 ++
>> src/spec/models/user_group_spec.rb | 43 ++++
>> 29 files changed, 851 insertions(+), 44 deletions(-)
>> create mode 100644 src/app/controllers/user_groups_controller.rb
>> copy src/app/{models/common_filter_methods.rb =>
>> helpers/user_groups_helper.rb} (55%) create mode 100644
>> src/app/views/user_groups/_form.html.haml
>> create mode 100644 src/app/views/user_groups/_list.html.haml
>> create mode 100644 src/app/views/user_groups/add_members.html.haml
>> create mode 100644 src/app/views/user_groups/edit.html.haml
>> create mode 100644 src/app/views/user_groups/index.html.haml
>> create mode 100644 src/app/views/user_groups/new.html.haml
>> create mode 100644 src/app/views/user_groups/show.html.haml
>> copy src/{app/models/entity.rb =>
>> features/step_definitions/user_group_steps.rb} (52%) create mode 100644
>> src/features/user_group.feature
>> create mode 100644 src/spec/controllers/user_groups_controller_spec.rb
>> copy src/{app/models/common_filter_methods.rb =>
>> spec/factories/user_group.rb} (56%) create mode 100644
>> src/spec/models/user_group_spec.rb
>>
>> diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in
>> index d2c4efd..1ed8159 100644
>> --- a/aeolus-conductor.spec.in
>> +++ b/aeolus-conductor.spec.in
>> @@ -199,6 +199,7 @@ haml="app/views/hardware_profiles
>> app/views/realm_mappings \ app/views/api/hooks \
>> app/views/api \
>> app/views/images \
>> + app/views/user_groups \
>> app/views/api/builds app/views/api/provider_images \
>> app/views/api/target_images app/views/api/entrypoint \
>> app/views/api/environments \
>> diff --git a/src/app/controllers/application_controller.rb
>> b/src/app/controllers/application_controller.rb index eb5931b..b30326b
>> 100644
>> --- a/src/app/controllers/application_controller.rb
>> +++ b/src/app/controllers/application_controller.rb
>> @@ -281,7 +281,7 @@ class ApplicationController< ActionController::Base
>>
>> def set_admin_users_tabs(tab)
>> @tabs = [{:name => t('application_controller.admin_tabs.users'), :url
>> => users_url, :id => 'users'}, - #{:name =>
>> t('application_controller.admin_tabs.groups'), :url => groups_url, :id =>
>> 'groups'}, + {:name =>
>> t('application_controller.admin_tabs.user_groups'), :url =>
>> user_groups_url, :id => 'user_groups'}, {:name =>
>> t('application_controller.admin_tabs.permissions'), :url =>
>> permissions_url, :id => 'permissions'}, ]
>> unless @details_tab = @tabs.find {|t| t[:id] == tab}
>> @@ -350,7 +350,10 @@ class ApplicationController< ActionController::Base
>> else
>> local_perms = @permission_object.permissions
>> end
>> - @permissions = paginate_collection(local_perms, params[:page])
>> + @permissions = paginate_collection(local_perms.
>> + apply_filters(:preset_filter_id =>
>> params[:permissions_preset_filter], + :search_filter =>
>> params[:permissions_search]), +
>> params[:page])
>>
>> @permission_list_header = []
>> unless (@show_inherited or @show_global)
>> diff --git a/src/app/controllers/permissions_controller.rb
>> b/src/app/controllers/permissions_controller.rb index acdbb2c..6d8ae54
>> 100644
>> --- a/src/app/controllers/permissions_controller.rb
>> +++ b/src/app/controllers/permissions_controller.rb
>> @@ -165,11 +165,21 @@ class PermissionsController< ApplicationController
>>
>> :permission_object_id => p.permission_object_id
>>
>> end
>>
>> + def filter
>> + redirect_to_original({"permissions_preset_filter" =>
>> params[:permissions_preset_filter], "permissions_search" =>
>> params[:permissions_search]}) + end
>> +
>> + def filter_entities
>> + redirect_to_original({"entities_preset_filter" =>
>> params[:entities_preset_filter], "entities_search" =>
>> params[:entities_search]}) + end
>> +
>> private
>>
>> def load_entities
>> sort_order = params[:sort_by].nil? ? "name" : params[:sort_by]
>> - @entities = paginate_collection(Entity.all(:order => sort_order),
>> params[:page]) + @entities =
>> paginate_collection(Entity.order(sort_order).
>> + apply_filters(:preset_filter_id => params[:entities_preset_filter],
>> + :search_filter => params[:entities_search]),
>> params[:page]) end
>>
>> def load_headers
>> diff --git a/src/app/controllers/user_groups_controller.rb
>> b/src/app/controllers/user_groups_controller.rb new file mode 100644
>> index 0000000..189ec09
>> --- /dev/null
>> +++ b/src/app/controllers/user_groups_controller.rb
>> @@ -0,0 +1,202 @@
>> +#
>> +# Copyright 2011 Red Hat, Inc.
>> +#
>> +# 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.
>> +#
>> +
>> +class UserGroupsController< ApplicationController
>> + before_filter :require_user, :except => [:new, :create]
>> +
>> + def index
>> + require_privilege(Privilege::VIEW, User)
>> + @title = t'user_groups.groups'
>> + clear_breadcrumbs
>> + save_breadcrumb(user_groups_path)
>> + set_admin_users_tabs 'user_groups'
>> + @params = params
>> + load_headers
>> + load_user_groups
>> + respond_to do |format|
>> + format.html
>> + format.js { render :partial => 'list' }
>> + end
>> + end
>> +
>> + def show
>> + @user_group = UserGroup.find(params[:id])
>> + require_privilege(Privilege::VIEW, User)
>> + @title = @user_group.name
>> + save_breadcrumb(user_group_path(@user_group), @user_group.name)
>> + @tab_captions = ['Properties']
>> + @details_tab = params[:details_tab].blank? ? 'properties' :
>> params[:details_tab] + @members =
>> paginate_collection(@user_group.members, params[:page]) + respond_to do
>> |format|
>> + format.html
>> + format.js do
>> + if params.delete :details_pane
>> + render :partial => 'layouts/details_pane' and return
>> + end
>> + render :partial => @details_tab
>> + end
>> + end
>> + end
>> +
>> + def new
>> + require_privilege(Privilege::CREATE, User)
>> + @title = t'user_groups.new.new_user_group'
>> + @user_group = UserGroup.new
>> + # remove when we enable ldap
>> + @user_group.membership_source = UserGroup::MEMBERSHIP_SOURCE_LOCAL
>> + end
>> +
>> + def create
>> + if params[:commit] == "Reset"
>> + redirect_to :action => 'new' and return
>> + end
>> +
>> + require_privilege(Privilege::MODIFY, User)
>> + @user_group = UserGroup.new(params[:user_group])
>> + unless @user_group.save
>> + render :action => 'new' and return
>> + end
>> +
>> + respond_to do |format|
>> + if @user_group.save
>> + flash[:notice] = t "user_groups.flash.notice.added"
>> + format.html { redirect_to user_groups_path }
>> + format.json { render :json => @user_group, :status => :created }
>> + else
>> + flash.now[:warning] = t "user_groups.flash.warning.creation_failed"
>> + format.html { render :new }
>> + format.js { render :partial => 'new' }
>> + format.json { render :json => @user_group.errors, :status =>
>> :unprocessable_entity } + end
>> + end
>> + end
>> +
>> + def edit
>> + @user_group = UserGroup.find(params[:id])
>> + require_privilege(Privilege::MODIFY, User)
>> + @title = t'user_groups.edit.edit_user_group'
>> + end
>> +
>> + def update
>> + @user_group = UserGroup.find(params[:id])
>> + require_privilege(Privilege::MODIFY, User)
>> +
>> + if params[:commit] == "Reset"
>> + redirect_to edit_user_group_url(@user_group) and return
>> + end
>> +
>> + redirect_to root_url and return unless @user_group
>> +
>> + unless @user_group.update_attributes(params[:user_group])
>> + render :action => 'edit' and return
>> + else
>> + flash[:notice] = t"user_groups.flash.notice.updated"
>> + redirect_to user_group_path(@user_group)
>> + end
>> + end
>> +
>> + def multi_destroy
>> + require_privilege(Privilege::MODIFY, User)
>> + deleted_user_groups = []
>> +
>> + begin
>> + UserGroup.transaction do
>> + UserGroup.find(params[:user_group_selected]).each do |user_group|
>> + if user_group.destroy
>> + deleted_user_groups<< user_group.name
>> + end
>> + end
>> + end
>> +
>> + unless deleted_user_groups.empty?
>> + flash[:notice] = "#{t('user_groups.flash.notice.more_deleted',
>> :count => deleted_user_groups.length)} #{deleted_user_groups.join(', ')}" +
>> end
>> +
>> + rescue => ex
>> + flash[:warning] = t('user_groups.flash.warning.not_delete', :reason
>> => ex.message) + end
>> +
>> + redirect_to user_groups_url
>> + end
>> +
>> + def destroy
>> + require_privilege(Privilege::MODIFY, User)
>> + user_group = UserGroup.find(params[:id])
>> + if user_group.destroy
>> + flash[:notice] = t"user_groups.flash.notice.deleted"
>> + else
>> + flash[:notice] = t"user_groups.flash.warning.delete_failed"
>> + end
>> +
>> + respond_to do |format|
>> + format.html { redirect_to user_groups_path }
>> + end
>> + end
>> +
>> + def add_members
>> + @user_group = UserGroup.find(params[:id])
>> + require_privilege(Privilege::MODIFY, User)
>> +
>> + unless @user_group.membership_source ==
>> UserGroup::MEMBERSHIP_SOURCE_LOCAL + flash[:error] =
>> t('user_groups.flash.error.not_a_local_group') + redirect_to
>> user_group_path(@user_group) and return
>> + end
>> +
>> + @users = paginate_collection(User.where('users.id not in (?)',
>> + @user_group.members.empty? ?
>> + 0 :
>> @user_group.members.map(&:id)), +
>> params[:page])
>> +
>> + added = []
>> + not_added = []
>> +
>> + if params[:members_selected].blank?
>> + flash[:error] = t"user_groups.flash.error.select_to_add_members" if
>> request.post? + else
>> + User.find(params[:members_selected]).each do |member|
>> + if !@user_group.members.include?(member) and
>> + @user_group.members<< member
>> + added<< member.name
>> + else
>> + not_added<< member.name
>> + end
>> + end
>> + unless added.empty?
>> + flash[:notice] = "#{t('user_groups.flash.notice.members_added')}:
>> #{added.join(', ')}" + end
>> + unless not_added.empty?
>> + flash[:error] = "#{t('user_groups.flash.error.members_not_added')}:
>> #{not_added.join(', ')}" + end
>> + respond_to do |format|
>> + format.html { redirect_to user_group_path(@user_group) }
>> + end
>> + end
>> + end
>> +
>> + def load_user_groups
>> + sort_order = params[:sort_by].nil? ? "name" : params[:sort_by]
>> + @user_groups = UserGroup.apply_filters(:preset_filter_id =>
>> params[:users_preset_filter], :search_filter =>
>> params[:user_groups_search]).order(sort_order) + end
>> +
>> + def load_headers
>> + @header = [
>> + { :name => 'checkbox', :class => 'checkbox', :sortable => false },
>> + { :name => t('user_groups.index.name'), :sortable => false },
>> + { :name => t('user_groups.index.type'), :sortable => false },
>> + ]
>> + end
>> +
>> +end
>> diff --git a/src/app/models/common_filter_methods.rb
>> b/src/app/helpers/user_groups_helper.rb similarity index 55%
>> copy from src/app/models/common_filter_methods.rb
>> copy to src/app/helpers/user_groups_helper.rb
>> index 7bb2be2..85ad81f 100644
>> --- a/src/app/models/common_filter_methods.rb
>> +++ b/src/app/helpers/user_groups_helper.rb
>> @@ -1,5 +1,5 @@
>> #
>> -# Copyright 2011 Red Hat, Inc.
>> +# Copyright 2012 Red Hat, Inc.
>> #
>> # Licensed under the Apache License, Version 2.0 (the "License");
>> # you may not use this file except in compliance with the License.
>> @@ -13,19 +13,12 @@
>> # See the License for the specific language governing permissions and
>> # limitations under the License.
>> #
>> -#this module contains functions for filtering table data
>> -module CommonFilterMethods
>> - def apply_filters(options = {})
>> -
>> apply_preset_filter(options[:preset_filter_id]).apply_search_filter(options
>> [:search_filter]) - end
>> -
>> - private
>> -
>> - def apply_preset_filter(preset_filter_id)
>> - if preset_filter_id.present?
>> - self::PRESET_FILTERS_OPTIONS.select{|item| item[:id] ==
>> preset_filter_id}.first[:query] - else
>> - scoped
>> - end
>> +module UserGroupsHelper
>> + def members_header
>> + [
>> + { :name => 'checkbox', :class => 'checkbox', :sortable => false },
>> + { :name => t('users.index.username'), :sortable => false },
>> + { :name => t('user_groups.index.name'), :sortable => false },
>> + ]
>> end
>> end
>> diff --git a/src/app/models/common_filter_methods.rb
>> b/src/app/models/common_filter_methods.rb index 7bb2be2..9491ecb 100644
>> --- a/src/app/models/common_filter_methods.rb
>> +++ b/src/app/models/common_filter_methods.rb
>> @@ -23,7 +23,13 @@ module CommonFilterMethods
>>
>> def apply_preset_filter(preset_filter_id)
>> if preset_filter_id.present?
>> - self::PRESET_FILTERS_OPTIONS.select{|item| item[:id] ==
>> preset_filter_id}.first[:query] + option =
>> self::PRESET_FILTERS_OPTIONS.select { |item|
>> + item[:id] == preset_filter_id}.first
>> + if option[:query]
>> + option[:query]
>> + else
>> + includes(option[:includes]).where(option[:where])
>> + end
>> else
>> scoped
>> end
>> diff --git a/src/app/models/derived_permission.rb
>> b/src/app/models/derived_permission.rb index b7a2530..80d055d 100644
>> --- a/src/app/models/derived_permission.rb
>> +++ b/src/app/models/derived_permission.rb
>> @@ -15,6 +15,9 @@
>> #
>>
>> class DerivedPermission< ActiveRecord::Base
>> + class<< self
>> + include CommonFilterMethods
>> + end
>> # the source permission for the denormalized object
>> belongs_to :permission
>> validates_presence_of :permission_id
>> @@ -54,4 +57,24 @@ class DerivedPermission< ActiveRecord::Base
>> validates_uniqueness_of :permission_id, :scope => [:permission_object_id,
>> :permission_object_typ
>> :e]
>>
>> + # :query is handled differently for permission
>> + PRESET_FILTERS_OPTIONS = [
>> + {:title => "permissions.preset_filters.user_permissions",
>> + :id => "user_permissions",
>> + :includes => :entity,
>> + :where => {"entities.entity_target_type" => "User"}},
>> + {:title => "permissions.preset_filters.group_permissions",
>> + :id => "group_permissions",
>> + :includes => :entity,
>> + :where => {"entities.entity_target_type" => "UserGroup"}}
>> + ]
>> +
>> + def self.apply_search_filter(search)
>> + if search
>> + includes("entity").where("lower(entities.name) LIKE :search", :search
>> => "%#{search.downcase}%") + else
>> + scoped
>> + end
>> + end
>> +
>> end
>> diff --git a/src/app/models/entity.rb b/src/app/models/entity.rb
>> index bbc56fe..db88a5e 100644
>> --- a/src/app/models/entity.rb
>> +++ b/src/app/models/entity.rb
>> @@ -15,6 +15,9 @@
>> #
>>
>> class Entity< ActiveRecord::Base
>> + class<< self
>> + include CommonFilterMethods
>> + end
>> belongs_to :entity_target, :polymorphic => true
>> validates_presence_of :entity_target_id
>> has_many :session_entities, :dependent => :destroy
>> @@ -26,4 +29,20 @@ class Entity< ActiveRecord::Base
>> belongs_to :user_group, :class_name => "UserGroup",
>>
>> :foreign_key => "entity_target_id"
>>
>> + PRESET_FILTERS_OPTIONS = [
>> + {:title => "user",
>> + :id => "users",
>> + :where => {"entities.entity_target_type" => "User"}},
>> + {:title => "user_group",
>> + :id => "user_groups",
>> + :where => {"entities.entity_target_type" => "UserGroup"}}
>> + ]
>> +
>> + def self.apply_search_filter(search)
>> + if search
>> + where("lower(entities.name) LIKE :search", :search =>
>> "%#{search.downcase}%") + else
>> + scoped
>> + end
>> + end
>> end
>> diff --git a/src/app/models/permission.rb b/src/app/models/permission.rb
>> index 048f7a5..9b4c0ac 100644
>> --- a/src/app/models/permission.rb
>> +++ b/src/app/models/permission.rb
>> @@ -30,6 +30,9 @@
>> #
>>
>> class Permission< ActiveRecord::Base
>> + class<< self
>> + include CommonFilterMethods
>> + end
>> belongs_to :role
>> belongs_to :entity
>>
>> @@ -67,6 +70,17 @@ class Permission< ActiveRecord::Base
>>
>> after_save :update_derived_permissions
>>
>> + # :query is handled differently for permission
>> + PRESET_FILTERS_OPTIONS = [
>> + {:title => "permissions.preset_filters.user_permissions",
>> + :id => "user_permissions",
>> + :includes => :entity,
>> + :where => {"entities.entity_target_type" => "User"}},
>> + {:title => "permissions.preset_filters.group_permissions",
>> + :id => "group_permissions",
>> + :includes => :entity,
>> + :where => {"entities.entity_target_type" => "UserGroup"}}
>> + ]
>> def user
>> entity.user
>> end
>> @@ -100,4 +114,13 @@ class Permission< ActiveRecord::Base
>> end
>> end
>> end
>> +
>> + def self.apply_search_filter(search)
>> + if search
>> + includes("entity").where("lower(entities.name) LIKE :search", :search
>> => "%#{search.downcase}%") + else
>> + scoped
>> + end
>> + end
>> +
>> end
>> diff --git a/src/app/models/user_group.rb b/src/app/models/user_group.rb
>> index 293d0db..dcb2f63 100644
>> --- a/src/app/models/user_group.rb
>> +++ b/src/app/models/user_group.rb
>> @@ -15,6 +15,9 @@
>> #
>>
>> class UserGroup< ActiveRecord::Base
>> + class<< self
>> + include CommonFilterMethods
>> + end
>> # name will correspond to the group name if we're using LDAP, otherwise
>> it's # entered by the admin creating the group
>>
>> @@ -42,4 +45,13 @@ class UserGroup< ActiveRecord::Base
>> self.entity.name = "#{self.name} (#{self.membership_source})"
>> self.entity.save!
>> end
>> +
>> + def self.apply_search_filter(search)
>> + if search
>> + where("lower(name) LIKE :search", :search => "%#{search.downcase}%")
>> + else
>> + scoped
>> + end
>> + end
>> +
>> end
>> diff --git a/src/app/views/permissions/_form.html.haml
>> b/src/app/views/permissions/_form.html.haml index 95aa05d..39b1865 100644
>> --- a/src/app/views/permissions/_form.html.haml
>> +++ b/src/app/views/permissions/_form.html.haml
>> @@ -1,3 +1,23 @@
>> +- content_for :entities_filter_controls do
>> + %li
>> + = label_tag :entities_preset_filter, t('filter_table.viewing')
>> + = select_tag(:entities_preset_filter,
>> preset_filters_options_for_select(Entity::PRESET_FILTERS_OPTIONS,
>> params[:entities_preset_filter]), :include_blank =>
>> t("permissions.preset_filters.all_entities"), :disabled => false) + =
>> hidden_field_tag :current_path, request.fullpath
>> + = restful_submit_tag t("filter_table.apply_filters"), "filter",
>> filter_entities_permissions_path, 'POST', :class => 'button', :id =>
>> 'apply_entities_preset_filter' + %span.label.badge.dark= @entities.count
>> + %li.table-search-filter
>> + = text_field_tag :entities_search, params[:entities_search],
>> :placeholder => t("filter_table.search") + = restful_submit_tag "",
>> "search", filter_entities_permissions_path, 'POST', :class => 'button', :id
>> => 'apply_entities_search' +
>> + :javascript
>> + $(document).ready(function(){
>> + $("#apply_entities_preset_filter").hide();
>> + $("#entities_preset_filter").change(function() {
>> + $("#apply_entities_preset_filter").click();
>> + });
>> + Conductor.clickOnEnterKeypress($('#entities_search'),
>> $('#apply_entities_search')); + });
>> +
>> - content_for :form_footer do
>> = hidden_field_tag :permission_object_type, @permission_object.class.name
>> = hidden_field_tag :permission_object_id, @permission_object.id @@ -5,7
>> +25,8 @@
>> = hidden_field_tag :use_tabs, @use_tabs
>> = link_to t('cancel'), @return_path, :class => 'button danger'
>> = restful_submit_tag t('permissions.form.grant_access'), "create",
>> permissions_path, 'POST', :id => 'save_button', :class => 'button' -=
>> filter_table(@header, @entities) do |entity|
>> += filter_table(@header, @entities,
>> + :filter_controls => :entities_filter_controls) do |entity|
>> %tr{:class => cycle('nostripe','stripe')}
>> %td
>> -# - selected = params[:select] == 'all'
>> diff --git a/src/app/views/permissions/_permissions.html.haml
>> b/src/app/views/permissions/_permissions.html.haml index b1e18f7..56a0c8e
>> 100644
>> --- a/src/app/views/permissions/_permissions.html.haml
>> +++ b/src/app/views/permissions/_permissions.html.haml
>> @@ -24,6 +24,26 @@
>> %li= link_to t('permissions.inherited_access'),
>> params.merge(:show_inherited => true, :show_global => false, :page => 1), {
>> :class => 'button primary', :id => 'inherited_permission_button'} %li=
>> link_to t('permissions.global_access'), params.merge(:show_inherited =>
>> false, :show_global => true, :page => 1), { :class => 'button primary', :id
>> => 'global_permission_button'}
>>
>> +- content_for :permissions_filter_controls do
>> + %li
>> + = label_tag :permissions_preset_filter, t('filter_table.viewing')
>> + = select_tag(:permissions_preset_filter,
>> preset_filters_options_for_select(Permission::PRESET_FILTERS_OPTIONS,
>> params[:permissions_preset_filter]), :include_blank =>
>> t("permissions.preset_filters.all_permissions"), :disabled => false) + =
>> hidden_field_tag :current_path, request.fullpath
>> + = restful_submit_tag t("filter_table.apply_filters"), "filter",
>> filter_permissions_path, 'POST', :class => 'button', :id =>
>> 'apply_permissions_preset_filter' + %span.label.badge.dark=
>> @permissions.count
>> + %li.table-search-filter
>> + = text_field_tag :permissions_search, params[:permissions_search],
>> :placeholder => t("filter_table.search") + = restful_submit_tag "",
>> "search", filter_permissions_path, 'POST', :class => 'button', :id =>
>> 'apply_permissions_search' +
>> + :javascript
>> + $(document).ready(function(){
>> + $("#apply_permissions_preset_filter").hide();
>> + $("#permissions_preset_filter").change(function() {
>> + $("#apply_permissions_preset_filter").click();
>> + });
>> + Conductor.clickOnEnterKeypress($('#permissions_search'),
>> $('#apply_permissions_search')); + });
>> +
>> = filter_table(@permission_list_header,
>> @permissions,
>>
>> :form_header => :permissions_form_header,
>>
>> diff --git a/src/app/views/user_groups/_form.html.haml
>> b/src/app/views/user_groups/_form.html.haml new file mode 100644
>> index 0000000..1db6a7a
>> --- /dev/null
>> +++ b/src/app/views/user_groups/_form.html.haml
>> @@ -0,0 +1,26 @@
>> +- if @user_group.errors.any?
>> + = render 'layouts/error_messages', :object => @user_group
>> +
>> +%fieldset
>> + .field
>> + = form.label :type
>> + .input
>> + - if @user_group.new_record?
>> + = form.select(:membership_source,
>> UserGroup::MEMBERSHIP_SOURCES.collect {|x| [t("user_groups.#{x.downcase}"),
>> x]}, {}, {:disabled => true}) + = form.hidden_field
>> :membership_source
>> + - else
>> + = t("user_groups.#{@user_group.membership_source.downcase}")
>> + .field
>> + = form.label :name
>> + .input
>> + - if @user_group.new_record? or @user_group.membership_source ==
>> UserGroup::MEMBERSHIP_SOURCE_LOCAL + = form.text_field :name
>> + - else
>> + = @user_group.name
>> + .field
>> + = form.label :description
>> + .input
>> + = form.text_area :description, :class => 'long'
>> +
>> +%fieldset.options
>> + = form.submit "#{t'user_groups.form.save_user_group'}", :class =>
>> "submit button pill" diff --git a/src/app/views/user_groups/_list.html.haml
>> b/src/app/views/user_groups/_list.html.haml new file mode 100644
>> index 0000000..5c99b39
>> --- /dev/null
>> +++ b/src/app/views/user_groups/_list.html.haml
>> @@ -0,0 +1,41 @@
>> +%header
>> + %h2#user_groups.groups= @title
>> +
>> +- content_for :form_header do
>> + %li= restful_submit_tag "#{t'user_groups.list.delete_selected'}",
>> "destroy", multi_destroy_user_groups_path, 'DELETE', :id =>
>> 'delete_button', :class => 'button danger' + %li= link_to
>> t("user_groups.list.add_user_group"), new_user_group_path, :class =>
>> 'button', :id => 'add_user_group_button' +
>> +- content_for :filter_controls do
>> + %li
>> + = label_tag :user_groups_preset_filter, t('filter_table.viewing')
>> + = hidden_field_tag :current_path, request.fullpath
>> + = select_tag(:user_groups_preset_filter,
>> preset_filters_options_for_select(User::PRESET_FILTERS_OPTIONS,
>> params[:user_groups_preset_filter]), :include_blank =>
>> t("user_groups.preset_filters.all_user_groups"), :disabled => true) + =
>> restful_submit_tag t("filter_table.apply_filters"), "index",
>> filter_user_groups_path, 'POST', :class => 'button', :id =>
>> 'apply_user_groups_preset_filter' + %span.label.badge.dark=
>> @user_groups.count
>> + / = link_to "Filter", "#", :class => 'button pill'
>> + /%li
>> + /%li.more_actions
>> + / %span= image_tag "button-userdrop.png"
>> + / %ul
>> + / %li= link_to "Add/Remove Columns", "#"
>> + / %li= link_to "Freeze Column", "#"
>> + %li.table-search-filter
>> + = text_field_tag :user_groups_search, params[:user_groups_search],
>> :placeholder => t("filter_table.search") + = restful_submit_tag "",
>> "index", filter_user_groups_path, 'POST', :class => 'button', :id =>
>> 'apply_user_groups_search' +
>> + :javascript
>> + $(document).ready(function(){
>> + $("#apply_user_groups_preset_filter").hide();
>> + $("#user_groups_preset_filter").change(function() {
>> + $("#apply_user_groups_preset_filter").click();
>> + });
>> + Conductor.clickOnEnterKeypress($('#user_groups_search'),
>> $('#apply_user_groups_search')); + });
>> +
>> += filter_table(@header, @user_groups) do |user_group|
>> + %tr{:class => cycle('nostripe','stripe')}
>> + %td{:class => 'checkbox'}
>> + - selected = params[:select] == 'all'
>> + = check_box_tag "user_group_selected[]", user_group.id, selected, :id
>> => "user_group_checkbox_#{user_group.id}" + %td= link_to
>> user_group.name, user_group_path(user_group)
>> + %td= t("user_groups.#{user_group.membership_source.downcase}")
>> diff --git a/src/app/views/user_groups/add_members.html.haml
>> b/src/app/views/user_groups/add_members.html.haml new file mode 100644
>> index 0000000..4b3a30c
>> --- /dev/null
>> +++ b/src/app/views/user_groups/add_members.html.haml
>> @@ -0,0 +1,25 @@
>> += render :partial => 'layouts/admin_nav'
>> +%header.page-header
>> + .obj_actions
>> + .return_to
>> + = t'return_to'
>> + = link_to @user_group.name, user_group_path(@user_group), :id =>
>> 'user_group_button' + %h1.user_groups= @user_group.name
>> +
>> +%section.content-section.user_groups
>> + %header
>> + .align-center
>> + %strong= t("user_groups.choose_members")
>> + .content
>> + - content_for :form_footer do
>> + = link_to t('cancel'), user_group_path(@user_group), :class =>
>> 'button danger' + = restful_submit_tag
>> t('user_groups.show.add_members'), "add",
>> add_members_user_group_path(@user_group), 'POST', :id => 'save_button',
>> :class => 'button' + = filter_table(members_header, @users) do |user|
>> + %tr{:class => cycle('nostripe','stripe')}
>> + %td{:class => 'checkbox'}
>> + - selected = params[:select] == 'all'
>> + = check_box_tag "members_selected[]", user.id, selected, :id =>
>> "member_checkbox_#{user.id}" + %td
>> + = link_to user.login, users_path(user)
>> + %td
>> + = user.name
>> diff --git a/src/app/views/user_groups/edit.html.haml
>> b/src/app/views/user_groups/edit.html.haml new file mode 100644
>> index 0000000..7350a43
>> --- /dev/null
>> +++ b/src/app/views/user_groups/edit.html.haml
>> @@ -0,0 +1,14 @@
>> += render :partial => 'layouts/admin_nav'
>> +%header.page-header
>> + .obj_actions
>> + .return_to
>> + =t'return_to'
>> + = link_to "#{t'user_groups.groups'}", user_groups_path
>> + %h1.users= @title
>> +
>> +%section.content-section.user_groups
>> + .content
>> + .align-center
>> + = @user_group.name
>> + = form_for @user_group, :url => user_group_path(@user_group), :html =>
>> {:class => 'generic horizontal'} do |f| + = render :partial => "form",
>> :locals => { :form => f }
>> diff --git a/src/app/views/user_groups/index.html.haml
>> b/src/app/views/user_groups/index.html.haml new file mode 100644
>> index 0000000..7cc23db
>> --- /dev/null
>> +++ b/src/app/views/user_groups/index.html.haml
>> @@ -0,0 +1,2 @@
>> += render :partial => 'layouts/admin_nav'
>> += render :partial => 'layouts/admin_users_tabs'
>> diff --git a/src/app/views/user_groups/new.html.haml
>> b/src/app/views/user_groups/new.html.haml new file mode 100644
>> index 0000000..eaaf3a7
>> --- /dev/null
>> +++ b/src/app/views/user_groups/new.html.haml
>> @@ -0,0 +1,13 @@
>> += render :partial => 'layouts/admin_nav'
>> +%header.page-header
>> + .obj_actions
>> + .return_to
>> + =t'return_to'
>> + = link_to "#{t'user_groups.groups'}", user_groups_path
>> + %h1.users= @title
>> +
>> +%section.content-section.user_groups
>> + .content
>> + .align-center
>> + = form_for @user_group, :url => user_groups_path, :html => {:class =>
>> 'generic horizontal'} do |f| + = render :partial => "form", :locals =>
>> { :form => f }
>> diff --git a/src/app/views/user_groups/show.html.haml
>> b/src/app/views/user_groups/show.html.haml new file mode 100644
>> index 0000000..426137f
>> --- /dev/null
>> +++ b/src/app/views/user_groups/show.html.haml
>> @@ -0,0 +1,71 @@
>> += render :partial => 'layouts/admin_nav'
>> +%header.page-header
>> + .obj_actions
>> + .return_to
>> + = t'return_to'
>> + = link_to t("user_groups.groups"), user_groups_path
>> + - if check_privilege(Privilege::CREATE, User)
>> + = link_to t('user_groups.new.new_user_group'), new_user_group_url,
>> :class => 'button primary', :id => 'new_user_group_button' +
>> .button-group
>> + - if check_privilege(Privilege::MODIFY, User)
>> + = link_to t('edit'), edit_user_group_path(@user_group), :class =>
>> 'button pill', :id => 'edit_button' + = button_to t("delete"),
>> user_group_path(@user_group), :method => 'delete', :confirm => "Are you
>> sure you want to delete?", :class => 'button pill danger', :id => 'delete'
>> + %h1.no-icon= @title
>> +
>> +%section.content-section.user
>> + %header
>> + %h2=t'properties'
>> +
>> + .content
>> + %table.properties_table
>> + %tbody
>> + %tr
>> + %td= t('user_groups.show.type')
>> + %td= @user_group.membership_source
>> + %tr
>> + %td= t('user_groups.show.name')
>> + %td= @user_group.name
>> + %tr
>> + %td= t('user_groups.show.description')
>> + %td= @user_group.description
>> +
>> +- if @user_group.membership_source == UserGroup::MEMBERSHIP_SOURCE_LOCAL
>> + %section.content-section
>> + %header
>> + %h2=t('user_groups.show.members')
>> +
>> + .content
>> + - content_for :form_header do
>> + - if check_privilege(Privilege::CREATE, Deployable)
>> + %li= restful_submit_tag t("remove"), "destroy",
>> remove_members_user_group_path(@user_group), 'DELETE', :id =>
>> 'delete_button', :class => 'button danger' + %li= link_to
>> t("user_groups.show.add_members"),
>> add_members_user_group_path(@user_group), :class => 'button', :id =>
>> 'add_members_button' +
>> + - content_for :filter_controls do
>> + %li
>> + = label_tag :members_preset_filter, t('filter_table.viewing')
>> + = hidden_field_tag :current_path, request.fullpath
>> + = select_tag(:members_preset_filter,
>> preset_filters_options_for_select(Deployable::PRESET_FILTERS_OPTIONS,
>> params[:members_preset_filter]), :include_blank =>
>> t("users.preset_filters.all_users"), :disabled => true) + =
>> restful_submit_tag t("filter_table.apply_filters"), "filter",
>> filter_members_user_group_path(@user_group), 'POST', :class => 'button',
>> :id => 'apply_members_preset_filter' + %span.label.badge.dark=
>> @user_group.members.count
>> + %li.table-search-filter
>> + = text_field_tag :members_search, params[:members_search],
>> :placeholder => t("filter_table.search") + = restful_submit_tag
>> "", "search", filter_members_user_group_path(@user_group), 'POST', :class
>> => 'button', :id => 'apply_members_search' +
>> + :javascript
>> + $(document).ready(function(){
>> + $("#apply_members_preset_filter").hide();
>> + $("#members_preset_filter").change(function() {
>> + $("#apply_members_preset_filter").click();
>> + });
>> + Conductor.clickOnEnterKeypress($('#members_search'),
>> $('#apply_members_search')); + });
>> +
>> + = filter_table(members_header, @members) do |member|
>> + %tr{:class => cycle('nostripe','stripe')}
>> + %td{:class => 'checkbox'}
>> + - selected = params[:select] == 'all'
>> + = check_box_tag "members_selected[]", member.id, selected, :id
>> => "member_checkbox_#{member.id}" + %td
>> + = link_to member.login, users_path(member)
>> + %td
>> + = member.name
>> diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
>> index 8c2e010..19b825a 100644
>> --- a/src/config/locales/en.yml
>> +++ b/src/config/locales/en.yml
>> @@ -102,6 +102,62 @@ en:
>> name_starts_with_B: "Name starts with B"
>> errors:
>> has_running_instances: '%{login} has running instances'
>> + user_groups:
>> + groups: "User Groups"
>> + local: Local
>> + ldap: LDAP
>> + return_to: "Return to:"
>> + confirm_delete: "Are you sure you want to delete this user group?"
>> + quick_jump: "Quick Jump:"
>> + choose_members: "Choose Users to add to this Group."
>> + index:
>> + name: Name
>> + type: Type
>> + show:
>> + name: Name
>> + type: Type
>> + description: Description
>> + members: Members
>> + add_members: Add Members
>> + edit: Edit
>> + delete: Delete
>> + created: CREATED
>> + last_updated: LAST UPDATED
>> + form:
>> + name: Name
>> + type: Type
>> + save_user_group: Save User Group
>> + new:
>> + new_user_group: New User Group
>> + neccessary_information: "Enter necessary information about your new
>> user group and click 'Save User Group' when you are finished." + list:
>> + delete_selected: Delete Selected
>> + add_user_group: Add User Group
>> + edit:
>> + edit_user_group: Edit User Group
>> + flash:
>> + notice:
>> + added: "User Group added"
>> + updated: "User Group updated!"
>> + deleted: "User Group has been successfully deleted."
>> + more_deleted:
>> + one: Deleted user group
>> + other: Deleted user groups
>> + members_added: "These users have been added"
>> + members_removed: "These users have been removed"
>> + warning:
>> + creation_failed: 'Could not create user group'
>> + delete_failed: 'Could not delete user group'
>> + not_delete: 'Cannot delete: %{reason}'
>> + error:
>> + members_not_added: "Could not add these users"
>> + members_not_removed: "Could not remove these users"
>> + not_a_local_group: 'Only locally-managed groups can be managed
>> here.' + select_to_add_members: 'You must select at least one user
>> to add.' + preset_filters:
>> + all_user_groups: "All User Groups"
>> + local: "Locally-managed User Groups"
>> + ldap: "LDAP-managed User Groups"
>> user_sessions:
>> new:
>> username: "Username:"
>> @@ -151,6 +207,7 @@ en:
>> role: Role
>> role_assignments: Role Assignments
>> user: User
>> + user_group: User Group
>> privileges: Privileges
>> general_settings: General Settings
>> new_user: New User
>> @@ -1285,7 +1342,10 @@ en:
>> user_and_role: "%{user} (%{role})"
>> user_and_role_change: "%{user} (from %{old_role} to %{role})"
>> preset_filters:
>> + all_entities: All Entities
>> all_permissions: All Permissions
>> + user_permissions: User Permissions
>> + group_permissions: Group Permissions
>> quotas:
>> quota: Quota
>> edit:
>> @@ -1353,7 +1413,7 @@ en:
>> realms: Realms
>> hardware: Hardware
>> users: Users
>> - groups: Groups
>> + user_groups: User Groups
>> permissions: Global Role Grants
>> pool_families: Pool Families
>> images: Images
>> diff --git a/src/config/routes.rb b/src/config/routes.rb
>> index da762a7..38fbb53 100644
>> --- a/src/config/routes.rb
>> +++ b/src/config/routes.rb
>> @@ -83,6 +83,8 @@ Conductor::Application.routes.draw do
>> get :list
>> delete :multi_destroy
>> post :multi_update
>> + post :filter
>> + post :filter_entities
>> end
>> end
>>
>> @@ -156,6 +158,19 @@ Conductor::Application.routes.draw do
>> post :filter, :on => :collection
>> end
>>
>> + resources :user_groups do
>> + collection do
>> + delete 'multi_destroy'
>> + post :filter
>> + end
>> + member do
>> + get 'add_members'
>> + post 'add_members'
>> + post 'remove_members'
>> + post 'filter_members'
>> + end
>> + end
>> +
>> resources :logs do
>> collection do
>> post 'filter'
>> diff --git a/src/app/models/entity.rb
>> b/src/features/step_definitions/user_group_steps.rb similarity index 52%
>> copy from src/app/models/entity.rb
>> copy to src/features/step_definitions/user_group_steps.rb
>> index bbc56fe..b5426f2 100644
>> --- a/src/app/models/entity.rb
>> +++ b/src/features/step_definitions/user_group_steps.rb
>> @@ -13,17 +13,23 @@
>> # See the License for the specific language governing permissions and
>> # limitations under the License.
>> #
>> +Given /^a user group "([^"]*)" exists$/ do |name|
>> + unless UserGroup.find_by_name(name)
>> + FactoryGirl.create :user_group, :name => name
>> + end
>> +end
>>
>> -class Entity< ActiveRecord::Base
>> - belongs_to :entity_target, :polymorphic => true
>> - validates_presence_of :entity_target_id
>> - has_many :session_entities, :dependent => :destroy
>> - has_many :permissions, :dependent => :destroy
>> - has_many :derived_permissions, :dependent => :destroy
>> +Given /^there is a user group "([^"]*)"$/ do |name|
>> + unless UserGroup.find_by_name(name)
>> + FactoryGirl.create :user_group, :name => name
>> + end
>> +end
>>
>> - # type-specific associations
>> - belongs_to :user, :class_name => "User", :foreign_key =>
>> "entity_target_id" - belongs_to :user_group, :class_name => "UserGroup",
>> - :foreign_key => "entity_target_id"
>> +Then /^there should be (\d+) user groups?$/ do |number|
>> + UserGroup.count.should == number.to_i
>> +end
>>
>> +When /^I check "([^"]*)" user group$/ do |user_group_name|
>> + user_group = UserGroup.find_by_name(user_group_name)
>> + check("user_group_checkbox_#{user_group.id}")
>> end
>> diff --git a/src/features/support/paths.rb b/src/features/support/paths.rb
>> index 38f926d..f809a8c 100644
>> --- a/src/features/support/paths.rb
>> +++ b/src/features/support/paths.rb
>> @@ -35,6 +35,9 @@ module NavigationHelpers
>> when /^(.*)'s user page$/i
>> user_path(User.find_by_login($1))
>>
>> + when /^(.*)'s user group page$/i
>> + user_group_path(UserGroup.find_by_name($1))
>> +
>> when /^(.*)'s role page$/i
>> role_path(Role.find_by_name($1))
>>
>> @@ -179,6 +182,9 @@ module NavigationHelpers
>> when /^the (.*)'s edit user page$/
>> edit_user_path(User.find_by_login($1))
>>
>> + when /^the (.*)'s edit user group page$/
>> + edit_user_group_path(UserGroup.find_by_name($1))
>> +
>> when /^the "(.*)" catalog page/
>> url_for catalog_path(Catalog.find_by_name($1))
>>
>> diff --git a/src/features/user_group.feature
>> b/src/features/user_group.feature new file mode 100644
>> index 0000000..d858035
>> --- /dev/null
>> +++ b/src/features/user_group.feature
>> @@ -0,0 +1,54 @@
>> +Feature: Manage User Groups
>> + In order to manage user groups
>> + As an admin
>> + I want to add/edit/remove user groupss
>> +
>> + Background:
>> + Given I am an authorised user
>> + And I am logged in
>> + And a user group "testgroup" exists
>> +
>> + Scenario: Show user group detials
>> + Given I am on the user groups page
>> + And there is a user group "testgroup"
>> + When I follow "testgroup"
>> + Then I should be on testgroup's user group page
>> +
>> + Scenario: Delete user groups
>> + Given there is a user group "testgroup"
>> + Given there is a user group "testgroup2"
>> + And I am on the user groups page
>> + Then there should be 2 user groups
>> + And I should be on the user groups page
>> + When I check "testgroup" user group
>> + And I press "Delete"
>> + Then I should see "Deleted user group"
>> + And there should be 1 user group
>> +
>> + Scenario: Create new user
>> + Given I am on the user groups page
>> + When I follow "add_user_group_button"
>> + Then I should be on the new user group page
>> + And I should see "New User Group"
>> + When I fill in the following:
>> + | Name | testgroup3 |
>> + And I press "Save"
>> + Then I should be on the user groups page
>> + And I should see "User Group added"
>> +
>> + Scenario: Edit existing user group
>> + Given I am on the user groups page
>> + And I follow "testgroup"
>> + Then I should be on testgroup's user group page
>> + And I should see "testgroup"
>> + When I follow "Edit"
>> + Then I should be on the testgroup's edit user group page
>> + And I fill in "user_group_name" with "newname"
>> + When I press "Save"
>> + Then I should be on newname's user group page
>> + And I should see "User Group updated"
>> + And I should see "newname"
>> +
>> +
>> +
>> +
> remove this ^, because git said "src/features/user_group.feature:51: new blank
> line at EOF" when I applied this patch
>
>> diff --git a/src/spec/controllers/user_groups_controller_spec.rb
>> b/src/spec/controllers/user_groups_controller_spec.rb new file mode 100644
>> index 0000000..d5e68bb
>> --- /dev/null
>> +++ b/src/spec/controllers/user_groups_controller_spec.rb
>> @@ -0,0 +1,75 @@
>> +#
>> +# Copyright 2011 Red Hat, Inc.
>> +#
>> +# 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.
>> +#
>> +
>> +require 'spec_helper'
>> +
>> +describe UserGroupsController do
>> +
>> + fixtures :all
>> + before(:each) do
>> + @user_group = Factory.create(:user_group)
>> + @tuser = FactoryGirl.create :tuser
>> + @admin_permission = FactoryGirl.create :admin_permission
>> + @admin = @admin_permission.user
>> + end
>> +
>> + describe "#create" do
>> + context "user enters valid input" do
>> + it "creates user group" do
>> + mock_warden(@admin)
>> + lambda do
>> + post :create, :user_group => {
>> + :name => "user_group2", :membership_source => "local" }
>> + end.should change(UserGroup, :count).by(1)
>> +
>> + response.should redirect_to(user_groups_path)
>> + end
>> +
>> + it "fails to create user" do
>> + mock_warden(@admin)
>> + lambda do
>> + post :create, :user_group => {}
>> + end.should_not change(UserGroup, :count)
>> +
>> + returned_user_group = assigns[:user_group]
>> + returned_user_group.errors.empty?.should be_false
>> + returned_user_group.should have(1).errors_on(:name)
>> + returned_user_group.should have(2).errors_on(:membership_source)
>> +
>> + response.should render_template('new')
>> + end
>> + end
>> + end
>> +
>> + it "allows an admin to create user group" do
>> + mock_warden(@admin)
>> + lambda do
>> + post :create, :user_group => {
>> + :name => "user_group3", :membership_source => "local" }
>> + end.should change(UserGroup, :count)
>> +
>> + response.should redirect_to(user_groups_url)
>> + end
>> +
>> + it "should not allow a regular user to create user group" do
>> + mock_warden(@tuser)
>> + lambda do
>> + post :create, :user_group => {
>> + :name => "user_group4", :membership_source => "local" }
>> + end.should_not change(UserGroup, :count)
>> + end
>> +
>> +end
>> diff --git a/src/spec/factories/permission.rb
>> b/src/spec/factories/permission.rb index e401fe8..4b2d2b4 100644
>> --- a/src/spec/factories/permission.rb
>> +++ b/src/spec/factories/permission.rb
>> @@ -62,4 +62,11 @@ FactoryGirl.define do
>> entity { |r| FactoryGirl.create(:pool_family_user).entity }
>> end
>>
>> + factory :group_admin_permission, :parent => :permission do
>> + role { |r| Role.first(:conditions => ['name = ?', 'base.admin']) ||
>> FactoryGirl.create(:role, :name => 'base.admin') } + permission_object {
>> |r| BasePermissionObject.general_permission_scope } + entity { |r|
>> FactoryGirl.create(:user_group).entity }
>> + end
>> +
>> +
>> end
>> diff --git a/src/app/models/common_filter_methods.rb
>> b/src/spec/factories/user_group.rb similarity index 56%
>> copy from src/app/models/common_filter_methods.rb
>> copy to src/spec/factories/user_group.rb
>> index 7bb2be2..bf1f6fc 100644
>> --- a/src/app/models/common_filter_methods.rb
>> +++ b/src/spec/factories/user_group.rb
>> @@ -1,5 +1,5 @@
>> #
>> -# Copyright 2011 Red Hat, Inc.
>> +# Copyright 2012 Red Hat, Inc.
>> #
>> # Licensed under the Apache License, Version 2.0 (the "License");
>> # you may not use this file except in compliance with the License.
>> @@ -13,19 +13,16 @@
>> # See the License for the specific language governing permissions and
>> # limitations under the License.
>> #
>> -#this module contains functions for filtering table data
>> -module CommonFilterMethods
>> - def apply_filters(options = {})
>> -
>> apply_preset_filter(options[:preset_filter_id]).apply_search_filter(options
>> [:search_filter]) - end
>>
>> - private
>> +FactoryGirl.define do
>> +
>> + factory :user_group do |u|
>> + sequence(:name) { |n| "group#{n}" }
>> + membership_source 'local'
>> + end
>>
>> - def apply_preset_filter(preset_filter_id)
>> - if preset_filter_id.present?
>> - self::PRESET_FILTERS_OPTIONS.select{|item| item[:id] ==
>> preset_filter_id}.first[:query] - else
>> - scoped
>> - end
>> + factory :ldap_group , :parent => :user_group do
>> + membership_source = 'LDAP'
>> end
>> +
>> end
>> diff --git a/src/spec/models/permission_spec.rb
>> b/src/spec/models/permission_spec.rb index 7f05587..ea9a20d 100644
>> --- a/src/spec/models/permission_spec.rb
>> +++ b/src/spec/models/permission_spec.rb
>> @@ -84,4 +84,23 @@ describe Permission do
>> should be_false
>> end
>>
>> + it "User added to Admin group should be able to create users" do
>> + newuser = FactoryGirl.create(:user)
>> + group_admin_permission = FactoryGirl.create(:group_admin_permission)
>> + user_group = group_admin_permission.user_group
>> + SessionEntity.update_session(@session_id, newuser)
>> +
>> BasePermissionObject.general_permission_scope.has_privilege(@session_id, +
>> newuser, +
>>
>> Privilege::CREATE, +
>> User).should be_false + user_group.members<< newuser
>> + newuser.reload
>> + SessionEntity.update_session(@session_id, newuser)
>> +
>> BasePermissionObject.general_permission_scope.has_privilege(@session_id, +
>> newuser, +
>>
>> Privilege::CREATE, +
>> User).should be_true +
>> + end
>> +
>> end
>> diff --git a/src/spec/models/user_group_spec.rb
>> b/src/spec/models/user_group_spec.rb new file mode 100644
>> index 0000000..915df0a
>> --- /dev/null
>> +++ b/src/spec/models/user_group_spec.rb
>> @@ -0,0 +1,43 @@
>> +#
>> +# Copyright 2012 Red Hat, Inc.
>> +#
>> +# 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.
>> +#
>> +
>> +require 'spec_helper'
>> +
>> +describe UserGroup do
>> + before(:each) do
>> + end
>> +
>> + it "should create a new local group" do
>> + user_group = Factory.create(:user_group)
>> + user_group.should be_valid
>> + user_group.members.size.should == 0
>> + end
>> +
>> + it "should create a new ldap group" do
>> + user_group = Factory.create(:ldap_group)
>> + user_group.should be_valid
>> + end
>> +
>> + it "should add members to a new local group" do
>> + user_group = Factory.create(:user_group)
>> + user = Factory.create(:tuser)
>> + user_group.members.size.should == 0
>> + user_group.members<< user
>> + user_group.reload
>> + user_group.members.size.should == 1
>> + end
>> +
>> +end
> NACK with one inline nit.
>
> I'd like to advise you for next time to split patch to smaller parts(patches),
> then the reviewing will be more comfortable. Also whole new funcionality could
> be more readable.
>
> It's good approach to have only 1-3 changed files per patch, in this patch is
> 29 files changed, 851 insertions(+), 44 deletions(-)
>
> Issues to fix:
> - navigation.rb - need to be added user_groups to "second_level.item :users
> ... , :highlights_on => .."
> - method remove_members is missing in user_groups_controller.rb (what caused
> that member cannot be removed from group)
> - missing test for removing members
>
I've fixed the mentioned issues above (including the whitespace one),
and I'm about to send an updated patch.
Scott
>
More information about the aeolus-devel
mailing list