From 600a8974909f0cf95fc9fcdbb10dca8179f00433 Mon Sep 17 00:00:00 2001 From: George Vinogradov Date: Fri, 21 Oct 2011 19:39:32 +0400 Subject: [PATCH 1/3] Added route to roles controller. --- Gemfile | 4 ++-- Gemfile.lock | 2 ++ config/routes.rb | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index c2aae76a5..b04da7ff6 100644 --- a/Gemfile +++ b/Gemfile @@ -39,8 +39,8 @@ group :development do gem 'ruby-debug' # gem 'looksee' # gem 'awesome_print' - # gem 'wirble' - # gem 'hirb' + gem 'wirble' + gem 'hirb' # gem 'rails-footnotes', '>= 3.7.5.rc4' # this shit is very buggy don't forget to switch it off back # deploy diff --git a/Gemfile.lock b/Gemfile.lock index 6c351be91..f809dfee0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -242,6 +242,7 @@ GEM activesupport (>= 2.3.4) chronic (~> 0.6.3) will_paginate (3.0.2) + wirble (0.1.3) yui-compressor (0.9.5) PLATFORMS @@ -277,4 +278,5 @@ DEPENDENCIES web-app-theme whenever will_paginate (~> 3.0.2) + wirble yui-compressor (= 0.9.5) diff --git a/config/routes.rb b/config/routes.rb index 2b479b21d..8d4ad2891 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,6 +4,8 @@ Rosa::Application.routes.draw do end resources :users + resources :roles + resources :event_logs, :only => :index resources :downloads, :only => :index From a69b55502d945730ba20b7c7855c0aae838429bc Mon Sep 17 00:00:00 2001 From: George Vinogradov Date: Fri, 21 Oct 2011 19:41:03 +0400 Subject: [PATCH 2/3] Added specs form merged branches --- spec/routing/permissions_routing_spec.rb | 35 +++++++++++++++++++ spec/routing/rights_routing_spec.rb | 35 +++++++++++++++++++ spec/routing/roles_routing_spec.rb | 35 +++++++++++++++++++ spec/views/permissions/edit.html.haml_spec.rb | 22 ++++++++++++ .../views/permissions/index.html.haml_spec.rb | 28 +++++++++++++++ spec/views/permissions/new.html.haml_spec.rb | 22 ++++++++++++ spec/views/permissions/show.html.haml_spec.rb | 21 +++++++++++ spec/views/rights/edit.html.haml_spec.rb | 22 ++++++++++++ spec/views/rights/index.html.haml_spec.rb | 28 +++++++++++++++ spec/views/rights/new.html.haml_spec.rb | 22 ++++++++++++ spec/views/rights/show.html.haml_spec.rb | 21 +++++++++++ spec/views/roles/edit.html.haml_spec.rb | 18 ++++++++++ spec/views/roles/index.html.haml_spec.rb | 20 +++++++++++ spec/views/roles/new.html.haml_spec.rb | 18 ++++++++++ spec/views/roles/show.html.haml_spec.rb | 15 ++++++++ test/integration/permission_test.rb | 10 ++++++ test/integration/right_test.rb | 10 ++++++ test/integration/role_test.rb | 10 ++++++ 18 files changed, 392 insertions(+) create mode 100644 spec/routing/permissions_routing_spec.rb create mode 100644 spec/routing/rights_routing_spec.rb create mode 100644 spec/routing/roles_routing_spec.rb create mode 100644 spec/views/permissions/edit.html.haml_spec.rb create mode 100644 spec/views/permissions/index.html.haml_spec.rb create mode 100644 spec/views/permissions/new.html.haml_spec.rb create mode 100644 spec/views/permissions/show.html.haml_spec.rb create mode 100644 spec/views/rights/edit.html.haml_spec.rb create mode 100644 spec/views/rights/index.html.haml_spec.rb create mode 100644 spec/views/rights/new.html.haml_spec.rb create mode 100644 spec/views/rights/show.html.haml_spec.rb create mode 100644 spec/views/roles/edit.html.haml_spec.rb create mode 100644 spec/views/roles/index.html.haml_spec.rb create mode 100644 spec/views/roles/new.html.haml_spec.rb create mode 100644 spec/views/roles/show.html.haml_spec.rb create mode 100644 test/integration/permission_test.rb create mode 100644 test/integration/right_test.rb create mode 100644 test/integration/role_test.rb diff --git a/spec/routing/permissions_routing_spec.rb b/spec/routing/permissions_routing_spec.rb new file mode 100644 index 000000000..287f50156 --- /dev/null +++ b/spec/routing/permissions_routing_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe PermissionsController do + describe "routing" do + + it "routes to #index" do + get("/permissions").should route_to("permissions#index") + end + + it "routes to #new" do + get("/permissions/new").should route_to("permissions#new") + end + + it "routes to #show" do + get("/permissions/1").should route_to("permissions#show", :id => "1") + end + + it "routes to #edit" do + get("/permissions/1/edit").should route_to("permissions#edit", :id => "1") + end + + it "routes to #create" do + post("/permissions").should route_to("permissions#create") + end + + it "routes to #update" do + put("/permissions/1").should route_to("permissions#update", :id => "1") + end + + it "routes to #destroy" do + delete("/permissions/1").should route_to("permissions#destroy", :id => "1") + end + + end +end diff --git a/spec/routing/rights_routing_spec.rb b/spec/routing/rights_routing_spec.rb new file mode 100644 index 000000000..5ae75a976 --- /dev/null +++ b/spec/routing/rights_routing_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe RightsController do + describe "routing" do + + it "routes to #index" do + get("/rights").should route_to("rights#index") + end + + it "routes to #new" do + get("/rights/new").should route_to("rights#new") + end + + it "routes to #show" do + get("/rights/1").should route_to("rights#show", :id => "1") + end + + it "routes to #edit" do + get("/rights/1/edit").should route_to("rights#edit", :id => "1") + end + + it "routes to #create" do + post("/rights").should route_to("rights#create") + end + + it "routes to #update" do + put("/rights/1").should route_to("rights#update", :id => "1") + end + + it "routes to #destroy" do + delete("/rights/1").should route_to("rights#destroy", :id => "1") + end + + end +end diff --git a/spec/routing/roles_routing_spec.rb b/spec/routing/roles_routing_spec.rb new file mode 100644 index 000000000..4084a6e7e --- /dev/null +++ b/spec/routing/roles_routing_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe RolesController do + describe "routing" do + + it "routes to #index" do + get("/roles").should route_to("roles#index") + end + + it "routes to #new" do + get("/roles/new").should route_to("roles#new") + end + + it "routes to #show" do + get("/roles/1").should route_to("roles#show", :id => "1") + end + + it "routes to #edit" do + get("/roles/1/edit").should route_to("roles#edit", :id => "1") + end + + it "routes to #create" do + post("/roles").should route_to("roles#create") + end + + it "routes to #update" do + put("/roles/1").should route_to("roles#update", :id => "1") + end + + it "routes to #destroy" do + delete("/roles/1").should route_to("roles#destroy", :id => "1") + end + + end +end diff --git a/spec/views/permissions/edit.html.haml_spec.rb b/spec/views/permissions/edit.html.haml_spec.rb new file mode 100644 index 000000000..05715ddbd --- /dev/null +++ b/spec/views/permissions/edit.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "permissions/edit.html.haml" do + before(:each) do + @permission = assign(:permission, stub_model(Permission, + :role_id => 1, + :right_id => 1, + :access_obj_id => 1 + )) + end + + it "renders the edit permission form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => permissions_path(@permission), :method => "post" do + assert_select "input#permission_role_id", :name => "permission[role_id]" + assert_select "input#permission_right_id", :name => "permission[right_id]" + assert_select "input#permission_access_obj_id", :name => "permission[access_obj_id]" + end + end +end diff --git a/spec/views/permissions/index.html.haml_spec.rb b/spec/views/permissions/index.html.haml_spec.rb new file mode 100644 index 000000000..67d29ede2 --- /dev/null +++ b/spec/views/permissions/index.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe "permissions/index.html.haml" do + before(:each) do + assign(:permissions, [ + stub_model(Permission, + :role_id => 1, + :right_id => 1, + :access_obj_id => 1 + ), + stub_model(Permission, + :role_id => 1, + :right_id => 1, + :access_obj_id => 1 + ) + ]) + end + + it "renders a list of permissions" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => 1.to_s, :count => 2 + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => 1.to_s, :count => 2 + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => 1.to_s, :count => 2 + end +end diff --git a/spec/views/permissions/new.html.haml_spec.rb b/spec/views/permissions/new.html.haml_spec.rb new file mode 100644 index 000000000..151976539 --- /dev/null +++ b/spec/views/permissions/new.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "permissions/new.html.haml" do + before(:each) do + assign(:permission, stub_model(Permission, + :role_id => 1, + :right_id => 1, + :access_obj_id => 1 + ).as_new_record) + end + + it "renders new permission form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => permissions_path, :method => "post" do + assert_select "input#permission_role_id", :name => "permission[role_id]" + assert_select "input#permission_right_id", :name => "permission[right_id]" + assert_select "input#permission_access_obj_id", :name => "permission[access_obj_id]" + end + end +end diff --git a/spec/views/permissions/show.html.haml_spec.rb b/spec/views/permissions/show.html.haml_spec.rb new file mode 100644 index 000000000..0460962bf --- /dev/null +++ b/spec/views/permissions/show.html.haml_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe "permissions/show.html.haml" do + before(:each) do + @permission = assign(:permission, stub_model(Permission, + :role_id => 1, + :right_id => 1, + :access_obj_id => 1 + )) + end + + it "renders attributes in

" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/1/) + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/1/) + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/1/) + end +end diff --git a/spec/views/rights/edit.html.haml_spec.rb b/spec/views/rights/edit.html.haml_spec.rb new file mode 100644 index 000000000..a1a9c538b --- /dev/null +++ b/spec/views/rights/edit.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "rights/edit.html.haml" do + before(:each) do + @right = assign(:right, stub_model(Right, + :controller_name => "MyString", + :method_name => "MyString", + :name => "MyString" + )) + end + + it "renders the edit right form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => rights_path(@right), :method => "post" do + assert_select "input#right_controller_name", :name => "right[controller_name]" + assert_select "input#right_method_name", :name => "right[method_name]" + assert_select "input#right_name", :name => "right[name]" + end + end +end diff --git a/spec/views/rights/index.html.haml_spec.rb b/spec/views/rights/index.html.haml_spec.rb new file mode 100644 index 000000000..2a7129898 --- /dev/null +++ b/spec/views/rights/index.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe "rights/index.html.haml" do + before(:each) do + assign(:rights, [ + stub_model(Right, + :controller_name => "Controller Name", + :method_name => "Method Name", + :name => "Name" + ), + stub_model(Right, + :controller_name => "Controller Name", + :method_name => "Method Name", + :name => "Name" + ) + ]) + end + + it "renders a list of rights" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => "Controller Name".to_s, :count => 2 + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => "Method Name".to_s, :count => 2 + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => "Name".to_s, :count => 2 + end +end diff --git a/spec/views/rights/new.html.haml_spec.rb b/spec/views/rights/new.html.haml_spec.rb new file mode 100644 index 000000000..063a74cd5 --- /dev/null +++ b/spec/views/rights/new.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "rights/new.html.haml" do + before(:each) do + assign(:right, stub_model(Right, + :controller_name => "MyString", + :method_name => "MyString", + :name => "MyString" + ).as_new_record) + end + + it "renders new right form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => rights_path, :method => "post" do + assert_select "input#right_controller_name", :name => "right[controller_name]" + assert_select "input#right_method_name", :name => "right[method_name]" + assert_select "input#right_name", :name => "right[name]" + end + end +end diff --git a/spec/views/rights/show.html.haml_spec.rb b/spec/views/rights/show.html.haml_spec.rb new file mode 100644 index 000000000..81a8a36fa --- /dev/null +++ b/spec/views/rights/show.html.haml_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe "rights/show.html.haml" do + before(:each) do + @right = assign(:right, stub_model(Right, + :controller_name => "Controller Name", + :method_name => "Method Name", + :name => "Name" + )) + end + + it "renders attributes in

" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/Controller Name/) + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/Method Name/) + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/Name/) + end +end diff --git a/spec/views/roles/edit.html.haml_spec.rb b/spec/views/roles/edit.html.haml_spec.rb new file mode 100644 index 000000000..9560395a1 --- /dev/null +++ b/spec/views/roles/edit.html.haml_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe "roles/edit.html.haml" do + before(:each) do + @role = assign(:role, stub_model(Role, + :name => "MyString" + )) + end + + it "renders the edit role form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => roles_path(@role), :method => "post" do + assert_select "input#role_name", :name => "role[name]" + end + end +end diff --git a/spec/views/roles/index.html.haml_spec.rb b/spec/views/roles/index.html.haml_spec.rb new file mode 100644 index 000000000..d0ba6c026 --- /dev/null +++ b/spec/views/roles/index.html.haml_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe "roles/index.html.haml" do + before(:each) do + assign(:roles, [ + stub_model(Role, + :name => "Name" + ), + stub_model(Role, + :name => "Name" + ) + ]) + end + + it "renders a list of roles" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => "Name".to_s, :count => 2 + end +end diff --git a/spec/views/roles/new.html.haml_spec.rb b/spec/views/roles/new.html.haml_spec.rb new file mode 100644 index 000000000..dba3ada41 --- /dev/null +++ b/spec/views/roles/new.html.haml_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe "roles/new.html.haml" do + before(:each) do + assign(:role, stub_model(Role, + :name => "MyString" + ).as_new_record) + end + + it "renders new role form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => roles_path, :method => "post" do + assert_select "input#role_name", :name => "role[name]" + end + end +end diff --git a/spec/views/roles/show.html.haml_spec.rb b/spec/views/roles/show.html.haml_spec.rb new file mode 100644 index 000000000..f49a5a36d --- /dev/null +++ b/spec/views/roles/show.html.haml_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe "roles/show.html.haml" do + before(:each) do + @role = assign(:role, stub_model(Role, + :name => "Name" + )) + end + + it "renders attributes in

" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/Name/) + end +end diff --git a/test/integration/permission_test.rb b/test/integration/permission_test.rb new file mode 100644 index 000000000..41f04d956 --- /dev/null +++ b/test/integration/permission_test.rb @@ -0,0 +1,10 @@ +require 'test_helper' + +class PermissionTest < ActionDispatch::IntegrationTest + fixtures :all + + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/test/integration/right_test.rb b/test/integration/right_test.rb new file mode 100644 index 000000000..1f13dc615 --- /dev/null +++ b/test/integration/right_test.rb @@ -0,0 +1,10 @@ +require 'test_helper' + +class RightTest < ActionDispatch::IntegrationTest + fixtures :all + + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/test/integration/role_test.rb b/test/integration/role_test.rb new file mode 100644 index 000000000..8bc8544bd --- /dev/null +++ b/test/integration/role_test.rb @@ -0,0 +1,10 @@ +require 'test_helper' + +class RoleTest < ActionDispatch::IntegrationTest + fixtures :all + + # Replace this with your real tests. + test "the truth" do + assert true + end +end From 82d72a851c839ba89dfd1bc9ca988bdb24c96467 Mon Sep 17 00:00:00 2001 From: George Vinogradov Date: Mon, 24 Oct 2011 01:39:44 +0400 Subject: [PATCH 3/3] ACL for testing. --- Gemfile | 2 +- Gemfile.lock | 4 +- app/controllers/application_controller.rb | 12 +- app/controllers/roles_controller.rb | 25 +++- app/models/group.rb | 5 + app/models/permission.rb | 4 +- app/models/platform.rb | 6 + app/models/project.rb | 8 + app/models/relation.rb | 5 + app/models/repository.rb | 7 + app/models/right.rb | 21 +++ app/models/role.rb | 5 + app/models/user.rb | 4 + app/views/roles/_form.html.haml | 47 +++++- app/views/roles/show.html.haml | 50 +++++-- config/application.rb | 2 + config/locales/ru.yml | 20 ++- db/migrate/20111022170400_create_rights.rb | 15 ++ ...20111023154034_add_global_role_to_users.rb | 9 ++ ...0111023154130_add_global_role_to_groups.rb | 9 ++ .../20111023195205_add_can_see_to_roles.rb | 9 ++ db/schema.rb | 19 ++- lib/ext/active_record/base.rb | 139 ++++++++++++++++++ lib/ext/application_controller/base.rb | 24 +++ lib/tasks/generate_roles.rake | 34 +++++ public/javascripts/application.js | 13 ++ 26 files changed, 460 insertions(+), 38 deletions(-) create mode 100644 app/models/right.rb create mode 100644 db/migrate/20111022170400_create_rights.rb create mode 100644 db/migrate/20111023154034_add_global_role_to_users.rb create mode 100644 db/migrate/20111023154130_add_global_role_to_groups.rb create mode 100644 db/migrate/20111023195205_add_can_see_to_roles.rb create mode 100644 lib/ext/active_record/base.rb create mode 100644 lib/ext/application_controller/base.rb create mode 100644 lib/tasks/generate_roles.rake diff --git a/Gemfile b/Gemfile index de01fd4d4..63df318e8 100644 --- a/Gemfile +++ b/Gemfile @@ -42,7 +42,7 @@ group :development do gem 'ruby-debug' # gem 'looksee' # gem 'awesome_print' - gem 'wirble' +# gem 'wirble' gem 'hirb' # gem 'rails-footnotes', '>= 3.7.5.rc4' # this shit is very buggy don't forget to switch it off back diff --git a/Gemfile.lock b/Gemfile.lock index afea16edc..a3a4cd4b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,6 +87,7 @@ GEM haml (~> 3.0) railties (~> 3.0) highline (1.6.2) + hirb (0.5.0) hpricot (0.8.4) i18n (0.5.0) jammit (0.6.3) @@ -243,7 +244,6 @@ GEM activesupport (>= 2.3.4) chronic (~> 0.6.3) will_paginate (3.0.2) - wirble (0.1.3) yui-compressor (0.9.5) PLATFORMS @@ -261,6 +261,7 @@ DEPENDENCIES factory_girl_rails (~> 1.3.0) grit haml-rails (~> 0.3.4) + hirb hpricot jammit mysql2 (<= 0.2.9) @@ -279,5 +280,4 @@ DEPENDENCIES web-app-theme whenever will_paginate (~> 3.0.2) - wirble yui-compressor (= 0.9.5) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5af2cd547..b7f6bf6a8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,10 +4,18 @@ class ApplicationController < ActionController::Base layout :layout_by_resource private + def rights_to(type) + Right.where(:rtype => type.to_s).map{|r| r.name} + end + + def rights_of_user(id) + User.find(id).global_role ? User.find(id).global_role.rights{|r| r.name} : "has no role" + end + def get_role(object_id, object_type, target_id, target_type) Relation.where(:object_id=>object_id, :object_type=>object_type, :target_id=>target_id, :target_type=>target_type).first.try(:roles) end - + def checkaccess @roles=current_user.roles+current.user.groups.roles @ok=false @@ -17,7 +25,7 @@ class ApplicationController < ActionController::Base redirect_to(:back) end end - + def checkright(role_id) @role=Role.find(role_id) if @role.name.downcase!="admin" diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 2a6429bdb..a835c409c 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -1,12 +1,12 @@ class RolesController < ApplicationController before_filter :find_role, :only => [:show, :edit, :update, :destroy] + before_filter :find_visibilities, :only => [:new, :edit] def index @roles = Role.all end def show - @permissions = Permission.where(:role_id => @role.id) end def new @@ -31,12 +31,10 @@ class RolesController < ApplicationController end def update + puts params[:inspect] if @role.update_attributes(params[:role]) - if params[:right][:id] - Permission.destroy_all(:role_id => @role.id) - for right in params[:right][:id] - Permission.create(:role_id => @role.id, :right_id => right) - end + if params[:rights] and params[:rights][:id] + @role.rights = Right.find(params[:rights][:id]) end flash[:notice] = t('flash.role.saved') redirect_to roles_path @@ -57,4 +55,17 @@ class RolesController < ApplicationController def find_role @role = Role.find(params[:id]) end -end \ No newline at end of file + + def find_visibilities + @visibilities = ActiveRecord::Base.descendants.inject({}) do |h, m| + if m.public_instance_methods.include? 'visibility' + begin + h[m.name] = m::VISIBILITIES + rescue + nil + end + end + h + end + end +end diff --git a/app/models/group.rb b/app/models/group.rb index 060e4e5e0..842d68a92 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -1,9 +1,14 @@ class Group < ActiveRecord::Base + relationable :as => :object + relationable :as => :target + has_many :roles, :through => :targets validates :name, :uname, :owner_id, :presence => true validates :name, :uname, :uniqueness => true validates :uname, :format => { :with => /^[a-zA-Z0-9_]+$/ }, :allow_nil => false, :allow_blank => false + belongs_to :global_role, :class_name => 'Role' + belongs_to :owner, :class_name => 'User' has_many :own_projects, :as => :owner, :class_name => 'Project' diff --git a/app/models/permission.rb b/app/models/permission.rb index 5db19cfa5..ee04111f2 100644 --- a/app/models/permission.rb +++ b/app/models/permission.rb @@ -1,5 +1,7 @@ class Permission < ActiveRecord::Base belongs_to :role + belongs_to :right + def name Permission.right(self.right_id) end @@ -30,4 +32,4 @@ class Permission < ActiveRecord::Base "Платформа - Сборка" end end -end \ No newline at end of file +end diff --git a/app/models/platform.rb b/app/models/platform.rb index 4a14012a7..849731938 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -1,5 +1,8 @@ #require 'lib/build_server.rb' class Platform < ActiveRecord::Base + VISIBILITIES = ['open', 'hidden'] + relationable :as => :target + belongs_to :parent, :class_name => 'Platform', :foreign_key => 'parent_platform_id' belongs_to :owner, :polymorphic => true @@ -21,6 +24,9 @@ class Platform < ActiveRecord::Base # before_destroy :xml_rpc_destroy # before_update :check_freezing + scope :by_visibilities, lambda {|v| {:conditions => ['visibility in (?)', v.join(',')]}} + + attr_accessible :visibility def path build_path(unixname) diff --git a/app/models/project.rb b/app/models/project.rb index 27d9e3601..86a4d3ec7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,4 +1,8 @@ class Project < ActiveRecord::Base + VISIBILITIES = ['open', 'hidden'] + + relationable :as => :target + belongs_to :category, :counter_cache => true belongs_to :owner, :polymorphic => true @@ -20,12 +24,16 @@ class Project < ActiveRecord::Base scope :recent, order("name ASC") scope :by_name, lambda { |name| {:conditions => ['name like ?', '%' + name + '%']} } + scope :by_visibilities, lambda {|v| {:conditions => ['visibility in (?)', v.join(',')]}} + before_save :create_directory#, :create_git_repo before_save :make_owner_rel after_destroy :remove_directory # before_create :xml_rpc_create # before_destroy :xml_rpc_destroy + attr_accessible :visibility + def members collaborators + groups end diff --git a/app/models/relation.rb b/app/models/relation.rb index bb6d03112..81f9a8f1e 100644 --- a/app/models/relation.rb +++ b/app/models/relation.rb @@ -1,5 +1,10 @@ class Relation < ActiveRecord::Base belongs_to :target, :polymorphic => true belongs_to :object, :polymorphic => true + + has_many :role_lines has_many :roles, :autosave => true, :through => :role_lines + + 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]}} end diff --git a/app/models/repository.rb b/app/models/repository.rb index 1ee8a3850..3cecd90ab 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,4 +1,8 @@ class Repository < ActiveRecord::Base + + VISIBILITIES = ['open', 'hidden'] + relationable :as => :target + belongs_to :platform belongs_to :owner, :polymorphic => true @@ -14,6 +18,7 @@ class Repository < ActiveRecord::Base validates :platform_id, :presence => true scope :recent, order("name ASC") + scope :by_visibilities, lambda {|v| {:conditions => ['visibility in (?)', v.join(',')]}} before_save :create_directory before_save :make_owner_rel @@ -22,6 +27,8 @@ class Repository < ActiveRecord::Base # before_create :xml_rpc_create # before_destroy :xml_rpc_destroy + attr_accessible :visibility + def path build_path(unixname) end diff --git a/app/models/right.rb b/app/models/right.rb new file mode 100644 index 000000000..ac92a0581 --- /dev/null +++ b/app/models/right.rb @@ -0,0 +1,21 @@ +class Right < ActiveRecord::Base + before_save :generate_name + + scope :for_controller, lambda { |cont| {:conditions => ['controller = ?', cont.controller_name]}} + + class << self + def by_controller + all.inject({}) do |h, i| + h[i.controller] ||= [] + h[i.controller] << i + h + end + end + end + protected + NAME_TEMPL = 'Right to perform %s action.' + + def generate_name + self.name = sprintf(NAME_TEMPL, action) unless name and name.size == 0 + end +end diff --git a/app/models/role.rb b/app/models/role.rb index 114fb2877..25ad40798 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,4 +1,9 @@ class Role < ActiveRecord::Base has_many :permissions + has_many :rights, :through => :permissions has_many :relations, :through => :role_lines + + serialize :can_see, Hash + + validate :name, :presence => true end diff --git a/app/models/user.rb b/app/models/user.rb index d691b9790..6374b5bb7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,9 +1,13 @@ class User < ActiveRecord::Base + relationable :as => :object + inherit_rights_from :groups + devise :database_authenticatable, :registerable, :omniauthable, # :token_authenticatable, :encryptable, :timeoutable :recoverable, :rememberable, :validatable #, :trackable, :confirmable, :lockable has_many :authentications, :dependent => :destroy + belongs_to :global_role, :class_name => 'Role' has_many :roles, :through => :targets has_many :targets, :as => :object, :class_name => 'Relation' diff --git a/app/views/roles/_form.html.haml b/app/views/roles/_form.html.haml index 8710ea245..9c1127620 100644 --- a/app/views/roles/_form.html.haml +++ b/app/views/roles/_form.html.haml @@ -1,15 +1,52 @@ .group = f.label :name, t("activerecord.attributes.role.name"), :class => :label = f.text_field :name, :class => 'text_field' + - acters = [['All', '']].concat Role.relation_acters.map{|a| [a.name, a.name]} + - targets = [['System', '']].concat Role.relation_targets.map{|t| [t.name, t.name]} + = f.label :to, t("activerecord.attributes.role.applicable_to"), :class => :label + = f.select :to, options_for_select(acters, @role.to) + = f.label :on, t("activerecord.attributes.role.applicable_on"), :class => :label + = f.select :on, options_for_select(targets, @role.on) + +- unless @visibilities.empty? + .group + %fieldset + %legend= t("activerecord.attributes.role.can_see") + - @visibilities.each_pair do |model, vis_group| + %div{:style => 'float: left; width: 200px; margin-left: 10px; margin-top: 10px'} + = label_tag "can_see_#{model}", model, :class => :label + = select_tag "role[can_see][#{model}][]", + options_for_select(vis_group, (@role.can_see and @role.can_see[model]) ? @role.can_see[model] : []), + {:multiple => true, :size =>5, :id => "can_see_#{model}", :style => 'width:95%' } .group - %label.label Разрешения - - rights = Permission.get_rights_list - - rights_selected = Permission.where(:role_id => @role.id).map { |perm| perm.right_id } - = select_tag("right[id]", options_for_select(rights, rights_selected), :size => 10, :multiple => true) + %fieldset + %legend= t("layout.menu.permissions") + - rights = Right.by_controller + - added_rights = @role.rights.map(&:id) + - rights.each do |key, value| + %div{:style => 'float: left; width: 385px; margin-left: 10px; margin-top: 10px'} + %fieldset{:style => 'width: 95%; height: 100%; padding: 10px;'} + %legend= t("layout.menu.#{key}") + :javascript + function select_#{key}() { + check_by_ids(#{'[\'' + value.map{|r| 'right_' + r.id.to_s}.join('\',\'') + '\']'}); + } + function deselect_#{key}() { + uncheck_by_ids(#{'[\'' + value.map{|r| 'right_' + r.id.to_s}.join('\',\'') + '\']'}); + } + = link_to_function 'Select All', "select_#{key}()" + = link_to_function 'Deselect All', "deselect_#{key}()" + %br + %br + - value.each do |right| + - id = 'right_' + right.id.to_s + = check_box_tag 'rights[id][]', right.id, added_rights.include?(right.id), :id => id + = label_tag id, right.name + %br .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"), roles_path, :class => "text_button_padding link_button" \ No newline at end of file + = link_to t("layout.cancel"), roles_path, :class => "text_button_padding link_button" diff --git a/app/views/roles/show.html.haml b/app/views/roles/show.html.haml index 6a98822b6..7a7d077b2 100644 --- a/app/views/roles/show.html.haml +++ b/app/views/roles/show.html.haml @@ -18,21 +18,43 @@ = @role.name %p %b - = t("activerecord.models.permission") + = t("activerecord.attributes.role.applicable_to") \: - -unless @permissions.empty? + = (@role.to and @role.to.size > 0) ? @role.to : 'All' + %p + %b + = t("activerecord.attributes.role.applicable_on") + \: + = (@role.on and @role.on.size > 0) ? @role.on : 'System' + - unless @role.can_see.empty? + %p + %b + = t("activerecord.attributes.role.can_see") + \: %table.table - %tr - %th.first ID - %th= t("activerecord.attributes.right.name") - - @permissions.each do |permission| - %tr{:class => cycle("odd", "even")} - %td - = permission.right_id - %td - = permission.name - .wat-cf - = link_to image_tag("web-app-theme/icons/application_edit.png", :alt => t("layout.edit")) + " " + t("layout.edit"), edit_role_path(@role), :class => "button" - = link_to image_tag("web-app-theme/icons/cross.png", :alt => t("layout.delete")) + " " + t("layout.delete"), role_path(@role), :method => "delete", :class => "button", :confirm => t("layout.users.confirm_delete") + - @role.can_see.each_pair do |model, list| + %tr{:class => cycle('odd', 'even')} + %td{:style => 'width:25%'} + %b + =model + %td{:stule => 'width:75%'} + = list.join(', ') + -rights = @role.rights.by_controller + -unless rights.empty? + %p + %b + = t("activerecord.models.rights") + \: + - rights.each do |key, value| + %div{:style => 'float: left; width: 385px; margin-left: 10px; margin-top: 10px'} + %fieldset{:style => 'width: 95%; height: 100%; padding: 10px;'} + %legend= t("layout.menu.#{key}") + - value.each do |right| + %span= right.name + %br + %div{:style => 'clear: both'} + .wat-cf + = link_to image_tag("web-app-theme/icons/application_edit.png", :alt => t("layout.edit")) + " " + t("layout.edit"), edit_role_path(@role), :class => "button" + = link_to image_tag("web-app-theme/icons/cross.png", :alt => t("layout.delete")) + " " + t("layout.delete"), role_path(@role), :method => "delete", :class => "button", :confirm => t("layout.users.confirm_delete") - content_for :sidebar, render(:partial => 'sidebar') diff --git a/config/application.rb b/config/application.rb index ee44a64a4..0ea158e7b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -42,5 +42,7 @@ module Rosa # Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password] config.action_mailer.default_url_options = { :host => 'abs.rosalab.ru' } + + end end diff --git a/config/locales/ru.yml b/config/locales/ru.yml index add473eec..8c9ab355f 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -35,12 +35,18 @@ ru: Sunday: Воскресенье menu: - users: Пользователи - platforms: Платформы - groups: Группы + categories: Категории + containers: Контейнеры downloads: Статистика event_logs: Лог событий - categories: Категории + groups: Группы + platforms: Платформы + products: Продукты + projects: Проекты + repositories: Репозитории + rights: Права + roles: Роли + users: Пользователи sessions: sign_in_header: Вход в систему @@ -87,6 +93,9 @@ ru: distrib_type: Тип дистрибутива private_users: Пользователи приватного репозитория + roles: + confirm_delete: Вы уверены, что хотите удалить эту роль? + event_logs: list: Список list_header: Лог событий @@ -380,6 +389,9 @@ ru: created_at: Создан updated_at: Обновлен + roles: + name: Название + group: name: Название uname: Unixname diff --git a/db/migrate/20111022170400_create_rights.rb b/db/migrate/20111022170400_create_rights.rb new file mode 100644 index 000000000..fea0cf008 --- /dev/null +++ b/db/migrate/20111022170400_create_rights.rb @@ -0,0 +1,15 @@ +class CreateRights < ActiveRecord::Migration + def self.up + create_table :rights do |t| + t.string :name, :null => false + t.string :controller, :null => false + t.string :action, :null => false + + t.timestamps + end + end + + def self.down + drop_table :rights + end +end diff --git a/db/migrate/20111023154034_add_global_role_to_users.rb b/db/migrate/20111023154034_add_global_role_to_users.rb new file mode 100644 index 000000000..94ea1f1c4 --- /dev/null +++ b/db/migrate/20111023154034_add_global_role_to_users.rb @@ -0,0 +1,9 @@ +class AddGlobalRoleToUsers < ActiveRecord::Migration + def self.up + add_column :users, :global_role_id, :integer + end + + def self.down + remove_column :users, :global_role_id + end +end diff --git a/db/migrate/20111023154130_add_global_role_to_groups.rb b/db/migrate/20111023154130_add_global_role_to_groups.rb new file mode 100644 index 000000000..b1d5f38a2 --- /dev/null +++ b/db/migrate/20111023154130_add_global_role_to_groups.rb @@ -0,0 +1,9 @@ +class AddGlobalRoleToGroups < ActiveRecord::Migration + def self.up + add_column :groups, :global_role_id, :integer + end + + def self.down + remove_column :groups, :global_role_id + end +end diff --git a/db/migrate/20111023195205_add_can_see_to_roles.rb b/db/migrate/20111023195205_add_can_see_to_roles.rb new file mode 100644 index 000000000..fdcde3348 --- /dev/null +++ b/db/migrate/20111023195205_add_can_see_to_roles.rb @@ -0,0 +1,9 @@ +class AddCanSeeToRoles < ActiveRecord::Migration + def self.up + add_column :roles, :can_see, :text + end + + def self.down + remove_column :roles, :can_see + end +end diff --git a/db/schema.rb b/db/schema.rb index dfd07736f..661bddc74 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111021164945) do +ActiveRecord::Schema.define(:version => 20111023195205) do create_table "arches", :force => true do |t| t.string "name", :null => false @@ -124,6 +124,7 @@ ActiveRecord::Schema.define(:version => 20111021164945) do t.datetime "created_at" t.datetime "updated_at" t.string "uname" + t.integer "global_role_id" end create_table "permissions", :force => true do |t| @@ -202,6 +203,7 @@ ActiveRecord::Schema.define(:version => 20111021164945) do t.string "object_type" t.integer "target_id" t.string "target_type" + t.integer "role_id" t.datetime "created_at" t.datetime "updated_at" end @@ -217,6 +219,14 @@ ActiveRecord::Schema.define(:version => 20111021164945) do t.string "visibility", :default => "open" end + create_table "rights", :force => true do |t| + t.string "name", :null => false + t.string "controller", :null => false + t.string "action", :null => false + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "role_lines", :force => true do |t| t.integer "role_id" t.integer "relation_id" @@ -226,8 +236,11 @@ ActiveRecord::Schema.define(:version => 20111021164945) do create_table "roles", :force => true do |t| t.string "name" + t.string "to" + t.string "on" t.datetime "created_at" t.datetime "updated_at" + t.text "can_see" end create_table "rpms", :force => true do |t| @@ -251,8 +264,10 @@ ActiveRecord::Schema.define(:version => 20111021164945) do t.datetime "remember_created_at" t.datetime "created_at" t.datetime "updated_at" - t.text "ssh_key" t.string "uname" + t.text "ssh_key" + t.integer "role_id" + t.integer "global_role_id" end add_index "users", ["email"], :name => "index_users_on_email", :unique => true diff --git a/lib/ext/active_record/base.rb b/lib/ext/active_record/base.rb new file mode 100644 index 000000000..3e11e9739 --- /dev/null +++ b/lib/ext/active_record/base.rb @@ -0,0 +1,139 @@ +class ActiveRecord::Base + + def add_role_to model, role + return false unless ActiveRecord::Base.relation_acter? model and ActiveRecord::Base.relation_target? self.class + return false unless ['', model.class.to_s].include? role.to + rel = Relation.by_object(model).by_target(self).first + rel = Relation.new(:object_id => model.id, :object_type => model.class.to_s, + :target_id => self.id, :target_type => self.class.to_s) if rel.nil? + rel.roles << role unless rel.roles.include? role + rel.save + end + + def add_role_on model, role + return false unless ActiveRecord::Base.relation_target? model and ActiveRecord::Base.relation_acter? self.class + return false unless ['', self.class.to_s].include? role.to + rel = Relation.by_object(self).by_target(model).first + rel = Relation.new(:object_id => self.id, :object_type => self.class.to_s, + :target_id => model.id, :target_type => model.class.to_s) if rel.nil? + rel.roles << role unless rel.roles.include? role + rel.save + end + + def roles_to object + return [] unless ActiveRecord::Base.relation_acter? self.class + object = object.downcase.to_sym if object.is_a? String + possible = [self] + @@relationable[self.class.to_s][:inherits].each do |n| + possible.concat method(n).call + end + possible.flatten + if object.is_a? Symbol and object == :system + return possible.map{|obj| obj.global_role}.uniq! + else + r = possible.inject([]) do |arr, mod| + rels = Relation.by_object(mod).by_target(object) + arr.concat rel.map{|rel| rel.roles} if rels.size > 0 + arr << mod.global_role + arr + end + return r.flatten.uniq + end + end + + def can_perform? controller, action, target = :system + all_rights = rights_to target + needed_right = right_to controller, action + return all_rights.include? needed_right + end + + def right_to controller, action + Right.where(:controller => controller, :action => action).first + end + + def rights_to object + r = roles_to object + return [] if r.nil? + r.map {|role| role.rights}.flatten.uniq + end + + class << self + + def visible_to object + return all unless public_instance_methods.include? 'visibility' + rs = object.roles_to :system + vis = rs.inject({}) do |h, r| + h.merge!(r.can_see) {|k, old, new| old.concat(new).uniq} + h + end + vis = vis[self.name] + return [] if !vis or vis.empty? + if vis == self::VISIBILITIES + return all + else + return by_visibilities(vis) + end + end + + def inherit_rights_from arg + if relation_acters.include? self + @@relationable[self.name] ||= {} + @@relationable[self.name][:inherits] ||= [] + + if arg.is_a? Array + @@relationable[self.name][:inherits].concat(arg) + else + @@relationable[self.name][:inherits] << arg + end + end + end + + def relationable? + return true if @@relationable[self.name] and @@relationable[self.name].size > 0 + false + end + + def relation_acter? model + relation_acters.include? model + end + + def relation_target? model + relation_targets.include? model + end + + def relation_acters + load_all unless @@all_models_loaded + return Hash[@@relationable.select {|(k,v)| v[:as].include? :object}].keys.map{|m| m.constantize} + end + + def relation_targets + load_all unless @@all_models_loaded + return Hash[@@relationable.select {|(k,v)| v[:as].include? :target}].keys.map{|m| m.constantize} + end + + def load_all + Dir["app/models/**/*.rb"].each do |fn| + require File.expand_path(fn) + end + @@all_modles_loaded = true + end + + protected + + @@relationable = {} + @@all_models_loaded = false + + def relationable(arg) + @@relationable[self.name] ||= {} + @@relationable[self.name][:as] ||= [] + + if arg[:as] and [:object, :target].include? arg[:as] + @@relationable[self.name][:as] << arg[:as] + else + @@relationable[self.name][:as] << :target + end + @@relationable[self.name][:as].uniq! + end + end + +end diff --git a/lib/ext/application_controller/base.rb b/lib/ext/application_controller/base.rb new file mode 100644 index 000000000..f6546e589 --- /dev/null +++ b/lib/ext/application_controller/base.rb @@ -0,0 +1,24 @@ +class ApplicationController::Base + + def can_perform? target = :system + c = self.controller_name + a = self.action_name + + current_user.can_perform? c, a, target + end + + def check_global_rights + unless can_perform? + flash[:notice] = t('layout.not_access') + redirect_to(:back) + end + end + + class << self + + def rights_to target + Rights.where :rtype => target.class.to_s + end + + end +end diff --git a/lib/tasks/generate_roles.rake b/lib/tasks/generate_roles.rake new file mode 100644 index 000000000..357308b61 --- /dev/null +++ b/lib/tasks/generate_roles.rake @@ -0,0 +1,34 @@ +namespace :rights do + + desc "Generate rights from site" + task :generate => :environment do + Dir.glob('app/controllers/*.rb') do |file| + require file + end + + clist = ApplicationController.descendants + hash = clist.inject({}) do |h, cont| + tmp = (cont.public_instance_methods - ApplicationController.public_instance_methods).reject{|n| n.first == '_'} + h[cont.controller_name] = tmp if tmp.size > 0 + h + end + + rights = Right.all.inject([]) do |arr, r| + arr << [r.controller, r.action] + arr + end + + hash.each do |key, value| + hash[key] = value.reject {|n| rights.include? [key, n]} + end + hash.delete_if {|k, v| v.size == 0} + + hash.each do |controller, value| + value.each do |action| + r = Right.create(:controller => controller, :action => action) + puts '"' + r.name + '" was generated' + end + end + puts 'All rights was generated' + end +end diff --git a/public/javascripts/application.js b/public/javascripts/application.js index e69de29bb..e48f1db44 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -0,0 +1,13 @@ +function check_by_ids(ids) { + for(var i = 0; i < ids.length; i++){ + $('#'+ids[i]).attr('checked', true); + } + return false; +} + +function uncheck_by_ids(ids) { + for(var i = 0; i < ids.length; i++){ + $('#'+ids[i]).attr('checked', false); + } + return false; +}