FIX: group membership leak
FIX: raised a proper NotFound exception when filtering groups by username with invalid username. FIX: properly filter the groups based on current user visibility when viewing another user's groups. DEV: Guardian.can_see_group?(group) is now using Guardian.can_see_groups(groups) instead of duplicating the same code. FIX: spec for groups_controller#index when group directory is disabled for logged in user. FIX: groups_controller.sortable specs to actually test all sorting combinations. DEV: s/response_body/body/g for slightly shorter spec code. FIX: rewrote the "view another user's groups" specs to test all group_visibility and members_group_visibility combinations. DEV: Various refactoring for cleaner and more consistent code.
This commit is contained in:
parent
ac865112a3
commit
5d75f90b27
|
@ -29,10 +29,7 @@ class GroupsController < ApplicationController
|
||||||
groups.where(public_admission: true, automatic: false)
|
groups.where(public_admission: true, automatic: false)
|
||||||
},
|
},
|
||||||
close: Proc.new { |groups|
|
close: Proc.new { |groups|
|
||||||
groups.where(
|
groups.where(public_admission: false, automatic: false)
|
||||||
public_admission: false,
|
|
||||||
automatic: false
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
automatic: Proc.new { |groups|
|
automatic: Proc.new { |groups|
|
||||||
groups.where(automatic: true)
|
groups.where(automatic: true)
|
||||||
|
@ -44,24 +41,23 @@ class GroupsController < ApplicationController
|
||||||
raise Discourse::InvalidAccess.new(:enable_group_directory)
|
raise Discourse::InvalidAccess.new(:enable_group_directory)
|
||||||
end
|
end
|
||||||
|
|
||||||
page_size = MobileDetection.mobile_device?(request.user_agent) ? 15 : 36
|
|
||||||
page = params[:page]&.to_i || 0
|
|
||||||
order = %w{name user_count}.delete(params[:order])
|
order = %w{name user_count}.delete(params[:order])
|
||||||
dir = params[:asc] ? 'ASC' : 'DESC'
|
dir = params[:asc].to_s == "true" ? "ASC" : "DESC"
|
||||||
groups = Group.visible_groups(current_user, order ? "#{order} #{dir}" : nil)
|
sort = order ? "#{order} #{dir}" : nil
|
||||||
|
groups = Group.visible_groups(current_user, sort)
|
||||||
|
type_filters = TYPE_FILTERS.keys
|
||||||
|
|
||||||
|
if (username = params[:username]).present?
|
||||||
|
raise Discourse::NotFound unless user = User.find_by_username(username)
|
||||||
|
groups = TYPE_FILTERS[:my].call(groups.members_visible_groups(current_user, sort), user)
|
||||||
|
type_filters = type_filters - [:my, :owner]
|
||||||
|
end
|
||||||
|
|
||||||
if (filter = params[:filter]).present?
|
if (filter = params[:filter]).present?
|
||||||
groups = Group.search_groups(filter, groups: groups)
|
groups = Group.search_groups(filter, groups: groups)
|
||||||
end
|
end
|
||||||
|
|
||||||
type_filters = TYPE_FILTERS.keys
|
if !guardian.is_staff?
|
||||||
|
|
||||||
if username = params[:username]
|
|
||||||
groups = TYPE_FILTERS[:my].call(groups, User.find_by_username(username))
|
|
||||||
type_filters = type_filters - [:my, :owner]
|
|
||||||
end
|
|
||||||
|
|
||||||
unless guardian.is_staff?
|
|
||||||
# hide automatic groups from all non stuff to de-clutter page
|
# hide automatic groups from all non stuff to de-clutter page
|
||||||
groups = groups.where("automatic IS FALSE OR groups.id = #{Group::AUTO_GROUPS[:moderators]}")
|
groups = groups.where("automatic IS FALSE OR groups.id = #{Group::AUTO_GROUPS[:moderators]}")
|
||||||
type_filters.delete(:automatic)
|
type_filters.delete(:automatic)
|
||||||
|
@ -72,10 +68,7 @@ class GroupsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
if type = params[:type]&.to_sym
|
if type = params[:type]&.to_sym
|
||||||
callback = TYPE_FILTERS[type]
|
raise Discourse::InvalidParameters.new(:type) unless callback = TYPE_FILTERS[type]
|
||||||
if !callback
|
|
||||||
raise Discourse::InvalidParameters.new(:type)
|
|
||||||
end
|
|
||||||
groups = callback.call(groups, current_user)
|
groups = callback.call(groups, current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -87,7 +80,8 @@ class GroupsController < ApplicationController
|
||||||
type_filters = type_filters - [:my, :owner]
|
type_filters = type_filters - [:my, :owner]
|
||||||
end
|
end
|
||||||
|
|
||||||
count = groups.count
|
page = params[:page].to_i
|
||||||
|
page_size = MobileDetection.mobile_device?(request.user_agent) ? 15 : 36
|
||||||
groups = groups.offset(page * page_size).limit(page_size)
|
groups = groups.offset(page * page_size).limit(page_size)
|
||||||
|
|
||||||
render_json_dump(
|
render_json_dump(
|
||||||
|
@ -99,7 +93,7 @@ class GroupsController < ApplicationController
|
||||||
extras: {
|
extras: {
|
||||||
type_filters: type_filters
|
type_filters: type_filters
|
||||||
},
|
},
|
||||||
total_rows_groups: count,
|
total_rows_groups: groups.count,
|
||||||
load_more_groups: groups_path(
|
load_more_groups: groups_path(
|
||||||
page: page + 1,
|
page: page + 1,
|
||||||
type: type,
|
type: type,
|
||||||
|
@ -122,10 +116,7 @@ class GroupsController < ApplicationController
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
groups = Group.visible_groups(current_user)
|
groups = Group.visible_groups(current_user)
|
||||||
|
groups = groups.where(automatic: false) if !guardian.is_staff?
|
||||||
if !guardian.is_staff?
|
|
||||||
groups = groups.where(automatic: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
render_json_dump(
|
render_json_dump(
|
||||||
group: serialize_data(group, GroupShowSerializer, root: nil),
|
group: serialize_data(group, GroupShowSerializer, root: nil),
|
||||||
|
@ -214,7 +205,7 @@ class GroupsController < ApplicationController
|
||||||
raise Discourse::InvalidParameters.new(:limit) if limit < 0 || limit > 1000
|
raise Discourse::InvalidParameters.new(:limit) if limit < 0 || limit > 1000
|
||||||
raise Discourse::InvalidParameters.new(:offset) if offset < 0
|
raise Discourse::InvalidParameters.new(:offset) if offset < 0
|
||||||
|
|
||||||
dir = (params[:desc] && !params[:desc].blank?) ? 'DESC' : 'ASC'
|
dir = (params[:desc] && params[:desc].present?) ? 'DESC' : 'ASC'
|
||||||
order = ""
|
order = ""
|
||||||
|
|
||||||
if params[:requesters]
|
if params[:requesters]
|
||||||
|
@ -488,7 +479,7 @@ class GroupsController < ApplicationController
|
||||||
.where("groups.id <> ?", Group::AUTO_GROUPS[:everyone])
|
.where("groups.id <> ?", Group::AUTO_GROUPS[:everyone])
|
||||||
.order(:name)
|
.order(:name)
|
||||||
|
|
||||||
if term = params[:term].to_s
|
if (term = params[:term]).present?
|
||||||
groups = groups.where("name ILIKE :term OR full_name ILIKE :term", term: "%#{term}%")
|
groups = groups.where("name ILIKE :term OR full_name ILIKE :term", term: "%#{term}%")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -557,8 +548,7 @@ class GroupsController < ApplicationController
|
||||||
|
|
||||||
def find_group(param_name, ensure_can_see: true)
|
def find_group(param_name, ensure_can_see: true)
|
||||||
name = params.require(param_name)
|
name = params.require(param_name)
|
||||||
group = Group
|
group = Group.find_by("LOWER(name) = ?", name.downcase)
|
||||||
group = group.find_by("lower(name) = ?", name.downcase)
|
|
||||||
guardian.ensure_can_see!(group) if ensure_can_see
|
guardian.ensure_can_see!(group) if ensure_can_see
|
||||||
group
|
group
|
||||||
end
|
end
|
||||||
|
|
|
@ -104,47 +104,46 @@ class Group < ActiveRecord::Base
|
||||||
groups = groups.where("groups.id > 0")
|
groups = groups.where("groups.id > 0")
|
||||||
end
|
end
|
||||||
|
|
||||||
unless user&.admin
|
if !user&.admin
|
||||||
sql = <<~SQL
|
sql = <<~SQL
|
||||||
groups.id IN (
|
groups.id IN (
|
||||||
SELECT g.id FROM groups g WHERE g.visibility_level = :public
|
SELECT id
|
||||||
|
FROM groups
|
||||||
|
WHERE visibility_level = :public
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT id
|
||||||
WHERE g.visibility_level = :logged_on_users AND :user_id IS NOT NULL
|
FROM groups
|
||||||
|
WHERE visibility_level = :logged_on_users
|
||||||
|
AND :user_id IS NOT NULL
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT g.id
|
||||||
JOIN group_users gu ON gu.group_id = g.id AND
|
FROM groups g
|
||||||
gu.user_id = :user_id
|
JOIN group_users gu ON gu.group_id = g.id AND gu.user_id = :user_id
|
||||||
WHERE g.visibility_level = :members
|
WHERE g.visibility_level = :members
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT g.id
|
||||||
LEFT JOIN group_users gu ON gu.group_id = g.id AND
|
FROM groups g
|
||||||
gu.user_id = :user_id AND
|
LEFT JOIN group_users gu ON gu.group_id = g.id AND gu.user_id = :user_id AND gu.owner
|
||||||
gu.owner
|
WHERE g.visibility_level = :staff
|
||||||
WHERE g.visibility_level = :staff AND (gu.id IS NOT NULL OR :is_staff)
|
AND (gu.id IS NOT NULL OR :is_staff)
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT g.id
|
||||||
JOIN group_users gu ON gu.group_id = g.id AND
|
FROM groups g
|
||||||
gu.user_id = :user_id AND
|
JOIN group_users gu ON gu.group_id = g.id AND gu.user_id = :user_id AND gu.owner
|
||||||
gu.owner
|
WHERE g.visibility_level = :owners
|
||||||
WHERE g.visibility_level = :owners
|
|
||||||
|
|
||||||
)
|
)
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
groups = groups.where(
|
params = Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: !!user&.staff?)
|
||||||
sql,
|
groups = groups.where(sql, params)
|
||||||
Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: !!user&.staff?)
|
|
||||||
)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
groups
|
groups
|
||||||
|
@ -157,47 +156,46 @@ class Group < ActiveRecord::Base
|
||||||
groups = groups.where("groups.id > 0")
|
groups = groups.where("groups.id > 0")
|
||||||
end
|
end
|
||||||
|
|
||||||
unless user&.admin
|
if !user&.admin
|
||||||
sql = <<~SQL
|
sql = <<~SQL
|
||||||
groups.id IN (
|
groups.id IN (
|
||||||
SELECT g.id FROM groups g WHERE g.members_visibility_level = :public
|
SELECT id
|
||||||
|
FROM groups
|
||||||
|
WHERE members_visibility_level = :public
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT id
|
||||||
WHERE g.members_visibility_level = :logged_on_users AND :user_id IS NOT NULL
|
FROM groups
|
||||||
|
WHERE members_visibility_level = :logged_on_users
|
||||||
|
AND :user_id IS NOT NULL
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT g.id
|
||||||
JOIN group_users gu ON gu.group_id = g.id AND
|
FROM groups g
|
||||||
gu.user_id = :user_id
|
JOIN group_users gu ON gu.group_id = g.id AND gu.user_id = :user_id
|
||||||
WHERE g.members_visibility_level = :members
|
WHERE g.members_visibility_level = :members
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT g.id
|
||||||
LEFT JOIN group_users gu ON gu.group_id = g.id AND
|
FROM groups g
|
||||||
gu.user_id = :user_id AND
|
LEFT JOIN group_users gu ON gu.group_id = g.id AND gu.user_id = :user_id AND gu.owner
|
||||||
gu.owner
|
WHERE g.members_visibility_level = :staff
|
||||||
WHERE g.members_visibility_level = :staff AND (gu.id IS NOT NULL OR :is_staff)
|
AND (gu.id IS NOT NULL OR :is_staff)
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
SELECT g.id FROM groups g
|
SELECT g.id
|
||||||
JOIN group_users gu ON gu.group_id = g.id AND
|
FROM groups g
|
||||||
gu.user_id = :user_id AND
|
JOIN group_users gu ON gu.group_id = g.id AND gu.user_id = :user_id AND gu.owner
|
||||||
gu.owner
|
WHERE g.members_visibility_level = :owners
|
||||||
WHERE g.members_visibility_level = :owners
|
|
||||||
|
|
||||||
)
|
)
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
groups = groups.where(
|
params = Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: !!user&.staff?)
|
||||||
sql,
|
groups = groups.where(sql, params)
|
||||||
Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: !!user&.staff?)
|
|
||||||
)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
groups
|
groups
|
||||||
|
@ -243,22 +241,24 @@ class Group < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.alias_levels(user)
|
def self.alias_levels(user)
|
||||||
levels = [ALIAS_LEVELS[:everyone]]
|
if user&.admin?
|
||||||
|
[
|
||||||
if user && user.admin?
|
ALIAS_LEVELS[:everyone],
|
||||||
levels = [ALIAS_LEVELS[:everyone],
|
ALIAS_LEVELS[:only_admins],
|
||||||
ALIAS_LEVELS[:only_admins],
|
ALIAS_LEVELS[:mods_and_admins],
|
||||||
ALIAS_LEVELS[:mods_and_admins],
|
ALIAS_LEVELS[:members_mods_and_admins],
|
||||||
ALIAS_LEVELS[:members_mods_and_admins],
|
ALIAS_LEVELS[:owners_mods_and_admins],
|
||||||
ALIAS_LEVELS[:owners_mods_and_admins]]
|
]
|
||||||
elsif user && user.moderator?
|
elsif user&.moderator?
|
||||||
levels = [ALIAS_LEVELS[:everyone],
|
[
|
||||||
ALIAS_LEVELS[:mods_and_admins],
|
ALIAS_LEVELS[:everyone],
|
||||||
ALIAS_LEVELS[:members_mods_and_admins],
|
ALIAS_LEVELS[:mods_and_admins],
|
||||||
ALIAS_LEVELS[:owners_mods_and_admins]]
|
ALIAS_LEVELS[:members_mods_and_admins],
|
||||||
|
ALIAS_LEVELS[:owners_mods_and_admins],
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ALIAS_LEVELS[:everyone]]
|
||||||
end
|
end
|
||||||
|
|
||||||
levels
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.plugin_editable_group_custom_fields
|
def self.plugin_editable_group_custom_fields
|
||||||
|
@ -724,9 +724,9 @@ class Group < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.member_of(groups, user)
|
def self.member_of(groups, user)
|
||||||
groups.joins(
|
groups
|
||||||
"LEFT JOIN group_users gu ON gu.group_id = groups.id
|
.joins("LEFT JOIN group_users gu ON gu.group_id = groups.id ")
|
||||||
").where("gu.user_id = ?", user.id)
|
.where("gu.user_id = ?", user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.owner_of(groups, user)
|
def self.owner_of(groups, user)
|
||||||
|
@ -747,7 +747,6 @@ class Group < ActiveRecord::Base
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def name_format_validator
|
def name_format_validator
|
||||||
|
|
||||||
return if !name_changed?
|
return if !name_changed?
|
||||||
|
|
||||||
# avoid strip! here, it works now
|
# avoid strip! here, it works now
|
||||||
|
|
|
@ -190,61 +190,38 @@ class Guardian
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_see_group?(group)
|
def can_see_group?(group)
|
||||||
return false if group.blank?
|
group.present? && can_see_groups?([group])
|
||||||
return true if group.visibility_level == Group.visibility_levels[:public]
|
|
||||||
return true if is_admin?
|
|
||||||
return true if is_staff? && group.visibility_level == Group.visibility_levels[:staff]
|
|
||||||
return true if authenticated? && group.visibility_level == Group.visibility_levels[:logged_on_users]
|
|
||||||
return false if user.blank?
|
|
||||||
|
|
||||||
membership = GroupUser.find_by(group_id: group.id, user_id: user.id)
|
|
||||||
|
|
||||||
return false unless membership
|
|
||||||
|
|
||||||
if !membership.owner
|
|
||||||
return false if group.visibility_level == Group.visibility_levels[:owners]
|
|
||||||
return false if group.visibility_level == Group.visibility_levels[:staff]
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_see_group_members?(group)
|
def can_see_group_members?(group)
|
||||||
return false if group.blank?
|
return false if group.blank?
|
||||||
return true if group.members_visibility_level == Group.visibility_levels[:public]
|
return true if is_admin? || group.members_visibility_level == Group.visibility_levels[:public]
|
||||||
return true if is_admin?
|
|
||||||
return true if is_staff? && group.members_visibility_level == Group.visibility_levels[:staff]
|
return true if is_staff? && group.members_visibility_level == Group.visibility_levels[:staff]
|
||||||
return true if authenticated? && group.members_visibility_level == Group.visibility_levels[:logged_on_users]
|
return true if authenticated? && group.members_visibility_level == Group.visibility_levels[:logged_on_users]
|
||||||
return false if user.blank?
|
return false if user.blank?
|
||||||
|
|
||||||
membership = GroupUser.find_by(group_id: group.id, user_id: user.id)
|
return false unless membership = GroupUser.find_by(group_id: group.id, user_id: user.id)
|
||||||
|
return true if membership.owner
|
||||||
|
|
||||||
return false unless membership
|
return false if group.members_visibility_level == Group.visibility_levels[:owners]
|
||||||
|
return false if group.members_visibility_level == Group.visibility_levels[:staff]
|
||||||
if !membership.owner
|
|
||||||
return false if group.members_visibility_level == Group.visibility_levels[:owners]
|
|
||||||
return false if group.members_visibility_level == Group.visibility_levels[:staff]
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_see_groups?(groups)
|
def can_see_groups?(groups)
|
||||||
return false if groups.blank?
|
return false if groups.blank?
|
||||||
return true if groups.all? { |g| g.visibility_level == Group.visibility_levels[:public] }
|
return true if is_admin? || groups.all? { |g| g.visibility_level == Group.visibility_levels[:public] }
|
||||||
return true if is_admin?
|
|
||||||
return true if is_staff? && groups.all? { |g| g.visibility_level == Group.visibility_levels[:staff] }
|
return true if is_staff? && groups.all? { |g| g.visibility_level == Group.visibility_levels[:staff] }
|
||||||
return true if authenticated? && groups.all? { |g| g.visibility_level == Group.visibility_levels[:logged_on_users] }
|
return true if authenticated? && groups.all? { |g| g.visibility_level == Group.visibility_levels[:logged_on_users] }
|
||||||
return false if user.blank?
|
return false if user.blank?
|
||||||
|
|
||||||
memberships = GroupUser.where(group: groups, user_id: user.id).pluck(:owner)
|
memberships = GroupUser.where(group: groups, user_id: user.id).pluck(:owner)
|
||||||
|
return false if memberships.size < groups.size
|
||||||
|
return true if memberships.all? # owner of all groups
|
||||||
|
|
||||||
return false if memberships.empty? || memberships.length < groups.size
|
return false if groups.all? { |g| g.visibility_level == Group.visibility_levels[:owners] }
|
||||||
|
return false if groups.all? { |g| g.visibility_level == Group.visibility_levels[:staff] }
|
||||||
if !memberships.all?
|
|
||||||
return false if groups.all? { |g| g.visibility_level == Group.visibility_levels[:owners] }
|
|
||||||
return false if groups.all? { |g| g.visibility_level == Group.visibility_levels[:staff] }
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -253,9 +230,9 @@ class Guardian
|
||||||
return false if groups.blank?
|
return false if groups.blank?
|
||||||
|
|
||||||
requested_group_ids = groups.map(&:id) # Can't use pluck, groups could be a regular array
|
requested_group_ids = groups.map(&:id) # Can't use pluck, groups could be a regular array
|
||||||
matching_groups = Group.where(id: requested_group_ids).members_visible_groups(user)
|
matching_group_ids = Group.where(id: requested_group_ids).members_visible_groups(user).pluck(:id)
|
||||||
|
|
||||||
matching_groups.pluck(:id).sort == requested_group_ids.sort
|
matching_group_ids.sort == requested_group_ids.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
# Can we impersonate this user?
|
# Can we impersonate this user?
|
||||||
|
|
|
@ -11,7 +11,7 @@ describe GroupsController do
|
||||||
|
|
||||||
describe '#index' do
|
describe '#index' do
|
||||||
let(:staff_group) do
|
let(:staff_group) do
|
||||||
Fabricate(:group, name: '0000', visibility_level: Group.visibility_levels[:staff])
|
Fabricate(:group, name: 'staff_group', visibility_level: Group.visibility_levels[:staff])
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when group directory is disabled' do
|
context 'when group directory is disabled' do
|
||||||
|
@ -19,24 +19,26 @@ describe GroupsController do
|
||||||
SiteSetting.enable_group_directory = false
|
SiteSetting.enable_group_directory = false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should deny access for an anon user' do
|
it 'should deny access for an anon' do
|
||||||
get "/groups.json"
|
get "/groups.json"
|
||||||
expect(response.status).to eq(403)
|
expect(response.status).to eq(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should deny access for a normal user' do
|
it 'should deny access for a normal user' do
|
||||||
|
sign_in(user)
|
||||||
get "/groups.json"
|
get "/groups.json"
|
||||||
|
|
||||||
expect(response.status).to eq(403)
|
expect(response.status).to eq(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not deny access for an admin' do
|
it 'should allow access for an admin' do
|
||||||
sign_in(admin)
|
sign_in(admin)
|
||||||
get "/groups.json"
|
get "/groups.json"
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not deny access for a moderator' do
|
it 'should allow access for a moderator' do
|
||||||
sign_in(moderator)
|
sign_in(moderator)
|
||||||
get "/groups.json"
|
get "/groups.json"
|
||||||
|
|
||||||
|
@ -45,73 +47,85 @@ describe GroupsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'searchable' do
|
context 'searchable' do
|
||||||
it 'should return the right response' do
|
it 'should return the searched groups' do
|
||||||
other_group = Fabricate(:group, name: 'testing')
|
testing_group = Fabricate(:group, name: 'testing')
|
||||||
|
|
||||||
get "/groups.json", params: { filter: 'test' }
|
get "/groups.json", params: { filter: 'test' }
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
expect(response_body["groups"].first["id"]).to eq(other_group.id)
|
expect(body["groups"].first["id"]).to eq(testing_group.id)
|
||||||
|
expect(body["load_more_groups"]).to eq("/groups?filter=test&page=1")
|
||||||
expect(response_body["load_more_groups"]).to eq(
|
|
||||||
"/groups?filter=test&page=1"
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'sortable' do
|
context 'sortable' do
|
||||||
before do
|
before do
|
||||||
|
group
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
let!(:other_group) { Fabricate(:group, name: "zzzzzz", users: [user]) }
|
let!(:other_group) { Fabricate(:group, name: "other_group", users: [user]) }
|
||||||
|
|
||||||
%w{
|
context "with default (descending) order" do
|
||||||
desc
|
it "sorts by name" do
|
||||||
asc
|
get "/groups.json", params: { order: "name" }
|
||||||
}.each do |order|
|
|
||||||
context "#{order} order" do
|
|
||||||
it 'should return the right response' do
|
|
||||||
is_asc = order == 'asc'
|
|
||||||
params = { order: 'name' }
|
|
||||||
params.merge!(asc: true) if is_asc
|
|
||||||
group
|
|
||||||
get "/groups.json", params: params
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
|
|
||||||
group_ids = [moderator_group_id, group.id, other_group.id]
|
|
||||||
group_ids.reverse! if !is_asc
|
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
|
||||||
|
|
||||||
expect(response_body["groups"].map { |group| group["id"] })
|
|
||||||
.to eq(group_ids)
|
|
||||||
|
|
||||||
expect(response_body["load_more_groups"]).to eq(
|
|
||||||
"/groups?#{is_asc ? 'asc=true&' : '' }order=name&page=1"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'ascending order' do
|
|
||||||
it 'should return the right response' do
|
|
||||||
group
|
|
||||||
get "/groups.json", params: { order: 'name' }
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
expect(response_body["groups"].map { |group| group["id"] })
|
expect(body["groups"].map { |g| g["id"] }).to eq([
|
||||||
.to eq([other_group.id, group.id, moderator_group_id])
|
other_group.id, group.id, moderator_group_id
|
||||||
|
])
|
||||||
|
|
||||||
expect(response_body["load_more_groups"]).to eq(
|
expect(body["load_more_groups"]).to eq("/groups?order=name&page=1")
|
||||||
"/groups?order=name&page=1"
|
end
|
||||||
)
|
|
||||||
|
it "sorts by user_count" do
|
||||||
|
get "/groups.json", params: { order: "user_count" }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
|
expect(body["groups"].map { |g| g["id"] }).to eq([
|
||||||
|
group.id, other_group.id, moderator_group_id
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(body["load_more_groups"]).to eq("/groups?order=user_count&page=1")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with ascending order" do
|
||||||
|
it "sorts by name" do
|
||||||
|
get "/groups.json", params: { order: "name", asc: true }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
|
expect(body["groups"].map { |g| g["id"] }).to eq([
|
||||||
|
moderator_group_id, group.id, other_group.id
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(body["load_more_groups"]).to eq("/groups?asc=true&order=name&page=1")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sorts by user_count" do
|
||||||
|
get "/groups.json", params: { order: "user_count", asc: "true" }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
|
expect(body["groups"].map { |g| g["id"] }).to eq([
|
||||||
|
moderator_group_id, group.id, other_group.id
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(body["load_more_groups"]).to eq("/groups?asc=true&order=user_count&page=1")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -119,20 +133,20 @@ describe GroupsController do
|
||||||
it 'should return the right response' do
|
it 'should return the right response' do
|
||||||
group
|
group
|
||||||
staff_group
|
staff_group
|
||||||
|
|
||||||
get "/groups.json"
|
get "/groups.json"
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
group_ids = response_body["groups"].map { |g| g["id"] }
|
group_ids = body["groups"].map { |g| g["id"] }
|
||||||
|
|
||||||
expect(group_ids).to include(group.id)
|
expect(group_ids).to contain_exactly(group.id)
|
||||||
expect(group_ids).to_not include(staff_group.id)
|
|
||||||
expect(response_body["load_more_groups"]).to eq("/groups?page=1")
|
|
||||||
expect(response_body["total_rows_groups"]).to eq(1)
|
|
||||||
|
|
||||||
expect(response_body["extras"]["type_filters"].map(&:to_sym)).to eq(
|
expect(body["load_more_groups"]).to eq("/groups?page=1")
|
||||||
|
expect(body["total_rows_groups"]).to eq(1)
|
||||||
|
expect(body["extras"]["type_filters"].map(&:to_sym)).to eq(
|
||||||
described_class::TYPE_FILTERS.keys - [:my, :owner, :automatic]
|
described_class::TYPE_FILTERS.keys - [:my, :owner, :automatic]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -148,19 +162,71 @@ describe GroupsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return the right response' do
|
it 'should return the right response' do
|
||||||
user2 = Fabricate(:user)
|
u = Fabricate(:user)
|
||||||
group
|
m = Fabricate(:user)
|
||||||
sign_in(user2)
|
o = Fabricate(:user)
|
||||||
|
|
||||||
get "/groups.json", params: { username: user.username }
|
levels = Group.visibility_levels.values
|
||||||
|
|
||||||
|
levels.product(levels).each { |group_level, members_level|
|
||||||
|
g = Fabricate(:group,
|
||||||
|
name: "#{group_level}_#{members_level}",
|
||||||
|
visibility_level: group_level,
|
||||||
|
members_visibility_level: members_level,
|
||||||
|
users: [u]
|
||||||
|
)
|
||||||
|
|
||||||
|
g.add(m) if group_level == Group.visibility_levels[:members] || members_level == Group.visibility_levels[:members]
|
||||||
|
g.add_owner(o) if group_level == Group.visibility_levels[:owners] || members_level == Group.visibility_levels[:owners]
|
||||||
|
}
|
||||||
|
|
||||||
|
# anonymous user
|
||||||
|
get "/groups.json", params: { username: u.username }
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
group_names = JSON.parse(response.body)["groups"].map { |g| g["name"] }
|
||||||
|
expect(group_names).to contain_exactly("0_0")
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
# logged in user
|
||||||
|
sign_in(Fabricate(:user))
|
||||||
|
get "/groups.json", params: { username: u.username }
|
||||||
|
|
||||||
group_ids = response_body["groups"].map { |g| g["id"] }
|
expect(response.status).to eq(200)
|
||||||
|
group_names = JSON.parse(response.body)["groups"].map { |g| g["name"] }
|
||||||
|
expect(group_names).to contain_exactly("0_0", "0_1", "1_0", "1_1")
|
||||||
|
|
||||||
expect(group_ids).to contain_exactly(group.id)
|
# member of the group
|
||||||
|
sign_in(m)
|
||||||
|
get "/groups.json", params: { username: u.username }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
group_names = JSON.parse(response.body)["groups"].map { |g| g["name"] }
|
||||||
|
expect(group_names).to contain_exactly("0_0", "0_1", "0_2", "1_0", "1_1", "1_2", "2_0", "2_1", "2_2")
|
||||||
|
|
||||||
|
# owner
|
||||||
|
sign_in(o)
|
||||||
|
get "/groups.json", params: { username: u.username }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
group_names = JSON.parse(response.body)["groups"].map { |g| g["name"] }
|
||||||
|
expect(group_names).to contain_exactly("0_0", "0_1", "0_4", "1_0", "1_1", "1_4", "2_4", "3_4", "4_0", "4_1", "4_2", "4_3", "4_4")
|
||||||
|
|
||||||
|
# moderator
|
||||||
|
sign_in(moderator)
|
||||||
|
get "/groups.json", params: { username: u.username }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
group_names = JSON.parse(response.body)["groups"].map { |g| g["name"] }
|
||||||
|
expect(group_names).to contain_exactly("0_0", "0_1", "0_3", "1_0", "1_1", "1_3", "3_0", "3_1", "3_3")
|
||||||
|
|
||||||
|
# admin
|
||||||
|
sign_in(admin)
|
||||||
|
get "/groups.json", params: { username: u.username }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
group_names = JSON.parse(response.body)["groups"].map { |g| g["name"] }
|
||||||
|
all_group_names = levels.product(levels).map { |a, b| "#{a}_#{b}" }
|
||||||
|
expect(group_names).to contain_exactly(*all_group_names)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -179,18 +245,18 @@ describe GroupsController do
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
group_ids = response_body["groups"].map { |g| g["id"] }
|
group_ids = body["groups"].map { |g| g["id"] }
|
||||||
group_body = response_body["groups"].find { |g| g["id"] == group.id }
|
group_body = body["groups"].find { |g| g["id"] == group.id }
|
||||||
|
|
||||||
expect(group_body["is_group_user"]).to eq(true)
|
expect(group_body["is_group_user"]).to eq(true)
|
||||||
expect(group_body["is_group_owner"]).to eq(true)
|
expect(group_body["is_group_owner"]).to eq(true)
|
||||||
expect(group_ids).to include(group.id, staff_group.id)
|
expect(group_ids).to include(group.id, staff_group.id)
|
||||||
expect(response_body["load_more_groups"]).to eq("/groups?page=1")
|
expect(body["load_more_groups"]).to eq("/groups?page=1")
|
||||||
expect(response_body["total_rows_groups"]).to eq(10)
|
expect(body["total_rows_groups"]).to eq(10)
|
||||||
|
|
||||||
expect(response_body["extras"]["type_filters"].map(&:to_sym)).to eq(
|
expect(body["extras"]["type_filters"].map(&:to_sym)).to eq(
|
||||||
described_class::TYPE_FILTERS.keys
|
described_class::TYPE_FILTERS.keys
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -201,10 +267,10 @@ describe GroupsController do
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
group_ids = response_body["groups"].map { |g| g["id"] }
|
group_ids = body["groups"].map { |g| g["id"] }
|
||||||
|
|
||||||
expect(response_body["total_rows_groups"]).to eq(expected_group_ids.count)
|
expect(body["total_rows_groups"]).to eq(expected_group_ids.count)
|
||||||
expect(group_ids).to contain_exactly(*expected_group_ids)
|
expect(group_ids).to contain_exactly(*expected_group_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -269,10 +335,10 @@ describe GroupsController do
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
expect(response_body['group']['id']).to eq(group.id)
|
expect(body['group']['id']).to eq(group.id)
|
||||||
expect(response_body['extras']["visible_group_names"]).to eq([group.name])
|
expect(body['extras']["visible_group_names"]).to eq([group.name])
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'as an admin' do
|
context 'as an admin' do
|
||||||
|
@ -282,15 +348,15 @@ describe GroupsController do
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
|
|
||||||
expect(response_body['group']['id']).to eq(group.id)
|
expect(body['group']['id']).to eq(group.id)
|
||||||
|
|
||||||
groups = Group::AUTO_GROUPS.keys
|
groups = Group::AUTO_GROUPS.keys
|
||||||
groups.delete(:everyone)
|
groups.delete(:everyone)
|
||||||
groups.push(group.name)
|
groups.push(group.name)
|
||||||
|
|
||||||
expect(response_body['extras']["visible_group_names"])
|
expect(body['extras']["visible_group_names"])
|
||||||
.to contain_exactly(*groups.map(&:to_s))
|
.to contain_exactly(*groups.map(&:to_s))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -318,9 +384,9 @@ describe GroupsController do
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)['group']
|
body = JSON.parse(response.body)['group']
|
||||||
|
|
||||||
expect(response_body["id"]).to eq(group.id)
|
expect(body["id"]).to eq(group.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -387,7 +453,6 @@ describe GroupsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "ensures that membership can be paginated" do
|
it "ensures that membership can be paginated" do
|
||||||
|
|
||||||
freeze_time
|
freeze_time
|
||||||
|
|
||||||
first_user = Fabricate(:user)
|
first_user = Fabricate(:user)
|
||||||
|
@ -459,8 +524,8 @@ describe GroupsController do
|
||||||
get "/groups/#{group.name}/mentionable.json"
|
get "/groups/#{group.name}/mentionable.json"
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
expect(response_body["mentionable"]).to eq(false)
|
expect(body["mentionable"]).to eq(false)
|
||||||
|
|
||||||
group.update!(
|
group.update!(
|
||||||
mentionable_level: Group::ALIAS_LEVELS[:everyone],
|
mentionable_level: Group::ALIAS_LEVELS[:everyone],
|
||||||
|
@ -470,8 +535,8 @@ describe GroupsController do
|
||||||
get "/groups/#{group.name}/mentionable.json"
|
get "/groups/#{group.name}/mentionable.json"
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
expect(response_body["mentionable"]).to eq(true)
|
expect(body["mentionable"]).to eq(true)
|
||||||
|
|
||||||
group.update!(
|
group.update!(
|
||||||
mentionable_level: Group::ALIAS_LEVELS[:nobody],
|
mentionable_level: Group::ALIAS_LEVELS[:nobody],
|
||||||
|
@ -481,8 +546,8 @@ describe GroupsController do
|
||||||
get "/groups/#{group.name}/mentionable.json"
|
get "/groups/#{group.name}/mentionable.json"
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
expect(response_body["mentionable"]).to eq(true)
|
expect(body["mentionable"]).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -493,8 +558,8 @@ describe GroupsController do
|
||||||
get "/groups/#{group.name}/messageable.json"
|
get "/groups/#{group.name}/messageable.json"
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
expect(response_body["messageable"]).to eq(false)
|
expect(body["messageable"]).to eq(false)
|
||||||
|
|
||||||
group.update!(
|
group.update!(
|
||||||
messageable_level: Group::ALIAS_LEVELS[:everyone],
|
messageable_level: Group::ALIAS_LEVELS[:everyone],
|
||||||
|
@ -504,8 +569,8 @@ describe GroupsController do
|
||||||
get "/groups/#{group.name}/messageable.json"
|
get "/groups/#{group.name}/messageable.json"
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
response_body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
expect(response_body["messageable"]).to eq(true)
|
expect(body["messageable"]).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue