#465: added pundit gem, wip...
This commit is contained in:
parent
f5a68ed4ae
commit
4fec2213c8
3
Gemfile
3
Gemfile
|
@ -14,8 +14,7 @@ gem 'omniauth-facebook'
|
||||||
gem 'omniauth-google-oauth2'
|
gem 'omniauth-google-oauth2'
|
||||||
gem 'omniauth-github'
|
gem 'omniauth-github'
|
||||||
# gem 'omniauth-openid', '~> 1.0.1'
|
# gem 'omniauth-openid', '~> 1.0.1'
|
||||||
# gem 'cancan', '1.6.10'
|
gem 'pundit'
|
||||||
gem 'cancan', git: 'git://github.com/rosa-abf/cancan.git', tag: '1.6.10-abf'
|
|
||||||
|
|
||||||
gem 'ancestry'
|
gem 'ancestry'
|
||||||
gem 'paperclip'
|
gem 'paperclip'
|
||||||
|
|
11
Gemfile.lock
11
Gemfile.lock
|
@ -26,13 +26,6 @@ GIT
|
||||||
ransack (~> 1.3)
|
ransack (~> 1.3)
|
||||||
sass-rails
|
sass-rails
|
||||||
|
|
||||||
GIT
|
|
||||||
remote: git://github.com/rosa-abf/cancan.git
|
|
||||||
revision: fe1089b70c08d3ed11bac4f8e69ecb3d1d9adc29
|
|
||||||
tag: 1.6.10-abf
|
|
||||||
specs:
|
|
||||||
cancan (1.6.10)
|
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/rosa-abf/grack.git
|
remote: git://github.com/rosa-abf/grack.git
|
||||||
revision: 020be3fef3fb308b9d214252522aa5945bf6584a
|
revision: 020be3fef3fb308b9d214252522aa5945bf6584a
|
||||||
|
@ -349,6 +342,8 @@ GEM
|
||||||
activemodel (>= 4.0.1, < 5.0)
|
activemodel (>= 4.0.1, < 5.0)
|
||||||
puma (2.11.1)
|
puma (2.11.1)
|
||||||
rack (>= 1.1, < 2.0)
|
rack (>= 1.1, < 2.0)
|
||||||
|
pundit (0.3.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
pygments.rb (0.6.2)
|
pygments.rb (0.6.2)
|
||||||
posix-spawn (~> 0.3.6)
|
posix-spawn (~> 0.3.6)
|
||||||
yajl-ruby (~> 1.2.0)
|
yajl-ruby (~> 1.2.0)
|
||||||
|
@ -590,7 +585,6 @@ DEPENDENCIES
|
||||||
better_errors
|
better_errors
|
||||||
binding_of_caller
|
binding_of_caller
|
||||||
bootstrap-sass
|
bootstrap-sass
|
||||||
cancan!
|
|
||||||
cape
|
cape
|
||||||
capistrano
|
capistrano
|
||||||
capistrano_colors
|
capistrano_colors
|
||||||
|
@ -637,6 +631,7 @@ DEPENDENCIES
|
||||||
pg
|
pg
|
||||||
protected_attributes
|
protected_attributes
|
||||||
puma
|
puma
|
||||||
|
pundit
|
||||||
rack-throttle (~> 0.3.0)
|
rack-throttle (~> 0.3.0)
|
||||||
rack-utf8_sanitizer
|
rack-utf8_sanitizer
|
||||||
rails (= 4.1.9)
|
rails (= 4.1.9)
|
||||||
|
|
|
@ -4,7 +4,7 @@ class Api::V1::BaseController < ApplicationController
|
||||||
|
|
||||||
helper_method :member_path
|
helper_method :member_path
|
||||||
|
|
||||||
rescue_from CanCan::AccessDenied do |exception|
|
rescue_from Pundit::NotAuthorizedError do |exception|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json { render json: {message: t('flash.exception_message')}.to_json, status: 403 }
|
format.json { render json: {message: t('flash.exception_message')}.to_json, status: 403 }
|
||||||
format.csv { render text: t('flash.exception_message'), status: 403 }
|
format.csv { render text: t('flash.exception_message'), status: 403 }
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Api::V1::ProjectsController < Api::V1::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_id
|
def get_id
|
||||||
if @project = Project.find_by_owner_and_name(params[:owner], params[:name])
|
if @project = Project.find_by_owner_and_name_cached(params[:owner], params[:name])
|
||||||
authorize! :show, @project
|
authorize! :show, @project
|
||||||
else
|
else
|
||||||
raise ActiveRecord::RecordNotFound
|
raise ActiveRecord::RecordNotFound
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
|
||||||
key, now = [@repository.platform.id, :repository_packages], Time.zone.now
|
key, now = [@repository.platform.id, :repository_packages], Time.zone.now
|
||||||
last_request = Rails.cache.read(key)
|
last_request = Rails.cache.read(key)
|
||||||
if last_request.present? && last_request + 15.minutes > now
|
if last_request.present? && last_request + 15.minutes > now
|
||||||
raise CanCan::AccessDenied
|
raise Pundit::NotAuthorizedError
|
||||||
else
|
else
|
||||||
|
|
||||||
Rails.cache.write(key, now, expires_at: 15.minutes)
|
Rails.cache.write(key, now, expires_at: 15.minutes)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
|
include StrongParams
|
||||||
|
include Pundit
|
||||||
|
|
||||||
AIRBRAKE_IGNORE = [
|
AIRBRAKE_IGNORE = [
|
||||||
ActionController::InvalidAuthenticityToken,
|
ActionController::InvalidAuthenticityToken,
|
||||||
AbstractController::ActionNotFound
|
AbstractController::ActionNotFound
|
||||||
|
@ -14,6 +17,7 @@ class ApplicationController < ActionController::Base
|
||||||
before_action :set_locale
|
before_action :set_locale
|
||||||
before_action -> { EventLog.current_controller = self },
|
before_action -> { EventLog.current_controller = self },
|
||||||
only: [:create, :destroy, :open_id, :cancel, :publish, :change_visibility] # :update
|
only: [:create, :destroy, :open_id, :cancel, :publish, :change_visibility] # :update
|
||||||
|
before_action :banned?
|
||||||
after_action -> { EventLog.current_controller = nil }
|
after_action -> { EventLog.current_controller = nil }
|
||||||
|
|
||||||
helper_method :get_owner
|
helper_method :get_owner
|
||||||
|
@ -27,7 +31,7 @@ class ApplicationController < ActionController::Base
|
||||||
AbstractController::ActionNotFound, with: :render_404
|
AbstractController::ActionNotFound, with: :render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue_from CanCan::AccessDenied do |exception|
|
rescue_from Pundit::NotAuthorizedError do |exception|
|
||||||
redirect_to forbidden_url, alert: t("flash.exception_message")
|
redirect_to forbidden_url, alert: t("flash.exception_message")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,6 +44,16 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
# Disables access to site for banned users
|
||||||
|
def banned?
|
||||||
|
authorize :user, :banned?
|
||||||
|
# if user_signed_in? && current_user.is_banned?
|
||||||
|
# sign_out current_user
|
||||||
|
# flash[:error] = I18n.t('messages.account_suspended')
|
||||||
|
# redirect_to root_path
|
||||||
|
# end
|
||||||
|
end
|
||||||
|
|
||||||
# For this example, we are simply using token authentication
|
# For this example, we are simply using token authentication
|
||||||
# via parameters. However, anyone could use Rails's token
|
# via parameters. However, anyone could use Rails's token
|
||||||
# authentication features to get the token from a header.
|
# authentication features to get the token from a header.
|
||||||
|
|
|
@ -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
|
|
@ -6,7 +6,7 @@ class Groups::MembersController < Groups::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
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.where(actor_id: params[:member_id], actor_type: 'User').first
|
||||||
relation ||= @group.actors.build(actor_id: params[:member_id], actor_type: 'User')
|
relation ||= @group.actors.build(actor_id: params[:member_id], actor_type: 'User')
|
||||||
|
|
|
@ -3,14 +3,14 @@ class Platforms::PlatformsController < Platforms::BaseController
|
||||||
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
skip_before_action :authenticate_user!, only: [:advisories, :members, :show] if APP_CONFIG['anonymous_access']
|
skip_before_action :authenticate_user!, only: [:advisories, :members, :show] if APP_CONFIG['anonymous_access']
|
||||||
load_and_authorize_resource
|
# load_and_authorize_resource
|
||||||
|
|
||||||
def index
|
def index
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {}
|
format.html {}
|
||||||
|
|
||||||
format.json {
|
format.json {
|
||||||
@platforms = @platforms.accessible_by(current_ability, :related)
|
@platforms = PlatformPolicy::Scope.new(current_user, Platform).related
|
||||||
@platforms_count = @platforms.count
|
@platforms_count = @platforms.count
|
||||||
@platforms = @platforms.paginate(page: current_page, per_page: Platform.per_page)
|
@platforms = @platforms.paginate(page: current_page, per_page: Platform.per_page)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ class Platforms::PlatformsController < Platforms::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
authorize @platform = Platform.find_cached(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
|
|
@ -125,7 +125,7 @@ class Projects::BuildListsController < Projects::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependent_projects
|
def dependent_projects
|
||||||
raise CanCan::AccessDenied if @build_list.save_to_platform.personal?
|
raise Pundit::NotAuthorizedError if @build_list.save_to_platform.personal?
|
||||||
|
|
||||||
if request.post?
|
if request.post?
|
||||||
prs = params[:build_list]
|
prs = params[:build_list]
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Projects::Git::BaseController < Projects::BaseController
|
||||||
before_action :authenticate_user, only: %i(show index blame raw archive diff tags branches)
|
before_action :authenticate_user, only: %i(show index blame raw archive diff tags branches)
|
||||||
end
|
end
|
||||||
|
|
||||||
load_and_authorize_resource :project
|
# load_and_authorize_resource :project
|
||||||
before_action :set_treeish_and_path
|
before_action :set_treeish_and_path
|
||||||
before_action :set_branch_and_tree
|
before_action :set_branch_and_tree
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ class Projects::PullRequestsController < Projects::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_destination_project bang=true
|
def find_destination_project bang=true
|
||||||
project = Project.find_by_owner_and_name params[:to_project]
|
project = Project.find_by_owner_and_name_cached params[:to_project]
|
||||||
raise ActiveRecord::RecordNotFound if bang && !project
|
raise ActiveRecord::RecordNotFound if bang && !project
|
||||||
project || @project.pull_requests.last.try(:to_project) || @project.root
|
project || @project.pull_requests.last.try(:to_project) || @project.root
|
||||||
end
|
end
|
||||||
|
|
|
@ -57,7 +57,7 @@ class BuildScript < ActiveRecord::Base
|
||||||
|
|
||||||
def attach_project
|
def attach_project
|
||||||
if @project_name.present?
|
if @project_name.present?
|
||||||
self.project = Project.find_by_owner_and_name(@project_name)
|
self.project = Project.find_by_owner_and_name_cached(@project_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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 slug.
|
||||||
|
#
|
||||||
|
# platform_id - ID or Slug (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', slug])
|
||||||
|
|
||||||
|
if chg = previous_changes["slug"]
|
||||||
|
Rails.cache.delete(['Platform.find', chg.first])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,82 @@
|
||||||
|
# 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 ID or slug.
|
||||||
|
#
|
||||||
|
# Returns Project record.
|
||||||
|
# Raises ActiveRecord::RecordNotFound if nothing was found.
|
||||||
|
def find_by_owner_and_name_cached(first, last = nil)
|
||||||
|
Rails.cache.fetch(['Project.find_by_owner_and_name', first, last]) do
|
||||||
|
find_by_owner_and_name(first, last)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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_cached(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])
|
||||||
|
Rails.cache.delete(['Project.find_by_owner_and_name', name_with_owner])
|
||||||
|
Rails.cache.delete(['Project.find', id])
|
||||||
|
Rails.cache.delete(['Project.find', slug])
|
||||||
|
|
||||||
|
if chg = previous_changes["slug"]
|
||||||
|
Rails.cache.delete(['Project.find', chg.first])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,15 +1,13 @@
|
||||||
require 'digest/md5'
|
require 'digest/md5'
|
||||||
|
|
||||||
class FlashNotify < ActiveRecord::Base
|
class FlashNotify < ActiveRecord::Base
|
||||||
# attr_accessible :title, :body
|
include FlashNotify::Finders
|
||||||
|
|
||||||
STATUSES = %w[error success info]
|
STATUSES = %w[error success info]
|
||||||
|
|
||||||
validates :status, inclusion: {in: STATUSES}
|
validates :status, inclusion: {in: STATUSES}
|
||||||
validates :body_ru, :body_en, :status, presence: true
|
validates :body_ru, :body_en, :status, presence: true
|
||||||
|
|
||||||
scope :published, -> { where(published: true) }
|
|
||||||
|
|
||||||
attr_accessible :body_ru, :body_en, :status, :published
|
attr_accessible :body_ru, :body_en, :status, :published
|
||||||
|
|
||||||
def hash_id
|
def hash_id
|
||||||
|
|
|
@ -109,7 +109,7 @@ class Issue < ActiveRecord::Base
|
||||||
owner_uname = Regexp.last_match[1].presence || Regexp.last_match[2].presence || project.owner.uname
|
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
|
project_name = Regexp.last_match[1] ? Regexp.last_match[2] : project.name
|
||||||
serial_id = Regexp.last_match[3]
|
serial_id = Regexp.last_match[3]
|
||||||
project = Project.find_by_owner_and_name(owner_uname.chomp('/'), project_name)
|
project = Project.find_by_owner_and_name_cached(owner_uname.chomp('/'), project_name)
|
||||||
return nil unless project
|
return nil unless project
|
||||||
return nil unless current_ability.can? :show, project
|
return nil unless current_ability.can? :show, project
|
||||||
project.issues.where(serial_id: serial_id).first
|
project.issues.where(serial_id: serial_id).first
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Platform < ActiveRecord::Base
|
||||||
include EventLoggable
|
include EventLoggable
|
||||||
include EmptyMetadata
|
include EmptyMetadata
|
||||||
include DefaultBranchable
|
include DefaultBranchable
|
||||||
|
include Platform::Finders
|
||||||
|
|
||||||
self.per_page = 20
|
self.per_page = 20
|
||||||
|
|
||||||
|
@ -96,16 +97,6 @@ class Platform < ActiveRecord::Base
|
||||||
after_create -> { symlink_directory unless hidden? }
|
after_create -> { symlink_directory unless hidden? }
|
||||||
after_destroy -> { remove_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
|
accepts_nested_attributes_for :platform_arch_settings, allow_destroy: true
|
||||||
attr_accessible :name,
|
attr_accessible :name,
|
||||||
:distrib_type,
|
:distrib_type,
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Project < ActiveRecord::Base
|
||||||
include UrlHelper
|
include UrlHelper
|
||||||
include EventLoggable
|
include EventLoggable
|
||||||
include Project::DefaultBranch
|
include Project::DefaultBranch
|
||||||
|
include Project::Finders
|
||||||
|
|
||||||
VISIBILITIES = ['open', 'hidden']
|
VISIBILITIES = ['open', 'hidden']
|
||||||
MAX_OWN_PROJECTS = 32000
|
MAX_OWN_PROJECTS = 32000
|
||||||
|
@ -67,37 +68,6 @@ class Project < ActiveRecord::Base
|
||||||
:autostart_status
|
:autostart_status
|
||||||
attr_readonly :owner_id, :owner_type
|
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_validation :truncate_name, on: :create
|
||||||
before_save -> { self.owner_uname = owner.uname if owner_uname.blank? || owner_id_changed? || owner_type_changed? }
|
before_save -> { self.owner_uname = owner.uname if owner_uname.blank? || owner_id_changed? || owner_type_changed? }
|
||||||
before_create :set_maintainer
|
before_create :set_maintainer
|
||||||
|
@ -106,19 +76,6 @@ class Project < ActiveRecord::Base
|
||||||
|
|
||||||
attr_accessor :url, :srpms_list, :mass_import, :add_to_repository_id
|
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
|
def init_mass_import
|
||||||
Project.perform_later :low, :run_mass_import, url, srpms_list, visibility, owner, add_to_repository_id
|
Project.perform_later :low, :run_mass_import, url, srpms_list, visibility, owner, add_to_repository_id
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
class AdvisoryPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
def index?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,117 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
# Public: Get user's group ids.
|
||||||
|
#
|
||||||
|
# Returns the Array of group ids.
|
||||||
|
def user_group_ids
|
||||||
|
Rails.cache.fetch(['ApplicationPolicy#user_group_ids', user.id]) do
|
||||||
|
user.group_ids
|
||||||
|
end
|
||||||
|
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
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
class BuildListPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
class GroupPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
class PlatformPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
def index?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
return true unless record.hidden?
|
||||||
|
return true if record.owner == user
|
||||||
|
return true if owner?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
is_admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def members?
|
||||||
|
owner? || local_admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def clone?
|
||||||
|
return false if record.personal?
|
||||||
|
owner? || local_admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
class Scope < Scope
|
||||||
|
|
||||||
|
def related
|
||||||
|
scope.where <<-SQL, { user_id: user.id, user_group_ids: 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)
|
||||||
|
)
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def related_platform_ids
|
||||||
|
Rails.cache.fetch(['PlatformPolicy::Scope#related_platform_ids', user.id]) do
|
||||||
|
user.repositories.pluck(:platform_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def owner?
|
||||||
|
record.owner == user ||
|
||||||
|
record.owner.is_a?(Group) && user_group_ids.include?(record.owner_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def local_admin?
|
||||||
|
Rails.cache.fetch(['PlatformPolicy#local_admin?', record, user]) do
|
||||||
|
user.best_role(record) == 'admin'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
class ProductPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
class ProjectPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
class StatisticPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,6 @@
|
||||||
|
class UserPolicy < ApplicationPolicy
|
||||||
|
|
||||||
|
def banned?
|
||||||
|
!is_banned?
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,7 +15,7 @@ json.feed do
|
||||||
end if user
|
end if user
|
||||||
|
|
||||||
project_name_with_owner = "#{item.data[:project_owner]}/#{item.data[:project_name]}"
|
project_name_with_owner = "#{item.data[:project_owner]}/#{item.data[:project_name]}"
|
||||||
@project = Project.find_by_owner_and_name(item.data[:project_owner], item.data[:project_name])
|
@project = Project.find_by_owner_and_name_cached(item.data[:project_owner], item.data[:project_name])
|
||||||
|
|
||||||
json.project_name_with_owner project_name_with_owner
|
json.project_name_with_owner project_name_with_owner
|
||||||
json.partial! item.partial, item: item, project_name_with_owner: project_name_with_owner
|
json.partial! item.partial, item: item, project_name_with_owner: project_name_with_owner
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
- if current_user || APP_CONFIG['anonymous_access']
|
- if current_user || APP_CONFIG['anonymous_access']
|
||||||
.flash_notify
|
.flash_notify
|
||||||
- if (flash_notify = FlashNotify.published.first) && flash_notify.should_show?(cookies[:flash_notify_hash])
|
- if (flash_notify = FlashNotify.published_first_cached) && flash_notify.should_show?(cookies[:flash_notify_hash])
|
||||||
.alert{class: "alert-#{flash_notify.status}"}
|
.alert{class: "alert-#{flash_notify.status}"}
|
||||||
= flash_notify.body(I18n.locale).html_safe
|
= flash_notify.body(I18n.locale).html_safe
|
||||||
%a.close#close-alert{:'data-dismiss'=>"alert", href: "#"} ×
|
%a.close#close-alert{:'data-dismiss'=>"alert", href: "#"} ×
|
||||||
|
|
|
@ -16,7 +16,7 @@ html
|
||||||
== yield :submenu if content_for?(:submenu)
|
== yield :submenu if content_for?(:submenu)
|
||||||
|
|
||||||
- if current_user || APP_CONFIG['anonymous_access']
|
- if current_user || APP_CONFIG['anonymous_access']
|
||||||
- if (flash_notify = FlashNotify.published.first) && flash_notify.should_show?(cookies[:flash_notify_hash])
|
- if (flash_notify = FlashNotify.published_first_cached) && flash_notify.should_show?(cookies[:flash_notify_hash])
|
||||||
javascript:
|
javascript:
|
||||||
var FLASH_HASH_ID = "#{flash_notify.hash_id}";
|
var FLASH_HASH_ID = "#{flash_notify.hash_id}";
|
||||||
.notify.alert.alert-dismissable.text-center class=alert_class(flash_notify.status)
|
.notify.alert.alert-dismissable.text-center class=alert_class(flash_notify.status)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
%li
|
%li
|
||||||
= image_tag 'square.png'
|
= image_tag 'square.png'
|
||||||
= link_to t('bottom_menu.developer_api'), t('bottom_menu.developer_api_url')
|
= link_to t('bottom_menu.developer_api'), t('bottom_menu.developer_api_url')
|
||||||
-if pr = Project.find_by_owner_and_name('abf/abf-ideas')
|
-if pr = Project.find_by_owner_and_name_cached('abf/abf-ideas')
|
||||||
%li
|
%li
|
||||||
= image_tag 'square.png'
|
= image_tag 'square.png'
|
||||||
= link_to t('bottom_menu.abf_ideas'), project_issues_url(pr)
|
= link_to t('bottom_menu.abf_ideas'), project_issues_url(pr)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
%li= link_to t('bottom_menu.support'), contact_url
|
%li= link_to t('bottom_menu.support'), contact_url
|
||||||
%li ·
|
%li ·
|
||||||
%li= link_to t('bottom_menu.developer_api'), t('bottom_menu.developer_api_url')
|
%li= link_to t('bottom_menu.developer_api'), t('bottom_menu.developer_api_url')
|
||||||
-if pr = Project.find_by_owner_and_name('abf/abf-ideas')
|
- if pr = Project.find_by_owner_and_name_cached('abf/abf-ideas')
|
||||||
%li ·
|
%li ·
|
||||||
%li= link_to t('bottom_menu.abf_ideas'), project_issues_url(pr)
|
%li= link_to t('bottom_menu.abf_ideas'), project_issues_url(pr)
|
||||||
%li ·
|
%li ·
|
||||||
|
|
|
@ -12,7 +12,7 @@ nav.navbar.navbar-inverse.top_menu role = "navigation"
|
||||||
#top-menu-navbar-collapse.collapse.navbar-collapse
|
#top-menu-navbar-collapse.collapse.navbar-collapse
|
||||||
ul.nav.navbar-nav
|
ul.nav.navbar-nav
|
||||||
- (collection = t 'top_menu').each do |base, title|
|
- (collection = t 'top_menu').each do |base, title|
|
||||||
- if can? :index, base.to_s.classify.constantize
|
- if policy(base).index?
|
||||||
li class=top_menu_class(base)
|
li class=top_menu_class(base)
|
||||||
a href=send("#{base}_path")
|
a href=send("#{base}_path")
|
||||||
i.fa.hidden-sm class=top_menu_icon(base)
|
i.fa.hidden-sm class=top_menu_icon(base)
|
||||||
|
|
|
@ -22,24 +22,24 @@
|
||||||
= link_to t("layout.repositories.list_header"), platform_repositories_path(@platform)
|
= link_to t("layout.repositories.list_header"), platform_repositories_path(@platform)
|
||||||
li class=('active' if contr == :contents)
|
li class=('active' if contr == :contents)
|
||||||
= link_to t('layout.platforms.contents'), platform_contents_path(@platform)
|
= link_to t('layout.platforms.contents'), platform_contents_path(@platform)
|
||||||
- if can? :show, @platform
|
- if policy(@platform).show?
|
||||||
li class=('active' if act == :index && contr == :maintainers)
|
li class=('active' if act == :index && contr == :maintainers)
|
||||||
= link_to t("layout.platforms.maintainers"), platform_maintainers_path(@platform)
|
= link_to t("layout.platforms.maintainers"), platform_maintainers_path(@platform)
|
||||||
li class=('active' if contr == :mass_builds)
|
li class=('active' if contr == :mass_builds)
|
||||||
= link_to t("layout.platforms.mass_build"), platform_mass_builds_path(@platform)
|
= link_to t("layout.platforms.mass_build"), platform_mass_builds_path(@platform)
|
||||||
- if can? :read, @platform.products.build
|
- if policy(@platform.products.build).index?
|
||||||
li class=('active' if contr == :products)
|
li class=('active' if contr == :products)
|
||||||
= link_to t("layout.products.list_header"), platform_products_path(@platform)
|
= link_to t("layout.products.list_header"), platform_products_path(@platform)
|
||||||
- if can? :advisories, @platform
|
- if policy(@platform.advisories.build).index?
|
||||||
li class=('active' if contr == :platforms && act == :advisories)
|
li class=('active' if contr == :platforms && act == :advisories)
|
||||||
= link_to t("layout.advisories.list_header"), advisories_platform_path(@platform)
|
= link_to t("layout.advisories.list_header"), advisories_platform_path(@platform)
|
||||||
- if can? :update, @platform
|
- if policy(@platform).update?
|
||||||
li class=('active' if act == :edit && contr == :platforms)
|
li class=('active' if act == :edit && contr == :platforms)
|
||||||
= link_to t("platform_menu.settings"), edit_platform_path(@platform)
|
= link_to t("platform_menu.settings"), edit_platform_path(@platform)
|
||||||
- if can? :members, @platform
|
- if policy(@platform).members?
|
||||||
li class=('active' if act == :members && contr == :platforms)
|
li class=('active' if act == :members && contr == :platforms)
|
||||||
= link_to t("layout.platforms.members"), members_platform_path(@platform)
|
= link_to t("layout.platforms.members"), members_platform_path(@platform)
|
||||||
- if can? :edit, @platform
|
- if policy(@platform).update?
|
||||||
li class=('active' if contr == :key_pairs)
|
li class=('active' if contr == :key_pairs)
|
||||||
= link_to t("layout.key_pairs.header"), platform_key_pairs_path(@platform)
|
= link_to t("layout.key_pairs.header"), platform_key_pairs_path(@platform)
|
||||||
li class=('active' if contr == :tokens)
|
li class=('active' if contr == :tokens)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
- set_meta_tags title: t('layout.platforms.list_header')
|
- set_meta_tags title: t('layout.platforms.list_header')
|
||||||
.row ng-controller='PlatformsCtrl'
|
.row ng-controller='PlatformsCtrl'
|
||||||
.col-md-6.col-md-offset-3 ng-cloak=true
|
.col-md-6.col-md-offset-3 ng-cloak=true
|
||||||
= link_to t('layout.platforms.new'), new_platform_path, class: 'btn btn-primary' if can? :create, Platform
|
- if policy(:platform).create?
|
||||||
|
a.btn.btn-primary href=new_platform_path
|
||||||
|
= t('layout.platforms.new')
|
||||||
table.table.table-hover.offset10
|
table.table.table-hover.offset10
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
b= t('layout.platforms.distrib_type')
|
b= t('layout.platforms.distrib_type')
|
||||||
.col-md-8= @platform.distrib_type
|
.col-md-8= @platform.distrib_type
|
||||||
|
|
||||||
- if can? :clone, @platform
|
- if policy(@platform).clone?
|
||||||
.row
|
.row
|
||||||
.col-md-4
|
.col-md-4
|
||||||
.col-md-8
|
.col-md-8
|
||||||
|
|
Loading…
Reference in New Issue