diff --git a/app/controllers/build_lists_controller.rb b/app/controllers/build_lists_controller.rb
index 8f713a7bb..728b52b5e 100644
--- a/app/controllers/build_lists_controller.rb
+++ b/app/controllers/build_lists_controller.rb
@@ -45,7 +45,7 @@ class BuildListsController < ApplicationController
@build_list = @project.build_lists.build(params[:build_list])
@build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version
@build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user
- @build_list.include_repos = @build_list.include_repos.select { |ir| @build_list.bpl.repository_ids.include? ir.to_i }
+ @build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.bpl.repository_ids.include? ir.to_i}
@build_list.priority = 100 # User builds more priority than mass rebuild with zero priority
flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl}
if @build_list.save
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index de1e56e82..6d5875178 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -1,26 +1,17 @@
# -*- encoding : utf-8 -*-
class CommentsController < ApplicationController
before_filter :authenticate_user!
+ load_and_authorize_resource :project
+ before_filter :find_commentable
+ before_filter :find_or_build_comment
+ load_and_authorize_resource
- load_resource :project
- before_filter :set_commentable
- before_filter :find_comment, :only => [:edit, :update, :destroy]
- authorize_resource
-
- def index
- @comments = @commentable.comments
- end
+ include CommentsHelper
def create
- @comment = @commentable.comments.build(params[:comment]) if @commentable.class == Issue
- if @commentable.class == Grit::Commit
- @comment = Comment.new(params[:comment].merge(:commentable_id => @commentable.id.hex, :commentable_type => @commentable.class.name))
- end
- @comment.project = @project
- @comment.user_id = current_user.id
if @comment.save
flash[:notice] = I18n.t("flash.comment.saved")
- redirect_to commentable_path
+ redirect_to project_commentable_path(@project, @commentable)
else
flash[:error] = I18n.t("flash.comment.save_error")
render :action => 'new'
@@ -28,19 +19,12 @@ class CommentsController < ApplicationController
end
def edit
- @update_url = case @commentable.class.name
- when "Issue"
- project_issue_comment_path(@project, @commentable, @comment)
- when "Grit::Commit"
- project_commit_comment_path(@project, @commentable, @comment)
- end
- @commentable_path = commentable_path
end
def update
if @comment.update_attributes(params[:comment])
flash[:notice] = I18n.t("flash.comment.saved")
- redirect_to commentable_path
+ redirect_to project_commentable_path(@project, @commentable)
else
flash[:error] = I18n.t("flash.comment.save_error")
render :action => 'new'
@@ -49,30 +33,19 @@ class CommentsController < ApplicationController
def destroy
@comment.destroy
-
flash[:notice] = t("flash.comment.destroyed")
- redirect_to commentable_path
+ redirect_to project_commentable_path(@project, @commentable)
end
- private
+ protected
- def set_commentable
- @commentable = if params[:issue_id].present?
- @project.issues.find_by_serial_id params[:issue_id]
- elsif params[:commit_id].present?
- @project.git_repository.commit params[:commit_id]
- end
+ def find_commentable
+ @commentable = params[:issue_id].present? && @project.issues.find_by_serial_id(params[:issue_id]) ||
+ params[:commit_id].present? && @project.git_repository.commit(params[:commit_id])
end
- def find_comment
- @comment = Comment.find(params[:id])
- if @comment.commit_comment?
- @comment.project = @project
- end
+ def find_or_build_comment
+ @comment = params[:id].present? && Comment.find(params[:id]) ||
+ current_user.comments.build(params[:comment]) {|c| c.commentable = @commentable; c.project = @project}
end
-
- def commentable_path
- @commentable.class == Issue ? [@project, @commentable] : commit_path(@project, @commentable.id)
- end
-
end
diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb
index cb5f47b33..6bfdd3f70 100644
--- a/app/helpers/comments_helper.rb
+++ b/app/helpers/comments_helper.rb
@@ -1,3 +1,20 @@
# -*- encoding : utf-8 -*-
module CommentsHelper
+ def project_commentable_comment_path(project, commentable, comment)
+ case
+ when Comment.issue_comment?(commentable.class)
+ project_issue_comment_path(project, commentable, comment)
+ when Comment.commit_comment?(commentable.class)
+ project_commit_comment_path(project, commentable, comment)
+ end
+ end
+
+ def project_commentable_path(project, commentable)
+ case
+ when Comment.issue_comment?(commentable.class)
+ polymorphic_path [project, commentable]
+ when Comment.commit_comment?(commentable.class)
+ commit_path project, commentable.id
+ end
+ end
end
diff --git a/app/models/activity_feed_observer.rb b/app/models/activity_feed_observer.rb
index b6d08342b..4738fccfa 100644
--- a/app/models/activity_feed_observer.rb
+++ b/app/models/activity_feed_observer.rb
@@ -35,7 +35,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
end
when 'Comment'
- if record.commentable.class == Issue
+ if record.issue_comment?
subscribes = record.commentable.subscribes
subscribes.each do |subscribe|
if record.user_id != subscribe.user_id
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 1eae5cc48..241cde404 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -6,23 +6,45 @@ class Comment < ActiveRecord::Base
validates :body, :user_id, :commentable_id, :commentable_type, :project_id, :presence => true
+ scope :for_commit, lambda {|c| where(:commentable_id => c.id.hex, :commentable_type => c.class)}
default_scope order('created_at')
after_create :subscribe_on_reply, :unless => lambda {|c| c.commit_comment?}
after_create :subscribe_users
- after_initialize do |comment|
- class_eval { def commentable; project.git_repository.commit(commentable_id.to_s(16)); end } if commit_comment?
+
+ attr_accessible :body
+
+ def commentable
+ commit_comment? ? project.git_repository.commit(commentable_id.to_s(16)) : super
end
- attr_accessible :body, :commentable_id, :commentable_type
- attr_readonly :commentable_id, :commentable_type
+ def commentable=(c)
+ if self.class.commit_comment?(c.class)
+ self.commentable_id = c.id.hex
+ self.commentable_type = c.class.name
+ else
+ super
+ end
+ end
- def own_comment?(user)
- user_id == user.id
+ def self.commit_comment?(class_name)
+ class_name.to_s == 'Grit::Commit'
end
def commit_comment?
- commentable_type == 'Grit::Commit'
+ self.class.commit_comment?(commentable_type)
+ end
+
+ def self.issue_comment?(class_name)
+ class_name.to_s == 'Issue'
+ end
+
+ def issue_comment?
+ self.class.issue_comment?(commentable_type)
+ end
+
+ def own_comment?(user)
+ user_id == user.id
end
def can_notify_on_new_comment?(subscribe)
@@ -32,19 +54,19 @@ class Comment < ActiveRecord::Base
protected
def subscribe_on_reply
- self.commentable.subscribes.create(:user_id => self.user_id) if !self.commentable.subscribes.exists?(:user_id => self.user_id)
+ commentable.subscribes.create(:user_id => user_id) if !commentable.subscribes.exists?(:user_id => user_id)
end
def subscribe_users
- if self.commentable.class == Issue
- self.commentable.subscribes.create(:user => self.user) if !self.commentable.subscribes.exists?(:user_id => self.user.id)
- elsif self.commit_comment?
- recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map &:object # admins
- recipients << self.user << User.where(:email => self.commentable.committer.email).first # commentor and committer
- recipients << self.project.owner if self.project.owner_type == 'User' # project owner
+ if issue_comment?
+ commentable.subscribes.create(:user => user) if !commentable.subscribes.exists?(:user_id => user.id)
+ elsif commit_comment?
+ recipients = project.relations.by_role('admin').where(:object_type => 'User').map &:object # admins
+ recipients << user << User.where(:email => commentable.committer.email).first # commentor and committer
+ recipients << project.owner if project.owner_type == 'User' # project owner
recipients.compact.uniq.each do |user|
- options = {:project_id => self.project.id, :subscribeable_id => self.commentable_id, :subscribeable_type => self.commentable.class.name, :user_id => user.id}
- Subscribe.subscribe_to_commit(options) if Subscribe.subscribed_to_commit?(self.project, user, self.commentable)
+ options = {:project_id => project.id, :subscribeable_id => commentable_id, :subscribeable_type => commentable.class.name, :user_id => user.id}
+ Subscribe.subscribe_to_commit(options) if Subscribe.subscribed_to_commit?(project, user, commentable)
end
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 4e8f6c12a..3f9b976a2 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -18,7 +18,7 @@ class Group < ActiveRecord::Base
scope :search_order, order("CHAR_LENGTH(uname) ASC")
scope :without, lambda {|a| where("groups.id NOT IN (?)", a)}
- scope :search, lambda {|q| where("uname ILIKE ?", "%#{q.strip}%")}
+ scope :search, lambda {|q| where("uname ILIKE ?", "%#{q.to_s.strip}%")}
scope :opened, where('1=1')
scope :by_owner, lambda {|owner| where(:owner_id => owner.id)}
scope :by_admin, lambda {|admin| joins(:objects).where(:'relations.role' => 'admin', :'relations.object_id' => admin.id, :'relations.object_type' => 'User')}
diff --git a/app/models/platform.rb b/app/models/platform.rb
index 03d749c15..85d799606 100644
--- a/app/models/platform.rb
+++ b/app/models/platform.rb
@@ -29,7 +29,7 @@ class Platform < ActiveRecord::Base
after_update :update_owner_relation
scope :search_order, order("CHAR_LENGTH(name) ASC")
- scope :search, lambda {|q| where("name ILIKE ?", "%#{q.strip}%")}
+ scope :search, lambda {|q| where("name ILIKE ?", "%#{q.to_s.strip}%")}
scope :by_visibilities, lambda {|v| where(:visibility => v)}
scope :opened, where(:visibility => 'open')
scope :hidden, where(:visibility => 'hidden')
diff --git a/app/models/project.rb b/app/models/project.rb
index b1cd682f8..5f0b097cd 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -29,7 +29,7 @@ class Project < ActiveRecord::Base
scope :recent, order("name ASC")
scope :search_order, order("CHAR_LENGTH(name) ASC")
- scope :search, lambda {|q| by_name("%#{q.strip}%")}
+ scope :search, lambda {|q| by_name("%#{q.to_s.strip}%")}
scope :by_name, lambda {|name| where('projects.name ILIKE ?', name)}
scope :by_visibilities, lambda {|v| where(:visibility => v)}
scope :opened, where(:visibility => 'open')
@@ -181,10 +181,6 @@ class Project < ActiveRecord::Base
system("#{Rails.root.join('bin', 'import_srpm.sh')} #{srpm_path} #{path} #{branch_name} >> /dev/null 2>&1")
end
- def self.commit_comments(commit, project)
- comments = Comment.where(:commentable_id => commit.id.hex, :commentable_type => 'Grit::Commit')
- end
-
def owner?(user)
owner == user
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 463264110..96b0acb13 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -49,7 +49,7 @@ class User < ActiveRecord::Base
scope :search_order, order("CHAR_LENGTH(uname) ASC")
scope :without, lambda {|a| where("users.id NOT IN (?)", a)}
- scope :search, lambda {|q| where("uname ILIKE ?", "%#{q.strip}%")}
+ scope :search, lambda {|q| where("uname ILIKE ?", "%#{q.to_s.strip}%")}
scope :opened, where('1=1')
scope :banned, where(:role => 'banned')
scope :admin, where(:role => 'admin')
diff --git a/app/presenters/comment_presenter.rb b/app/presenters/comment_presenter.rb
index 7575f1819..bab0b3343 100644
--- a/app/presenters/comment_presenter.rb
+++ b/app/presenters/comment_presenter.rb
@@ -30,10 +30,10 @@ class CommentPresenter < ApplicationPresenter
def buttons
project = options[:project]
commentable = options[:commentable]
- (ep, dp) = if commentable.class == Issue
+ (ep, dp) = if Comment.issue_comment?(commentable.class)
[edit_project_issue_comment_path(project, commentable, comment),
project_issue_comment_path(project, commentable, comment)]
- elsif commentable.class == Grit::Commit
+ elsif Comment.commit_comment?(commentable.class)
[edit_project_commit_comment_path(project, commentable, comment),
project_commit_comment_path(project, commentable, comment)]
end
diff --git a/app/views/comments/_add.html.haml b/app/views/comments/_add.html.haml
index efc5436a2..b31b0be40 100644
--- a/app/views/comments/_add.html.haml
+++ b/app/views/comments/_add.html.haml
@@ -1,10 +1,10 @@
#open-comment.comment.view
%h3.tmargin0= t("layout.comments.new_header")
- - if commentable.class == Issue
+ - if Comment.issue_comment?(commentable.class)
- new_path = project_issue_comments_path(project, commentable)
- is_subscribed = commentable.subscribes.exists?(:user_id => current_user.id)
- subscribe_path = is_subscribed ? project_issue_subscribe_path(project, commentable, current_user.id) : project_issue_subscribes_path(project, commentable)
- - else commentable.class == Grit::Commit
+ - else Comment.commit_comment?(commentable.class)
- new_path = project_commit_comments_path(project, commentable)
- is_subscribed = Subscribe.subscribed_to_commit?(project, current_user, commentable)
- subscribe_path = is_subscribed ? unsubscribe_commit_path(project, commentable) : subscribe_commit_path(project, commentable)
diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml
index 46e9c6970..d7814ddad 100644
--- a/app/views/comments/_form.html.haml
+++ b/app/views/comments/_form.html.haml
@@ -1,14 +1,2 @@
-.wrapper
- = f.text_area :body, :cols => 80
-.comment-right
- = submit_tag t("layout.save")
--#.group
- = f.label :body, t("activerecord.attributes.comment.body"), :class => :label
- = f.text_area :body, :class => 'text_field', :cols => 80
-
--#.group.navform.wat-cf
- %button.button{:type => "submit"}
- = image_tag("choose.png", :alt => t("layout.save"))
- = t("layout.save")
- %span.text_button_padding= t("layout.or")
- = link_to t("layout.cancel"), @commentable_path , :class => "text_button_padding link_button"
+.wrapper= f.text_area :body, :cols => 80
+.comment-right= submit_tag t("layout.save")
\ No newline at end of file
diff --git a/app/views/comments/_list.html.haml b/app/views/comments/_list.html.haml
index d4bd73309..1ba6b69ad 100644
--- a/app/views/comments/_list.html.haml
+++ b/app/views/comments/_list.html.haml
@@ -3,37 +3,4 @@
%h3= t("layout.comments.comments_header")
- list.each do |comment|
- CommentPresenter.present(comment, :project => project, :commentable => commentable) do |presenter|
- = render :partial => 'shared/feed_message', :locals => {:presenter => presenter}
--#.block#block-list
- .content
- %h2.title
- = t("layout.issues.comments_header")
- .inner
- %ul.list
- - list.each do |comment|
- %li
- .left
- = link_to comment.user.uname, user_path(comment.user.uname)
- .item
- = comment.body
- %br
- %br
- - if commentable.class == Issue
- - edit_path = edit_project_issue_comment_path(project, commentable, comment)
- - delete_path = project_issue_comment_path(project, commentable, comment)
- - elsif commentable.class == Grit::Commit
- - edit_path = edit_project_commit_comment_path(project, commentable, comment)
- - delete_path = project_commit_comment_path(project, commentable, comment)
- = link_to t("layout.edit"), edit_path if can? :update, comment
- =# link_to image_tag("x.png", :alt => t("layout.delete")) + " " + t("layout.delete"), delete_path, :method => "delete", :class => "button", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
- = link_to t("layout.delete"), delete_path, :method => "delete", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
-
--#.block
- .content
- %h2.title
- = t("layout.comments.new_header")
- .inner
- - new_path = project_issue_comments_path(project, commentable) if commentable.class == Issue
- - new_path = project_commit_comments_path(project, commentable) if commentable.class == Grit::Commit
- = form_for :comment, :url => new_path, :method => :post, :html => { :class => :form } do |f|
- = render :partial => "comments/form", :locals => {:f => f}
+ = render :partial => 'shared/feed_message', :locals => {:presenter => presenter}
\ No newline at end of file
diff --git a/app/views/comments/edit.html.haml b/app/views/comments/edit.html.haml
index b2b4e80fe..fff5309ef 100644
--- a/app/views/comments/edit.html.haml
+++ b/app/views/comments/edit.html.haml
@@ -2,10 +2,10 @@
.block
.secondary-navigation
%ul.wat-cf
- %li.first= link_to t("layout.comments.back"), @commentable_path
+ %li.first= link_to t("layout.comments.back"), project_commentable_path(@project, @commentable)
.content
%h2.title
= t("layout.comments.edit_header")
.inner
- = form_for @comment, :url => @update_url, :html => { :class => :form } do |f|
+ = form_for @comment, :url => project_commentable_comment_path(@project, @commentable, @comment), :html => {:class => :form} do |f|
= render :partial => "form", :locals => {:f => f}
diff --git a/app/views/git/commits/show.html.haml b/app/views/git/commits/show.html.haml
index ee11394e6..9329e7eb0 100644
--- a/app/views/git/commits/show.html.haml
+++ b/app/views/git/commits/show.html.haml
@@ -16,5 +16,5 @@
#repo-wrapper
= render :partial => 'show'
- = render :partial => "comments/list", :locals => {:list => Project.commit_comments(@commit, @project), :project => @project, :commentable => @commit}
+ = render :partial => "comments/list", :locals => {:list => Comment.for_commit(@commit), :project => @project, :commentable => @commit}
= render :partial => "comments/add", :locals => {:project => @project, :commentable => @commit} if current_user
diff --git a/app/views/user_mailer/new_comment_notification.en.haml b/app/views/user_mailer/new_comment_notification.en.haml
index 7c0f02cf9..7c6c93175 100644
--- a/app/views/user_mailer/new_comment_notification.en.haml
+++ b/app/views/user_mailer/new_comment_notification.en.haml
@@ -1,6 +1,6 @@
%p== Hello, #{@user.user_appeal}.
-- if @comment.commentable.class == Issue
+- if @comment.issue_comment?
- link = link_to @comment.commentable.title, project_issue_url(@comment.commentable.project, @comment.commentable)
- object = 'issue'
- elsif @comment.commit_comment?
diff --git a/app/views/user_mailer/new_comment_notification.ru.haml b/app/views/user_mailer/new_comment_notification.ru.haml
index a7d98870a..1c7b933e5 100644
--- a/app/views/user_mailer/new_comment_notification.ru.haml
+++ b/app/views/user_mailer/new_comment_notification.ru.haml
@@ -1,6 +1,6 @@
%p== Здравствуйте, #{@user.user_appeal}.
-- if @comment.commentable.class == Issue
+- if @comment.issue_comment?
- link = link_to @comment.commentable.title, project_issue_url(@comment.commentable.project, @comment.commentable)
- object = 'задаче'
- elsif @comment.commit_comment?
diff --git a/db/migrate/20120330201229_remove_containers_and_rpms.rb b/db/migrate/20120330201229_remove_containers_and_rpms.rb
index ac1dca3b8..65dcc4d40 100644
--- a/db/migrate/20120330201229_remove_containers_and_rpms.rb
+++ b/db/migrate/20120330201229_remove_containers_and_rpms.rb
@@ -1,3 +1,4 @@
+# -*- encoding : utf-8 -*-
class RemoveContainersAndRpms < ActiveRecord::Migration
def up
drop_table :containers
diff --git a/db/migrate/20120331180541_customize_platform.rb b/db/migrate/20120331180541_customize_platform.rb
index 004cf3f4c..8a02ffd2d 100644
--- a/db/migrate/20120331180541_customize_platform.rb
+++ b/db/migrate/20120331180541_customize_platform.rb
@@ -1,3 +1,4 @@
+# -*- encoding : utf-8 -*-
class CustomizePlatform < ActiveRecord::Migration
def self.up
change_column_null :platforms, :name, false
@@ -16,4 +17,4 @@ class CustomizePlatform < ActiveRecord::Migration
change_column_null :platforms, :visibility, true
remove_index "platforms", ["name"]
end
-end
\ No newline at end of file
+end
diff --git a/db/migrate/20120403110931_clear_product.rb b/db/migrate/20120403110931_clear_product.rb
index 0904057f7..4de34445b 100644
--- a/db/migrate/20120403110931_clear_product.rb
+++ b/db/migrate/20120403110931_clear_product.rb
@@ -1,3 +1,4 @@
+# -*- encoding : utf-8 -*-
class ClearProduct < ActiveRecord::Migration
def self.up
remove_column :products, :build_status
@@ -10,4 +11,4 @@ class ClearProduct < ActiveRecord::Migration
add_column :products, :build_path, :string
add_column :products, :system_wide, :boolean, :default => false
end
-end
\ No newline at end of file
+end
diff --git a/db/schema.rb b/db/schema.rb
index 73a140b90..b15f77dec 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,14 +11,14 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20120403110931) do
+ActiveRecord::Schema.define(:version => 20120404134602) do
create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false
t.string "kind"
t.text "data"
- t.datetime "created_at"
- t.datetime "updated_at"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
create_table "arches", :force => true do |t|
@@ -102,7 +102,7 @@ ActiveRecord::Schema.define(:version => 20120403110931) do
t.string "locked_by"
t.datetime "created_at"
t.datetime "updated_at"
- t.string "queue"
+ t.string "queue", :default => "default"
end
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
@@ -331,16 +331,16 @@ ActiveRecord::Schema.define(:version => 20120403110931) do
t.string "name"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
- t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
+ t.text "ssh_key"
t.string "uname"
t.string "role"
t.string "language", :default => "en"
- t.integer "own_projects_count", :default => 0, :null => false
t.datetime "reset_password_sent_at"
+ t.integer "own_projects_count", :default => 0, :null => false
t.text "professional_experience"
t.string "site"
t.string "company"
diff --git a/doc/acl/acl_intro.md b/doc/acl/acl_intro.md
deleted file mode 100644
index 0de8a5f95..000000000
--- a/doc/acl/acl_intro.md
+++ /dev/null
@@ -1,323 +0,0 @@
-КРАТКОЕ ОПИСАНИЕ ACL
-====================
-
-Предназначение
---------------
-
-ACL предназначена для контроля прав пользователя на выполнение действий в
-системе и доступа к моделям по областям видимости.
-
-Решаемые задачи
----------------
-
-* Проверка наличия у пользователя прав для выполнения метода контроллера;
-* Прозрачная фильтрация моделей для исключения невидимых для пользователя
- записей.
-
-Возможности
------------
-
-* Неограниченное количество моделей, над которыми могут выполняться
- действия (`target`);
-* Неограниченное количество моделей, которые могут выполнять действия над
- другими (`acter`);
-* Геренатор прав основывающийся на структуре приложения (см. далее);
-* Неограниченное количество ролей, которые могут назначаться для `acter` и
- содержать любую комбинацию прав и доступных видимостей;
-* Объединение прав `acter`-ов на глубину одной модели (см. далее);
-* Разграничение назначения ролей по классам (не завершено, на данный
- момент не критично);
-* Разграничение ролей на глобальные и локальные (см. далее).
-
-Типы моделей, с которыми взаимодействует ACL
---------------------------------------------
-
-* __ActerModel__ -- модель, которая может выполнять действия, разрешенные
- ролями, над другими моделями;
-* __TargetTarget__ -- модель, над которой могут выполняться действия,
- разрешенные ролями.
-
-__ActerModel__ может иметь глобальную роль, которая определяет возможность
-выполнения действий без привязки к конкретному экземпляру __TargetModel__ и
-неограниченное количество прав по отношению к конкретному экземпляру
-__TargetModel__.
-
-__TODO__: *Реализовать дополнение необходимым функционалом моделей, выбранных
-в качестве __ActerModel__ или __TargetModel__ при декларировании их роли в
-системе*
-
-Схема взаимодействия объектов ACL
----------------------------------
-
-Функционал ACL реализуется путем взаимодействия моделей `Right, Role, Relation`,
-реализующих основной функционал и особых моделей проекта, обозначенных на схеме
-как `ActerModel` и `TargetModel`.
-
-Экземпляры __ActerModel__ и __TargetModel__ связываются посредством модели
-`Relation`, через которую экземпляр __ActerModel__ получает неограниченное
-количество ролей по отношению к экземпляру __TargetModel__.
-
-### Схема связей моделей:
-
- --------------
- | ActerModel |
- / --------------
- --------- -------- |
- | Right | | Role | V
- --------- -------- ------------
- ... <= ... <= | Relation |
- --------- -------- ------------
- | Right | | Role | |
- --------- -------- V
- ---------------
- | TargetModel |
- ---------------
-
- * Обозначения: <= -- Связь с несколькими моделями
- <-,/,| -- Связь с одной моделью
-
-
-Генератор прав
---------------
-
-Генератор ролей является Rake-task-ом и запускается командой
-`rake rights:generate`.
-
-Желательно запускать после добавления нового метода в контроллер для того,
-чтобы на этот метод в системе появилось право.
-
-Загрузка ролей из дампа
------------------------
-
-Загрузку ролей из заранее подготовленного дампа можно произвести двумя
-способами:
-
-* В консоли, используя Rake task `rake roles:load`, который загрузит в базу
- роли, описанные в `config/roles.yml`
-* Через Web-интерфейс, на странице `/roles`, если у пользователя есть
- соответствующие права. Для загрузки через Web-интерфейс необходимо выбрать
- файл в поле выбора вверху страницы и нажать __Загрузить__.
-
-Получение дампа ролей
----------------------
-
-Дамп ролей может получить пользователь, имеющий на это права, зайдя на страницу
-`roles` и нажав кнопку `Скачать в YML`.
-
-Задание областей видимости моделей
-----------------------------------
-*Этот функционал скорее всего будет изменяться*
-
-Если модель должна иметь несколько областей видимости, нужно сделать следующее:
-
-* Добавить в модель константу `VISIBILITIES`, в которой задать названия областей
- видимости;
-* Добавить к таблице моделей поле `visibility:text`;
-* Добавить `attr_accessible :visibility` в модель;
-* Создать `scope :by_visibility`, принимающий аргументом массив областей
- видимости.
-
-После выполнения этих действий на странице редактирования роли появится поле
-выбора областей видимости для этой модели.
-
-### Пример:
-
- model VisibilitiesExample < ActiveRecord::Base
- VISIBILITIES = ['open', 'hidden', 'open_for_admins']
- attr_accessible :visibility
-
- scope :by_visibility, lambda {|v| {:conditions => ['visibility in (?)', v]}}
- end
-
-*Назначение методов описано в API*
-
-Задание типа модели
--------------------
-*Этот функционал скорее всего будет изменяться*
-
-Если модель должна иметь возможность быть связанной с другими с использованием
-ролей, необходимо произвести следующие действия:
-
-* Добавить в модель декларацию `relationable`, с аргументом `:as`, который
- может принимать заначения из `[:object, :target]`. Если модель будет
- __acter__-ом, передается `:object`, иначе `:target`
- Пример: `relationable :as => :object`
-* Добавить в модель связь `belongs_to :global_role, :class_name => 'Role'`
-* Добавить в модель связь с моделью `Relation`
-* Если модель -- __acter__ и она должна использовать как свои роли, так и
- роли из другой модели, необходимо добавить декларацию `inherit_rights_from`
- которой аргументом присвоить имя/имена связей с моделями, из которых должны
- браться роли.
-
-### Примеры:
-
-* Модель, являющаяся __acter__:
-
- class ActerModel < ActiveRecord::Base
- relationable :as => :object
-
- belongs_to :global_role, :class_name => 'Role'
- has_many :targets, :as => :object, :class_name => 'Relation'
- end
-* Модель, являющаяся __acter__ и наследующая права другой модели:
-
- class ActerWithInheritableRolesModel < ActiveRecord::Base
- relationable :as => :object
- ingerit_rights_from :another_acter_model
-
- has_many :another_acters_models
-
- belongs_to :global_role, :class_name => 'Role'
- has_many :targets, :as => :object, :class_name => 'Relation'
- end
-* Модель, являющаяся __target__:
-
- class TargetModel < ActiveRecord::Base
- relationable :as => :target
-
- has_many :objects, :as => :target, :class_name => 'Relation'
- end
-* Модель, являющаяся и __acter__, и __target__:
-
- class ActerAndTargetModel < ActiveRecord::Base
- relationable :as => :object
- relationable :as => :target
-
- belongs_to :global_role, :class_name => 'Role'
- has_many :targets, :as => :object, :class_name => 'Relation'
- has_many :objects, :as => :target, :class_name => 'Relation'
- end
-
-*Назначение методов описано в API*
-
-Использование ACL в контроллере
--------------------------------
-
-Если необходимо ограничить доступ ко всем методам контроллера по глобальной
-роли пользователя вне зависимости от текущей модели, необходимо установить
-`before_filter :check_global_rights`.
-В случае, если у пользователя нет прав для выполнения текущего действия, он
-будет переотправлен на предыдущую страницу.
-
-Если необходимо проверить, может ли пользователь выполнить конкретное действие,
-необходимо в начале этого метода вызвать метод `can_perform?`. Если методу
-передан параметр, являющийся экземпляром класса __TargetModel__, метод возвратит
-`true`, если одна или несколько ролей пользователя над этой моделью позволяет
-ему выполнить может выполнить действие и `false` в противном случае. Если
-необязательный параметр опущен, или в качестве параметра передано `:system`,
-учитываются только глобальные роли.
-
-### Примеры
-
-* Контроллер, некоторые методы которого доступны для всех:
-
- class StuffController < ApplicationController
- def index # доступ у всех
- ...
- end
-
- def show # 'Что-то полезное' выполнится только у тех, чьи роли над
- # @data позволяют выполнить конкретное действие.
- @data = Stuff.find(params[:id])
- if can_perform? @data
- #что-то полезное
- else
- # сообщаем пользователю, что он не может выполнить действие
- end
- end
-
- def create # 'Что-то полезное' выполнится только у тех, чьи
- # глобальные роли позволяют выполнить метод
- if can_perform?
- # что-то полезное
- else
- # сообщаем пользователю, что он не может выполнить действие
- end
- end
-
- end
-
-* Контроллер, доступ к методам которого возможен только при наличии необходимых
- прав в глобальных ролях:
-
- class StuffController < ApplicationController
- before_filter :check_global_rights # разрешаем доступ только тем,
- # чьи роли это позволяют.
-
- def index # доступ только у тех, кому это позволяет глобальная роль
- ...
- end
-
- def show # 'Что-то полезное' выполнится только у тех, чьи роли
- # над @data это позволяют
- @data = Stuff.find(params[:id])
- if can_perform? @data
- #что-то полезное
- else
- # сообщаем пользователю, что он не может выполнить действие
- end
- end
- end
-
-Использование ACL во view
--------------------------
-
-Используется метод `can_perform?` модели, для которой нужно проверить права
-доступа. Обычно этой моделью является `current_user`.
-
-### Примеры:
-
-* Проверка на возможность выполнения глобального действия:
-
- -if current_user.can_perform?('some_controller', 'some_aciton')
- %a{:href => controller_action_path}= Some description
-
-* Проверка на возможность выполнения действия над текущей моделью:
-
- -if current_user.can_perform?('some_controller', 'some_aciton', @data)
- %a{:href => controller_action_path(@data)}= Some description
-
-API для работы с ACL
---------------------
-*Этот функционал скорее всего будет изменяться*
-
-### Методы потомков `ActiveRecord::Base`
-
-* Методы классов:
- - `relationable` -- устанавливает, кем является модель (acter/target)
- - `relationable?` -- может ли иметь связь с ролью/ролями с другими
- - `relation_acters` -- список моделей, которые могут иметь роли
- по отношению к другим (след. метод)
- - `relation_targets` -- список моделей, над которыми могут совершаться
- действия
- - `relation_acter? (model)`, `relation_target? (model)` -- является ли
- тем или другим
- - `inherit_rights_from (:relation_name | [:relation_names])` -- права из
- каких связанных моделей наследовать
- - `visible_to (model)` -- все видимые для модели записи, может
- включаться в цепочку (например, для paginate)
-
-* Методы инстансов:
- - `add_role_to(acter, role)` -- привязать acter-а с ролью к текущей записи
- - `add_role_on(target, role)` -- привязать текущую модель с ролью
- - `roles_to(object)` -- если object == :system, возвращает глобальные роли
- текущей записи, если передана запись -- то роли текущей модели над записью
- - `rights_to(object)` -- аргументы те же, но возвращается список прав,
- собранный из всех ролей
- - `right_to(controller_name, action)` -- возвращает запись с правом на
- выполнение действия action в контроллере c именем `controller_name`
- - `can_perform? (controller_name, action, target = :system)` -- показывает,
- может ли текущая модель выполнить действие контроллера над целью
-
-### Методы потомков `ActiveController::Base`
-*Возможно, будут вынесены в хелпер для универсализации системы*
-
- - `can_perform? (target = :system)` -- может ли `current_user` выполнить
- текущее действие
- - `check_global_access` -- делает редирект назад или на главную, если
- пользователь вообще не может совершить текущее действие
- - `roles_to(object)` -- возвращает список ролей `current_user`-а по отношению
- к объекту
- - `rights_to(object)` -- возвращает список прав `current_user`-а по отношению
- к объекту
-
diff --git a/doc/design/abf-admin-build-project.html b/doc/design/abf-admin-build-project.html
index eadff5338..e74d6b449 100644
--- a/doc/design/abf-admin-build-project.html
+++ b/doc/design/abf-admin-build-project.html
@@ -23,9 +23,12 @@
-
-
-
+