Merge pull request #466 from abf/rosa-build:465-use-pundit-instead-of-cancan

#465: Use Pundit instead of cancan
This commit is contained in:
avm 2015-04-20 19:17:02 +04:00
commit 8a608cbe99
239 changed files with 5475 additions and 2497 deletions

View File

@ -14,8 +14,7 @@ gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
gem 'omniauth-github'
# gem 'omniauth-openid', '~> 1.0.1'
# gem 'cancan', '1.6.10'
gem 'cancan', git: 'git://github.com/rosa-abf/cancan.git', tag: '1.6.10-abf'
gem 'pundit'
gem 'ancestry'
gem 'paperclip'

View File

@ -26,13 +26,6 @@ GIT
ransack (~> 1.3)
sass-rails
GIT
remote: git://github.com/rosa-abf/cancan.git
revision: fe1089b70c08d3ed11bac4f8e69ecb3d1d9adc29
tag: 1.6.10-abf
specs:
cancan (1.6.10)
GIT
remote: git://github.com/rosa-abf/grack.git
revision: 020be3fef3fb308b9d214252522aa5945bf6584a
@ -349,6 +342,8 @@ GEM
activemodel (>= 4.0.1, < 5.0)
puma (2.11.1)
rack (>= 1.1, < 2.0)
pundit (0.3.0)
activesupport (>= 3.0.0)
pygments.rb (0.6.2)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.2.0)
@ -590,7 +585,6 @@ DEPENDENCIES
better_errors
binding_of_caller
bootstrap-sass
cancan!
cape
capistrano
capistrano_colors
@ -637,6 +631,7 @@ DEPENDENCIES
pg
protected_attributes
puma
pundit
rack-throttle (~> 0.3.0)
rack-utf8_sanitizer
rails (= 4.1.9)

View File

@ -1,11 +1,10 @@
class AdvisoriesController < ApplicationController
before_action :authenticate_user!
skip_before_action :authenticate_user! if APP_CONFIG['anonymous_access']
load_resource find_by: :advisory_id
authorize_resource
def index
@advisories = @advisories.includes(:platforms).search(params[:q]).uniq
authorize :advisories
@advisories = Advisory.includes(:platforms).search(params[:q]).uniq
@advisories_count = @advisories.count
@advisories = @advisories.paginate(page: current_page, per_page: Advisory.per_page)
respond_to do |format|
@ -16,10 +15,12 @@ class AdvisoriesController < ApplicationController
end
def show
authorize @advisory = Advisory.find_by(advisory_id: params[:id])
@packages_info = @advisory.fetch_packages_info
end
def search
authorize :advisories
@advisory = Advisory.by_update_type(params[:bl_type]).search_by_id(params[:query]).first
if @advisory.nil?
render nothing: true, status: 404

View File

@ -1,27 +1,26 @@
class Api::V1::AdvisoriesController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show] if APP_CONFIG['anonymous_access']
load_resource :advisory, find_by: :advisory_id
before_action :find_and_authorize_build_list, only: [:create, :update]
authorize_resource :build_list, only: [:create, :update]
skip_before_action :authenticate_user!, only: %i(index show) if APP_CONFIG['anonymous_access']
before_action :load_advisory, only: %i(show update)
before_action :load_build_list, only: %i(create update)
def index
@advisories = @advisories.includes(:platforms, :projects).paginate(paginate_params)
respond_to :json
authorize :advisory
@advisories = Advisory.includes(:platforms, :projects).paginate(paginate_params)
end
def show
@packages_info = @advisory.fetch_packages_info
respond_to :json
end
def create
authorize :advisory
if @build_list.can_attach_to_advisory? &&
@build_list.associate_and_create_advisory(params[:advisory]) &&
@build_list.save
render_json_response @advisory, 'Advisory has been created successfully'
render_json_response @build_list.advisory, 'Advisory has been created successfully'
else
render_validation_error @advisory, error_message(@build_list, 'Advisory has not been created')
render_validation_error @build_list.advisory, error_message(@build_list, 'Advisory has not been created')
end
end
@ -36,9 +35,14 @@ class Api::V1::AdvisoriesController < Api::V1::BaseController
protected
def find_and_authorize_build_list
def load_build_list
@build_list = BuildList.find params[:build_list_id]
authorize! :local_admin_manage, @build_list.save_to_platform
authorize @build_list.save_to_platform, :local_admin_manage?
end
def load_advisory
@advisory = Advisory.find_by(advisory_id: params[:id]) if params[:id]
authorize @advisory if @advisory
end
end

View File

@ -2,8 +2,8 @@ class Api::V1::ArchesController < Api::V1::BaseController
before_action :authenticate_user! unless APP_CONFIG['anonymous_access']
def index
authorize :arch
@arches = Arch.order(:id).paginate(paginate_params)
respond_to :json
end
end

View File

@ -4,7 +4,7 @@ class Api::V1::BaseController < ApplicationController
helper_method :member_path
rescue_from CanCan::AccessDenied do |exception|
rescue_from Pundit::NotAuthorizedError do |exception|
respond_to do |format|
format.json { render json: {message: t('flash.exception_message')}.to_json, status: 403 }
format.csv { render text: t('flash.exception_message'), status: 403 }
@ -35,6 +35,7 @@ class Api::V1::BaseController < ApplicationController
end
def create_subject(subject)
authorize subject, :create?
class_name = subject.class.name
if subject.save
render_json_response subject, "#{class_name} has been created successfully"
@ -44,6 +45,7 @@ class Api::V1::BaseController < ApplicationController
end
def update_member_in_subject(subject, relation = :relations)
authorize subject, :update_member?
role = params[:role]
class_name = subject.class.name.downcase
if member.present? && role.present? && subject.respond_to?(:owner) && subject.owner != member &&
@ -55,6 +57,7 @@ class Api::V1::BaseController < ApplicationController
end
def add_member_to_subject(subject, role = 'admin')
authorize subject, :add_member?
class_name = subject.class.name.downcase
if member.present? && subject.add_member(member, role)
render_json_response subject, "#{member.class.to_s} '#{member.id}' has been added to #{class_name} successfully"
@ -64,6 +67,7 @@ class Api::V1::BaseController < ApplicationController
end
def remove_member_from_subject(subject)
authorize subject, :remove_member?
class_name = subject.class.name.downcase
if member.present? && subject.remove_member(member)
render_json_response subject, "#{member.class.to_s} '#{member.id}' has been removed from #{class_name} successfully"
@ -73,11 +77,13 @@ class Api::V1::BaseController < ApplicationController
end
def destroy_subject(subject)
authorize subject, :destroy?
subject.destroy # later with resque
render_json_response subject, "#{subject.class.name} has been destroyed successfully"
end
def update_subject(subject)
authorize subject, :update?
class_name = subject.class.name
if subject.update_attributes(params[class_name.underscore.to_sym] || {})
render_json_response subject, "#{class_name} has been updated successfully"
@ -94,7 +100,7 @@ class Api::V1::BaseController < ApplicationController
id: id,
message: message
}
}.to_json, status: status
}, status: status
end
def render_validation_error(subject, message)

View File

@ -1,17 +1,26 @@
class Api::V1::BuildListsController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show, :index] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :build_list, only: [:show, :create, :cancel, :publish, :reject_publish, :create_container, :publish_into_testing, :rerun_tests]
before_action :load_build_list, only: %i(
cancel
create_container
publish
publish_into_testing
reject_publish
rerun_tests
show
)
skip_before_action :authenticate_user!, only: %i(show index) if APP_CONFIG['anonymous_access']
def show
authorize @build_list
respond_to :json
end
def index
authorize :build_list
@project = Project.find(params[:project_id]) if params[:project_id].present?
authorize!(:show, @project) if @project
filter = BuildList::Filter.new(@project, current_user, current_ability, params[:filter] || {})
authorize @project, :show? if @project
filter = BuildList::Filter.new(@project, current_user, params[:filter] || {})
@build_lists = filter.find.includes(:build_for_platform,
:save_to_repository,
:save_to_platform,
@ -36,34 +45,45 @@ class Api::V1::BuildListsController < Api::V1::BaseController
end
def cancel
authorize @build_list
render_json :cancel
end
def publish
authorize @build_list
@build_list.publisher = current_user
render_json :publish
end
def reject_publish
authorize @build_list
@build_list.publisher = current_user
render_json :reject_publish
end
def create_container
authorize @build_list
render_json :create_container, :publish_container
end
def rerun_tests
authorize @build_list
render_json :rerun_tests
end
def publish_into_testing
authorize @build_list
@build_list.publisher = current_user
render_json :publish_into_testing
end
private
# Private: before_action hook which loads BuidList.
def load_build_list
@build_list = BuildList.find params[:id]
end
def render_json(action_name, action_method = nil)
if @build_list.try("can_#{action_name}?") && @build_list.send(action_method || action_name)
render_json_response @build_list, t("layout.build_lists.#{action_name}_success")

View File

@ -2,22 +2,21 @@ class Api::V1::GroupsController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource
before_action :load_group, except: %i(index create)
def index
# accessible_by(current_ability)
authorize :group
@groups = current_user.groups.paginate(paginate_params)
respond_to :json
end
def show
respond_to :json
authorize @group
end
def members
authorize @group
@members = @group.members.where('actor_id != ?', @group.owner_id)
.order('name').paginate(paginate_params)
respond_to :json
end
def update
@ -48,4 +47,11 @@ class Api::V1::GroupsController < Api::V1::BaseController
update_member_in_subject @group, :actors
end
private
# Private: before_action hook which loads Group.
def load_group
@group = Group.find params[:id]
end
end

View File

@ -1,11 +1,13 @@
class Api::V1::IssuesController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :group_index, :show] if APP_CONFIG['anonymous_access']
include Api::V1::Issueable
load_and_authorize_resource :group, only: :group_index, find_by: :id, parent: false
load_and_authorize_resource :project
skip_load_and_authorize_resource :project, only: [:all_index, :user_index, :group_index]
load_and_authorize_resource :issue, through: :project, find_by: :serial_id, only: [:show, :update, :create, :index]
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: %i(index group_index show) if APP_CONFIG['anonymous_access']
before_action :load_group, only: :group_index
before_action :load_project
skip_before_action :load_project, only: %i(all_index user_index group_index)
before_action :load_issue, only: %i(show update index)
def index
@issues = @project.issues
@ -13,12 +15,14 @@ class Api::V1::IssuesController < Api::V1::BaseController
end
def all_index
project_ids = get_all_project_ids Project.accessible_by(current_ability, :membered).pluck(:id)
authorize :issue, :index?
project_ids = get_all_project_ids membered_projects.pluck(:id)
@issues = Issue.where(project_id: project_ids)
render_issues_list
end
def user_index
authorize :issue, :index?
project_ids = get_all_project_ids current_user.projects.pluck(:id)
@issues = Issue.where(project_id: project_ids)
render_issues_list
@ -26,7 +30,7 @@ class Api::V1::IssuesController < Api::V1::BaseController
def group_index
project_ids = @group.projects.pluck(:id)
project_ids = Project.accessible_by(current_ability, :membered).where(id: project_ids).pluck(:id)
project_ids = membered_projects.where(id: project_ids).pluck(:id)
@issues = Issue.where(project_id: project_ids)
render_issues_list
end
@ -40,13 +44,14 @@ class Api::V1::IssuesController < Api::V1::BaseController
end
def create
@issue = @project.issues.new(params[:issue])
@issue.user = current_user
@issue.assignee = nil if cannot?(:write, @project)
@issue.assignee = nil unless policy(@project).write?
create_subject @issue
end
def update
unless can?(:write, @project)
unless policy(@project).write?
params.delete :update_labels
[:assignee_id, :labelings, :labelings_attributes].each do |k|
params[:issue].delete k
@ -94,7 +99,7 @@ class Api::V1::IssuesController < Api::V1::BaseController
end
if params[:labels].present?
labels = params[:labels].split(',').map {|e| e.strip}.select {|e| e.present?}
labels = params[:labels].split(',').map(&:strip).select(&:present?)
@issues = @issues.where('labels.name IN (?)', labels)
end
@ -110,13 +115,4 @@ class Api::V1::IssuesController < Api::V1::BaseController
end
end
def get_all_project_ids default_project_ids
project_ids = []
if ['created', 'all'].include? params[:filter]
# add own issues
project_ids = Project.accessible_by(current_ability, :show).joins(:issues).
where(issues: {user_id: current_user.id}).pluck('projects.id')
end
project_ids |= default_project_ids
end
end

View File

@ -5,6 +5,7 @@ class Api::V1::JobsController < Api::V1::BaseController
QUEUE_CLASSES = %w(AbfWorker::RpmWorkerObserver)
before_action :authenticate_user!
skip_after_action :verify_authorized
def shift
@build_list = BuildList.next_build(arch_ids, platform_ids) if current_user.system?
@ -21,8 +22,8 @@ class Api::V1::JobsController < Api::V1::BaseController
@build_list ||= build_lists.external_nodes(:everything).first
else
@build_list = build_lists.external_nodes(:owned).for_user(current_user).first
@build_list ||= build_lists.external_nodes(:everything).
accessible_by(current_ability, :related).readonly(false).first
@build_list ||= BuildListPolicy::Scope.new(current_user, build_lists).owned.
external_nodes(:everything).readonly(false).first
end
set_builder
end

View File

@ -1,12 +1,11 @@
class Api::V1::MaintainersController < Api::V1::BaseController
before_action :authenticate_user! unless APP_CONFIG['anonymous_access']
load_and_authorize_resource :platform
def index
authorize @platform = Platform.find(params[:platform_id]), :show?
@maintainers = BuildList::Package.includes(:project)
.actual.by_platform(@platform)
.like_name(params[:package_name])
.paginate(paginate_params)
respond_to :json
end
end

View File

@ -2,9 +2,10 @@ class Api::V1::PlatformsController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: :allowed
skip_before_action :authenticate_user!, only: [:show, :platforms_for_build, :members] if APP_CONFIG['anonymous_access']
load_and_authorize_resource except: :allowed
before_action :load_platform, except: [:index, :allowed, :platforms_for_build, :create]
def allowed
authorize :platform
if request.authorization.present?
token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request)
end
@ -16,25 +17,24 @@ class Api::V1::PlatformsController < Api::V1::BaseController
end
def index
@platforms = @platforms.accessible_by(current_ability, :related)
.by_type(params[:type]).paginate(paginate_params)
respond_to :json
authorize :platform
@platforms = PlatformPolicy::Scope.new(current_user, Platform).show.
by_type(params[:type]).paginate(paginate_params)
end
def show
respond_to :json
end
def platforms_for_build
@platforms = Platform.availables_main_platforms(current_user, current_ability).paginate(paginate_params)
respond_to do |format|
format.json { render :index }
end
authorize :platform
@platforms = Platform.availables_main_platforms(current_user).paginate(paginate_params)
render :index
end
def create
platform_params = params[:platform] || {}
owner = User.where(id: platform_params[:owner_id]).first
@platform = Platform.new platform_params
@platform.owner = owner || get_owner
create_subject @platform
end
@ -48,7 +48,6 @@ class Api::V1::PlatformsController < Api::V1::BaseController
def members
@members = @platform.members.order('name').paginate(paginate_params)
respond_to :json
end
def add_member
@ -79,4 +78,11 @@ class Api::V1::PlatformsController < Api::V1::BaseController
destroy_subject @platform
end
private
# Private: before_action hook which loads Platform.
def load_platform
authorize @platform = Platform.find(params[:id])
end
end

View File

@ -2,21 +2,22 @@ class Api::V1::ProductBuildListsController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :product, only: :index
load_and_authorize_resource
before_action :load_product, only: :index
before_action :load_product_build_list, except: [:index, :create]
def index
@product_build_lists = if @product
@product.product_build_lists
else
ProductBuildList.accessible_by current_ability, :read
end
@product_build_lists =
if @product
@product.product_build_lists
else
PlatformPolicy::Scope.new(current_user, ProductBuildList.joins(product: :platform)).show
end
@product_build_lists = @product_build_lists.joins(:product, :project, :arch)
@product_build_lists = @product_build_lists.recent.paginate(paginate_params)
respond_to :json
end
def create
@product_build_list = ProductBuildList.new(params[:product_build_list])
@product_build_list.project ||= @product_build_list.try(:product).try(:project)
@product_build_list.main_script ||= @product_build_list.try(:product).try(:main_script)
@product_build_list.params ||= @product_build_list.try(:product).try(:params)
@ -25,7 +26,6 @@ class Api::V1::ProductBuildListsController < Api::V1::BaseController
end
def show
respond_to :json
end
def update
@ -44,4 +44,16 @@ class Api::V1::ProductBuildListsController < Api::V1::BaseController
render_validation_error @product_build_list, t("layout.product_build_lists.cancel_fail")
end
end
private
# Private: before_action hook which loads ProductBuildList.
def load_product_build_list
authorize @product_build_list = ProductBuildList.find(params[:id])
end
# Private: before_action hook which loads Product.
def load_product
authorize @product = Product.find(params[:product_id]), :show? if params[:product_id]
end
end

View File

@ -2,10 +2,10 @@ class Api::V1::ProductsController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource
before_action :load_product, except: :create
def create
create_subject @product
create_subject @product = Product.new(params[:product])
end
def update
@ -13,10 +13,17 @@ class Api::V1::ProductsController < Api::V1::BaseController
end
def show
respond_to :json
end
def destroy
destroy_subject @product
end
private
# Private: before_action hook which loads Product.
def load_product
authorize @product = Product.find(params[:id])
end
end

View File

@ -3,30 +3,23 @@ class Api::V1::ProjectsController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:get_id, :show, :refs_list] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :project
before_action :load_project, except: [:index, :create, :get_id]
def index
@projects = Project.accessible_by(current_ability, :membered)
.paginate(paginate_params)
respond_to :json
authorize :project
@projects = ProjectPolicy::Scope.new(current_user, Project).
membered.paginate(paginate_params)
end
def get_id
if @project = Project.find_by_owner_and_name(params[:owner], params[:name])
authorize! :show, @project
else
raise ActiveRecord::RecordNotFound
end
respond_to :json
authorize @project = Project.find_by_owner_and_name!(params[:owner], params[:name])
end
def show
respond_to :json
end
def refs_list
@refs = @project.repo.branches + @project.repo.tags.select{ |t| t.commit }
respond_to :json
end
def update
@ -38,21 +31,20 @@ class Api::V1::ProjectsController < Api::V1::BaseController
end
def create
p_params = params[:project] || {}
owner_type = p_params[:owner_type]
if owner_type.present? && %w(User Group).include?(owner_type)
@project.owner = owner_type.constantize.
where(id: p_params[:owner_id]).first
@project = Project.new(params[:project])
p_params = params[:project] || {}
owner_type = %w(User Group).find{ |t| t == p_params[:owner_type] }
if owner_type.present?
@project.owner = owner_type.constantize.find_by(id: p_params[:owner_id])
else
@project.owner = nil
end
authorize! :write, @project.owner if @project.owner != current_user
authorize @project
create_subject @project
end
def members
@members = @project.collaborators.order('uname').paginate(paginate_params)
respond_to :json
end
def add_member
@ -69,7 +61,9 @@ class Api::V1::ProjectsController < Api::V1::BaseController
def fork(is_alias = false)
owner = (Group.find params[:group_id] if params[:group_id].present?) || current_user
authorize! :write, owner if owner.class == Group
authorize @project, :show?
authorize owner, :write? if owner.is_a?(Group)
if forked = @project.fork(owner, new_name: params[:fork_name], is_alias: is_alias) and forked.valid?
render_json_response forked, 'Project has been forked successfully'
else
@ -78,6 +72,14 @@ class Api::V1::ProjectsController < Api::V1::BaseController
end
def alias
authorize @project
fork(true)
end
private
# Private: before_action hook which loads Project.
def load_project
authorize @project = Project.find(params[:id])
end
end

View File

@ -1,13 +1,13 @@
class Api::V1::PullRequestsController < Api::V1::BaseController
respond_to :json
include Api::V1::Issueable
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show, :index, :group_index, :commits, :files] if APP_CONFIG['anonymous_access']
skip_before_action :authenticate_user!, only: %i(show index group_index commits files) if APP_CONFIG['anonymous_access']
load_resource :group, only: :group_index, find_by: :id, parent: false
load_resource :project
load_resource :issue, through: :project, find_by: :serial_id, parent: false, only: [:show, :index, :commits, :files, :merge, :update]
load_and_authorize_resource instance_name: :pull, through: :issue, singleton: true, only: [:show, :index, :commits, :files, :merge, :update]
before_action :load_group, only: %i(group_index)
before_action :load_project, except: %i(all_index user_index)
before_action :load_issue, only: %i(show index commits files merge update)
before_action :load_pull, only: %i(show index commits files merge update)
def index
@pulls = @project.pull_requests
@ -16,13 +16,15 @@ class Api::V1::PullRequestsController < Api::V1::BaseController
end
def all_index
project_ids = get_all_project_ids Project.accessible_by(current_ability, :membered).pluck(:id)
authorize :pull_request, :index?
project_ids = get_all_project_ids membered_projects.pluck(:id)
@pulls = PullRequest.where('pull_requests.to_project_id IN (?)', project_ids)
@pulls_url = api_v1_pull_requests_path format: :json
render_pulls_list
end
def user_index
authorize :pull_request, :index?
project_ids = get_all_project_ids current_user.projects.pluck(:id)
@pulls = PullRequest.where('pull_requests.to_project_id IN (?)', project_ids)
@pulls_url = pull_requests_api_v1_user_path format: :json
@ -31,31 +33,31 @@ class Api::V1::PullRequestsController < Api::V1::BaseController
def group_index
project_ids = @group.projects.pluck(:id)
project_ids = Project.accessible_by(current_ability, :membered).where(id: project_ids).pluck(:id)
project_ids = membered_projects.where(id: project_ids).pluck(:id)
@pulls = PullRequest.where(to_project_id: project_ids)
@pulls_url = pull_requests_api_v1_group_path
render_pulls_list
end
def show
redirect_to api_v1_project_issue_path(@project.id, @issue.serial_id) if @pull.nil?
respond_to :json
redirect_to api_v1_project_issue_path(@project.id, @issue.serial_id) and return if @pull.nil?
end
def create
from_project = Project.find(pull_params[:from_project_id]) if pull_params[:from_project_id].present?
from_project = Project.find_by(id: pull_params[:from_project_id])
from_project ||= @project
authorize! :read, from_project
authorize from_project, :show?
@pull = @project.pull_requests.new
@pull = @project.pull_requests.build
@pull.build_issue title: pull_params[:title], body: pull_params[:body]
@pull.from_project = from_project
@pull.to_ref, @pull.from_ref = pull_params[:to_ref], pull_params[:from_ref]
@pull.issue.assignee_id = pull_params[:assignee_id] if can?(:write, @project)
@pull.issue.assignee_id = pull_params[:assignee_id] if policy(@project).write?
@pull.issue.user, @pull.issue.project = current_user, @project
@pull.issue.new_pull_request = true
render_validation_error(@pull, "#{@pull.class.name} has not been created") && return unless @pull.valid?
authorize @pull
@pull.save # set pull id
@pull.reload
@pull.check(false) # don't make event transaction
@ -71,13 +73,13 @@ class Api::V1::PullRequestsController < Api::V1::BaseController
def update
@pull = @project.pull_requests.includes(:issue).where(issues: {serial_id: params[:id]}).first
authorize! :update, @pull
authorize @pull
if pull_params.present?
attrs = pull_params.slice(:title, :body)
attrs.merge!(assignee_id: pull_params[:assignee_id]) if can?(:write, @project)
attrs.merge!(assignee_id: pull_params[:assignee_id]) if policy(@project).write?
if (action = pull_params[:status]) && %w(close reopen).include?(pull_params[:status])
if action = %w(close reopen).find{ |s| s == pull_params[:status] }
if @pull.send("can_#{action}?")
@pull.set_user_and_time current_user
need_check = true if action == 'reopen' && @pull.valid?
@ -96,16 +98,17 @@ class Api::V1::PullRequestsController < Api::V1::BaseController
end
def commits
authorize @pull
@commits = @pull.repo.commits_between(@pull.to_commit, @pull.from_commit).paginate(paginate_params)
respond_to :json
end
def files
authorize @pull
@stats = @pull.diff_stats.zip(@pull.diff).paginate(paginate_params)
respond_to :json
end
def merge
authorize @pull
class_name = @pull.class.name
if @pull.merge!(current_user)
render_json_response @pull, "#{class_name} has been merged successfully"
@ -116,6 +119,12 @@ class Api::V1::PullRequestsController < Api::V1::BaseController
private
# Private: before_action hook which loads PullRequest.
def load_pull
@pull = @issue.pull_request
authorize @pull, :show? if @pull
end
def render_pulls_list
@pulls = @pulls.includes(issue: [:user, :assignee])
if params[:status] == 'closed'
@ -154,22 +163,9 @@ class Api::V1::PullRequestsController < Api::V1::BaseController
@pulls = @pulls.where('issues.created_at >= to_timestamp(?)', params[:since]) if params[:since] =~ /\A\d+\z/
@pulls = @pulls.paginate(paginate_params)
respond_to do |format|
format.json { render :index }
end
render :index
end
def get_all_project_ids default_project_ids
project_ids = []
if ['created', 'all'].include? params[:filter]
# add own pulls
project_ids = Project.accessible_by(current_ability, :show).joins(:issues).
where(issues: {user_id: current_user.id}).pluck('projects.id')
end
project_ids |= default_project_ids
end
def pull_params
@pull_params ||= params[:pull_request] || {}
end

View File

@ -3,16 +3,13 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show, :projects] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :repository, through: :platform, shallow: true
before_action :load_repository
def show
respond_to :json
end
def projects
@projects = @repository.projects.recent.paginate(paginate_params)
respond_to :json
end
def update
@ -32,7 +29,6 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
end
def key_pair
respond_to :json
end
# Only one request per 15 minutes for each platform
@ -40,7 +36,7 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
key, now = [@repository.platform.id, :repository_packages], Time.zone.now
last_request = Rails.cache.read(key)
if last_request.present? && last_request + 15.minutes > now
raise CanCan::AccessDenied
raise Pundit::NotAuthorizedError
else
Rails.cache.write(key, now, expires_at: 15.minutes)
@ -77,7 +73,7 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
def add_project
if project = Project.where(id: params[:project_id]).first
if can?(:read, project)
if policy(project).read?
begin
@repository.projects << project
render_json_response @repository, "Project '#{project.id}' has been added to repository successfully"
@ -110,4 +106,11 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
end
end
private
# Private: before_action hook which loads Repository.
def load_repository
authorize @repository = Repository.find(params[:id])
end
end

View File

@ -1,14 +1,12 @@
class Api::V1::SearchController < Api::V1::BaseController
before_action :authenticate_user! unless APP_CONFIG['anonymous_access']
def index
search = Search.new(params[:query], current_ability, paginate_params)
authorize :search
search = Search.new(params[:query], current_user, paginate_params)
types = Search::TYPES.find{ |t| t == params[:type] } || Search::TYPES
@results = {}
[types].flatten.each do |type|
@results[type] = search.send(type)
end
respond_to :json
end
end

View File

@ -2,18 +2,15 @@ class Api::V1::UsersController < Api::V1::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :user, only: :show
before_action :load_user, only: %i(show)
before_action :set_current_user, except: :show
def show
@user = User.opened.find params[:id] # dont show system users
respond_to :json
end
def show_current_user
respond_to do |format|
format.json { render :show }
end
render :show
end
def update
@ -37,15 +34,18 @@ class Api::V1::UsersController < Api::V1::BaseController
else
render_json_response @user, error_message(@user.notifier, 'User notification settings have not been updated'), 422
end
else
respond_to :json
end
end
protected
def set_current_user
@user = current_user
authorize @user = current_user
end
# Private: before_action hook which loads User.
def load_user
authorize @user = User.find(params[:id])
end
end

View File

@ -1,4 +1,7 @@
class ApplicationController < ActionController::Base
include StrongParams
include Pundit
AIRBRAKE_IGNORE = [
ActionController::InvalidAuthenticityToken,
AbstractController::ActionNotFound
@ -14,7 +17,10 @@ class ApplicationController < ActionController::Base
before_action :set_locale
before_action -> { EventLog.current_controller = self },
only: [:create, :destroy, :open_id, :cancel, :publish, :change_visibility] # :update
before_action :banned?
after_action -> { EventLog.current_controller = nil }
after_action :verify_authorized, unless: :devise_controller?
skip_after_action :verify_authorized, only: %i(render_500 render_404)
helper_method :get_owner
@ -27,7 +33,7 @@ class ApplicationController < ActionController::Base
AbstractController::ActionNotFound, with: :render_404
end
rescue_from CanCan::AccessDenied do |exception|
rescue_from Pundit::NotAuthorizedError do |exception|
redirect_to forbidden_url, alert: t("flash.exception_message")
end
@ -40,6 +46,15 @@ class ApplicationController < ActionController::Base
protected
# Disables access to site for banned users
def banned?
if user_signed_in? && current_user.access_locked?
sign_out current_user
flash[:error] = I18n.t('devise.failure.locked')
redirect_to root_path
end
end
# For this example, we are simply using token authentication
# via parameters. However, anyone could use Rails's token
# authentication features to get the token from a header.
@ -75,6 +90,8 @@ class ApplicationController < ActionController::Base
if Rails.env.production? && !AIRBRAKE_IGNORE.include?(e.class)
notify_airbrake(e)
end
Rails.logger.error e.message
Rails.logger.error e.backtrace.inspect
render_error 500
end

View File

@ -1,5 +1,6 @@
class AutocompletesController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_user!
skip_after_action :verify_authorized
def autocomplete_user_uname
results = User.opened.search(params[:query]).search_order.limit(5)
@ -13,7 +14,8 @@ class AutocompletesController < ApplicationController
end
def autocomplete_extra_build_list
bl = BuildList.for_extra_build_lists(params[:term], current_ability, save_to_platform).first
bl = BuildListPolicy::Scope.new(current_user, BuildList).read.
for_extra_build_lists(params[:term], save_to_platform).first
results << { :id => bl.id,
:value => bl.id,
:label => "#{bl.id} (#{bl.project.name} - #{bl.arch.name})",
@ -29,16 +31,16 @@ class AutocompletesController < ApplicationController
value: mb.id,
label: "#{mb.id} - #{mb.name}",
path: platform_mass_build_path(mb.save_to_platform, mb)
} if mb && can?(:show, mb)
} if mb && policy(mb).show?
render json: results.to_json
end
def autocomplete_extra_repositories
# Only personal and build for platform repositories can be attached to the build
Platform.includes(:repositories).search(params[:term]).search_order
.accessible_by(current_ability, :read).limit(5)
.where("platforms.platform_type = 'personal' OR platforms.id = ?",
params[:build_for_platform_id].to_i).each do |platform|
platforms = PlatformPolicy::Scope.new(current_user, Platform).show.
includes(:repositories).search(params[:term]).search_order.limit(5).
where("platforms.platform_type = 'personal' OR platforms.id = ?", params[:build_for_platform_id])
platforms.each do |platform|
platform.repositories.each do |repository|
results <<
{
@ -56,7 +58,7 @@ class AutocompletesController < ApplicationController
protected
def save_to_platform
@save_to_platform ||= Platform.find(params[:platform_id])
@save_to_platform ||= Platform.find_cached(params[:platform_id])
end
def results

View File

@ -0,0 +1,45 @@
module Api
module V1
module Issueable
extend ActiveSupport::Concern
protected
# Private: before_action hook which loads Group.
def load_group
authorize @group = Group.find(params[:id]), :show?
end
# Private: before_action hook which loads Project.
def load_project
authorize @project = Project.find(params[:project_id]), :show?
end
# Private: before_action hook which loads Issue.
def load_issue
authorize @issue = @project.issues.find_by!(serial_id: params[:id]), :show?
end
# Private: Get membered projects.
#
# Returns the ActiveRecord::Relation instance.
def membered_projects
@membered_projects ||= ProjectPolicy::Scope.new(current_user, Project).membered
end
# Private: Get project ids which available for current user.
#
# Returns the Array of project ids.
def get_all_project_ids(default_project_ids)
project_ids = []
if %w(created all).include? params[:filter]
# add own issues
project_ids = Project.opened.joins(:issues).
where(issues: {user_id: current_user.id}).
pluck('projects.id')
end
project_ids | default_project_ids
end
end
end
end

View File

@ -0,0 +1,9 @@
module StrongParams
extend ActiveSupport::Concern
protected
def permit_params(param_name, *accessible)
(params[param_name] || ActionController::Parameters.new).permit(*accessible.flatten)
end
end

View File

@ -1,4 +1,5 @@
class ContactsController < ApplicationController
skip_after_action :verify_authorized
def new
@form = Feedback.new(current_user)

View File

@ -4,6 +4,7 @@ class Groups::BaseController < ApplicationController
protected
# Private: before_action hook which loads Group.
def find_group
if group_id = params[:uname] || params[:group_id] || params[:id]
@group = Group.find_by_insensitive_uname! group_id

View File

@ -1,12 +1,12 @@
class Groups::MembersController < Groups::BaseController
before_action -> { authorize! :manage_members, @group }
before_action -> { authorize @group, :manage_members? }
def index
@members = @group.members.order(:uname) - [@group.owner]
end
def update
raise CanCan::AccessDenied if @group.owner_id.to_s == params[:member_id]
raise Pundit::NotAuthorizedError if @group.owner_id.to_s == params[:member_id]
relation = @group.actors.where(actor_id: params[:member_id], actor_type: 'User').first
relation ||= @group.actors.build(actor_id: params[:member_id], actor_type: 'User')
@ -25,7 +25,7 @@ class Groups::MembersController < Groups::BaseController
end
def add
@user = User.where(id: params[:member_id]).first
@user = User.find_by(id: params[:member_id])
if !@user
flash[:error] = t("flash.collaborators.wrong_user", uname: params[:user_uname])
elsif @group.add_member(@user, params[:role])

View File

@ -2,15 +2,16 @@ class Groups::ProfileController < Groups::BaseController
include AvatarHelper
include PaginateHelper
load_and_authorize_resource class: Group, instance_name: 'group'
skip_before_action :authenticate_user!, only: :show if APP_CONFIG['anonymous_access']
def index
authorize :group
@groups = current_user.groups.paginate(page: params[:group_page]) # accessible_by(current_ability)
@groups = @groups.search(params[:query]) if params[:query].present?
end
def show
authorize @group
respond_to do |format|
format.html do
@members = @group.members.order(:uname)
@ -21,9 +22,10 @@ class Groups::ProfileController < Groups::BaseController
when 'open'
@projects = @projects.opened
when 'hidden'
@projects = @projects.by_visibilities('hidden').accessible_by(current_ability, :read)
@projects = @projects.by_visibilities('hidden')
@projects = @projects.none unless policy(@group).reader?
else
@projects = @projects.accessible_by(current_ability, :read)
@projects = @projects.opened unless policy(@group).reader?
end
@total_items = @projects.count
@projects = @projects.paginate(paginate_params)
@ -33,13 +35,15 @@ class Groups::ProfileController < Groups::BaseController
end
def new
authorize @group = current_user.own_groups.build
end
def edit
authorize @group
end
def create
@group = current_user.own_groups.new params[:group]
authorize @group = current_user.own_groups.build(params[:group])
if @group.save
flash[:notice] = t('flash.group.saved')
redirect_to group_path(@group)
@ -51,6 +55,7 @@ class Groups::ProfileController < Groups::BaseController
end
def update
authorize @group
if @group.update_attributes(params[:group])
update_avatar(@group, params)
flash[:notice] = t('flash.group.saved')
@ -62,12 +67,14 @@ class Groups::ProfileController < Groups::BaseController
end
def destroy
authorize @group
@group.destroy
flash[:notice] = t("flash.group.destroyed")
redirect_to groups_path
end
def remove_user
authorize @group
Relation.by_actor(current_user).by_target(@group).destroy_all
redirect_to groups_path
end

View File

@ -1,5 +1,6 @@
class HomeController < ApplicationController
before_action :authenticate_user!, only: [:activity, :issues, :pull_requests]
skip_after_action :verify_authorized
def root
respond_to do |format|
@ -23,7 +24,7 @@ class HomeController < ApplicationController
def issues
@created_issues = current_user.issues
@assigned_issues = Issue.where(assignee_id: current_user.id)
pr_ids = Project.accessible_by(current_ability, :membered).uniq.pluck(:id)
pr_ids = ProjectPolicy::Scope.new(current_user, Project).membered.uniq.pluck(:id)
@all_issues = Issue.where(project_id: pr_ids)
@created_issues, @assigned_issues, @all_issues =
if action_name == 'issues'

View File

@ -1,4 +1,5 @@
class PagesController < ApplicationController
skip_after_action :verify_authorized
def tour_inside
@entries = case params[:id]

View File

@ -1,2 +1,11 @@
class Platforms::BaseController < ApplicationController
before_action :load_platform
protected
def load_platform
return unless params[:platform_id]
authorize @platform = Platform.find_cached(params[:platform_id]), :show?
end
end

View File

@ -4,8 +4,6 @@ class Platforms::ContentsController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: :index if APP_CONFIG['anonymous_access']
load_and_authorize_resource :platform
def index
respond_to do |format|
format.html
@ -22,7 +20,7 @@ class Platforms::ContentsController < Platforms::BaseController
end
def remove_file
authorize!(:remove_file, @platform)
authorize @platform
PlatformContent.remove_file(@platform, params[:path])
render nothing: true
end

View File

@ -1,16 +1,14 @@
class Platforms::KeyPairsController < Platforms::BaseController
before_action :authenticate_user!
load_and_authorize_resource :platform
load_and_authorize_resource only: [:create, :destroy]
def index
@key_pair = KeyPair.new
end
def create
@key_pair = KeyPair.new params[:key_pair]
@key_pair.user_id = current_user.id
authorize @key_pair
if @key_pair.save
flash[:notice] = t('flash.key_pairs.saved')
redirect_to platform_key_pairs_path(@key_pair.repository.platform) and return
@ -21,6 +19,7 @@ class Platforms::KeyPairsController < Platforms::BaseController
end
def destroy
authorize @key_pair = @platform.key_pairs.find(params[:id])
if @key_pair.destroy
flash[:notice] = t('flash.key_pairs.destroyed')
else

View File

@ -1,7 +1,6 @@
class Platforms::MaintainersController < ApplicationController
class Platforms::MaintainersController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :platform
def index
@maintainer = BuildList::Package.new(params[:build_list_package])

View File

@ -4,28 +4,30 @@ class Platforms::MassBuildsController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :get_list] if APP_CONFIG['anonymous_access']
load_resource :platform
load_and_authorize_resource :through => :platform, :shallow => true
before_action :find_mass_build, only: %i(show publish cancel get_list)
def new
if params[:mass_build_id].present?
@mass_build = @platform.mass_builds.find(params[:mass_build_id]).dup
@mass_build.arches = Arch.where(name: @mass_build.arch_names.split(', ')).pluck(:id)
end
authorize @mass_build ||= @platform.mass_builds.build
@mass_build.arches ||= @platform.platform_arch_settings.by_default.pluck(:arch_id)
@mass_build.repositories ||= []
@mass_build.arches.map!(&:to_s)
end
def show
authorize @platform.mass_builds.find(params[:id])
end
def create
@mass_build = @platform.mass_builds.build(params[:mass_build])
@mass_build.user = current_user
@mass_build.arches = params[:arches] || []
@mass_build.repositories ||= params[:repositories] || []
authorize @mass_build
if @mass_build.save
redirect_to(platform_mass_builds_path(@platform), notice: t("flash.platform.build_all_success"))
else
@ -57,7 +59,6 @@ class Platforms::MassBuildsController < Platforms::BaseController
end
def get_list
text =
case params[:kind]
when 'failed_builds_list', 'tests_failed_builds_list', 'success_builds_list'
@ -67,4 +68,11 @@ class Platforms::MassBuildsController < Platforms::BaseController
end
render text: text
end
private
# Private: before_action hook which loads MassBuild.
def find_mass_build
authorize @mass_build = @platform.mass_builds.find(params[:id])
end
end

View File

@ -3,14 +3,14 @@ class Platforms::PlatformsController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:advisories, :members, :show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource
def index
authorize :platform
respond_to do |format|
format.html {}
format.json {
@platforms = @platforms.accessible_by(current_ability, :related)
@platforms = PlatformPolicy::Scope.new(current_user, Platform).related
@platforms_count = @platforms.count
@platforms = @platforms.paginate(page: current_page, per_page: Platform.per_page)
}
@ -21,18 +21,20 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def new
authorize @platform = Platform.new
@admin_uname = current_user.uname
@admin_id = current_user.id
@platform = Platform.new
end
def edit
authorize @platform
@admin_id = @platform.owner.id
@admin_uname = @platform.owner.uname
end
def create
@admin_id = params[:admin_id]
authorize @platform = Platform.new(params[:platform])
@admin_id = params[:admin_id]
@admin_uname = params[:admin_uname]
# FIXME: do not allow manipulate owner model, only platforms onwer_id and onwer_type
@platform.owner = @admin_id.blank? ? get_owner : User.find(@admin_id)
@ -47,6 +49,7 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def update
authorize @platform
@admin_id = params[:admin_id]
@admin_uname = params[:admin_uname]
@ -54,7 +57,6 @@ class Platforms::PlatformsController < Platforms::BaseController
platform_params = platform_params.slice(:description, :platform_arch_settings_attributes, :released, :automatic_metadata_regeneration, :default_branch)
platform_params[:owner] = User.find(@admin_id) if @admin_id.present?
respond_to do |format|
format.html do
if @platform.update_attributes(platform_params)
@ -76,6 +78,7 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def regenerate_metadata
authorize @platform
if @platform.regenerate
flash[:notice] = I18n.t('flash.platform.saved')
else
@ -85,6 +88,7 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def change_visibility
authorize @platform
if @platform.change_visibility
flash[:notice] = I18n.t("flash.platform.saved")
redirect_to @platform
@ -96,12 +100,14 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def clone
authorize @platform
@cloned = Platform.new
@cloned.name = @platform.name + "_clone"
@cloned.description = @platform.description + "_clone"
end
def make_clone
authorize @platform
@cloned = @platform.full_clone params[:platform].merge(owner: current_user)
if @cloned.persisted?
flash[:notice] = I18n.t("flash.platform.clone_success")
@ -113,16 +119,19 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def destroy
authorize @platform
@platform.destroy # later with resque
flash[:notice] = t("flash.platform.destroyed")
redirect_to platforms_path
end
def members
authorize @platform
@members = @platform.members.order(:uname)
end
def remove_members
authorize @platform
User.where(id: params[:members]).each do |user|
@platform.remove_member(user)
end
@ -130,7 +139,8 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def add_member
member = User.where(id: params[:member_id]).first
authorize @platform
member = User.find_by(id: params[:member_id])
if !member
flash[:error] = t("flash.collaborators.wrong_user", uname: params[:member_id])
elsif @platform.add_member(member)
@ -142,13 +152,22 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def advisories
authorize @platform
@advisories = @platform.advisories.paginate(page: params[:page])
end
def clear
authorize @platform
@platform.clear
flash[:notice] = t('flash.repository.clear')
redirect_to edit_platform_path(@platform)
end
private
# Private: before_action hook which loads Platform.
def load_platform
authorize @platform = Platform.find_cached(params[:id]), :show? if params[:id]
end
end

View File

@ -4,18 +4,17 @@ class Platforms::ProductBuildListsController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show, :log] if APP_CONFIG['anonymous_access']
before_action :redirect_to_full_path_if_short_url, only: [:show, :update]
load_and_authorize_resource :platform, except: :index
load_and_authorize_resource :product, through: :platform, except: :index
load_and_authorize_resource :product_build_list, through: :product, except: :index
load_and_authorize_resource only: [:index, :show, :log, :cancel, :update]
before_action :load_product, except: :index
before_action :load_product_build_list, except: [:index, :new, :create]
def new
product = @product_build_list.product
@product_build_list.params = product.params
@product_build_list.main_script = product.main_script
@product_build_list.time_living = product.time_living
@product_build_list.project_version = product.project_version
@product_build_list.project = product.project
@product_build_list = @product.product_build_lists.new
@product_build_list.params = @product.params
@product_build_list.main_script = @product.main_script
@product_build_list.time_living = @product.time_living
@product_build_list.project_version = @product.project_version
@product_build_list.project = @product.project
unless @product_build_list.project
flash[:error] = t('flash.product_build_list.no_project')
redirect_to edit_platform_product_path(@platform, @product)
@ -53,6 +52,7 @@ class Platforms::ProductBuildListsController < Platforms::BaseController
pbl.user = current_user
pbl.base_url = "http://#{request.host_with_port}"
authorize pbl
if pbl.save
flash[:notice] = t('flash.product.build_started')
redirect_to [@platform, @product]
@ -73,8 +73,11 @@ class Platforms::ProductBuildListsController < Platforms::BaseController
end
def index
authorize :product_build_list
@product_build_list = ProductBuildList.new(params[:product_build_list])
@product_build_list.status = nil if params[:product_build_list].try(:[], :status).blank?
@product_build_lists = @platform.product_build_lists if @platform
@product_build_lists ||= PlatformPolicy::Scope.new(current_user, ProductBuildList.joins(product: :platform)).show
if @product_build_list.product_id.present?
@product_build_lists = @product_build_lists.where(id: @product_build_list.product_id)
else
@ -98,4 +101,14 @@ class Platforms::ProductBuildListsController < Platforms::BaseController
end
end
# Private: before_action hook which loads ProductBuildList.
def load_product_build_list
authorize @product_build_list = ProductBuildList.find(params[:id])
end
# Private: before_action hook which loads Product.
def load_product
authorize @product = Product.find(params[:product_id]), :show? if params[:product_id]
end
end

View File

@ -4,22 +4,22 @@ class Platforms::ProductsController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :platform
load_and_authorize_resource :product, through: :platform, except: :autocomplete_project
before_action :load_product, except: %i(index new create autocomplete_project)
def index
@products = @products.paginate(page: params[:page])
authorize @platform.products.new
@products = @platform.products.paginate(page: params[:page])
end
def new
@product = @platform.products.new
authorize @product = @platform.products.new
end
def edit
end
def create
authorize @product = @platform.products.build(params[:product])
if @product.save
flash[:notice] = t('flash.product.saved')
redirect_to platform_product_path(@platform, @product)
@ -53,9 +53,17 @@ class Platforms::ProductsController < Platforms::BaseController
end
def autocomplete_project
@items = Project.accessible_by(current_ability, :membered)
.by_owner_and_name(params[:query]).limit(20)
authorize :project
@items = ProjectPolicy::Scope.new(current_user, Project).membered.
by_owner_and_name(params[:query]).limit(20)
#items.select! {|e| e.repo.branches.count > 0}
end
private
# Private: before_action hook which loads Product.
def load_product
authorize @product = Product.find(params[:id])
end
end

View File

@ -7,11 +7,12 @@ class Platforms::RepositoriesController < Platforms::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show, :projects_list] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :platform
load_and_authorize_resource :repository, through: :platform, shallow: true
before_action :set_members, only: [:edit, :update]
before_action :load_repository, except: [:index, :create, :new]
before_action :set_members, only: [:edit, :update]
before_action -> { @repository = @platform.repositories.find(params[:id]) if params[:id] }
def index
@repositories = @platform.repositories
@repositories = Repository.custom_sort(@repositories).paginate(page: current_page)
end
@ -23,6 +24,7 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def update
authorize @repository = @platform.repositories.build(params[:repository])
if @repository.update_attributes params[:repository].slice(:description, :synchronizing_publications, :publish_builds_only_from_branch).merge(publish_without_qa: (params[:repository][:publish_without_qa] || @repository.publish_without_qa))
flash[:notice] = I18n.t("flash.repository.updated")
redirect_to platform_repository_path(@platform, @repository)
@ -34,14 +36,14 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def remove_members
User.where(id: params[:members]).each do |user|
User.where(id: params[:members]).find_each do |user|
@repository.remove_member(user)
end
redirect_to edit_platform_repository_path(@platform, @repository)
end
def add_member
if member = User.where(id: params[:member_id]).first
if member = User.find_by(id: params[:member_id])
if @repository.add_member(member)
flash[:notice] = t('flash.repository.members.successfully_added', name: member.uname)
else
@ -52,11 +54,12 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def new
@repository = Repository.new
authorize @repository = @platform.repositories.new
@platform_id = params[:platform_id]
end
def destroy
authorize @repository
@repository.destroy
flash[:notice] = t("flash.repository.destroyed")
@ -64,7 +67,7 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def create
@repository = @platform.repositories.build(params[:repository])
authorize @repository = @platform.repositories.build(params[:repository])
if @repository.save
flash[:notice] = t('flash.repository.saved')
redirect_to platform_repository_path(@platform, @repository)
@ -75,6 +78,7 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def add_project
authorize @repository
if projects_list = params.try(:[], :repository).try(:[], :projects_list)
@repository.add_projects projects_list, current_user
redirect_to platform_repository_path(@platform, @repository), notice: t('flash.repository.projects_will_be_added')
@ -82,7 +86,7 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
if params[:project_id].present?
@project = Project.find(params[:project_id])
if can?(:read, @project)
if policy(@project).read?
begin
@repository.projects << @project
flash[:notice] = t('flash.repository.project_added')
@ -149,6 +153,7 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def regenerate_metadata
authorize @repository
if @repository.regenerate(params[:repository].try :[], :build_for_platform_id)
flash[:notice] = t('flash.repository.regenerate_in_queue')
else
@ -170,6 +175,11 @@ class Platforms::RepositoriesController < Platforms::BaseController
protected
# Private: before_action hook which loads Repository.
def load_repository
authorize @repository = @platform.repositories.find(params[:id])
end
def set_members
@members = @repository.members.order('name')
end

View File

@ -1,11 +1,10 @@
class Platforms::TokensController < Platforms::BaseController
before_action :authenticate_user!
load_resource :platform
load_and_authorize_resource :through => :platform, :shallow => true
before_action :load_token, except: [:index, :create, :new]
def index
authorize! :local_admin_manage, @platform
authorize @platform, :local_admin_manage?
@tokens = @platform.tokens.includes(:creator, :updater)
.paginate(per_page: 20, page: params[:page])
end
@ -24,11 +23,13 @@ class Platforms::TokensController < Platforms::BaseController
end
def new
authorize @token = @platform.tokens.new
end
def create
@token = @platform.tokens.build params[:token]
@token.creator = current_user
authorize @token
if @token.save
flash[:notice] = t('flash.tokens.saved')
redirect_to platform_tokens_path(@platform)
@ -39,4 +40,11 @@ class Platforms::TokensController < Platforms::BaseController
end
end
protected
# Private: before_action hook which loads Repository.
def load_token
authorize @token = @platform.tokens.find(params[:id])
end
end

View File

@ -12,7 +12,8 @@ class Projects::BaseController < ApplicationController
end
def find_project
@project = Project.find_by_owner_and_name! params[:name_with_owner] if params[:name_with_owner].present?
return if params[:name_with_owner].blank?
authorize @project = Project.find_by_owner_and_name!(params[:name_with_owner]), :show?
end
def init_statistics

View File

@ -7,23 +7,18 @@ class Projects::BuildListsController < Projects::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show, :index, :log] if APP_CONFIG['anonymous_access']
before_action :find_build_list, only: [:show, :publish, :cancel, :update, :log, :create_container, :dependent_projects]
load_and_authorize_resource :project, only: [:new, :create]
load_resource :project, only: :index, parent: false
load_and_authorize_resource :build_list, through: :project, only: NESTED_ACTIONS, shallow: true
load_and_authorize_resource except: NESTED_ACTIONS
before_action :load_build_list, except: NESTED_ACTIONS
before_action :create_from_build_list, only: :new
def index
authorize!(:show, @project) if @project
authorize :build_list
params[:filter].each{|k,v| params[:filter].delete(k) if v.blank? } if params[:filter]
respond_to do |format|
format.html
format.json do
@filter = BuildList::Filter.new(@project, current_user, current_ability, params[:filter] || {})
@filter = BuildList::Filter.new(@project, current_user, params[:filter] || {})
params[:page] = params[:page].to_i == 0 ? nil : params[:page]
params[:per_page] = if BuildList::Filter::PER_PAGE.include? params[:per_page].to_i
params[:per_page].to_i
@ -46,6 +41,7 @@ class Projects::BuildListsController < Projects::BaseController
end
def new
authorize @build_list = @project.build_lists.build
if params[:show] == 'inline' && params[:build_list_id].present?
render json: new_build_list_data(@build_list, @project, params), layout: false
else
@ -73,7 +69,8 @@ class Projects::BuildListsController < Projects::BaseController
@build_list.priority = current_user.build_priority # User builds more priority than mass rebuild with zero priority
flash_options = { project_version: @build_list.project_version, arch: arch.name, build_for_platform: build_for_platform.name }
if authorize!(:create, @build_list) && @build_list.save
authorize @build_list
if @build_list.save
build_lists << @build_list
notices << t('flash.build_list.saved', flash_options)
else
@ -125,8 +122,6 @@ class Projects::BuildListsController < Projects::BaseController
end
def dependent_projects
raise CanCan::AccessDenied if @build_list.save_to_platform.personal?
if request.post?
prs = params[:build_list]
if prs.present? && prs[:projects].present? && prs[:arches].present?
@ -211,6 +206,16 @@ class Projects::BuildListsController < Projects::BaseController
protected
# Private: before_action hook which loads BuidList.
def load_build_list
authorize @build_list =
if @project
@project.build_lists
else
BuildList
end.find(params[:id])
end
def do_and_back(action, prefix, success = 'success', fail = 'fail')
result = @build_list.send("can_#{action}?") && @build_list.send(action)
message = result ? success : fail
@ -218,10 +223,6 @@ class Projects::BuildListsController < Projects::BaseController
redirect_to :back
end
def find_build_list
@build_list = BuildList.find(params[:id])
end
def create_from_build_list
return if params[:build_list_id].blank?
build_list = @project.build_lists.find(params[:build_list_id])

View File

@ -2,7 +2,6 @@ class Projects::CollaboratorsController < Projects::BaseController
respond_to :html, :json
before_action :authenticate_user!
load_resource :project
before_action :authorize_collaborators
before_action :find_users
@ -74,6 +73,6 @@ class Projects::CollaboratorsController < Projects::BaseController
end
def authorize_collaborators
authorize! :update, @project
authorize @project, :update?
end
end

View File

@ -1,9 +1,7 @@
class Projects::CommentsController < Projects::BaseController
before_action :authenticate_user!
load_and_authorize_resource :project
before_action :find_commentable
before_action :find_or_build_comment
load_and_authorize_resource new: :new_line
include CommentsHelper
@ -58,5 +56,6 @@ class Projects::CommentsController < Projects::BaseController
def find_or_build_comment
@comment = params[:id].present? && Comment.where(automatic: false).find(params[:id]) ||
current_user.comments.build(params[:comment]) {|c| c.commentable = @commentable; c.project = @project}
authorize @comment
end
end

View File

@ -1,7 +1,5 @@
class Projects::CommitSubscribesController < Projects::BaseController
before_action :authenticate_user!
load_and_authorize_resource :project
before_action :find_commit
def create

View File

@ -5,7 +5,6 @@ class Projects::Git::BaseController < Projects::BaseController
before_action :authenticate_user, only: %i(show index blame raw archive diff tags branches)
end
load_and_authorize_resource :project
before_action :set_treeish_and_path
before_action :set_branch_and_tree

View File

@ -1,6 +1,6 @@
class Projects::Git::BlobsController < Projects::Git::BaseController
before_action :set_blob
before_action -> {authorize! :write, @project}, only: [:edit, :update]
before_action -> {authorize @project, :write? }, only: [:edit, :update]
def show
end

View File

@ -5,8 +5,8 @@ class Projects::Git::TreesController < Projects::Git::BaseController
before_action :redirect_to_project, only: :show
before_action :resolve_treeish, only: [:branch, :destroy]
skip_authorize_resource :project, only: [:destroy, :restore_branch, :create]
before_action -> { authorize!(:write, @project) }, only: [:destroy, :restore_branch, :create]
# skip_authorize_resource :project, only: [:destroy, :restore_branch, :create]
before_action -> { authorize(@project, :show?) }, only: [:show, :archive, :tags, :branches]
def show
unless request.xhr?
@ -54,16 +54,19 @@ class Projects::Git::TreesController < Projects::Git::BaseController
end
def restore_branch
authorize @project, :write?
status = @project.create_branch(@treeish, params[:sha], current_user) ? 200 : 422
render nothing: true, status: status
end
def create
authorize @project, :write?
status = @project.create_branch(params[:new_ref], params[:from_ref], current_user) ? 200 : 422
render nothing: true, status: status
end
def destroy
authorize @project, :write?
status = @branch && @project.delete_branch(@branch, current_user) ? 200 : 422
render nothing: true, status: status
end

View File

@ -1,22 +1,23 @@
class Projects::HooksController < Projects::BaseController
before_action :authenticate_user!
load_and_authorize_resource :project
load_and_authorize_resource :hook, through: :project
before_action -> { authorize @project, :update? }
before_action :load_hook, except: %i(index new create)
def index
authorize! :edit, @project
@name = params[:name]
@hooks = @project.hooks.for_name(@name).order('name asc, created_at desc')
render(:show) if @name.present?
end
def new
@hook = @project.hooks.build
end
def edit
end
def create
authorize @hook = @project.hooks.build(params[:hook])
if @hook.save
redirect_to project_hooks_path(@project, name: @hook.name), notice: t('flash.hook.created')
else
@ -41,4 +42,11 @@ class Projects::HooksController < Projects::BaseController
redirect_to project_hooks_path(@project, name: @hook.name)
end
private
# Private: before_action hook which loads Hook.
def load_hook
authorize @hook = @project.hooks.find(params[:id])
end
end

View File

@ -1,15 +1,15 @@
class Projects::IssuesController < Projects::BaseController
NON_RESTFUL_ACTION = [:create_label, :update_label, :destroy_label]
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show] if APP_CONFIG['anonymous_access']
load_resource :project
load_and_authorize_resource :issue, through: :project, find_by: :serial_id, only: [:show, :edit, :update, :destroy, :new, :create, :index]
before_action :load_and_authorize_label, only: NON_RESTFUL_ACTION
before_action :find_collaborators, only: [:new, :create, :show, :search_collaborators]
before_action :load_issue, only: %i(show edit update destroy)
before_action :load_and_authorize_label, only: %i(create_label update_label destroy_label)
before_action :find_collaborators, only: :search_collaborators
layout false, only: [:update, :search_collaborators]
def index
raise Pundit::NotAuthorizedError unless @project.has_issues?
params[:kind] = params[:kind] == 'pull_requests' ? 'pull_requests' : 'issues'
params[:filter] = params[:filter].in?(['created', 'assigned']) ? params[:filter] : 'all'
params[:sort] = params[:sort] == 'submitted' ? 'submitted' : 'updated'
@ -22,11 +22,12 @@ class Projects::IssuesController < Projects::BaseController
respond_to do |format|
format.html { render 'index' }
format.json do
if params[:kind] == 'pull_requests'
all_issues = @project.issues.joins(:pull_request)
else
all_issues = @project.issues.without_pull_requests
end
all_issues =
if params[:kind] == 'pull_requests'
@project.issues.joins(:pull_request)
else
@project.issues.without_pull_requests
end
@all_issues = all_issues
if current_user
@ -74,15 +75,18 @@ class Projects::IssuesController < Projects::BaseController
end
def new
authorize @issue = @project.issues.build
end
def create
@issue = @project.issues.build(params[:issue])
@issue.user_id = current_user.id
unless can?(:write, @project)
unless policy(@project).write?
@issue.assignee_id = nil
@issue.labelings = []
end
authorize @issue
if @issue.save
@issue.subscribe_creator(current_user.id)
flash[:notice] = I18n.t("flash.issue.saved")
@ -104,7 +108,7 @@ class Projects::IssuesController < Projects::BaseController
format.json {
status = 200
unless can?(:write, @project)
unless policy(@project).write?
params.delete :update_labels
[:assignee_id, :labelings, :labelings_attributes].each do |k|
params[:issue].delete k
@ -165,8 +169,14 @@ class Projects::IssuesController < Projects::BaseController
private
# Private: before_action hook which loads Issue.
def load_issue
authorize @issue = @project.issues.find_by!(serial_id: params[:id])
end
# Private: before_action hook which loads Label.
def load_and_authorize_label
authorize! :write, @project
@label = Label.find(params[:label_id]) if params[:label_id]
authorize @project, :write?
@label = @project.labels.find(params[:label_id]) if params[:label_id]
end
end

View File

@ -3,11 +3,11 @@ class Projects::ProjectsController < Projects::BaseController
include ProjectsHelper
before_action :authenticate_user!
load_and_authorize_resource id_param: :name_with_owner # to force member actions load
before_action :who_owns, only: [:new, :create, :mass_import, :run_mass_import]
def index
@projects = Project.accessible_by(current_ability, :membered).search(params[:search])
authorize :project
@projects = ProjectPolicy::Scope.new(current_user, Project).membered.search(params[:search])
respond_to do |format|
format.html {
@groups = current_user.groups
@ -24,18 +24,19 @@ class Projects::ProjectsController < Projects::BaseController
end
def new
authorize :project
@project = Project.new
end
def mass_import
authorize :project
@project = Project.new(mass_import: true)
end
def run_mass_import
@project = Project.new params[:project]
@project.owner = choose_owner
authorize! :write, @project.owner if @project.owner.class == Group
authorize! :add_project, Repository.find(params[:project][:add_to_repository_id])
authorize @project
@project.valid?
@project.errors.messages.slice! :url
if @project.errors.messages.blank? # We need only url validation
@ -48,13 +49,14 @@ class Projects::ProjectsController < Projects::BaseController
end
def edit
authorize @project
@project_aliases = Project.project_aliases(@project).paginate(page: current_page)
end
def create
@project = Project.new params[:project]
@project.owner = choose_owner
authorize! :write, @project.owner if @project.owner.class == Group
authorize @project
if @project.save
flash[:notice] = t('flash.project.saved')
@ -67,6 +69,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def update
authorize @project
params[:project].delete(:maintainer_id) if params[:project][:maintainer_id].blank?
respond_to do |format|
format.html do
@ -82,18 +85,19 @@ class Projects::ProjectsController < Projects::BaseController
end
format.json do
if @project.update_attributes(params[:project])
render json: { notice: I18n.t('flash.project.saved') }.to_json
render json: { notice: I18n.t('flash.project.saved') }
else
render json: { error: I18n.t('flash.project.save_error') }.to_json, status: 422
render json: { error: I18n.t('flash.project.save_error') }, status: 422
end
end
end
end
def schedule
authorize @project
p_to_r = @project.project_to_repositories.where(repository_id: params[:repository_id]).first
unless p_to_r.repository.publish_without_qa
authorize! :local_admin_manage, p_to_r.repository.platform
authorize p_to_r.repository.platform, :local_admin_manage?
end
p_to_r.user_id = current_user.id
p_to_r.enabled = params[:enabled].present?
@ -107,6 +111,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def destroy
authorize @project
@project.destroy
flash[:notice] = t("flash.project.destroyed")
redirect_to @project.owner
@ -114,8 +119,7 @@ class Projects::ProjectsController < Projects::BaseController
def fork(is_alias = false)
owner = (Group.find params[:group] if params[:group].present?) || current_user
authorize! :write, owner if owner.class == Group
authorize owner, :write?
if forked = @project.fork(owner, new_name: params[:fork_name], is_alias: is_alias) and forked.valid?
redirect_to forked, notice: t("flash.project.forked")
else
@ -126,15 +130,18 @@ class Projects::ProjectsController < Projects::BaseController
end
def alias
authorize @project
fork(true)
end
def possible_forks
authorize @project
render partial: 'projects/git/base/forks', layout: false,
locals: { owner: current_user, name: (params[:name].presence || @project.name) }
end
def sections
authorize @project, :update?
if request.patch?
if @project.update_attributes(params[:project])
flash[:notice] = t('flash.project.saved')
@ -147,6 +154,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def remove_user
authorize @project
@project.relations.by_actor(current_user).destroy_all
respond_to do |format|
format.html do
@ -158,6 +166,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def autocomplete_maintainers
authorize @project
term, limit = params[:query], params[:limit] || 10
items = User.member_of_project(@project)
.where("users.name ILIKE ? OR users.uname ILIKE ?", "%#{term}%", "%#{term}%")
@ -166,6 +175,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def preview
authorize @project
respond_to do |format|
format.json {}
format.html {render inline: view_context.markdown(params[:text]), layout: false}
@ -173,6 +183,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def refs_list
authorize @project
refs = @project.repo.branches_and_tags.map(&:name)
@selected = params[:selected] if refs.include?(params[:selected])
@selected ||= @project.resolve_default_branch

View File

@ -1,20 +1,19 @@
class Projects::PullRequestsController < Projects::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:index, :show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :project
load_resource :issue, through: :project, find_by: :serial_id, parent: false, except: [:index, :autocomplete_to_project]
load_and_authorize_resource instance_name: :pull, through: :issue, singleton: true, except: [:index, :autocomplete_to_project]
before_action :find_collaborators, only: [:new, :create, :show]
before_action :load_issue, except: %i(index autocomplete_to_project new create)
before_action :load_pull, except: %i(index autocomplete_to_project new create)
def new
to_project = find_destination_project(false)
authorize! :read, to_project
authorize to_project, :show?
@pull = to_project.pull_requests.new
@pull.issue = to_project.issues.new
@pull = to_project.pull_requests.new
@issue = @pull.issue = to_project.issues.new
set_attrs
authorize @pull
if PullRequest.check_ref(@pull, 'to', @pull.to_ref) && PullRequest.check_ref(@pull, 'from', @pull.from_ref) || @pull.uniq_merge
flash.now[:warning] = @pull.errors.full_messages.join('. ')
else
@ -33,15 +32,17 @@ class Projects::PullRequestsController < Projects::BaseController
redirect :back
end
to_project = find_destination_project
authorize! :read, to_project
authorize to_project, :show?
@pull = to_project.pull_requests.new pull_params
@pull.issue.assignee_id = (params[:issue] || {})[:assignee_id] if can?(:write, to_project)
@pull = to_project.pull_requests.new pull_params
@issue = @pull.issue
@pull.issue.assignee_id = (params[:issue] || {})[:assignee_id] if policy(to_project).write?
@pull.issue.user, @pull.issue.project, @pull.from_project = current_user, to_project, @project
@pull.from_project_owner_uname = @pull.from_project.owner.uname
@pull.from_project_name = @pull.from_project.name
@pull.issue.new_pull_request = true
authorize @pull
if @pull.valid? # FIXME more clean/clever logics
@pull.save # set pull id
@pull.reload
@ -67,11 +68,13 @@ class Projects::PullRequestsController < Projects::BaseController
end
def merge
authorize @pull
status = @pull.merge!(current_user) ? 200 : 422
render nothing: true, status: status
end
def update
authorize @pull
status = 422
if (action = params[:pull_request_action]) && %w(close reopen).include?(params[:pull_request_action])
if @pull.send("can_#{action}?")
@ -106,7 +109,7 @@ class Projects::PullRequestsController < Projects::BaseController
term = params[:query].to_s.strip.downcase
[ Project.where(id: @project.pull_requests.last.try(:to_project_id)),
@project.ancestors,
Project.accessible_by(current_ability, :membered)
ProjectPolicy::Scope.new(current_user, Project).membered
].each do |p|
items.concat p.by_owner_and_name(term)
end
@ -116,6 +119,17 @@ class Projects::PullRequestsController < Projects::BaseController
protected
# Private: before_action hook which loads Issue.
def load_issue
@issue = @project.issues.find_by!(serial_id: params[:id])
end
# Private: before_action hook which loads PullRequest.
def load_pull
@pull = @issue.pull_request
authorize @pull, :show? if @pull
end
def pull_params
@pull_params ||= params[:pull_request].presence
end

View File

@ -1,12 +1,10 @@
class Projects::SubscribesController < Projects::BaseController
before_action :authenticate_user!
load_and_authorize_resource :project
load_and_authorize_resource :issue, through: :project, find_by: :serial_id
load_and_authorize_resource :subscribe, through: :issue, find_by: :user_id
before_action :load_issue
def create
@subscribe = @issue.subscribes.build(user_id: current_user.id)
authorize @subscribe = @issue.subscribes.build(user_id: current_user.id)
if @subscribe.save
flash[:notice] = I18n.t("flash.subscribe.saved")
redirect_to :back
@ -17,9 +15,17 @@ class Projects::SubscribesController < Projects::BaseController
end
def destroy
authorize @subscribe = @issue.subscribes.find_by(user_id: current_user.id)
@subscribe.destroy
flash[:notice] = t("flash.subscribe.destroyed")
redirect_to :back
end
private
# Private: before_action hook which loads Issue.
def load_issue
authorize @issue = @project.issues.find_by!(serial_id: params[:issue_id]), :show?
end
end

View File

@ -6,7 +6,6 @@ class Projects::WikiController < Projects::BaseController
before_action :authenticate_user!
skip_before_action :authenticate_user!, only: [:show, :index, :git, :compare, :compare_wiki, :history, :wiki_history, :search, :pages] if APP_CONFIG['anonymous_access']
load_resource :project
before_action :authorize_read_actions, only: [:index, :show, :git, :compare, :compare_wiki, :history, :wiki_history, :search, :pages]
before_action :authorize_write_actions, only: [:edit, :update, :new, :create, :destroy, :revert, :revert_wiki, :preview]
@ -262,11 +261,11 @@ class Projects::WikiController < Projects::BaseController
def show_or_create_page
if @page
@content = @page.formatted_data
@editable = can?(:write, @project)
@editable = policy(@project).write?
render :show
elsif file = @wiki.file(@name)
render text: file.raw_data, content_type: file.mime_type
elsif can? :write, @project
elsif policy(@project).write?
@new = true
render :new
else
@ -279,11 +278,10 @@ class Projects::WikiController < Projects::BaseController
end
def authorize_read_actions
authorize! :show, @project
authorize @project, :show?
end
def authorize_write_actions
authorize! :write, @project
authorize @project, :write?
end
end

View File

@ -2,12 +2,12 @@ class SearchController < ApplicationController
include PaginateHelper
before_action :authenticate_user! unless APP_CONFIG['anonymous_access']
# load_and_authorize_resource
skip_after_action :verify_authorized
def index
@type = Search::TYPES.find{ |t| t == params[:type] } || Search::TYPES.first
@query = params[:query]
@search = Search.new(@query, current_ability, paginate_params)
@search = Search.new(@query, current_user, paginate_params)
@collection = @search.send(@type)
end
end

View File

@ -1,4 +1,5 @@
class SitemapController < ApplicationController
skip_after_action :verify_authorized
def show
redirect_to "/sitemaps/#{request.host_with_port.gsub(/www./, '')}/sitemap.xml.gz"

View File

@ -11,6 +11,7 @@ class StatisticsController < ApplicationController
]
def index
authorize :statistic
respond_to do |format|
format.html
format.json do

View File

@ -4,6 +4,7 @@ class Users::ProfileController < Users::BaseController
skip_before_action :authenticate_user!, only: :show if APP_CONFIG['anonymous_access']
def show
authorize @user
respond_to do |format|
format.html do
@groups = @user.groups.order(:uname)
@ -14,9 +15,9 @@ class Users::ProfileController < Users::BaseController
when 'open'
@projects = @projects.opened
when 'hidden'
@projects = @projects.by_visibilities('hidden').accessible_by(current_ability, :read)
@projects = ProjectPolicy::Scope.new(current_user, @projects.by_visibilities('hidden')).read
else
@projects = @projects.accessible_by(current_ability, :read)
@projects = ProjectPolicy::Scope.new(current_user, @projects).read
end
@total_items = @projects.count
@projects = @projects.paginate(paginate_params)

View File

@ -2,6 +2,7 @@ class Users::SettingsController < Users::BaseController
include AvatarHelper
before_action :set_current_user
before_action -> { authorize @user, :update? }
def profile
if request.patch?

View File

@ -1,5 +1,6 @@
class Users::SshKeysController < Users::BaseController
before_action :set_current_user
before_action -> { authorize current_user, :update? }
def index
@ssh_key = SshKey.new

View File

@ -1,16 +1,18 @@
class Users::UsersController < Users::BaseController
skip_before_action :authenticate_user!, only: [:allowed, :check, :discover]
skip_after_action :verify_authorized
before_action :find_user_by_key, only: [:allowed, :discover]
def allowed
project = Project.find_by_owner_and_name! params[:project]
action = case params[:action_type]
when 'git-upload-pack'
then :read
when 'git-receive-pack'
then :write
end
render inline: (!@user.access_locked? && Ability.new(@user).can?(action, project)).to_s
pp = ProjectPolicy.new(@user, project)
can = case params[:action_type]
when 'git-upload-pack'
pp.read?
when 'git-receive-pack'
pp.write?
end
render inline: (!@user.access_locked? && can).to_s
end
def check

View File

@ -20,7 +20,7 @@ module BuildListsHelper
end
def availables_main_platforms
Platform.availables_main_platforms current_user, current_ability
Platform.availables_main_platforms current_user
end
def dependent_projects(package)
@ -294,8 +294,9 @@ module BuildListsHelper
end
def default_extra_repos(project)
project.repositories.joins(:platform).accessible_by(current_ability, :read)
.where(platforms: { platform_type: 'personal' }).map do |extra|
scope = project.repositories.joins(:platform).where(platforms: { platform_type: 'personal' })
scope = PlatformPolicy::Scope.new(current_user, scope).show
scope.map do |extra|
{
id: extra.id,
platform_id: extra.platform.id,

View File

@ -153,7 +153,7 @@ module MarkdownHelper
end
def reference_issue(identifier)
if issue = Issue.find_by_hash_tag(identifier, current_ability, @project)
if issue = Issue.find_by_hash_tag(identifier, current_user, @project)
if issue.pull_request
title = "#{PullRequest.model_name.human}: #{issue.title}"
url = project_pull_request_path(issue.project, issue.pull_request)

View File

@ -3,7 +3,7 @@ module MassBuildHelper
def link_to_list platform, mass_build, which
link_to t("layout.mass_builds.#{which}"),
get_list_platform_mass_build_path(platform, mass_build, kind: which, format: :txt),
target: "_blank" if can?(:get_list, mass_build)
target: "_blank" if policy(mass_build).get_list?
end
def link_to_mass_build(mass_build)

View File

@ -17,7 +17,7 @@ module ProjectsHelper
def available_project_to_repositories(project)
project.project_to_repositories.includes(repository: :platform).select do |p_to_r|
p_to_r.repository.publish_without_qa ? true : can?(:local_admin_manage, p_to_r.repository.platform)
p_to_r.repository.publish_without_qa ? true : policy(p_to_r.repository.platform).local_admin_manage?
end.sort_by do |p_to_r|
"#{p_to_r.repository.platform.name}/#{p_to_r.repository.name}"
end.map do |p_to_r|
@ -33,8 +33,8 @@ module ProjectsHelper
def mass_import_repositories_for_group_select
groups = {}
Platform.accessible_by(current_ability, :related).order(:name).each do |platform|
next unless can?(:local_admin_manage, platform)
PlatformPolicy::Scope.new(current_user, Platform).related.order(:name).each do |platform|
next unless policy(platform).local_admin_manage?
groups[platform.name] = Repository.custom_sort(platform.repositories).map{ |r| [r.name, r.id] }
end
groups.to_a
@ -70,7 +70,9 @@ module ProjectsHelper
end
def alone_member?(project)
Relation.by_target(project).by_actor(current_user).size > 0
Rails.cache.fetch(['ProjectsHelper#alone_member?', project, current_user]) do
Relation.by_target(project).by_actor(current_user).exists?
end
end
def participant_path(participant)

View File

@ -6,13 +6,12 @@ module BuildLists
build_list = BuildList.find(build_list_id)
return if build_list.save_to_platform.personal?
user = User.find(user_id)
ability = Ability.new(user)
return unless ability.can?(:show, build_list)
return unless BuildListPolicy.new(user, build_list).show?
arches = Arch.where(id: arch_ids).to_a
Project.where(id: project_ids).to_a.each do |project|
next unless ability.can?(:write, project)
next unless ProjectPolicy.new(user, project).write?
build_for_platform = save_to_platform = build_list.build_for_platform
save_to_repository = save_to_platform.repositories.find{ |r| r.projects.exists?(project.id) }
@ -48,7 +47,7 @@ module BuildLists
use_extra_tests
).each { |field| bl.send("#{field}=", options[field]) }
ability.can?(:create, bl) && bl.save
BuildListPolicy.new(user, bl).create? && bl.save
end
end
end

View File

@ -1,269 +1,268 @@
# If rules goes one by one CanCan joins them by 'OR' sql operator
# If rule has multiple conditions CanCan joins them by 'AND' sql operator
# WARNING:
# - put cannot rules _after_ can rules and not before!
# - beware inner joins. Use sub queries against them!
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
@user = user
# Shared rights between guests and registered users
can [:show, :archive, :read], Project, visibility: 'open'
can :get_id, Project, visibility: 'open' # api
can(:refs_list, Project) {|project| can? :show, project}
can :read, Issue, project: { visibility: 'open' }
can [:read, :commits, :files], PullRequest, to_project: {visibility: 'open'}
can [:read, :log, :everything], BuildList, project: {visibility: 'open'}
can [:read, :log], ProductBuildList#, product: {platform: {visibility: 'open'}} # double nested hash don't work
can [:read, :search], Advisory
can :read, Statistic
# Platforms block
can [:show, :members, :advisories], Platform, visibility: 'open'
can :platforms_for_build, Platform, visibility: 'open', platform_type: 'main'
can([:read, :get_list], MassBuild) {|mass_build| can?(:show, mass_build.save_to_platform) }
can [:read, :projects_list, :projects], Repository, platform: {visibility: 'open'}
can :read, Product, platform: {visibility: 'open'}
can :show, Group
can :show, User
can :possible_forks, Project
if user.guest? # Guest rights
cannot :index, Project
# can [:new, :create], RegisterRequest
else # Registered user rights
if user.admin?
can :manage, :all
# Protection
cannot :approve, RegisterRequest, approved: true
cannot :reject, RegisterRequest, rejected: true
cannot [:destroy, :create], Subscribe
# Act admin as simple user
cannot :read, Product, platform: {platform_type: 'personal'}
cannot [:owned, :related], [BuildList, Platform]
cannot :membered, Project # list products which user members
end
if user.user?
can :edit, User, id: user.id
can [:read, :create], Group
can [:update, :manage_members, :members, :add_member, :remove_member, :remove_members, :update_member], Group do |group|
group.actors.exists?(actor_type: 'User', actor_id: user.id, role: 'admin') # or group.owner_id = user.id
end
can :write, Group do |group|
group.actors.exists?(actor_type: 'User', actor_id: user.id, role: ['writer', 'admin'])
end
can :destroy, Group, owner_id: user.id
can :remove_user, Group
can :create, Project
can([:mass_import, :run_mass_import], Project) if user.platforms.main.find{ |p| local_admin?(p) }.present?
can :read, Project, visibility: 'open'
can [:read, :archive, :membered, :get_id], Project, owner_type: 'User', owner_id: user.id
can [:read, :archive, :membered, :get_id], Project, owner_type: 'Group', owner_id: user_group_ids
# can([:read, :archive, :membered, :get_id], Project, read_relations_for('projects')) {|project| local_reader? project}
can([:read, :archive, :membered, :get_id], Project, read_relations_with_projects) {|project| local_reader? project}
can(:write, Project) {|project| local_writer? project} # for grack
can [:update, :sections, :manage_collaborators, :autocomplete_maintainers, :add_member, :remove_member, :remove_members, :update_member, :members, :schedule], Project do |project|
local_admin? project
end
can(:fork, Project) {|project| can? :read, project}
can(:alias, Project) {|project| local_admin?(project) }
can(:destroy, Project) {|project| owner? project}
can(:destroy, Project) {|project| project.owner_type == 'Group' and project.owner.actors.exists?(actor_type: 'User', actor_id: user.id, role: 'admin')}
can :remove_user, Project
can :preview, Project
can([:read, :create, :edit, :destroy, :update], Hook) {|hook| can?(:edit, hook.project)}
can [:read, :log, :owned, :everything], BuildList, user_id: user.id
can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'User', owner_id: user.id}
can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'Group', owner_id: user_group_ids}
# can([:read, :log, :everything, :list], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
# can([:read, :log, :everything, :list], BuildList, read_relations_for_build_lists_and_projects) {|build_list| can? :read, build_list.project}
can([:read, :log, :everything, :list], BuildList, read_relations_with_projects('build_lists')) {|build_list| can? :read, build_list.project}
can(:publish_into_testing, BuildList) { |build_list| ( can?(:create, build_list) || can?(:publish, build_list) ) && build_list.save_to_platform.main? }
can([:create, :rerun_tests], BuildList) {|build_list|
build_list.project &&
build_list.project.is_package &&
can?(:write, build_list.project) &&
(build_list.build_for_platform.blank? || can?(:show, build_list.build_for_platform))
}
can(:publish, BuildList) do |build_list|
if build_list.build_published?
local_admin?(build_list.save_to_platform) || build_list.save_to_repository.members.exists?(id: user.id)
else
build_list.save_to_repository.publish_without_qa ?
can?(:write, build_list.project) : local_admin?(build_list.save_to_platform)
end
end
can(:create_container, BuildList) do |build_list|
local_admin?(build_list.save_to_platform)
end
can(:reject_publish, BuildList) do |build_list|
build_list.save_to_repository.publish_without_qa ?
can?(:write, build_list.project) : local_admin?(build_list.save_to_platform)
end
can([:cancel, :create_container], BuildList) {|build_list| can?(:write, build_list.project)}
can [:read, :owned, :related, :members], Platform, owner_type: 'User', owner_id: user.id
can [:read, :related, :members], Platform, owner_type: 'Group', owner_id: user_group_ids
can([:read, :related, :members], Platform, read_relations_for('platforms')) {|platform| local_reader? platform}
can [:read, :related], Platform, id: user.repositories.pluck(:platform_id)
can([:update, :destroy, :change_visibility], Platform) {|platform| owner?(platform) }
can([:local_admin_manage, :members, :add_member, :remove_member, :remove_members, :remove_file] , Platform) {|platform| owner?(platform) || local_admin?(platform) }
can([:create, :publish], MassBuild) {|mass_build| owner?(mass_build.save_to_platform) || local_admin?(mass_build.save_to_platform)}
can(:cancel, MassBuild) {|mass_build| (owner?(mass_build.save_to_platform) || local_admin?(mass_build.save_to_platform)) && !mass_build.stop_build}
can [:read, :projects_list, :projects], Repository, platform: {owner_type: 'User', owner_id: user.id}
can [:read, :projects_list, :projects], Repository, platform: {owner_type: 'Group', owner_id: user_group_ids}
can([:read, :projects_list, :projects], Repository, read_relations_for('repositories')) {|repository| can? :show, repository.platform}
can([:read, :projects_list, :projects], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
can([:create, :edit, :update, :destroy, :projects_list, :projects, :add_project, :remove_project, :regenerate_metadata, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository) {|repository| local_admin? repository.platform}
can([:remove_member, :remove_members, :add_member, :signatures, :packages], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)}
can([:add_project, :remove_project], Repository) {|repository| repository.members.exists?(id: user.id)}
can(:clear, Platform) {|platform| owner?(platform) && platform.personal?}
can(:regenerate_metadata, Platform) {|platform| owner?(platform) || local_admin?(platform)}
can([:settings, :destroy, :edit, :update], Repository) {|repository| owner? repository.platform}
can([:create, :destroy], KeyPair) {|key_pair| key_pair.repository.blank? || owner?(key_pair.repository.platform) || local_admin?(key_pair.repository.platform)}
can([:read, :create, :withdraw], Token) {|token| local_admin?(token.subject)}
can :read, Product, platform: {owner_type: 'User', owner_id: user.id, platform_type: 'main'}
can :read, Product, platform: {owner_type: 'Group', owner_id: user_group_ids, platform_type: 'main'}
can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.main?}
can([:create, :update, :destroy, :clone], Product) {|product| local_admin? product.platform and product.platform.main?}
can([:create, :cancel], ProductBuildList) {|pbl| can?(:write, pbl.project)}
can([:create, :cancel, :update], ProductBuildList) {|pbl| can?(:update, pbl.product)}
can(:destroy, ProductBuildList) {|pbl| can?(:destroy, pbl.product)}
can :read, Issue, project: {owner_type: 'User', owner_id: user.id}
can :read, Issue, project: {owner_type: 'Group', owner_id: user_group_ids}
can(:read, Issue, read_relations_for('issues', 'projects')) {|issue| can? :read, issue.project rescue nil}
can(:create, Issue) {|issue| can? :read, issue.project}
can(:update, Issue) {|issue| issue.user_id == user.id or local_admin?(issue.project)}
cannot :manage, Issue, project: {has_issues: false} # switch off issues
can [:read, :commits, :files], PullRequest, to_project: {owner_type: 'User', owner_id: user.id}
can [:read, :commits, :files], PullRequest, to_project: {owner_type: 'Group', owner_id: user_group_ids}
can([:read, :commits, :files], PullRequest, read_relations_for('pull_requests', 'to_projects')) {|pull| can? :read, pull.to_project}
can :create, PullRequest
can(:update, PullRequest) {|pull| pull.user_id == user.id or local_writer?(pull.to_project)}
can(:merge, PullRequest) {|pull| local_writer?(pull.to_project)}
can([:create, :new_line], Comment) {|comment| can? :read, comment.project}
can([:update, :destroy], Comment) {|comment| comment.user == user or comment.project.owner == user or local_admin?(comment.project)}
cannot :manage, Comment do |c|
c.commentable_type == 'Issue' && !c.project.has_issues && !c.commentable.pull_request # when switch off issues
end
end
# Shared cannot rights for all users (registered, admin)
cannot [:regenerate_metadata, :destroy], Platform, platform_type: 'personal'
cannot [:create, :destroy], Repository, platform: {platform_type: 'personal'}, name: 'main'
cannot [:packages], Repository, platform: {platform_type: 'personal'}
cannot [:remove_member, :remove_members, :add_member, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository, platform: {platform_type: 'personal'}
cannot :clear, Platform, platform_type: 'main'
cannot :destroy, Issue
cannot [:members, :add_member, :remove_member, :remove_members], Platform, platform_type: 'personal'
cannot [:create, :update, :destroy, :clone], Product, platform: {platform_type: 'personal'}
cannot [:clone], Platform, platform_type: 'personal'
cannot [:publish, :publish_into_testing], BuildList, new_core: false
cannot :create_container, BuildList, new_core: false
cannot(:publish, BuildList) {|build_list| !build_list.can_publish? }
cannot(:publish_into_testing, BuildList) {|build_list| !build_list.can_publish_into_testing? }
cannot :publish_into_testing, BuildList, save_to_platform: {platform_type: 'personal'}
cannot(:cancel, MassBuild) {|mass_build| mass_build.stop_build}
if @user.system?
can %i(key_pair add_repo_lock_file remove_repo_lock_file), Repository
else
cannot :key_pair, Repository
end
can :create, Subscribe do |subscribe|
!subscribe.subscribeable.subscribes.exists?(user_id: user.id)
end
can :destroy, Subscribe do |subscribe|
subscribe.subscribeable.subscribes.exists?(user_id: user.id) && user.id == subscribe.user_id
end
end
end
def read_relations_for(table, parent = nil)
key = parent ? "#{parent.singularize}_id" : 'id'
parent ||= table
["#{table}.#{key} = ANY (
ARRAY (
SELECT target_id
FROM relations
WHERE relations.target_type = ? AND
(relations.actor_type = 'User' AND relations.actor_id = ? OR
relations.actor_type = 'Group' AND relations.actor_id IN (?))
)
)", parent.classify, @user, user_group_ids
]
end
def read_relations_with_projects(table = 'projects')
key = table == 'projects' ? 'id' : 'project_id'
["#{table}.#{key} = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN projects ON projects.id = relations.target_id
WHERE relations.target_type = 'Project' AND
(
projects.owner_type = 'User' AND projects.owner_id != :user OR
projects.owner_type = 'Group' AND projects.owner_id NOT IN (:groups)
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user OR
relations.actor_type = 'Group' AND relations.actor_id IN (:groups)
)
)
)", { user: @user, groups: user_group_ids }
]
end
def local_reader?(target)
%w{reader writer admin}.include? @user.best_role(target)
end
def local_writer?(target)
%w{writer admin}.include? @user.best_role(target)
end
def local_admin?(target)
@user.best_role(target) == 'admin'
end
def owner?(target)
target.owner == @user or user_own_groups.include?(target.owner)
end
def user_own_groups
@user_own_groups ||= @user.own_groups
end
def user_group_ids
@user_group_ids ||= @user.group_ids
end
end
# # If rules goes one by one CanCan joins them by 'OR' sql operator
# # If rule has multiple conditions CanCan joins them by 'AND' sql operator
# # WARNING:
# # - put cannot rules _after_ can rules and not before!
# # - beware inner joins. Use sub queries against them!
#
# class Ability
# include CanCan::Ability
#
# def initialize(user)
# user ||= User.new # guest user (not logged in)
# @user = user
#
# # Shared rights between guests and registered users
# can [:show, :archive, :read], Project, visibility: 'open'
# can :get_id, Project, visibility: 'open' # api
# can(:refs_list, Project) {|project| can? :show, project}
# can :read, Issue, project: { visibility: 'open' }
# can [:read, :commits, :files], PullRequest, to_project: {visibility: 'open'}
# can [:read, :log, :everything], BuildList, project: {visibility: 'open'}
# can [:read, :log], ProductBuildList#, product: {platform: {visibility: 'open'}} # double nested hash don't work
# can [:read, :search], Advisory
# can :read, Statistic
#
# # Platforms block
# can [:show, :members, :advisories], Platform, visibility: 'open'
# can :platforms_for_build, Platform, visibility: 'open', platform_type: 'main'
# can([:read, :get_list], MassBuild) {|mass_build| can?(:show, mass_build.save_to_platform) }
# can [:read, :projects_list, :projects], Repository, platform: {visibility: 'open'}
# can :read, Product, platform: {visibility: 'open'}
#
# can :show, Group
# can :show, User
# can :possible_forks, Project
#
# if user.guest? # Guest rights
# cannot :index, Project
# # can [:new, :create], RegisterRequest
# else # Registered user rights
# if user.admin?
# can :manage, :all
# # Protection
# cannot :approve, RegisterRequest, approved: true
# cannot :reject, RegisterRequest, rejected: true
# cannot [:destroy, :create], Subscribe
# # Act admin as simple user
# cannot :read, Product, platform: {platform_type: 'personal'}
# cannot [:owned, :related], [BuildList, Platform]
# cannot :membered, Project # list products which user members
# end
#
# if user.user?
# can :edit, User, id: user.id
# can [:read, :create], Group
# can [:update, :manage_members, :members, :add_member, :remove_member, :remove_members, :update_member], Group do |group|
# group.actors.exists?(actor_type: 'User', actor_id: user.id, role: 'admin') # or group.owner_id = user.id
# end
# can :write, Group do |group|
# group.actors.exists?(actor_type: 'User', actor_id: user.id, role: ['writer', 'admin'])
# end
# can :destroy, Group, owner_id: user.id
# can :remove_user, Group
#
# can :create, Project
# can([:mass_import, :run_mass_import], Project) if user.platforms.main.find{ |p| local_admin?(p) }.present?
# can :read, Project, visibility: 'open'
# can [:read, :archive, :membered, :get_id], Project, owner_type: 'User', owner_id: user.id
# can [:read, :archive, :membered, :get_id], Project, owner_type: 'Group', owner_id: user_group_ids
# # can([:read, :archive, :membered, :get_id], Project, read_relations_for('projects')) {|project| local_reader? project}
# can([:read, :archive, :membered, :get_id], Project, read_relations_with_projects) {|project| local_reader? project}
# can(:write, Project) {|project| local_writer? project} # for grack
# can [:update, :sections, :manage_collaborators, :autocomplete_maintainers, :add_member, :remove_member, :remove_members, :update_member, :members, :schedule], Project do |project|
# local_admin? project
# end
#
# can(:fork, Project) {|project| can? :read, project}
# can(:alias, Project) {|project| local_admin?(project) }
#
# can(:destroy, Project) {|project| owner? project}
# can(:destroy, Project) {|project| project.owner_type == 'Group' and project.owner.actors.exists?(actor_type: 'User', actor_id: user.id, role: 'admin')}
# can :remove_user, Project
# can :preview, Project
#
# can([:read, :create, :edit, :destroy, :update], Hook) {|hook| can?(:edit, hook.project)}
#
# can [:read, :log, :owned, :everything], BuildList, user_id: user.id
# can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'User', owner_id: user.id}
# can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'Group', owner_id: user_group_ids}
# # can([:read, :log, :everything, :list], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
# # can([:read, :log, :everything, :list], BuildList, read_relations_for_build_lists_and_projects) {|build_list| can? :read, build_list.project}
# can([:read, :log, :everything, :list], BuildList, read_relations_with_projects('build_lists')) {|build_list| can? :read, build_list.project}
#
# can(:publish_into_testing, BuildList) { |build_list| ( can?(:create, build_list) || can?(:publish, build_list) ) && build_list.save_to_platform.main? }
# can([:create, :rerun_tests], BuildList) {|build_list|
# build_list.project.is_package &&
# can?(:write, build_list.project) &&
# (build_list.build_for_platform.blank? || can?(:show, build_list.build_for_platform))
# }
#
# can(:publish, BuildList) do |build_list|
# if build_list.build_published?
# local_admin?(build_list.save_to_platform) || build_list.save_to_repository.members.exists?(id: user.id)
# else
# build_list.save_to_repository.publish_without_qa ?
# can?(:write, build_list.project) : local_admin?(build_list.save_to_platform)
# end
# end
# can(:create_container, BuildList) do |build_list|
# local_admin?(build_list.save_to_platform)
# end
# can(:reject_publish, BuildList) do |build_list|
# build_list.save_to_repository.publish_without_qa ?
# can?(:write, build_list.project) : local_admin?(build_list.save_to_platform)
# end
# can([:cancel, :create_container], BuildList) {|build_list| can?(:write, build_list.project)}
#
# can [:read, :owned, :related, :members], Platform, owner_type: 'User', owner_id: user.id
# can [:read, :related, :members], Platform, owner_type: 'Group', owner_id: user_group_ids
# can([:read, :related, :members], Platform, read_relations_for('platforms')) {|platform| local_reader? platform}
# can [:read, :related], Platform, id: user.repositories.pluck(:platform_id)
# can([:update, :destroy, :change_visibility], Platform) {|platform| owner?(platform) }
# can([:local_admin_manage, :members, :add_member, :remove_member, :remove_members, :remove_file] , Platform) {|platform| owner?(platform) || local_admin?(platform) }
#
# can([:create, :publish], MassBuild) {|mass_build| owner?(mass_build.save_to_platform) || local_admin?(mass_build.save_to_platform)}
# can(:cancel, MassBuild) {|mass_build| (owner?(mass_build.save_to_platform) || local_admin?(mass_build.save_to_platform)) && !mass_build.stop_build}
#
# can [:read, :projects_list, :projects], Repository, platform: {owner_type: 'User', owner_id: user.id}
# can [:read, :projects_list, :projects], Repository, platform: {owner_type: 'Group', owner_id: user_group_ids}
# can([:read, :projects_list, :projects], Repository, read_relations_for('repositories')) {|repository| can? :show, repository.platform}
# can([:read, :projects_list, :projects], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
# can([:create, :edit, :update, :destroy, :projects_list, :projects, :add_project, :remove_project, :regenerate_metadata, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository) {|repository| local_admin? repository.platform}
# can([:remove_member, :remove_members, :add_member, :signatures, :packages], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)}
# can([:add_project, :remove_project], Repository) {|repository| repository.members.exists?(id: user.id)}
# can(:clear, Platform) {|platform| owner?(platform) && platform.personal?}
# can(:regenerate_metadata, Platform) {|platform| owner?(platform) || local_admin?(platform)}
# can([:settings, :destroy, :edit, :update], Repository) {|repository| owner? repository.platform}
#
# can([:create, :destroy], KeyPair) {|key_pair| key_pair.repository.blank? || owner?(key_pair.repository.platform) || local_admin?(key_pair.repository.platform)}
#
# can([:read, :create, :withdraw], Token) {|token| local_admin?(token.subject)}
#
# can :read, Product, platform: {owner_type: 'User', owner_id: user.id, platform_type: 'main'}
# can :read, Product, platform: {owner_type: 'Group', owner_id: user_group_ids, platform_type: 'main'}
# can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.main?}
# can([:create, :update, :destroy, :clone], Product) {|product| local_admin? product.platform and product.platform.main?}
#
# can([:create, :cancel], ProductBuildList) {|pbl| can?(:write, pbl.project)}
# can([:create, :cancel, :update], ProductBuildList) {|pbl| can?(:update, pbl.product)}
# can(:destroy, ProductBuildList) {|pbl| can?(:destroy, pbl.product)}
#
# can :read, Issue, project: {owner_type: 'User', owner_id: user.id}
# can :read, Issue, project: {owner_type: 'Group', owner_id: user_group_ids}
# can(:read, Issue, read_relations_for('issues', 'projects')) {|issue| can? :read, issue.project rescue nil}
# can(:create, Issue) {|issue| can? :read, issue.project}
# can(:update, Issue) {|issue| issue.user_id == user.id or local_admin?(issue.project)}
# cannot :manage, Issue, project: {has_issues: false} # switch off issues
#
# can [:read, :commits, :files], PullRequest, to_project: {owner_type: 'User', owner_id: user.id}
# can [:read, :commits, :files], PullRequest, to_project: {owner_type: 'Group', owner_id: user_group_ids}
# can([:read, :commits, :files], PullRequest, read_relations_for('pull_requests', 'to_projects')) {|pull| can? :read, pull.to_project}
# can :create, PullRequest
# can(:update, PullRequest) {|pull| pull.user_id == user.id or local_writer?(pull.to_project)}
# can(:merge, PullRequest) {|pull| local_writer?(pull.to_project)}
#
# can([:create, :new_line], Comment) {|comment| can? :read, comment.project}
# can([:update, :destroy], Comment) {|comment| comment.user == user or comment.project.owner == user or local_admin?(comment.project)}
# cannot :manage, Comment do |c|
# c.commentable_type == 'Issue' && !c.project.has_issues && !c.commentable.pull_request # when switch off issues
# end
# end
#
# # Shared cannot rights for all users (registered, admin)
# cannot [:regenerate_metadata, :destroy], Platform, platform_type: 'personal'
# cannot [:create, :destroy], Repository, platform: {platform_type: 'personal'}, name: 'main'
# cannot [:packages], Repository, platform: {platform_type: 'personal'}
# cannot [:remove_member, :remove_members, :add_member, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository, platform: {platform_type: 'personal'}
#
# cannot :clear, Platform, platform_type: 'main'
# cannot :destroy, Issue
#
# cannot [:members, :add_member, :remove_member, :remove_members], Platform, platform_type: 'personal'
#
# cannot [:create, :update, :destroy, :clone], Product, platform: {platform_type: 'personal'}
# cannot [:clone], Platform, platform_type: 'personal'
#
# cannot [:publish, :publish_into_testing], BuildList, new_core: false
# cannot :create_container, BuildList, new_core: false
# cannot(:publish, BuildList) {|build_list| !build_list.can_publish? }
# cannot(:publish_into_testing, BuildList) {|build_list| !build_list.can_publish_into_testing? }
# cannot :publish_into_testing, BuildList, save_to_platform: {platform_type: 'personal'}
#
# cannot(:cancel, MassBuild) {|mass_build| mass_build.stop_build}
#
# if @user.system?
# can %i(key_pair add_repo_lock_file remove_repo_lock_file), Repository
# else
# cannot :key_pair, Repository
# end
#
# can :create, Subscribe do |subscribe|
# !subscribe.subscribeable.subscribes.exists?(user_id: user.id)
# end
# can :destroy, Subscribe do |subscribe|
# subscribe.subscribeable.subscribes.exists?(user_id: user.id) && user.id == subscribe.user_id
# end
# end
# end
#
# def read_relations_for(table, parent = nil)
# key = parent ? "#{parent.singularize}_id" : 'id'
# parent ||= table
#
# ["#{table}.#{key} = ANY (
# ARRAY (
# SELECT target_id
# FROM relations
# WHERE relations.target_type = ? AND
# (relations.actor_type = 'User' AND relations.actor_id = ? OR
# relations.actor_type = 'Group' AND relations.actor_id IN (?))
# )
# )", parent.classify, @user, user_group_ids
# ]
# end
#
# def read_relations_with_projects(table = 'projects')
# key = table == 'projects' ? 'id' : 'project_id'
# ["#{table}.#{key} = ANY (
# ARRAY (
# SELECT target_id
# FROM relations
# INNER JOIN projects ON projects.id = relations.target_id
# WHERE relations.target_type = 'Project' AND
# (
# projects.owner_type = 'User' AND projects.owner_id != :user OR
# projects.owner_type = 'Group' AND projects.owner_id NOT IN (:groups)
# ) AND (
# relations.actor_type = 'User' AND relations.actor_id = :user OR
# relations.actor_type = 'Group' AND relations.actor_id IN (:groups)
# )
# )
# )", { user: @user, groups: user_group_ids }
# ]
# end
#
# def local_reader?(target)
# %w{reader writer admin}.include? @user.best_role(target)
# end
#
# def local_writer?(target)
# %w{writer admin}.include? @user.best_role(target)
# end
#
# def local_admin?(target)
# @user.best_role(target) == 'admin'
# end
#
# def owner?(target)
# target.owner == @user or user_own_groups.include?(target.owner)
# end
#
# def user_own_groups
# @user_own_groups ||= @user.own_groups
# end
#
# def user_group_ids
# @user_group_ids ||= @user.group_ids
# end
# end

View File

@ -131,9 +131,8 @@ class BuildList < ActiveRecord::Base
HUMAN_STATUSES.freeze
scope :recent, -> { order(updated_at: :desc) }
scope :for_extra_build_lists, ->(ids, current_ability, save_to_platform) {
s = all
s = s.where(id: ids).published_container.accessible_by(current_ability, :read)
scope :for_extra_build_lists, ->(ids, save_to_platform) {
s = where(id: ids, container_status: BuildList::BUILD_PUBLISHED)
s = s.where(save_to_platform_id: save_to_platform.id) if save_to_platform && save_to_platform.main?
s
}
@ -725,17 +724,13 @@ class BuildList < ActiveRecord::Base
save
end
def current_ability
@current_ability ||= Ability.new(user)
end
def prepare_extra_repositories
if save_to_platform && save_to_platform.main?
self.extra_repositories = nil
else
self.extra_repositories = Repository.joins(:platform).
self.extra_repositories = PlatformPolicy::Scope.new(user, Repository.joins(:platform)).show.
where(id: extra_repositories, platforms: {platform_type: 'personal'}).
accessible_by(current_ability, :read).pluck('repositories.id')
pluck('repositories.id')
end
end
@ -745,7 +740,8 @@ class BuildList < ActiveRecord::Base
extra_build_lists.flatten!
end
return if extra_build_lists.blank?
bls = BuildList.for_extra_build_lists(extra_build_lists, current_ability, save_to_platform)
bls = BuildListPolicy::Scope.new(user, BuildList).read.
for_extra_build_lists(extra_build_lists, save_to_platform)
if save_to_platform
if save_to_platform.distrib_type == 'rhel'
bls = bls.where('

View File

@ -3,8 +3,8 @@ class BuildList::Filter
attr_reader :options
def initialize(project, user, current_ability, options = {})
@project, @user, @current_ability = project, user, current_ability
def initialize(project, user, options = {})
@project, @user = project, user
set_options(options)
end
@ -14,12 +14,19 @@ class BuildList::Filter
if @options[:id]
build_lists = build_lists.where(id: @options[:id])
else
build_lists =
case @options[:ownership]
when 'owned'
BuildListPolicy::Scope.new(@user, build_lists).owned
when 'related'
BuildListPolicy::Scope.new(@user, build_lists).related
else
BuildListPolicy::Scope.new(@user, build_lists).everything
end
build_lists = build_lists.scoped_to_new_core(@options[:new_core] == '0' ? nil : true) if @options[:new_core].present?
if @options[:mass_build_id]
build_lists = build_lists.by_mass_build(@options[:mass_build_id] == '-1' ? nil : @options[:mass_build_id])
end
build_lists = build_lists.accessible_by(@current_ability, @options[:ownership].to_sym) if @options[:ownership]
build_lists = build_lists.for_status(@options[:status])
.scoped_to_arch(@options[:arch_id])
.scoped_to_save_platform(@options[:save_to_platform_id])

View File

@ -38,6 +38,7 @@ class Collaborator
end
def initialize(args = {})
return false if args.blank?
args.to_options!
acc_options = args.select{ |(k, v)| k.in? [:actor, :project, :relation] }
acc_options.each_pair do |name, value|

View File

@ -134,7 +134,6 @@ class Comment < ActiveRecord::Base
def self.create_link_on_issues_from_item item, commits = nil
linker = item.user
current_ability = Ability.new(linker)
case
when item.is_a?(GitHook)
@ -155,7 +154,7 @@ class Comment < ActiveRecord::Base
elements.each do |element|
element[1].scan(ISSUES_REGEX).each do |hash|
issue = Issue.find_by_hash_tag hash, current_ability, item.project
issue = Issue.find_by_hash_tag hash, linker, item.project
next unless issue
# dont create link to the same issue
next if opts[:created_from_issue_id] == issue.id

View File

@ -5,7 +5,7 @@ module Feed::Issue
after_commit :new_issue_notifications, on: :create
after_commit :send_assign_notifications, on: :create, if: ->(i) { i.assignee }
after_update -> { send_assign_notifications(:update) }
after_update :send_assign_notifications
after_commit :send_hooks, on: :create
after_update -> { send_hooks(:update) }, if: ->(i) { i.previous_changes['status'].present? }
@ -37,8 +37,10 @@ module Feed::Issue
::Comment.create_link_on_issues_from_item(self)
end
def send_assign_notifications(action = :create)
if(action == :create && assignee_id) || previous_changes['assignee_id'].present?
def send_assign_notifications
return if @skip_assign_notifications
@skip_assign_notifications = true
if assignee_id && assignee_id_changed?
if assignee.notifier.issue_assign && assignee.notifier.can_notify
UserMailer.issue_assign_notification(self, assignee).deliver
end
@ -57,7 +59,7 @@ module Feed::Issue
)
end
# dont remove outdated issues link
::Comment.create_link_on_issues_from_item(self) if previous_changes['title'].present? || previous_changes['body'].present?
::Comment.create_link_on_issues_from_item(self) if title_changed? || body_changed?
end
def send_hooks(action = :create)

View File

@ -0,0 +1,33 @@
# Private: Finders of all sorts: methods to find FlashNotify records, methods to find
# other records which belong to given FlashNotify.
#
# This module gets included into FlashNotify.
module FlashNotify::Finders
extend ActiveSupport::Concern
included do
scope :published, -> { where(published: true) }
after_commit :clear_caches
after_touch :clear_caches
end
module ClassMethods
# Public: Get cached first published FlashNotify record.
#
# Returns FlashNotify record or nil.
def published_first_cached
Rails.cache.fetch('FlashNotify.published.first') do
published.first
end
end
end
protected
# Private: after_commit and after_touch hook which clears find_cached cache.
def clear_caches
Rails.cache.delete('FlashNotify.published.first')
end
end

View File

@ -0,0 +1,50 @@
# Private: Finders of all sorts: methods to find Platform records, methods to find
# other records which belong to given Platform.
#
# This module gets included into Platform.
module Platform::Finders
extend ActiveSupport::Concern
included do
scope :search_order, -> { order(:name) }
scope :search, -> (q) { where("#{table_name}.name ILIKE ?", "%#{q.to_s.strip}%") }
scope :by_visibilities, -> (v) { where(visibility: v) }
scope :opened, -> { where(visibility: Platform::VISIBILITY_OPEN) }
scope :hidden, -> { where(visibility: Platform::VISIBILITY_HIDDEN) }
scope :by_type, -> (type) { where(platform_type: type) if type.present? }
scope :main, -> { by_type(Platform::TYPE_MAIN) }
scope :personal, -> { by_type(Platform::TYPE_PERSONAL) }
scope :waiting_for_regeneration, -> { where(status: Platform::WAITING_FOR_REGENERATION) }
after_commit :clear_caches
after_touch :clear_caches
end
module ClassMethods
# Public: Get cached Platform record by ID or name.
#
# platform_id - ID or Name (Numeric/String)
#
# Returns Platform record.
# Raises ActiveRecord::RecordNotFound if nothing was found.
def find_cached(platform_id)
Rails.cache.fetch(['Platform.find', platform_id]) do
find(platform_id)
end
end
end
protected
# Private: after_commit and after_touch hook which clears find_cached cache.
def clear_caches
Rails.cache.delete(['Platform.find', id])
Rails.cache.delete(['Platform.find', name])
if chg = previous_changes["name"]
Rails.cache.delete(['Platform.find', chg.first])
end
end
end

View File

@ -0,0 +1,71 @@
# Private: Finders of all sorts: methods to find Project records, methods to find
# other records which belong to given Project.
#
# This module gets included into Project.
module Project::Finders
extend ActiveSupport::Concern
included do
scope :recent, -> { order(:name) }
scope :search_order, -> { order('CHAR_LENGTH(projects.name) ASC') }
scope :search, ->(q) {
q = q.to_s.strip
by_name("%#{q}%").search_order if q.present?
}
scope :by_name, ->(name) { where('projects.name ILIKE ?', name) if name.present? }
scope :by_owner, ->(name) { where('projects.owner_uname ILIKE ?', "%#{name}%") if name.present? }
scope :by_owner_and_name, ->(*params) {
term = params.map(&:strip).join('/').downcase
where("lower(concat(owner_uname, '/', name)) ILIKE ?", "%#{term}%") if term.present?
}
scope :by_visibilities, ->(v) { where(visibility: v) }
scope :opened, -> { where(visibility: 'open') }
scope :package, -> { where(is_package: true) }
scope :addable_to_repository, ->(repository_id) {
where('projects.id NOT IN (
SELECT ptr.project_id
FROM project_to_repositories AS ptr
WHERE ptr.repository_id = ?)', repository_id)
}
scope :by_owners, ->(group_owner_ids, user_owner_ids) {
where("(projects.owner_id in (?) AND projects.owner_type = 'Group') OR
(projects.owner_id in (?) AND projects.owner_type = 'User')", group_owner_ids, user_owner_ids)
}
scope :project_aliases, ->(project) {
where.not(id: project.id).
where('alias_from_id IN (:ids) OR id IN (:ids)', { ids: [project.alias_from_id, project.id].compact })
}
after_commit :clear_caches
after_touch :clear_caches
end
module ClassMethods
# Public: Get cached Project record by owner and name.
#
# Returns Project record.
# Raises ActiveRecord::RecordNotFound if nothing was found.
def find_by_owner_and_name(first, last = nil)
arr = first.try(:split, '/') || []
arr = (arr << last).compact
return nil if arr.length != 2
Rails.cache.fetch(['Project.find_by_owner_and_name', arr.first, arr.last]) do
find_by(owner_uname: arr.first, name: arr.last)
end || by_owner_and_name(*arr).first
end
def find_by_owner_and_name!(first, last = nil)
find_by_owner_and_name(first, last) or raise ActiveRecord::RecordNotFound
end
end
protected
# Private: after_commit and after_touch hook which clears find_cached cache.
def clear_caches
Rails.cache.delete(['Project.find_by_owner_and_name', owner_uname, name])
end
end

View File

@ -1,15 +1,13 @@
require 'digest/md5'
class FlashNotify < ActiveRecord::Base
# attr_accessible :title, :body
include FlashNotify::Finders
STATUSES = %w[error success info]
validates :status, inclusion: {in: STATUSES}
validates :body_ru, :body_en, :status, presence: true
scope :published, -> { where(published: true) }
attr_accessible :body_ru, :body_en, :status, :published
def hash_id

View File

@ -104,14 +104,14 @@ class Issue < ActiveRecord::Base
recipients
end
def self.find_by_hash_tag(hash_tag, current_ability, project)
def self.find_by_hash_tag(hash_tag, current_user, project)
hash_tag =~ HASH_TAG_REGEXP
owner_uname = Regexp.last_match[1].presence || Regexp.last_match[2].presence || project.owner.uname
project_name = Regexp.last_match[1] ? Regexp.last_match[2] : project.name
serial_id = Regexp.last_match[3]
project = Project.find_by_owner_and_name(owner_uname.chomp('/'), project_name)
return nil unless project
return nil unless current_ability.can? :show, project
return nil unless ProjectPolicy.new(current_user, project).show?
project.issues.where(serial_id: serial_id).first
end

View File

@ -90,8 +90,6 @@ class MassBuild < ActiveRecord::Base
return unless start
# later with resque
arches_list = arch_names ? Arch.where(name: arch_names.split(', ')) : Arch.all
current_ability = Ability.new(user)
projects_list.lines.each do |name|
next if name.blank?
name.chomp!; name.strip!
@ -100,7 +98,7 @@ class MassBuild < ActiveRecord::Base
begin
return if self.reload.stop_build
# Ensures that user has rights to create a build_list
next unless current_ability.can?(:write, project)
next unless ProjectPolicy.new(user, project).write?
increase_rt = increase_release_tag?
arches_list.each do |arch|
rep_id = (project.repository_ids & save_to_platform.repository_ids).first

View File

@ -8,6 +8,7 @@ class Platform < ActiveRecord::Base
include EventLoggable
include EmptyMetadata
include DefaultBranchable
include Platform::Finders
self.per_page = 20
@ -96,16 +97,6 @@ class Platform < ActiveRecord::Base
after_create -> { symlink_directory unless hidden? }
after_destroy -> { remove_symlink_directory unless hidden? }
scope :search_order, -> { order(:name) }
scope :search, -> (q) { where("#{table_name}.name ILIKE ?", "%#{q.to_s.strip}%") }
scope :by_visibilities, -> (v) { where(visibility: v) }
scope :opened, -> { where(visibility: VISIBILITY_OPEN) }
scope :hidden, -> { where(visibility: VISIBILITY_HIDDEN) }
scope :by_type, -> (type) { where(platform_type: type) if type.present? }
scope :main, -> { by_type(TYPE_MAIN) }
scope :personal, -> { by_type(TYPE_PERSONAL) }
scope :waiting_for_regeneration, -> { where(status: WAITING_FOR_REGENERATION) }
accepts_nested_attributes_for :platform_arch_settings, allow_destroy: true
attr_accessible :name,
:distrib_type,
@ -281,8 +272,7 @@ class Platform < ActiveRecord::Base
return false if token.blank?
return true if platform.tokens.by_active.where(authentication_token: token).exists?
user = User.find_by(authentication_token: token)
current_ability = Ability.new(user)
user && current_ability.can?(:show, platform) ? true : false
!!(user && PlatformPolicy.new(user, platform).show?)
end
end
@ -302,10 +292,9 @@ class Platform < ActiveRecord::Base
Platform.main.where(automatic_metadata_regeneration: value).each(&:regenerate)
end
def self.availables_main_platforms(user, ability = nil)
def self.availables_main_platforms(user)
p_ids = Rails.cache.fetch([:availables_main_platforms, user], expires_in: 10.minutes) do
ability ||= Ability.new user
Platform.main.accessible_by(ability, :show).joins(:repositories).
PlatformPolicy::Scope.new(user, Platform).show.main.joins(:repositories).
where('repositories.id IS NOT NULL').uniq.pluck(:id)
end
Platform.preload(:repositories).where(id: p_ids).order(:name)

View File

@ -8,6 +8,7 @@ class Project < ActiveRecord::Base
include UrlHelper
include EventLoggable
include Project::DefaultBranch
include Project::Finders
VISIBILITIES = ['open', 'hidden']
MAX_OWN_PROJECTS = 32000
@ -67,37 +68,6 @@ class Project < ActiveRecord::Base
:autostart_status
attr_readonly :owner_id, :owner_type
scope :recent, -> { order(:name) }
scope :search_order, -> { order('CHAR_LENGTH(projects.name) ASC') }
scope :search, ->(q) {
q = q.to_s.strip
by_name("%#{q}%").search_order if q.present?
}
scope :by_name, ->(name) { where('projects.name ILIKE ?', name) if name.present? }
scope :by_owner, ->(name) { where('projects.owner_uname ILIKE ?', "%#{name}%") if name.present? }
scope :by_owner_and_name, ->(*params) {
term = params.map(&:strip).join('/').downcase
where("lower(concat(owner_uname, '/', name)) ILIKE ?", "%#{term}%") if term.present?
}
scope :by_visibilities, ->(v) { where(visibility: v) }
scope :opened, -> { where(visibility: 'open') }
scope :package, -> { where(is_package: true) }
scope :addable_to_repository, ->(repository_id) {
where('projects.id NOT IN (
SELECT ptr.project_id
FROM project_to_repositories AS ptr
WHERE ptr.repository_id = ?)', repository_id)
}
scope :by_owners, ->(group_owner_ids, user_owner_ids) {
where("(projects.owner_id in (?) AND projects.owner_type = 'Group') OR
(projects.owner_id in (?) AND projects.owner_type = 'User')", group_owner_ids, user_owner_ids)
}
scope :project_aliases, ->(project) {
where.not(id: project.id).
where('alias_from_id IN (:ids) OR id IN (:ids)', { ids: [project.alias_from_id, project.id].compact })
}
before_validation :truncate_name, on: :create
before_save -> { self.owner_uname = owner.uname if owner_uname.blank? || owner_id_changed? || owner_type_changed? }
before_create :set_maintainer
@ -106,19 +76,6 @@ class Project < ActiveRecord::Base
attr_accessor :url, :srpms_list, :mass_import, :add_to_repository_id
class << self
def find_by_owner_and_name(first, last = nil)
arr = first.try(:split, '/') || []
arr = (arr << last).compact
return nil if arr.length != 2
where(owner_uname: arr.first, name: arr.last).first || by_owner_and_name(*arr).first
end
def find_by_owner_and_name!(first, last = nil)
find_by_owner_and_name(first, last) or raise ActiveRecord::RecordNotFound
end
end
def init_mass_import
Project.perform_later :low, :run_mass_import, url, srpms_list, visibility, owner, add_to_repository_id
end

View File

@ -75,14 +75,13 @@ class Repository < ActiveRecord::Base
later :clone_relations, loner: true, queue: :low
def add_projects(list, user)
current_ability = Ability.new(user)
list.lines.each do |line|
begin
line.chomp!; line.strip!
owner, name = line.split('/')
next if owner.blank? || name.blank?
project = Project.where(owner_uname: owner, name: name).accessible_by(current_ability, :read).first
project = ProjectPolicy::Scope.new(user, Project).read.where(owner_uname: owner, name: name).first
projects << project if project
rescue RuntimeError, Exception
end

View File

@ -1,4 +1,4 @@
class Search < Struct.new(:query, :ability, :paginate_params)
class Search < Struct.new(:query, :user, :paginate_params)
include ActiveModel::Conversion
extend ActiveModel::Naming
@ -18,7 +18,8 @@ class Search < Struct.new(:query, :ability, :paginate_params)
if type == 'users'
User.opened
else
type.classify.constantize.accessible_by(ability, :show)
klass = type.classify.constantize
"#{klass}Policy::Scope".constantize.new(user, klass).show
end
scope.search(query).
search_order.

View File

@ -4,6 +4,7 @@ class Subscribe < ActiveRecord::Base
belongs_to :project
attr_accessible :status, :user_id
validates :user, presence: true
def commit_subscribe?
subscribeable_type == 'Grit::Commit'

View File

@ -161,8 +161,7 @@ class User < Avatar
if target.is_a? Project
assigned_issues.where(project_id: target.id).update_all(assignee_id: nil)
else
ability = Ability.new self
project_ids = Project.accessible_by(ability, :membered).uniq.pluck(:id)
project_ids = ProjectPolicy::Scope.new(self, Project).membered.uniq.pluck(:id)
issues = assigned_issues
issues = issues.where('project_id not in (?)', project_ids) if project_ids.present?
@ -181,8 +180,13 @@ class User < Avatar
gr = gr.where('groups.id != ?', target.owner.id) # exclude target owner group from users group list
end
if target.class == Group
roles += target.actors.where(actor_id: self.id, actor_type: 'User') # user is member of a target group
else
roles += rel.where(actor_id: gr.pluck('DISTINCT groups.id'), actor_type: 'Group') # user group is member
end
roles += rel.where(actor_id: self.id, actor_type: 'User') # user is member
roles += rel.where(actor_id: gr.pluck('DISTINCT groups.id'), actor_type: 'Group') # user group is member
roles.map(&:role).uniq
end

View File

@ -0,0 +1,14 @@
class AdvisoryPolicy < ApplicationPolicy
def index?
true
end
alias_method :search?, :index?
alias_method :show?, :index?
def create?
!user.guest?
end
alias_method :update?, :create?
end

View File

@ -0,0 +1,178 @@
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
# raise Pundit::NotAuthorizedError, 'must be logged in' unless user
@user = user || User.new
@record = record
end
BASIC_ACTIONS = %i(index? show? create? update? destroy? destroy_all?)
def index?
false
end
def show?
false
end
def new?
create?
end
def edit?
update?
end
def update?
false
end
def create?
false
end
def destroy?
false
end
def permitted_attributes
[]
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
# Public: Get user's group ids.
#
# Returns the Array of group ids.
def user_group_ids
Rails.cache.fetch(['ApplicationPolicy#user_group_ids', user]) do
user.group_ids
end
end
protected
# Public: Check if provided user is the current user.
#
# Returns true if it is, false otherwise.
def current_user?(u)
u == user
end
# Public: Check if provided user is guest.
#
# Returns true if he is, false otherwise.
def is_guest?
user.new_record?
end
# Public: Check if provided user is user.
#
# Returns true if he is, false otherwise.
def is_user?
user.persisted?
end
# Public: Check if provided user is tester.
#
# Returns true if he is, false otherwise.
def is_tester?
user.role == 'tester'
end
# Public: Check if provided user is system.
#
# Returns true if he is, false otherwise.
def is_system?
user.role == 'system'
end
# Public: Check if provided user is admin.
#
# Returns true if he is, false otherwise.
def is_admin?
user.role == 'admin'
end
# Public: Check if provided user is banned.
#
# Returns true if he is, false otherwise.
def is_banned?
user.role == 'banned'
end
# Private: Check if provided user is at least record admin.
#
# Returns true if he is, false otherwise.
def local_admin?(r = record)
owner?(r) || best_role(r) == 'admin'
end
# Private: Check if provided user is at least record reader.
#
# Returns true if he is, false otherwise.
def local_reader?(r = record)
owner?(r) || %w(reader writer admin).include?(best_role(r))
end
# Private: Check if provided user is at least record writer.
#
# Returns true if he is, false otherwise.
def local_writer?(r = record)
owner?(r) || %w(writer admin).include?(best_role(r))
end
# Private: Check if provided user is record owner.
#
# Returns true if he is, false otherwise.
def owner?(r = record)
(
!r.try(:owner_type) && r.owner_id == user.id
) || (
r.try(:owner_type) == 'User' && r.owner_id == user.id
) || (
r.try(:owner_type) == 'Group' && user_own_group_ids.include?(r.owner_id)
)
end
# Private: Get the best role of user for record.
#
# Returns the String role or nil.
def best_role(r = record)
Rails.cache.fetch(['ApplicationPolicy#best_role', r, user]) do
user.best_role(r)
end
end
# Public: Get own user's group ids.
#
# Returns the Array of own group ids.
def user_own_group_ids
Rails.cache.fetch(['ApplicationPolicy#user_own_group_ids', user]) do
user.own_group_ids
end
end
# Public: Get user's platform ids.
#
# Returns the Array of platform ids.
def user_platform_ids
Rails.cache.fetch(['ApplicationPolicy#user_platform_ids', user]) do
user.repositories.pluck(:platform_id)
end
end
end

View File

@ -0,0 +1,6 @@
class ArchPolicy < ApplicationPolicy
def index?
true
end
end

View File

@ -0,0 +1,129 @@
class BuildListPolicy < ApplicationPolicy
def index?
true
end
def show?
record.user_id == user.id || ProjectPolicy.new(user, record.project).show?
end
alias_method :read?, :show?
alias_method :log?, :show?
alias_method :everything?, :show?
alias_method :owned?, :show?
alias_method :everything?, :show?
alias_method :list?, :show?
def create?
return false unless record.project.is_package
return false unless ProjectPolicy.new(user, record.project).write?
record.build_for_platform.blank? || PlatformPolicy.new(user, record.build_for_platform).show?
end
alias_method :rerun_tests?, :create?
def dependent_projects?
record.save_to_platform.main? && create?
end
def publish_into_testing?
return false unless record.new_core?
return false unless record.can_publish_into_testing?
create? || ( record.save_to_platform.main? && publish? )
end
def publish?
return false unless record.new_core?
return false unless record.can_publish?
if record.build_published?
local_admin?(record.save_to_platform) || record.save_to_repository.members.exists?(id: user.id)
else
record.save_to_repository.publish_without_qa ?
ProjectPolicy.new(user, record.project).write? : local_admin?(record.save_to_platform)
end
end
def create_container?
return false unless record.new_core?
ProjectPolicy.new(user, record.project).write? || local_admin?(record.save_to_platform)
end
def reject_publish?
record.save_to_repository.publish_without_qa ?
ProjectPolicy.new(user, record.project).write? : local_admin?(record.save_to_platform)
end
def cancel?
ProjectPolicy.new(user, record.project).write?
end
class Scope < Scope
def read
scope.joins(:project).where <<-SQL, { user_id: policy.user.id, user_group_ids: policy.user_group_ids }
(
build_lists.user_id = :user_id
) OR (
projects.visibility = 'open'
) OR (
projects.owner_type = 'User' AND projects.owner_id = :user_id
) OR (
projects.owner_type = 'Group' AND projects.owner_id IN (:user_group_ids)
) OR (
projects.id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN projects ON projects.id = relations.target_id
WHERE relations.target_type = 'Project' AND
(
projects.owner_type = 'User' AND projects.owner_id != :user_id OR
projects.owner_type = 'Group' AND projects.owner_id NOT IN (:user_group_ids)
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user_id OR
relations.actor_type = 'Group' AND relations.actor_id IN (:user_group_ids)
)
)
)
)
SQL
end
alias_method :everything, :read
def related
scope.joins(:project).where <<-SQL, { user_id: policy.user.id, user_group_ids: policy.user_group_ids }
(
build_lists.user_id = :user_id
) OR (
projects.owner_type = 'User' AND projects.owner_id = :user_id
) OR (
projects.owner_type = 'Group' AND projects.owner_id IN (:user_group_ids)
) OR (
projects.id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN projects ON projects.id = relations.target_id
WHERE relations.target_type = 'Project' AND
(
projects.owner_type = 'User' AND projects.owner_id != :user_id OR
projects.owner_type = 'Group' AND projects.owner_id NOT IN (:user_group_ids)
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user_id OR
relations.actor_type = 'Group' AND relations.actor_id IN (:user_group_ids)
)
)
)
)
SQL
end
def owned
scope.joins(:project).where(user_id: policy.user)
end
def policy
@policy ||= Pundit.policy!(user, :build_list)
end
end
end

View File

@ -0,0 +1,13 @@
class CommentPolicy < ApplicationPolicy
def create?
!user.guest? && ProjectPolicy.new(user, record.project).show?
end
alias_method :new_line?, :create?
def update?
is_admin? || record.user_id == user.id || local_admin?(record.project)
end
alias_method :destroy?, :update?
end

View File

@ -0,0 +1,41 @@
class GroupPolicy < ApplicationPolicy
def index?
!user.guest?
end
alias_method :create?, :index?
alias_method :remove_user?, :index?
def show?
true
end
def reader?
!user.guest? && ( is_admin? || local_reader? )
end
def write?
!user.guest? && ( is_admin? || owner? || local_writer? )
end
def update?
!user.guest? && ( is_admin? || owner? || local_admin? )
end
alias_method :add_member?, :update?
alias_method :manage_members?, :update?
alias_method :members?, :update?
alias_method :remove_member?, :update?
alias_method :remove_members?, :update?
alias_method :update_member?, :update?
def destroy?
!user.guest? && ( is_admin? || owner? )
end
class Scope < Scope
def show
scope
end
end
end

View File

@ -0,0 +1,11 @@
class HookPolicy < ApplicationPolicy
def show?
ProjectPolicy.new(user, record.project).update?
end
alias_method :read?, :show?
alias_method :create?, :show?
alias_method :destroy?, :show?
alias_method :update?, :show?
end

View File

@ -0,0 +1,20 @@
class IssuePolicy < ApplicationPolicy
def index?
# record.project.has_issues?
true
end
def show?
return false unless record.project.has_issues?
ProjectPolicy.new(user, record.project).show?
end
alias_method :create?, :show?
alias_method :read?, :show?
def update?
return false if user.guest?
is_admin? || record.user_id == user.id || local_admin?(record.project)
end
end

View File

@ -0,0 +1,9 @@
class KeyPairPolicy < ApplicationPolicy
def create?
return false unless record.repository
is_admin? || local_admin?(record.repository.platform)
end
alias_method :destroy?, :create?
end

View File

@ -0,0 +1,18 @@
class MassBuildPolicy < ApplicationPolicy
def show?
is_admin? || PlatformPolicy.new(user, record.save_to_platform).show?
end
alias_method :read?, :show?
alias_method :get_list?, :show?
def create?
is_admin? || owner?(record.save_to_platform) || local_admin?(record.save_to_platform)
end
alias_method :publish?, :create?
def cancel?
!record.stop_build && create?
end
end

View File

@ -0,0 +1,134 @@
class PlatformPolicy < ApplicationPolicy
def index?
!user.guest?
end
def allowed?
true
end
alias_method :platforms_for_build?, :allowed?
def show?
return true if is_admin?
return true unless record.hidden?
return true if record.owner == user
owner? || local_reader? || user_platform_ids.include?(record.id)
end
alias_method :advisories?, :show?
alias_method :owned?, :show?
alias_method :read?, :show?
alias_method :related?, :show?
def members?
return true if is_admin?
return true unless record.hidden?
return true if record.owner == user
owner? || local_reader?
end
def create?
is_admin?
end
def update?
is_admin? || owner?
end
alias_method :change_visibility?, :update?
def destroy?
record.main? && ( is_admin? || owner? )
end
def local_admin_manage?
is_admin? || owner? || local_admin?
end
alias_method :add_project?, :local_admin_manage?
alias_method :remove_file?, :local_admin_manage?
def clone?
record.main? && is_admin?
end
alias_method :make_clone?, :clone?
def add_member?
record.main? && ( is_admin? || owner? || local_admin? )
end
alias_method :regenerate_metadata?, :add_member?
alias_method :remove_member?, :add_member?
alias_method :remove_members?, :add_member?
def clear?
record.personal? && ( is_admin? || owner? )
end
class Scope < Scope
def related
scope.where <<-SQL, { user_id: policy.user.id, user_group_ids: policy.user_group_ids, platform_ids: related_platform_ids }
(
platforms.id IN (:platform_ids)
) OR (
platforms.owner_type = 'User' AND platforms.owner_id = :user_id
) OR (
platforms.owner_type = 'Group' AND platforms.owner_id IN (:user_group_ids)
) OR (
platforms.id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN platforms ON platforms.id = relations.target_id
WHERE relations.target_type = 'Platform' AND
(
platforms.owner_type = 'User' AND platforms.owner_id != :user_id
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user_id
)
)
)
)
SQL
end
def show
scope.where <<-SQL, { user_id: policy.user.id, user_group_ids: policy.user_group_ids, platform_ids: related_platform_ids, visibility: Platform::VISIBILITY_OPEN }
(
platforms.visibility = :visibility
) OR (
platforms.id IN (:platform_ids)
) OR (
platforms.owner_type = 'User' AND platforms.owner_id = :user_id
) OR (
platforms.owner_type = 'Group' AND platforms.owner_id IN (:user_group_ids)
) OR (
platforms.id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN platforms ON platforms.id = relations.target_id
WHERE relations.target_type = 'Platform' AND
(
platforms.owner_type = 'User' AND platforms.owner_id != :user_id
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user_id
)
)
)
)
SQL
end
protected
def policy
@policy ||= Pundit.policy!(user, :platform)
end
def related_platform_ids
Rails.cache.fetch(['PlatformPolicy::Scope#related_platform_ids', policy.user]) do
policy.user.repositories.pluck(:platform_id)
end
end
end
end

View File

@ -0,0 +1,27 @@
class ProductBuildListPolicy < ApplicationPolicy
def index?
true
end
def show?
is_admin? || ProductPolicy.new(user, record.product).show?
end
alias_method :log?, :show?
alias_method :read?, :show?
def create?
return false unless record.project && record.product
is_admin? || ProjectPolicy.new(user, record.project).write? || ProductPolicy.new(user, record.product).update?
end
alias_method :cancel?, :create?
def update?
is_admin? || ProductPolicy.new(user, record.product).update?
end
def destroy?
is_admin? || ProductPolicy.new(user, record.product).destroy?
end
end

View File

@ -0,0 +1,20 @@
class ProductPolicy < ApplicationPolicy
def index?
record.platform.main?
end
def show?
is_admin? || PlatformPolicy.new(user, record.platform).show?
end
alias_method :read?, :show?
def create?
return false unless record.platform
is_admin? || record.platform.main? && ( owner?(record.platform) || local_admin?(record.platform) )
end
alias_method :clone?, :create?
alias_method :destroy?, :create?
alias_method :update?, :create?
end

View File

@ -0,0 +1,148 @@
class ProjectPolicy < ApplicationPolicy
def index?
!user.guest?
end
alias_method :autocomplete_project?, :index?
alias_method :remove_user?, :index?
alias_method :preview?, :index?
def show?
return true if is_admin?
return true if record.public?
return true if record.owner == user
return true if record.owner.is_a?(Group) && user_group_ids.include?(record.owner_id)
local_reader?
end
alias_method :read?, :show?
alias_method :archive?, :show?
alias_method :get_id?, :show?
alias_method :refs_list?, :show?
def fork?
!user.guest? && show?
end
def create?
return false if user.guest?
return true if is_admin?
record.is_a?(Symbol) || owner_policy.write?
end
def update?
return false if user.guest?
is_admin? || owner? || local_admin?
end
alias_method :add_member?, :update?
alias_method :alias?, :update?
alias_method :autocomplete_maintainers?, :update?
alias_method :manage_collaborators?, :update?
alias_method :members?, :update?
alias_method :remove_member?, :update?
alias_method :remove_members?, :update?
alias_method :schedule?, :update?
alias_method :sections?, :update?
alias_method :update_member?, :update?
def destroy?
return false if user.guest?
is_admin? || owner? || record.owner.is_a?(Group) && record.owner.actors.exists?(actor_type: 'User', actor_id: user.id, role: 'admin')
end
def mass_import?
return false if user.guest?
is_admin? || user.platforms.main.find{ |p| local_admin?(p) }.present?
end
def run_mass_import?
return true if is_admin?
return false unless owner_policy.write?
repo = Repository.find(record.add_to_repository_id)
repo.platform.main? && PlatformPolicy.new(user, repo.platform).add_project?
end
# for grack
def write?
return false if user.guest?
is_admin? || owner? || local_writer?
end
def possible_forks
true
end
class Scope < Scope
def membered
scope.where <<-SQL, { user_id: policy.user.id, user_group_ids: policy.user_group_ids }
(
projects.owner_type = 'User' AND projects.owner_id = :user_id
) OR (
projects.owner_type = 'Group' AND projects.owner_id IN (:user_group_ids)
) OR (
projects.id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN projects ON projects.id = relations.target_id
WHERE relations.target_type = 'Project' AND
(
projects.owner_type = 'User' AND projects.owner_id != :user_id OR
projects.owner_type = 'Group' AND projects.owner_id NOT IN (:user_group_ids)
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user_id OR
relations.actor_type = 'Group' AND relations.actor_id IN (:user_group_ids)
)
)
)
)
SQL
end
def read
scope.where <<-SQL, { user_id: policy.user.id, user_group_ids: policy.user_group_ids }
(
projects.visibility = 'open'
) OR (
projects.owner_type = 'User' AND projects.owner_id = :user_id
) OR (
projects.owner_type = 'Group' AND projects.owner_id IN (:user_group_ids)
) OR (
projects.id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN projects ON projects.id = relations.target_id
WHERE relations.target_type = 'Project' AND
(
projects.owner_type = 'User' AND projects.owner_id != :user_id OR
projects.owner_type = 'Group' AND projects.owner_id NOT IN (:user_group_ids)
) AND (
relations.actor_type = 'User' AND relations.actor_id = :user_id OR
relations.actor_type = 'Group' AND relations.actor_id IN (:user_group_ids)
)
)
)
)
SQL
end
alias_method :show, :read
protected
def policy
@policy ||= Pundit.policy!(user, :project)
end
end
private
def owner_policy
if record.owner.is_a?(User)
UserPolicy.new(user, record.owner)
else
GroupPolicy.new(user, record.owner)
end
end
end

View File

@ -0,0 +1,25 @@
class PullRequestPolicy < ApplicationPolicy
def index?
true
end
def show?
is_admin? || ProjectPolicy.new(user, record.to_project).show?
end
alias_method :read?, :show?
alias_method :commits?, :show?
alias_method :files?, :show?
alias_method :create?, :show?
def update?
return false if user.guest?
is_admin? || record.user_id == user.id || local_writer?(record.to_project)
end
def merge?
return false if user.guest?
is_admin? || local_writer?(record.to_project)
end
end

View File

@ -0,0 +1,68 @@
class RepositoryPolicy < ApplicationPolicy
def show?
is_admin? || PlatformPolicy.new(user, record.platform).show?
end
alias_method :projects?, :show?
alias_method :projects_list?, :show?
alias_method :read?, :show?
def reader?
is_admin? || local_reader?(record.platform)
end
def write?
is_admin? || local_writer?(record.platform)
end
def update?
is_admin? || local_admin?(record.platform)
end
alias_method :manage_members?, :update?
alias_method :regenerate_metadata?, :update?
alias_method :signatures?, :update?
def create?
return false if record.platform.personal? && record.name == 'main'
is_admin? || owner?(record.platform) || local_admin?(record.platform)
end
alias_method :destroy?, :create?
def packages?
record.platform.main? && ( is_admin? || local_admin?(record.platform) )
end
alias_method :remove_member?, :packages?
alias_method :remove_members?, :packages?
alias_method :add_member?, :packages?
alias_method :sync_lock_file?, :packages?
def add_project?
is_admin? || local_admin?(record.platform) || repository_user_ids.include?(user.id)
end
alias_method :remove_project?, :add_project?
def settings?
is_admin? || owner?(record.platform) || local_admin?(record.platform)
end
def key_pair?
user.system?
end
def add_repo_lock_file?
is_admin? || user.system? || ( record.platform.main? && local_admin?(record.platform) )
end
alias_method :remove_repo_lock_file?, :add_repo_lock_file?
private
# Public: Get user ids of repository.
#
# Returns the Set of user ids.
def repository_user_ids
Rails.cache.fetch(['RepositoryPolicy#repository_user_ids', record]) do
Set.new record.member_ids
end
end
end

View File

@ -0,0 +1,7 @@
class SearchPolicy < ApplicationPolicy
def index?
APP_CONFIG['anonymous_access'] || !user.guest?
end
end

Some files were not shown because too many files have changed in this diff Show More