Merge branch 'groups_reincarnation' into staging
Conflicts: app/models/ability.rb app/models/project.rb config/environments/production.rb
This commit is contained in:
commit
2f5ce7cebe
|
@ -15,8 +15,13 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def get_owner
|
def get_owner
|
||||||
params['user_id'] && User.find_by_id(params['user_id']) ||
|
# params['user_id'] && User.find_by_id(params['user_id']) ||
|
||||||
params['group_id'] && Group.find_by_id(params['group_id']) || current_user
|
# params['group_id'] && Group.find_by_id(params['group_id']) || current_user
|
||||||
|
if parent and (parent.is_a? User or parent.is_a? Group)
|
||||||
|
parent
|
||||||
|
else
|
||||||
|
current_user
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def layout_by_resource
|
def layout_by_resource
|
||||||
|
|
|
@ -29,8 +29,11 @@ class CollaboratorsController < ApplicationController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
all_user_ids = []
|
all_user_ids = []
|
||||||
|
all_groups_ids = []
|
||||||
|
puts params.inspect
|
||||||
Relation::ROLES.each { |r|
|
Relation::ROLES.each { |r|
|
||||||
all_user_ids = all_user_ids | params[r.to_sym].keys if params[r.to_sym]
|
all_user_ids = all_user_ids | params['user'][r.to_sym].keys if params['user'][r.to_sym]
|
||||||
|
all_groups_ids = all_groups_ids | params['group'][r.to_sym].keys if params['group'][r.to_sym]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Remove relations
|
# Remove relations
|
||||||
|
@ -40,11 +43,17 @@ class CollaboratorsController < ApplicationController
|
||||||
users_for_removing.each do |u|
|
users_for_removing.each do |u|
|
||||||
Relation.by_object(u).by_target(@project).each {|r| r.destroy}
|
Relation.by_object(u).by_target(@project).each {|r| r.destroy}
|
||||||
end
|
end
|
||||||
|
groups_for_removing = @project.groups.select do |u|
|
||||||
|
!all_groups_ids.map{|k| k.to_i}.include? u.id and @project.owner != u
|
||||||
|
end
|
||||||
|
groups_for_removing.each do |u|
|
||||||
|
Relation.by_object(u).by_target(@project).each {|r| r.destroy}
|
||||||
|
end
|
||||||
|
|
||||||
# Create relations
|
# Create relations
|
||||||
Relation::ROLES.each { |r|
|
Relation::ROLES.each { |r|
|
||||||
#users_for_creating = users_for_creating params[:user].keys.map{|p| p.to_i} - @project.collaborators.map(&:id)
|
#users_for_creating = users_for_creating params[:user].keys.map{|p| p.to_i} - @project.collaborators.map(&:id)
|
||||||
params[r.to_sym].keys.each { |u|
|
params['user'][r.to_sym].keys.each { |u|
|
||||||
if relation = @project.relations.find_by_object_id_and_object_type(u, 'User')
|
if relation = @project.relations.find_by_object_id_and_object_type(u, 'User')
|
||||||
relation.update_attribute(:role, r)
|
relation.update_attribute(:role, r)
|
||||||
else
|
else
|
||||||
|
@ -53,7 +62,17 @@ class CollaboratorsController < ApplicationController
|
||||||
puts r
|
puts r
|
||||||
relation.save!
|
relation.save!
|
||||||
end
|
end
|
||||||
} if params[r.to_sym]
|
} if params['user'][r.to_sym]
|
||||||
|
params['group'][r.to_sym].keys.each { |u|
|
||||||
|
if relation = @project.relations.find_by_object_id_and_object_type(u, 'Group')
|
||||||
|
relation.update_attribute(:role, r)
|
||||||
|
else
|
||||||
|
relation = @project.relations.build(:object_id => u, :object_type => 'Group', :role => r)
|
||||||
|
puts relation.inspect
|
||||||
|
puts r
|
||||||
|
relation.save!
|
||||||
|
end
|
||||||
|
} if params['group'][r.to_sym]
|
||||||
}
|
}
|
||||||
|
|
||||||
if @project.save
|
if @project.save
|
||||||
|
|
|
@ -1,12 +1,27 @@
|
||||||
# coding: UTF-8
|
# coding: UTF-8
|
||||||
class GroupsController < ApplicationController
|
class GroupsController < ApplicationController
|
||||||
|
is_related_controller!
|
||||||
|
|
||||||
|
belongs_to :user, :optional => true
|
||||||
|
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
before_filter :find_group, :only => [:show, :edit, :update, :destroy]
|
before_filter :find_group, :only => [:show, :edit, :update, :destroy]
|
||||||
|
|
||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@groups = Group.paginate(:page => params[:group_page])
|
puts parent.inspect
|
||||||
|
@groups = if parent? and !parent.nil?
|
||||||
|
parent.groups
|
||||||
|
else
|
||||||
|
Group
|
||||||
|
end.accessible_by(current_ability)
|
||||||
|
|
||||||
|
@groups = if params[:query]
|
||||||
|
@groups.where(["name LIKE ?", "%#{params[:query]}%"])
|
||||||
|
else
|
||||||
|
@groups
|
||||||
|
end.paginate(:page => params[:group_page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
@ -24,13 +39,18 @@ class GroupsController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@group = Group.new params[:group]
|
@group = Group.new params[:group]
|
||||||
@group.owner = current_user
|
@group.owner = if parent? and parent.is_a? User
|
||||||
@group.members << current_user
|
parent
|
||||||
if @group.save
|
else
|
||||||
|
current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
if @group.save!
|
||||||
flash[:notice] = t('flash.group.saved')
|
flash[:notice] = t('flash.group.saved')
|
||||||
redirect_to edit_group_path(@group)
|
redirect_to edit_group_path(@group)
|
||||||
else
|
else
|
||||||
flash[:error] = t('flash.group.save_error')
|
flash[:error] = t('flash.group.save_error')
|
||||||
|
flash[:warning] = @project.errors[:base]
|
||||||
render :action => :new
|
render :action => :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
class MembersController < ApplicationController
|
||||||
|
before_filter :authenticate_user!
|
||||||
|
is_related_controller!
|
||||||
|
|
||||||
|
belongs_to :group, :optional => true
|
||||||
|
|
||||||
|
# before_filter :find_target
|
||||||
|
before_filter :find_users
|
||||||
|
|
||||||
|
def index
|
||||||
|
redirect_to edit_group_members_path(parent)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
if params[:id]
|
||||||
|
@user = User.find params[:id]
|
||||||
|
render :edit_rights and return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
all_user_ids = []
|
||||||
|
Relation::ROLES.each { |r|
|
||||||
|
all_user_ids = all_user_ids | params[r.to_sym].keys if params[r.to_sym]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove relations
|
||||||
|
users_for_removing = parent.members.select do |u|
|
||||||
|
!all_user_ids.map{|k| k.to_i}.include? u.id and parent.owner != u
|
||||||
|
end
|
||||||
|
users_for_removing.each do |u|
|
||||||
|
Relation.by_object(u).by_target(parent).each {|r| r.destroy}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create relations
|
||||||
|
Relation::ROLES.each { |r|
|
||||||
|
#users_for_creating = users_for_creating params[:user].keys.map{|p| p.to_i} - @project.collaborators.map(&:id)
|
||||||
|
params[r.to_sym].keys.each { |u|
|
||||||
|
if relation = parent.objects.find_by_object_id_and_object_type(u, 'User')
|
||||||
|
relation.update_attribute(:role, r)
|
||||||
|
else
|
||||||
|
relation = parent.objects.build(:object_id => u, :object_type => 'User', :role => r)
|
||||||
|
puts relation.inspect
|
||||||
|
puts r
|
||||||
|
relation.save!
|
||||||
|
end
|
||||||
|
} if params[r.to_sym]
|
||||||
|
}
|
||||||
|
|
||||||
|
if parent.save
|
||||||
|
flash[:notice] = t("flash.members.successfully_changed")
|
||||||
|
else
|
||||||
|
flash[:error] = t("flash.members.error_in_changing")
|
||||||
|
end
|
||||||
|
redirect_to parent_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def find_users
|
||||||
|
@users = User.all
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,4 +1,8 @@
|
||||||
class ProjectsController < ApplicationController
|
class ProjectsController < ApplicationController
|
||||||
|
is_related_controller!
|
||||||
|
|
||||||
|
belongs_to :user, :group, :polymorphic => true, :optional => true
|
||||||
|
|
||||||
before_filter :authenticate_user!, :except => :auto_build
|
before_filter :authenticate_user!, :except => :auto_build
|
||||||
before_filter :find_project, :only => [:show, :edit, :update, :destroy, :fork, :build, :process_build]
|
before_filter :find_project, :only => [:show, :edit, :update, :destroy, :fork, :build, :process_build]
|
||||||
before_filter :get_paths, :only => [:new, :create, :edit, :update]
|
before_filter :get_paths, :only => [:new, :create, :edit, :update]
|
||||||
|
@ -6,12 +10,20 @@ class ProjectsController < ApplicationController
|
||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params[:query]
|
# puts parent.inspect
|
||||||
@projects = Project.accessible_by(current_ability).where(:name => params[:query]).paginate(:page => params[:project_page])
|
# puts parent.is_a? User
|
||||||
else
|
@projects = if parent? and !parent.nil?
|
||||||
@projects = Project.accessible_by(current_ability).paginate(:page => params[:project_page])
|
parent.projects
|
||||||
end
|
else
|
||||||
|
Project
|
||||||
|
end.accessible_by(current_ability)
|
||||||
|
|
||||||
|
@projects = if params[:query]
|
||||||
|
@projects.where(["name LIKE ?", "%#{params[:query]}%"])
|
||||||
|
else
|
||||||
|
@projects
|
||||||
|
end.paginate(:page => params[:project_page])
|
||||||
|
|
||||||
@own_projects = current_user.own_projects
|
@own_projects = current_user.own_projects
|
||||||
@part_projects = current_user.projects - @own_projects
|
@part_projects = current_user.projects - @own_projects
|
||||||
end
|
end
|
||||||
|
@ -30,6 +42,7 @@ class ProjectsController < ApplicationController
|
||||||
def create
|
def create
|
||||||
@project = Project.new params[:project]
|
@project = Project.new params[:project]
|
||||||
@project.owner = get_owner
|
@project.owner = get_owner
|
||||||
|
# puts @project.owner.inspect
|
||||||
|
|
||||||
if @project.save
|
if @project.save
|
||||||
flash[:notice] = t('flash.project.saved')
|
flash[:notice] = t('flash.project.saved')
|
||||||
|
@ -46,7 +59,7 @@ class ProjectsController < ApplicationController
|
||||||
flash[:notice] = t('flash.project.saved')
|
flash[:notice] = t('flash.project.saved')
|
||||||
redirect_to @project
|
redirect_to @project
|
||||||
else
|
else
|
||||||
@project.save!
|
@project.save
|
||||||
flash[:error] = t('flash.project.save_error')
|
flash[:error] = t('flash.project.save_error')
|
||||||
render :action => :edit
|
render :action => :edit
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,12 +29,19 @@ class Ability
|
||||||
can [:index, :destroy], AutoBuildList, :project_id => user.own_project_ids
|
can [:index, :destroy], AutoBuildList, :project_id => user.own_project_ids
|
||||||
# If rules goes one by one CanCan joins them by 'OR' sql operator
|
# If rules goes one by one CanCan joins them by 'OR' sql operator
|
||||||
can :read, Project, :visibility => 'open'
|
can :read, Project, :visibility => 'open'
|
||||||
|
can :read, Group
|
||||||
can :read, User
|
can :read, User
|
||||||
can :manage_collaborators, Project do |project|
|
can :manage_collaborators, Project do |project|
|
||||||
project.relations.exists? :object_id => user.id, :object_type => 'User', :role => 'admin'
|
project.relations.exists? :object_id => user.id, :object_type => 'User', :role => 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
can :manage_members, Group do |group|
|
||||||
|
group.objects.exists? :object_id => user.id, :object_type => 'User', :role => 'admin'
|
||||||
|
end
|
||||||
|
|
||||||
# Put here model names which objects can user create
|
# Put here model names which objects can user create
|
||||||
can :create, Project
|
can :create, Project
|
||||||
|
can :create, Group
|
||||||
can :publish, BuildList do |build_list|
|
can :publish, BuildList do |build_list|
|
||||||
build_list.can_published? && build_list.project.relations.exists?(:object_type => 'User', :object_id => user.id)
|
build_list.can_published? && build_list.project.relations.exists?(:object_type => 'User', :object_id => user.id)
|
||||||
end
|
end
|
||||||
|
@ -60,6 +67,10 @@ class Ability
|
||||||
product.platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
|
product.platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
can [:read, :update], Group, groups_in_relations_with(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id) do |group|
|
||||||
|
group.objects.exists?(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id)
|
||||||
|
end
|
||||||
|
|
||||||
can :manage, Platform, :owner_type => 'User', :owner_id => user.id
|
can :manage, Platform, :owner_type => 'User', :owner_id => user.id
|
||||||
can :manage, Platform, platforms_in_relations_with(:role => 'admin', :object_type => 'User', :object_id => user.id) do |platform|
|
can :manage, Platform, platforms_in_relations_with(:role => 'admin', :object_type => 'User', :object_id => user.id) do |platform|
|
||||||
platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
|
platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
|
||||||
|
@ -128,7 +139,7 @@ class Ability
|
||||||
|
|
||||||
# Sub query for platforms, projects relations
|
# Sub query for platforms, projects relations
|
||||||
# TODO: Replace table names list by method_missing way
|
# TODO: Replace table names list by method_missing way
|
||||||
%w[platforms projects products repositories].each do |table_name|
|
%w[platforms projects products repositories groups].each do |table_name|
|
||||||
define_method table_name + "_in_relations_with" do |opts|
|
define_method table_name + "_in_relations_with" do |opts|
|
||||||
query = "#{ table_name }.id IN (SELECT target_id FROM relations WHERE relations.target_type = '#{ table_name.singularize.camelize }'"
|
query = "#{ table_name }.id IN (SELECT target_id FROM relations WHERE relations.target_type = '#{ table_name.singularize.camelize }'"
|
||||||
opts.each do |key, value|
|
opts.each do |key, value|
|
||||||
|
|
|
@ -20,6 +20,14 @@ class Group < ActiveRecord::Base
|
||||||
|
|
||||||
delegate :ssh_key, :to => :owner
|
delegate :ssh_key, :to => :owner
|
||||||
|
|
||||||
|
after_create :add_owner_to_members
|
||||||
|
|
||||||
include Modules::Models::PersonalRepository
|
include Modules::Models::PersonalRepository
|
||||||
include Modules::Models::Owner
|
include Modules::Models::Owner
|
||||||
|
|
||||||
|
protected
|
||||||
|
def add_owner_to_members
|
||||||
|
Relation.create_with_role(self.owner, self, 'admin')
|
||||||
|
# members << self.owner if !members.exists?(:id => self.owner.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,21 @@ class Relation < ActiveRecord::Base
|
||||||
ROLES = %w[reader writer admin]
|
ROLES = %w[reader writer admin]
|
||||||
validates :role, :inclusion => {:in => ROLES}
|
validates :role, :inclusion => {:in => ROLES}
|
||||||
|
|
||||||
|
before_validation :add_default_role
|
||||||
|
|
||||||
scope :by_object, lambda {|obj| {:conditions => ['object_id = ? AND object_type = ?', obj.id, obj.class.to_s]}}
|
scope :by_object, lambda {|obj| {:conditions => ['object_id = ? AND object_type = ?', obj.id, obj.class.to_s]}}
|
||||||
scope :by_target, lambda {|tar| {:conditions => ['target_id = ? AND target_type = ?', tar.id, tar.class.to_s]}}
|
scope :by_target, lambda {|tar| {:conditions => ['target_id = ? AND target_type = ?', tar.id, tar.class.to_s]}}
|
||||||
|
|
||||||
|
def self.create_with_role(object, target, role)
|
||||||
|
r = new
|
||||||
|
r.object = object
|
||||||
|
r.target = target
|
||||||
|
r.role = role
|
||||||
|
r.save
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def add_default_role
|
||||||
|
self.role = ROLES.first if role.nil? || role.empty?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,28 +22,29 @@
|
||||||
= link_to user.name, user_path(user)
|
= link_to user.name, user_path(user)
|
||||||
%td
|
%td
|
||||||
- Relation::ROLES.each do |role|
|
- Relation::ROLES.each do |role|
|
||||||
= check_box_tag "#{ role }[#{user.id}]", '1', ((@project.relations.exists? :object_id => user.id, :object_type => 'User', :role => role) ? :checked : nil), {:class => "user_role_chbx"}
|
= check_box_tag "user[#{ role }][#{user.id}]", '1', ((@project.relations.exists? :object_id => user.id, :object_type => 'User', :role => role) ? :checked : nil), {:class => "user_role_chbx"}
|
||||||
= label_tag "#{ role }[#{user.id}]", t("layout.collaborators.roles.#{ role }")
|
= label_tag "user[#{ role }][#{user.id}]", t("layout.collaborators.roles.#{ role }")
|
||||||
%td
|
%td
|
||||||
= user.uname
|
= user.uname
|
||||||
/%h2.title= t("layout.groups.list_header")
|
%h2.title= t("layout.groups.list_header")
|
||||||
/%table.table
|
%table.table
|
||||||
/ %tr
|
%tr
|
||||||
/ %th.first ID
|
%th.first ID
|
||||||
/ %th= t("activerecord.attributes.group.name")
|
%th= t("activerecord.attributes.group.name")
|
||||||
/ %th= t("activerecord.attributes.group.uname")
|
%th= t("activerecord.attributes.group.uname")
|
||||||
/ %th.last= t("layout.collaborators.add")
|
%th.last= t("layout.collaborators.add")
|
||||||
/ - @groups.each do |group|
|
- @groups.each do |group|
|
||||||
/ %tr{:class => cycle("odd", "even")}
|
%tr{:class => cycle("odd", "even")}
|
||||||
/ %td
|
%td
|
||||||
/ = group.id
|
= group.id
|
||||||
/ %td
|
%td
|
||||||
/ = link_to group.name, group_path(group)
|
= link_to group.name, group_path(group)
|
||||||
/ %td
|
%td
|
||||||
/ = group.uname
|
- Relation::ROLES.each do |role|
|
||||||
/ %td.last
|
= check_box_tag "group[#{role}][#{group.id}]", '1', ((@project.relations.exists? :object_id => group.id, :object_type => 'Group', :role => role) ? :checked : nil), {:class => "user_role_chbx"}
|
||||||
/ = check_box_tag "group[#{group.id}]", '1', (@project.groups.include? group) ? :checked : nil
|
= label_tag "group[#{role}][#{group.id}]", t("layout.collaborators.roles.#{role}")
|
||||||
/ = label_tag "group[#{group.id}]", t("layout.collaborators.add")
|
%td
|
||||||
|
= group.uname
|
||||||
.group.navform.wat-cf
|
.group.navform.wat-cf
|
||||||
%button.button{:type => "submit"}
|
%button.button{:type => "submit"}
|
||||||
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
|
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
.block.notice
|
.block.notice
|
||||||
%h3= t("layout.groups.members")
|
%h3= t("layout.groups.members")
|
||||||
.content
|
.content
|
||||||
- @group.members.each do |member|
|
%p
|
||||||
%p= link_to member.name, member
|
%ul
|
||||||
|
- @group.members.each do |user|
|
||||||
|
%li
|
||||||
|
- if can? :read, user
|
||||||
|
= link_to user.name, user_path(user)
|
||||||
|
- else
|
||||||
|
= user.name
|
||||||
|
- if (@group.owner == user)
|
||||||
|
= '(' + t("layout.owner") + ')'
|
||||||
|
%br
|
||||||
|
= link_to t("layout.groups.edit_members"), edit_group_members_path(@group) if can? :manage_members, @group
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
-if can? :index, Project
|
-if can? :index, Project
|
||||||
%li{:class => controller.controller_path == 'projects' ? 'active' : '' }
|
%li{:class => controller.controller_path == 'projects' ? 'active' : '' }
|
||||||
%a{:href => projects_path}= t("layout.menu.projects")
|
%a{:href => projects_path}= t("layout.menu.projects")
|
||||||
|
-if can? :index, Group
|
||||||
|
%li{:class => controller.controller_path == 'groups' ? 'active' : '' }
|
||||||
|
%a{:href => groups_path}= t("layout.menu.groups")
|
||||||
-if can? :index, Download
|
-if can? :index, Download
|
||||||
%li{:class => controller.controller_path == 'downloads' ? 'active' : '' }
|
%li{:class => controller.controller_path == 'downloads' ? 'active' : '' }
|
||||||
%a{:href => downloads_path}= t("layout.menu.downloads")
|
%a{:href => downloads_path}= t("layout.menu.downloads")
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
.block
|
||||||
|
.secondary-navigation
|
||||||
|
%ul.wat-cf
|
||||||
|
%li.first= link_to t("layout.members.back_to_group"), parent_path
|
||||||
|
%li.active= link_to t("layout.members.edit"), edit_group_members_path(@group)
|
||||||
|
.content
|
||||||
|
.inner
|
||||||
|
= form_tag group_members_path(parent) do
|
||||||
|
%h2.title= t("layout.users.list_header")
|
||||||
|
%table.table
|
||||||
|
%tr
|
||||||
|
%th.first ID
|
||||||
|
%th= t("activerecord.attributes.user.name")
|
||||||
|
%th= t("activerecord.attributes.user.roles")
|
||||||
|
%th= t("activerecord.attributes.user.uname")
|
||||||
|
- #TODO: Replace this Chelyabinsk add/remove collaborators method by more human method
|
||||||
|
- @users.each do |user|
|
||||||
|
%tr{:class => cycle("odd", "even")}
|
||||||
|
%td
|
||||||
|
= user.id
|
||||||
|
%td
|
||||||
|
= link_to user.name, user_path(user)
|
||||||
|
%td
|
||||||
|
- Relation::ROLES.each do |role|
|
||||||
|
= check_box_tag "#{ role }[#{user.id}]", '1', ((parent.relations.exists? :object_id => user.id, :object_type => 'User', :role => role) ? :checked : nil), {:class => "user_role_chbx"}
|
||||||
|
= label_tag "#{ role }[#{user.id}]", t("layout.members.roles.#{ role }")
|
||||||
|
%td
|
||||||
|
= user.uname
|
||||||
|
.group.navform.wat-cf
|
||||||
|
%button.button{:type => "submit"}
|
||||||
|
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
|
||||||
|
= t("layout.save")
|
||||||
|
%span.text_button_padding= t("layout.or")
|
||||||
|
= link_to t("layout.cancel"), group_path(parent), :class => "text_button_padding link_button"
|
||||||
|
|
|
@ -13,8 +13,18 @@
|
||||||
= user.name
|
= user.name
|
||||||
- if (@project.owner == user)
|
- if (@project.owner == user)
|
||||||
= '(' + t("layout.owner") + ')'
|
= '(' + t("layout.owner") + ')'
|
||||||
%br
|
/%br
|
||||||
-# if can? :update, @project
|
-# if can? :update, @project
|
||||||
|
%p
|
||||||
|
%b
|
||||||
|
= "#{t("layout.projects.groups")}:"
|
||||||
|
%ul
|
||||||
|
- @project.groups.each do |group|
|
||||||
|
%li
|
||||||
|
= link_to group.name, group_path(group)
|
||||||
|
- if (@project.owner == group)
|
||||||
|
= '(' + t("layout.owner") + ')'
|
||||||
|
%br
|
||||||
= link_to t("layout.projects.edit_collaborators"), edit_project_collaborators_path(@project) if can? :manage_collaborators, @project
|
= link_to t("layout.projects.edit_collaborators"), edit_project_collaborators_path(@project) if can? :manage_collaborators, @project
|
||||||
|
|
||||||
/ %p
|
/ %p
|
||||||
|
|
|
@ -223,6 +223,10 @@ ru:
|
||||||
roles_header: Роли для
|
roles_header: Роли для
|
||||||
add_role: Добавить/Удалить роль
|
add_role: Добавить/Удалить роль
|
||||||
|
|
||||||
|
members:
|
||||||
|
back_to_group: Вернуться к группе
|
||||||
|
edit: Редактировать список
|
||||||
|
roles: Роли
|
||||||
|
|
||||||
groups:
|
groups:
|
||||||
list: Список
|
list: Список
|
||||||
|
@ -235,6 +239,7 @@ ru:
|
||||||
show: Группа
|
show: Группа
|
||||||
back_to_the_list: ⇐ К списку групп
|
back_to_the_list: ⇐ К списку групп
|
||||||
confirm_delete: Вы уверены, что хотите удалить эту группу?
|
confirm_delete: Вы уверены, что хотите удалить эту группу?
|
||||||
|
edit_members: Изменить список участников
|
||||||
|
|
||||||
users:
|
users:
|
||||||
list: Список
|
list: Список
|
||||||
|
@ -321,6 +326,10 @@ ru:
|
||||||
successfully_changed: Список коллабораторов успешно изменен
|
successfully_changed: Список коллабораторов успешно изменен
|
||||||
error_in_changing: Ошибка изменения списка коллабораторов
|
error_in_changing: Ошибка изменения списка коллабораторов
|
||||||
|
|
||||||
|
members:
|
||||||
|
successfully_changed: Список участников успешно изменен
|
||||||
|
error_in_changing: Ошибка изменения списка участников
|
||||||
|
|
||||||
auto_build_list:
|
auto_build_list:
|
||||||
success: Сборка проекта автоматизорована!
|
success: Сборка проекта автоматизорована!
|
||||||
failed: Не удалось автоматизировать сборку!
|
failed: Не удалось автоматизировать сборку!
|
||||||
|
|
|
@ -6,7 +6,9 @@ Rosa::Application.routes.draw do
|
||||||
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
|
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :users
|
resources :users do
|
||||||
|
resources :groups, :only => [:new, :create, :index]
|
||||||
|
end
|
||||||
|
|
||||||
resources :event_logs, :only => :index
|
resources :event_logs, :only => :index
|
||||||
|
|
||||||
|
@ -105,10 +107,22 @@ Rosa::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :groups do
|
||||||
|
resources :members, :only => [:index, :edit, :update] do
|
||||||
|
collection do
|
||||||
|
get :edit
|
||||||
|
post :update
|
||||||
|
end
|
||||||
|
member do
|
||||||
|
post :update
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
resources :users, :groups do
|
resources :users, :groups do
|
||||||
resources :platforms, :only => [:new, :create]
|
resources :platforms, :only => [:new, :create]
|
||||||
|
|
||||||
resources :projects, :only => [:new, :create]
|
resources :projects, :only => [:new, :create, :index]
|
||||||
|
|
||||||
resources :repositories, :only => [:new, :create]
|
resources :repositories, :only => [:new, :create]
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (c) 2011 [name of plugin creator]
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,13 @@
|
||||||
|
RelatedModels
|
||||||
|
=============
|
||||||
|
|
||||||
|
Introduction goes here.
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
=======
|
||||||
|
|
||||||
|
Example goes here.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2011 [name of plugin creator], released under the MIT license
|
|
@ -0,0 +1,23 @@
|
||||||
|
require 'rake'
|
||||||
|
require 'rake/testtask'
|
||||||
|
require 'rdoc/task'
|
||||||
|
|
||||||
|
desc 'Default: run unit tests.'
|
||||||
|
task :default => :test
|
||||||
|
|
||||||
|
desc 'Test the related_models plugin.'
|
||||||
|
Rake::TestTask.new(:test) do |t|
|
||||||
|
t.libs << 'lib'
|
||||||
|
t.libs << 'test'
|
||||||
|
t.pattern = 'test/**/*_test.rb'
|
||||||
|
t.verbose = true
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Generate documentation for the related_models plugin.'
|
||||||
|
RDoc::Task.new(:rdoc) do |rdoc|
|
||||||
|
rdoc.rdoc_dir = 'rdoc'
|
||||||
|
rdoc.title = 'RelatedModels'
|
||||||
|
rdoc.options << '--line-numbers' << '--inline-source'
|
||||||
|
rdoc.rdoc_files.include('README')
|
||||||
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||||
|
end
|
|
@ -0,0 +1,23 @@
|
||||||
|
module RelatedModels
|
||||||
|
class Base < ::ApplicationController
|
||||||
|
def self.is_child!(base)
|
||||||
|
base.class_eval do
|
||||||
|
# include InheritedResources::Actions
|
||||||
|
# include InheritedResources::BaseHelpers
|
||||||
|
extend RelatedModels::ClassMethods
|
||||||
|
extend RelatedModels::UrlHelpers
|
||||||
|
|
||||||
|
helper_method :parent_url, :parent_path
|
||||||
|
|
||||||
|
self.class_attribute :parents_symbols, :resources_configuration, :instance_writer => false
|
||||||
|
|
||||||
|
self.parents_symbols ||= []
|
||||||
|
self.resources_configuration ||= {}
|
||||||
|
|
||||||
|
protected :parents_symbols, :resources_configuration, :parents_symbols?, :resources_configuration?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
is_child!(self)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Include hook code here
|
||||||
|
require 'related_models'
|
|
@ -0,0 +1 @@
|
||||||
|
# Install hook code here
|
|
@ -0,0 +1,14 @@
|
||||||
|
# RelatedModels
|
||||||
|
module RelatedModels
|
||||||
|
autoload :ClassMethods, 'related_models/class_methods'
|
||||||
|
autoload :BelongsToHelpers, 'related_models/belongs_to_helpers'
|
||||||
|
autoload :PolymorphicHelpers, 'related_models/polymorphic_helpers'
|
||||||
|
autoload :UrlHelpers, 'related_models/url_helpers'
|
||||||
|
end
|
||||||
|
|
||||||
|
class ActionController::Base
|
||||||
|
#include ClassMethods
|
||||||
|
def self.is_related_controller!
|
||||||
|
RelatedModels::Base.is_child!(self)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,39 @@
|
||||||
|
module RelatedModels
|
||||||
|
module BelongsToHelpers
|
||||||
|
protected
|
||||||
|
def parent?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent
|
||||||
|
@parent ||= find_parent
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent_type
|
||||||
|
parent.class.name.underscore.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def symbols_for_association_chain
|
||||||
|
parents_symbols.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_parent
|
||||||
|
k = params.symbolize_keys.keys
|
||||||
|
res = nil
|
||||||
|
|
||||||
|
symbols_for_association_chain.reverse.each do |sym|
|
||||||
|
if k.include? resources_configuration[sym][:param]
|
||||||
|
parent_config = resources_configuration[sym]
|
||||||
|
res = parent_config[:parent_class].send(parent_config[:finder], params[parent_config[:param]])
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unless res
|
||||||
|
raise "Couldn't find parent"
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,68 @@
|
||||||
|
module RelatedModels
|
||||||
|
module ClassMethods
|
||||||
|
protected
|
||||||
|
def belongs_to(*symbols)
|
||||||
|
options = symbols.extract_options!
|
||||||
|
|
||||||
|
options.symbolize_keys!
|
||||||
|
options.assert_valid_keys(:polymorphic, :optional, :finder)
|
||||||
|
|
||||||
|
optional = options.delete(:optional)
|
||||||
|
polymorphic = options.delete(:polymorphic)
|
||||||
|
finder = options.delete(:finder)
|
||||||
|
|
||||||
|
include BelongsToHelpers if self.parents_symbols.empty?
|
||||||
|
|
||||||
|
acts_as_polymorphic! if polymorphic || optional
|
||||||
|
|
||||||
|
raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
|
||||||
|
raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty?
|
||||||
|
|
||||||
|
symbols.each do |symbol|
|
||||||
|
symbol = symbol.to_sym
|
||||||
|
|
||||||
|
if polymorphic || optional
|
||||||
|
self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic)
|
||||||
|
self.resources_configuration[:polymorphic] ||= {}
|
||||||
|
self.resources_configuration[:polymorphic][:symbols] ||= []
|
||||||
|
|
||||||
|
self.resources_configuration[:polymorphic][:symbols] << symbol
|
||||||
|
self.resources_configuration[:polymorphic][:optional] ||= optional
|
||||||
|
else
|
||||||
|
self.parents_symbols << symbol
|
||||||
|
end
|
||||||
|
|
||||||
|
config = self.resources_configuration[symbol] = {}
|
||||||
|
|
||||||
|
config[:parent_class] = begin
|
||||||
|
class_name = symbol.to_s.pluralize.classify
|
||||||
|
class_name.constantize
|
||||||
|
rescue NameError => e
|
||||||
|
raise unless e.message.include?(class_name)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
config[:collection_name] = symbol.to_s.pluralize.to_sym
|
||||||
|
config[:instance_name] = symbol
|
||||||
|
config[:param] = :"#{symbol}_id"
|
||||||
|
config[:route_name] = symbol
|
||||||
|
config[:finder] = finder || :find
|
||||||
|
end
|
||||||
|
|
||||||
|
create_resources_url_helpers!
|
||||||
|
helper_method :parent, :parent?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def acts_as_polymorphic! #:nodoc:
|
||||||
|
unless self.parents_symbols.include?(:polymorphic)
|
||||||
|
include PolymorphicHelpers
|
||||||
|
helper_method :parent_type, :parent_class
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def inherited(base)
|
||||||
|
super(base)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,80 @@
|
||||||
|
module RelatedModels
|
||||||
|
module PolymorphicHelpers
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
# Returns the parent type. A Comments class can have :task, :file, :note
|
||||||
|
# as parent types.
|
||||||
|
#
|
||||||
|
def parent_type
|
||||||
|
@parent_type
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent_class
|
||||||
|
parent.class if @parent_type
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the parent object. They are also available with the instance
|
||||||
|
# variable name: @task, @file, @note...
|
||||||
|
#
|
||||||
|
def parent
|
||||||
|
k = params.symbolize_keys.keys
|
||||||
|
res = nil
|
||||||
|
|
||||||
|
symbols_for_association_chain.reverse.each do |sym|
|
||||||
|
if k.include? resources_configuration[sym][:param]
|
||||||
|
parent_config = resources_configuration[sym]
|
||||||
|
res = parent_config[:parent_class].send(parent_config[:finder], params[parent_config[:param]])
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
# If the polymorphic association is optional, we might not have a parent.
|
||||||
|
#
|
||||||
|
def parent?
|
||||||
|
if resources_configuration[:polymorphic][:optional]
|
||||||
|
parents_symbols.size > 1 || !@parent_type.nil?
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Maps parents_symbols to build association chain.
|
||||||
|
#
|
||||||
|
# If the parents_symbols find :polymorphic, it goes through the
|
||||||
|
# params keys to see which polymorphic parent matches the given params.
|
||||||
|
#
|
||||||
|
# When optional is given, it does not raise errors if the polymorphic
|
||||||
|
# params are missing.
|
||||||
|
#
|
||||||
|
def symbols_for_association_chain #:nodoc:
|
||||||
|
polymorphic_config = resources_configuration[:polymorphic]
|
||||||
|
parents_symbols.map do |symbol|
|
||||||
|
if symbol == :polymorphic
|
||||||
|
params_keys = params.keys
|
||||||
|
|
||||||
|
keys = polymorphic_config[:symbols].map do |poly|
|
||||||
|
params_keys.include?(resources_configuration[poly][:param].to_s) ? poly : nil
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
if keys.empty?
|
||||||
|
raise ScriptError, "Could not find param for polymorphic association. The request" <<
|
||||||
|
"parameters are #{params.keys.inspect} and the polymorphic " <<
|
||||||
|
"associations are #{polymorphic_config[:symbols].inspect}." unless polymorphic_config[:optional]
|
||||||
|
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
@parent_type = keys[-1].to_sym
|
||||||
|
@parent_types = keys.map(&:to_sym)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
symbol
|
||||||
|
end
|
||||||
|
end.flatten.compact
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
module RelatedModels
|
||||||
|
module UrlHelpers
|
||||||
|
protected
|
||||||
|
|
||||||
|
def create_resources_url_helpers!
|
||||||
|
segment = if parents_symbols.include? :polymorphic
|
||||||
|
:polymorphic
|
||||||
|
else
|
||||||
|
resources_configuration[symbols_for_association_chain.first][:route_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
unless parent.nil?
|
||||||
|
class_eval <<-URL_HELPERS, __FILE__, __LINE__
|
||||||
|
protected
|
||||||
|
def parent_path(*given_args)
|
||||||
|
given_options = given_args.extract_options!
|
||||||
|
#{segment}_path(parent, given_options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent_url(*given_args)
|
||||||
|
given_options = given_args.extract_options!
|
||||||
|
#{segment}_url(parent, given_options)
|
||||||
|
end
|
||||||
|
URL_HELPERS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,8 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class RelatedModelsTest < ActiveSupport::TestCase
|
||||||
|
# Replace this with your real tests.
|
||||||
|
test "the truth" do
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
require 'rubygems'
|
||||||
|
require 'test/unit'
|
||||||
|
require 'active_support'
|
|
@ -0,0 +1 @@
|
||||||
|
# Uninstall hook code here
|
Loading…
Reference in New Issue