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 | 13 +-
src/app/controllers/user_groups_controller.rb | 238 ++++++++++++++++++++
.../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 | 63 +++++-
src/config/navigation.rb | 2 +-
src/config/routes.rb | 15 ++
src/features/step_definitions/user_group_steps.rb | 56 +++++
src/features/support/paths.rb | 6 +
src/features/user_group.feature | 72 ++++++
.../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 ++++
30 files changed, 948 insertions(+), 35 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
create mode 100644 src/features/step_definitions/user_group_steps.rb
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 6186651..30e6f43 100644
--- a/aeolus-conductor.spec.in
+++ b/aeolus-conductor.spec.in
@@ -209,6 +209,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 1907d23..d5da863 100644
--- a/src/app/controllers/application_controller.rb
+++ b/src/app/controllers/application_controller.rb
@@ -282,7 +282,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}
@@ -352,7 +352,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 c4d1371..41cad43 100644
--- a/src/app/controllers/permissions_controller.rb
+++ b/src/app/controllers/permissions_controller.rb
@@ -165,11 +165,22 @@ 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_column(Entity,
sort_order)),
+ @entities = paginate_collection(Entity.
+ all(:order => sort_column(Entity, sort_order)).
+ apply_filters(:preset_filter_id => params[:entities_preset_filter],
+ :search_filter => params[:entities_search]),
params[:page])
end
diff --git a/src/app/controllers/user_groups_controller.rb
b/src/app/controllers/user_groups_controller.rb
new file mode 100644
index 0000000..59b8665
--- /dev/null
+++ b/src/app/controllers/user_groups_controller.rb
@@ -0,0 +1,238 @@
+#
+# 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((a)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 !(a)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 remove_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
+
+ removed=[]
+ not_removed=[]
+
+ if params[:members_selected].blank?
+ if request.post?
+ flash[:error] = t"user_groups.flash.error.select_to_remove_members"
+ end
+ else
+ User.find(params[:members_selected]).each do |member|
+ if @user_group.members.delete member
+ removed << member.name
+ else
+ not_removed << member.name
+ end
+ end
+ unless removed.empty?
+ flash[:notice] = "#{t('user_groups.flash.notice.members_removed')}:
#{removed.join(', ')}"
+ end
+ unless not_removed.empty?
+ flash[:error] =
"#{t('user_groups.flash.error.members_not_removed')}:
#{not_removed.join(', ')}"
+ end
+ end
+ respond_to do |format|
+ format.html { redirect_to user_group_path(@user_group) }
+ 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_type]
+ # :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.#{(a)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..9295373 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:
@@ -1333,6 +1393,7 @@ en:
administer: Administer
second_level:
users: Users
+ user_groups: User Groups
environments: Environments
content: Content
cloud_providers: Cloud Providers
@@ -1353,7 +1414,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/navigation.rb b/src/config/navigation.rb
index c8a48a2..4c37e23 100644
--- a/src/config/navigation.rb
+++ b/src/config/navigation.rb
@@ -20,7 +20,7 @@ SimpleNavigation::Configuration.run do |navigation|
first_level.dom_class = 'container'
first_level.item :monitor, t('navigation.first_level.monitor'), pools_path,
:class => 'monitor', :link => { :id => 'monitor' },
:highlights_on => /\/deployments|\/pools|\/instances|\/logs|\/\z/
first_level.item :administer, t('navigation.first_level.administer'),
users_path, :class => 'administer' do |second_level|
- second_level.item :users, t('navigation.second_level.users'), users_path,
:link => { :class => 'users' }, :highlights_on =>
/\/users|\/roles|\/permissions|\/account/
+ second_level.item :users, t('navigation.second_level.users'), users_path,
:link => { :class => 'users' }, :highlights_on =>
/\/users|\/user_groups|\/roles|\/permissions|\/account/
second_level.item :environments, t('navigation.second_level.environments'),
pool_families_path, :link => { :class => 'environments' }, :highlights_on
=> /\/pool_families|\/images/
second_level.item :content, t('navigation.second_level.content'),
catalogs_path, :link => { :class => 'content' }, :highlights_on =>
/\/catalogs|\/catalog_entries|\/realms|\/hardware_profiles|\/realm_mappings|\/deployables/
second_level.item :cloud_providers,
t('navigation.second_level.cloud_providers'), providers_path, :link => { :class
=> 'providers' }, :highlights_on =>
/\/providers|\/provider_realms|\/config_servers/
diff --git a/src/config/routes.rb b/src/config/routes.rb
index da762a7..68ed728 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'
+ delete 'remove_members'
+ post 'filter_members'
+ end
+ end
+
resources :logs do
collection do
post 'filter'
diff --git a/src/features/step_definitions/user_group_steps.rb
b/src/features/step_definitions/user_group_steps.rb
new file mode 100644
index 0000000..2959a21
--- /dev/null
+++ b/src/features/step_definitions/user_group_steps.rb
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+Given /^a user group "([^"]*)" exists$/ do |name|
+ unless UserGroup.find_by_name(name)
+ FactoryGirl.create :user_group, :name => name
+ end
+end
+
+Given /^there is a user group "([^"]*)"$/ do |name|
+ unless UserGroup.find_by_name(name)
+ FactoryGirl.create :user_group, :name => name
+ end
+end
+
+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
+
+When /^I check the "([^"]*)" member$/ do |login|
+ member = User.find_by_login(login)
+ check("member_checkbox_#{member.id}")
+end
+
+Then /^there should be (\d+) user belonging to "([^"]*)"$/ do |count,
name|
+ user_group = UserGroup.find_by_name(name)
+ user_group.members.count == count
+end
+
+Given /^there is a user "([^"]*)" belonging to user group
"([^"]*)"$/ do |login, group_name|
+ member = User.find_by_login(login)
+ user_group = UserGroup.find_by_name(group_name)
+ user_group.members << member
+end
+
+Then /^there should not exist a member belonging to "([^"]*)"$/ do
|group_name|
+ user_group = UserGroup.find_by_name(group_name)
+ user_group.members.count == 0
+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..08f4db7
--- /dev/null
+++ b/src/features/user_group.feature
@@ -0,0 +1,72 @@
+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
+ And a user "testuser" 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 group
+ 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"
+
+ Scenario: Add member to 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 "Add Member"
+ And I check the "testuser" member
+ And I press "Add Member"
+ Then there should be 1 user belonging to "testgroup"
+ And I should see "testuser"
+
+ Scenario: Remove member from user group
+ And there is a user "testuser" belonging to user group
"testgroup"
+ Given I am on the user groups page
+ And I follow "testgroup"
+ Then I should be on testgroup's user group page
+ Then I should see "testuser"
+ When I check the "testuser" member
+ And I press "Remove"
+ Then there should not exist a member belonging to "testgroup"
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
--
1.7.6.5