end
def self.default_orders
- ["#{table_name}.modified_at desc", "#{table_name}.uuid"]
+ ["#{table_name}.modified_at desc", "#{table_name}.uuid desc"]
end
def self.unique_columns
# Return [] if this is a frozen project and the current user can't
# unfreeze
return [] if respond_to?(:frozen_by_uuid) && frozen_by_uuid &&
- !(Rails.configuration.API.UnfreezeProjectRequiresAdmin ?
- current_user.andand.is_admin :
- current_user.can?(manage: uuid))
+ (Rails.configuration.API.UnfreezeProjectRequiresAdmin ?
+ !current_user.andand.is_admin :
+ !current_user.can?(manage: uuid))
# Return [] if nobody can write because this object is inside a
# frozen project
return [] if FrozenGroup.where(uuid: owner_uuid).any?
end.compact.uniq
end
+ def can_write
+ if respond_to?(:frozen_by_uuid) && frozen_by_uuid
+ return false
+ else
+ return owner_uuid == current_user.uuid ||
+ current_user.is_admin ||
+ current_user.can?(write: uuid)
+ end
+ end
+
+ def can_manage
+ return owner_uuid == current_user.uuid ||
+ current_user.is_admin ||
+ current_user.can?(manage: uuid)
+ end
+
# Return a query with read permissions restricted to the union of the
# permissions of the members of users_list, i.e. if something is readable by
# any user in users_list, it will be readable in the query returned by this
# For details on how the trashed_groups table is constructed, see
# see db/migrate/20200501150153_permission_table.rb
+ # excluded_trash is a SQL expression that determines whether a row
+ # should be excluded from the results due to being trashed.
+ # Trashed items inside frozen projects are invisible to regular
+ # (non-admin) users even when using include_trash, so we have:
+ #
+ # (item_trashed || item_inside_trashed_project)
+ # &&
+ # (!caller_requests_include_trash ||
+ # (item_inside_frozen_project && caller_is_not_admin))
if (admin && include_trash) || sql_table == "api_client_authorizations"
excluded_trash = "false"
else
# on trashed items.
if !include_trash && sql_table != "api_client_authorizations"
# Only include records where the owner is not trashed
- sql_conds = "NOT #{excluded_trash}"
+ sql_conds = "NOT (#{excluded_trash})"
end
else
# The core of the permission check is a join against the
" WHERE user_uuid IN (#{user_uuids_subquery}) AND perm_level >= 3))) "
end
- sql_conds = "(#{owner_check} #{direct_check} #{links_cond}) AND NOT #{excluded_trash}"
+ sql_conds = "(#{owner_check} #{direct_check} #{links_cond}) AND NOT (#{excluded_trash})"
end
# itself. (If we're in the act of unfreezing, we only need
# :unfreeze permission, which means "what write permission would
# be if target weren't frozen")
- unless ((respond_to?(:frozen_by_uuid) && frozen_by_uuid_in_database && !frozen_by_uuid) ?
+ unless ((respond_to?(:frozen_by_uuid) && frozen_by_uuid_was && !frozen_by_uuid) ?
current_user.can?(unfreeze: uuid) :
current_user.can?(write: uuid))
logger.warn "User #{current_user.uuid} tried to modify #{self.class.to_s} #{self.uuid} without write permission"