Commit eb1004f7890d25a86beb0ca0a7eca802d9fce665
1 parent
a1ffc673
Exists in
master
and in
4 other branches
Refactor abilities. Added ProjectUpdate context. Fixed few bugs with namespaces
Showing
18 changed files
with
127 additions
and
53 deletions
Show diff stats
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +class ProjectUpdateContext < BaseContext | ||
2 | + def execute(role = :default) | ||
3 | + namespace_id = params[:project].delete(:namespace_id) | ||
4 | + | ||
5 | + if namespace_id.present? | ||
6 | + if namespace_id == Namespace.global_id | ||
7 | + if project.namespace.present? | ||
8 | + # Transfer to global namespace from anyone | ||
9 | + project.transfer(nil) | ||
10 | + end | ||
11 | + elsif namespace_id.to_i != project.namespace_id | ||
12 | + # Transfer to someone namespace | ||
13 | + namespace = Namespace.find(namespace_id) | ||
14 | + project.transfer(namespace) | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | + project.update_attributes(params[:project], as: role) | ||
19 | + end | ||
20 | +end | ||
21 | + |
app/controllers/admin/projects_controller.rb
@@ -24,13 +24,9 @@ class Admin::ProjectsController < AdminController | @@ -24,13 +24,9 @@ class Admin::ProjectsController < AdminController | ||
24 | end | 24 | end |
25 | 25 | ||
26 | def update | 26 | def update |
27 | - owner_id = params[:project].delete(:owner_id) | 27 | + status = ProjectUpdateContext.new(project, current_user, params).execute(:admin) |
28 | 28 | ||
29 | - if owner_id | ||
30 | - @project.owner = User.find(owner_id) | ||
31 | - end | ||
32 | - | ||
33 | - if @project.update_attributes(params[:project], as: :admin) | 29 | + if status |
34 | redirect_to [:admin, @project], notice: 'Project was successfully updated.' | 30 | redirect_to [:admin, @project], notice: 'Project was successfully updated.' |
35 | else | 31 | else |
36 | render action: "edit" | 32 | render action: "edit" |
app/controllers/application_controller.rb
@@ -2,6 +2,7 @@ class ApplicationController < ActionController::Base | @@ -2,6 +2,7 @@ class ApplicationController < ActionController::Base | ||
2 | before_filter :authenticate_user! | 2 | before_filter :authenticate_user! |
3 | before_filter :reject_blocked! | 3 | before_filter :reject_blocked! |
4 | before_filter :set_current_user_for_observers | 4 | before_filter :set_current_user_for_observers |
5 | + before_filter :add_abilities | ||
5 | before_filter :dev_tools if Rails.env == 'development' | 6 | before_filter :dev_tools if Rails.env == 'development' |
6 | 7 | ||
7 | protect_from_forgery | 8 | protect_from_forgery |
@@ -65,11 +66,17 @@ class ApplicationController < ActionController::Base | @@ -65,11 +66,17 @@ class ApplicationController < ActionController::Base | ||
65 | def project | 66 | def project |
66 | id = params[:project_id] || params[:id] | 67 | id = params[:project_id] || params[:id] |
67 | 68 | ||
68 | - @project ||= current_user.projects.find_with_namespace(id) | ||
69 | - @project || render_404 | 69 | + @project = Project.find_with_namespace(id) |
70 | + | ||
71 | + if @project and can?(current_user, :read_project, @project) | ||
72 | + @project | ||
73 | + else | ||
74 | + @project = nil | ||
75 | + render_404 | ||
76 | + end | ||
70 | end | 77 | end |
71 | 78 | ||
72 | - def add_project_abilities | 79 | + def add_abilities |
73 | abilities << Ability | 80 | abilities << Ability |
74 | end | 81 | end |
75 | 82 |
app/controllers/dashboard_controller.rb
@@ -5,7 +5,7 @@ class DashboardController < ApplicationController | @@ -5,7 +5,7 @@ class DashboardController < ApplicationController | ||
5 | before_filter :event_filter, only: :index | 5 | before_filter :event_filter, only: :index |
6 | 6 | ||
7 | def index | 7 | def index |
8 | - @groups = Group.where(id: current_user.projects.pluck(:namespace_id)) | 8 | + @groups = current_user.accessed_groups |
9 | @projects = @projects.page(params[:page]).per(30) | 9 | @projects = @projects.page(params[:page]).per(30) |
10 | @events = Event.in_projects(current_user.project_ids) | 10 | @events = Event.in_projects(current_user.project_ids) |
11 | @events = @event_filter.apply_filter(@events) | 11 | @events = @event_filter.apply_filter(@events) |
app/controllers/groups_controller.rb
@@ -4,7 +4,6 @@ class GroupsController < ApplicationController | @@ -4,7 +4,6 @@ class GroupsController < ApplicationController | ||
4 | 4 | ||
5 | before_filter :group | 5 | before_filter :group |
6 | before_filter :projects | 6 | before_filter :projects |
7 | - before_filter :add_project_abilities | ||
8 | 7 | ||
9 | def show | 8 | def show |
10 | @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0) | 9 | @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0) |
@@ -45,7 +44,7 @@ class GroupsController < ApplicationController | @@ -45,7 +44,7 @@ class GroupsController < ApplicationController | ||
45 | end | 44 | end |
46 | 45 | ||
47 | def people | 46 | def people |
48 | - @users = group.users.all | 47 | + @users = group.users |
49 | end | 48 | end |
50 | 49 | ||
51 | protected | 50 | protected |
@@ -55,7 +54,11 @@ class GroupsController < ApplicationController | @@ -55,7 +54,11 @@ class GroupsController < ApplicationController | ||
55 | end | 54 | end |
56 | 55 | ||
57 | def projects | 56 | def projects |
58 | - @projects ||= current_user.projects_sorted_by_activity.where(namespace_id: @group.id) | 57 | + @projects ||= if can?(current_user, :manage_group, @group) |
58 | + @group.projects.all | ||
59 | + else | ||
60 | + current_user.projects_sorted_by_activity.where(namespace_id: @group.id) | ||
61 | + end | ||
59 | end | 62 | end |
60 | 63 | ||
61 | def project_ids | 64 | def project_ids |
app/controllers/project_resource_controller.rb
app/controllers/projects_controller.rb
@@ -34,20 +34,10 @@ class ProjectsController < ProjectResourceController | @@ -34,20 +34,10 @@ class ProjectsController < ProjectResourceController | ||
34 | end | 34 | end |
35 | 35 | ||
36 | def update | 36 | def update |
37 | - if params[:project].has_key?(:namespace_id) | ||
38 | - namespace_id = params[:project].delete(:namespace_id) | ||
39 | - if namespace_id == Namespace.global_id and project.namespace.present? | ||
40 | - # Transfer to global namespace from anyone | ||
41 | - project.transfer(nil) | ||
42 | - elsif namespace_id.present? and namespace_id.to_i != project.namespace_id | ||
43 | - # Transfer to someone namespace | ||
44 | - namespace = Namespace.find(namespace_id) | ||
45 | - project.transfer(namespace) | ||
46 | - end | ||
47 | - end | 37 | + status = ProjectUpdateContext.new(project, current_user, params).execute |
48 | 38 | ||
49 | respond_to do |format| | 39 | respond_to do |format| |
50 | - if project.update_attributes(params[:project]) | 40 | + if status |
51 | flash[:notice] = 'Project was successfully updated.' | 41 | flash[:notice] = 'Project was successfully updated.' |
52 | format.html { redirect_to edit_project_path(project), notice: 'Project was successfully updated.' } | 42 | format.html { redirect_to edit_project_path(project), notice: 'Project was successfully updated.' } |
53 | format.js | 43 | format.js |
app/models/ability.rb
@@ -15,7 +15,37 @@ class Ability | @@ -15,7 +15,37 @@ class Ability | ||
15 | def project_abilities(user, project) | 15 | def project_abilities(user, project) |
16 | rules = [] | 16 | rules = [] |
17 | 17 | ||
18 | - rules << [ | 18 | + # Rules based on role in project |
19 | + if project.master_access_for?(user) | ||
20 | + # TODO: replace with master rules. | ||
21 | + # Only allow project administration for owners | ||
22 | + rules << project_admin_rules | ||
23 | + | ||
24 | + elsif project.dev_access_for?(user) | ||
25 | + rules << project_dev_rules | ||
26 | + | ||
27 | + elsif project.report_access_for?(user) | ||
28 | + rules << project_report_rules | ||
29 | + | ||
30 | + elsif project.guest_access_for?(user) | ||
31 | + rules << project_guest_rules | ||
32 | + end | ||
33 | + | ||
34 | + # If user own project namespace (Ex. group owner or account owner) | ||
35 | + if project.namespace && project.namespace.owner == user | ||
36 | + rules << project_admin_rules | ||
37 | + end | ||
38 | + | ||
39 | + # If user was set as direct project owner | ||
40 | + if project.owner == user | ||
41 | + rules << project_admin_rules | ||
42 | + end | ||
43 | + | ||
44 | + rules.flatten | ||
45 | + end | ||
46 | + | ||
47 | + def project_guest_rules | ||
48 | + [ | ||
19 | :read_project, | 49 | :read_project, |
20 | :read_wiki, | 50 | :read_wiki, |
21 | :read_issue, | 51 | :read_issue, |
@@ -27,28 +57,30 @@ class Ability | @@ -27,28 +57,30 @@ class Ability | ||
27 | :write_project, | 57 | :write_project, |
28 | :write_issue, | 58 | :write_issue, |
29 | :write_note | 59 | :write_note |
30 | - ] if project.guest_access_for?(user) | 60 | + ] |
61 | + end | ||
31 | 62 | ||
32 | - rules << [ | 63 | + def project_report_rules |
64 | + project_guest_rules + [ | ||
33 | :download_code, | 65 | :download_code, |
34 | :write_merge_request, | 66 | :write_merge_request, |
35 | :write_snippet | 67 | :write_snippet |
36 | - ] if project.report_access_for?(user) | 68 | + ] |
69 | + end | ||
37 | 70 | ||
38 | - rules << [ | 71 | + def project_dev_rules |
72 | + project_report_rules + [ | ||
39 | :write_wiki, | 73 | :write_wiki, |
40 | :push_code | 74 | :push_code |
41 | - ] if project.dev_access_for?(user) | ||
42 | - | ||
43 | - rules << [ | ||
44 | - :push_code_to_protected_branches | ||
45 | - ] if project.master_access_for?(user) | 75 | + ] |
76 | + end | ||
46 | 77 | ||
47 | - rules << [ | 78 | + def project_master_rules |
79 | + project_dev_rules + [ | ||
80 | + :push_code_to_protected_branches, | ||
48 | :modify_issue, | 81 | :modify_issue, |
49 | :modify_snippet, | 82 | :modify_snippet, |
50 | :modify_merge_request, | 83 | :modify_merge_request, |
51 | - :admin_project, | ||
52 | :admin_issue, | 84 | :admin_issue, |
53 | :admin_milestone, | 85 | :admin_milestone, |
54 | :admin_snippet, | 86 | :admin_snippet, |
@@ -57,9 +89,13 @@ class Ability | @@ -57,9 +89,13 @@ class Ability | ||
57 | :admin_note, | 89 | :admin_note, |
58 | :accept_mr, | 90 | :accept_mr, |
59 | :admin_wiki | 91 | :admin_wiki |
60 | - ] if project.master_access_for?(user) || project.owner == user | 92 | + ] |
93 | + end | ||
61 | 94 | ||
62 | - rules.flatten | 95 | + def project_admin_rules |
96 | + project_master_rules + [ | ||
97 | + :admin_project | ||
98 | + ] | ||
63 | end | 99 | end |
64 | 100 | ||
65 | def group_abilities user, group | 101 | def group_abilities user, group |
app/models/group.rb
@@ -13,7 +13,9 @@ | @@ -13,7 +13,9 @@ | ||
13 | 13 | ||
14 | class Group < Namespace | 14 | class Group < Namespace |
15 | def users | 15 | def users |
16 | - User.joins(:users_projects).where(users_projects: {project_id: project_ids}).uniq | 16 | + users = User.joins(:users_projects).where(users_projects: {project_id: project_ids}) |
17 | + users = users << owner | ||
18 | + users.uniq | ||
17 | end | 19 | end |
18 | 20 | ||
19 | def human_name | 21 | def human_name |
app/models/namespace.rb
@@ -53,12 +53,14 @@ class Namespace < ActiveRecord::Base | @@ -53,12 +53,14 @@ class Namespace < ActiveRecord::Base | ||
53 | end | 53 | end |
54 | 54 | ||
55 | def move_dir | 55 | def move_dir |
56 | - old_path = File.join(Gitlab.config.git_base_path, path_was) | ||
57 | - new_path = File.join(Gitlab.config.git_base_path, path) | ||
58 | - if File.exists?(new_path) | ||
59 | - raise "Already exists" | 56 | + if path_changed? |
57 | + old_path = File.join(Gitlab.config.git_base_path, path_was) | ||
58 | + new_path = File.join(Gitlab.config.git_base_path, path) | ||
59 | + if File.exists?(new_path) | ||
60 | + raise "Already exists" | ||
61 | + end | ||
62 | + system("mv #{old_path} #{new_path}") | ||
60 | end | 63 | end |
61 | - system("mv #{old_path} #{new_path}") | ||
62 | end | 64 | end |
63 | 65 | ||
64 | def rm_dir | 66 | def rm_dir |
app/models/project.rb
@@ -29,7 +29,7 @@ class Project < ActiveRecord::Base | @@ -29,7 +29,7 @@ class Project < ActiveRecord::Base | ||
29 | attr_accessible :name, :path, :description, :default_branch, :issues_enabled, | 29 | attr_accessible :name, :path, :description, :default_branch, :issues_enabled, |
30 | :wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin] | 30 | :wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin] |
31 | 31 | ||
32 | - attr_accessible :namespace_id, as: :admin | 32 | + attr_accessible :namespace_id, :owner_id, as: :admin |
33 | 33 | ||
34 | attr_accessor :error_code | 34 | attr_accessor :error_code |
35 | 35 |
app/models/user.rb
@@ -123,4 +123,11 @@ class User < ActiveRecord::Base | @@ -123,4 +123,11 @@ class User < ActiveRecord::Base | ||
123 | self.password = self.password_confirmation = Devise.friendly_token.first(8) | 123 | self.password = self.password_confirmation = Devise.friendly_token.first(8) |
124 | end | 124 | end |
125 | end | 125 | end |
126 | + | ||
127 | + def accessed_groups | ||
128 | + @accessed_groups ||= begin | ||
129 | + groups = Group.where(id: self.projects.pluck(:namespace_id)).all | ||
130 | + groups + self.groups | ||
131 | + end | ||
132 | + end | ||
126 | end | 133 | end |
app/views/admin/projects/_form.html.haml
@@ -22,7 +22,7 @@ | @@ -22,7 +22,7 @@ | ||
22 | - unless project.new_record? | 22 | - unless project.new_record? |
23 | .clearfix | 23 | .clearfix |
24 | = f.label :namespace_id | 24 | = f.label :namespace_id |
25 | - .input= f.select :namespace_id, namespaces_options, {}, {class: 'chosen'} | 25 | + .input= f.select :namespace_id, namespaces_options(@project.namespace_id), {}, {class: 'chosen'} |
26 | 26 | ||
27 | .clearfix | 27 | .clearfix |
28 | = f.label :owner_id | 28 | = f.label :owner_id |
app/views/errors/access_denied.html.haml
app/views/groups/show.html.haml
@@ -10,7 +10,7 @@ | @@ -10,7 +10,7 @@ | ||
10 | - if @events.any? | 10 | - if @events.any? |
11 | .content_list= render @events | 11 | .content_list= render @events |
12 | - else | 12 | - else |
13 | - %h4.nothing_here_message Projects activity will be displayed here | 13 | + %p.nothing_here_message Projects activity will be displayed here |
14 | .loading.hide | 14 | .loading.hide |
15 | .side | 15 | .side |
16 | = render "projects", projects: @projects | 16 | = render "projects", projects: @projects |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +Group.seed(:id, [ | ||
2 | + { id: 100, name: "Gitlab", path: 'gitlab', owner_id: 1}, | ||
3 | + { id: 101, name: "Rails", path: 'rails', owner_id: 1 }, | ||
4 | + { id: 102, name: "KDE", path: 'kde', owner_id: 1 } | ||
5 | +]) | ||
6 | + | ||
7 | +Project.seed(:id, [ | ||
8 | + { id: 10, name: "kdebase", path: "kdebase", owner_id: 1, namespace_id: 102 }, | ||
9 | + { id: 11, name: "kdelibs", path: "kdelibs", owner_id: 1, namespace_id: 102 }, | ||
10 | + { id: 12, name: "amarok", path: "amarok", owner_id: 1, namespace_id: 102 } | ||
11 | +]) |
spec/models/group_spec.rb
@@ -24,7 +24,7 @@ describe Group do | @@ -24,7 +24,7 @@ describe Group do | ||
24 | it { should validate_presence_of :owner } | 24 | it { should validate_presence_of :owner } |
25 | 25 | ||
26 | describe :users do | 26 | describe :users do |
27 | - it { group.users.should == [] } | 27 | + it { group.users.should == [group.owner] } |
28 | end | 28 | end |
29 | 29 | ||
30 | describe :human_name do | 30 | describe :human_name do |
spec/models/namespace_spec.rb
@@ -55,9 +55,10 @@ describe Namespace do | @@ -55,9 +55,10 @@ describe Namespace do | ||
55 | describe :move_dir do | 55 | describe :move_dir do |
56 | before do | 56 | before do |
57 | @namespace = create :namespace | 57 | @namespace = create :namespace |
58 | + @namespace.stub(path_changed?: true) | ||
58 | end | 59 | end |
59 | 60 | ||
60 | - it "should raise error when called directly" do | 61 | + it "should raise error when dirtory exists" do |
61 | expect { @namespace.move_dir }.to raise_error("Already exists") | 62 | expect { @namespace.move_dir }.to raise_error("Already exists") |
62 | end | 63 | end |
63 | 64 |