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 @@ |
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 | 24 | end |
25 | 25 | |
26 | 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 | 30 | redirect_to [:admin, @project], notice: 'Project was successfully updated.' |
35 | 31 | else |
36 | 32 | render action: "edit" | ... | ... |
app/controllers/application_controller.rb
... | ... | @@ -2,6 +2,7 @@ class ApplicationController < ActionController::Base |
2 | 2 | before_filter :authenticate_user! |
3 | 3 | before_filter :reject_blocked! |
4 | 4 | before_filter :set_current_user_for_observers |
5 | + before_filter :add_abilities | |
5 | 6 | before_filter :dev_tools if Rails.env == 'development' |
6 | 7 | |
7 | 8 | protect_from_forgery |
... | ... | @@ -65,11 +66,17 @@ class ApplicationController < ActionController::Base |
65 | 66 | def project |
66 | 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 | 77 | end |
71 | 78 | |
72 | - def add_project_abilities | |
79 | + def add_abilities | |
73 | 80 | abilities << Ability |
74 | 81 | end |
75 | 82 | ... | ... |
app/controllers/dashboard_controller.rb
... | ... | @@ -5,7 +5,7 @@ class DashboardController < ApplicationController |
5 | 5 | before_filter :event_filter, only: :index |
6 | 6 | |
7 | 7 | def index |
8 | - @groups = Group.where(id: current_user.projects.pluck(:namespace_id)) | |
8 | + @groups = current_user.accessed_groups | |
9 | 9 | @projects = @projects.page(params[:page]).per(30) |
10 | 10 | @events = Event.in_projects(current_user.project_ids) |
11 | 11 | @events = @event_filter.apply_filter(@events) | ... | ... |
app/controllers/groups_controller.rb
... | ... | @@ -4,7 +4,6 @@ class GroupsController < ApplicationController |
4 | 4 | |
5 | 5 | before_filter :group |
6 | 6 | before_filter :projects |
7 | - before_filter :add_project_abilities | |
8 | 7 | |
9 | 8 | def show |
10 | 9 | @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0) |
... | ... | @@ -45,7 +44,7 @@ class GroupsController < ApplicationController |
45 | 44 | end |
46 | 45 | |
47 | 46 | def people |
48 | - @users = group.users.all | |
47 | + @users = group.users | |
49 | 48 | end |
50 | 49 | |
51 | 50 | protected |
... | ... | @@ -55,7 +54,11 @@ class GroupsController < ApplicationController |
55 | 54 | end |
56 | 55 | |
57 | 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 | 62 | end |
60 | 63 | |
61 | 64 | def project_ids | ... | ... |
app/controllers/project_resource_controller.rb
app/controllers/projects_controller.rb
... | ... | @@ -34,20 +34,10 @@ class ProjectsController < ProjectResourceController |
34 | 34 | end |
35 | 35 | |
36 | 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 | 39 | respond_to do |format| |
50 | - if project.update_attributes(params[:project]) | |
40 | + if status | |
51 | 41 | flash[:notice] = 'Project was successfully updated.' |
52 | 42 | format.html { redirect_to edit_project_path(project), notice: 'Project was successfully updated.' } |
53 | 43 | format.js | ... | ... |
app/models/ability.rb
... | ... | @@ -15,7 +15,37 @@ class Ability |
15 | 15 | def project_abilities(user, project) |
16 | 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 | 49 | :read_project, |
20 | 50 | :read_wiki, |
21 | 51 | :read_issue, |
... | ... | @@ -27,28 +57,30 @@ class Ability |
27 | 57 | :write_project, |
28 | 58 | :write_issue, |
29 | 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 | 65 | :download_code, |
34 | 66 | :write_merge_request, |
35 | 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 | 73 | :write_wiki, |
40 | 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 | 81 | :modify_issue, |
49 | 82 | :modify_snippet, |
50 | 83 | :modify_merge_request, |
51 | - :admin_project, | |
52 | 84 | :admin_issue, |
53 | 85 | :admin_milestone, |
54 | 86 | :admin_snippet, |
... | ... | @@ -57,9 +89,13 @@ class Ability |
57 | 89 | :admin_note, |
58 | 90 | :accept_mr, |
59 | 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 | 99 | end |
64 | 100 | |
65 | 101 | def group_abilities user, group | ... | ... |
app/models/group.rb
... | ... | @@ -13,7 +13,9 @@ |
13 | 13 | |
14 | 14 | class Group < Namespace |
15 | 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 | 19 | end |
18 | 20 | |
19 | 21 | def human_name | ... | ... |
app/models/namespace.rb
... | ... | @@ -53,12 +53,14 @@ class Namespace < ActiveRecord::Base |
53 | 53 | end |
54 | 54 | |
55 | 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 | 63 | end |
61 | - system("mv #{old_path} #{new_path}") | |
62 | 64 | end |
63 | 65 | |
64 | 66 | def rm_dir | ... | ... |
app/models/project.rb
... | ... | @@ -29,7 +29,7 @@ class Project < ActiveRecord::Base |
29 | 29 | attr_accessible :name, :path, :description, :default_branch, :issues_enabled, |
30 | 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 | 34 | attr_accessor :error_code |
35 | 35 | ... | ... |
app/models/user.rb
... | ... | @@ -123,4 +123,11 @@ class User < ActiveRecord::Base |
123 | 123 | self.password = self.password_confirmation = Devise.friendly_token.first(8) |
124 | 124 | end |
125 | 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 | 133 | end | ... | ... |
app/views/admin/projects/_form.html.haml
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | - unless project.new_record? |
23 | 23 | .clearfix |
24 | 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 | 27 | .clearfix |
28 | 28 | = f.label :owner_id | ... | ... |
app/views/errors/access_denied.html.haml
app/views/groups/show.html.haml
... | ... | @@ -10,7 +10,7 @@ |
10 | 10 | - if @events.any? |
11 | 11 | .content_list= render @events |
12 | 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 | 14 | .loading.hide |
15 | 15 | .side |
16 | 16 | = render "projects", projects: @projects | ... | ... |
... | ... | @@ -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
spec/models/namespace_spec.rb
... | ... | @@ -55,9 +55,10 @@ describe Namespace do |
55 | 55 | describe :move_dir do |
56 | 56 | before do |
57 | 57 | @namespace = create :namespace |
58 | + @namespace.stub(path_changed?: true) | |
58 | 59 | end |
59 | 60 | |
60 | - it "should raise error when called directly" do | |
61 | + it "should raise error when dirtory exists" do | |
61 | 62 | expect { @namespace.move_dir }.to raise_error("Already exists") |
62 | 63 | end |
63 | 64 | ... | ... |