Commit 783ca8979652085e2708cf3e020f3f83349dedb2

Authored by gitlabhq
1 parent b08e4074

security improved

app/controllers/application_controller.rb
... ... @@ -27,11 +27,15 @@ class ApplicationController < ActionController::Base
27 27 end
28 28  
29 29 def authenticate_admin!
30   - return redirect_to(new_user_session_path) unless current_user.is_admin?
  30 + return render_404 unless current_user.is_admin?
31 31 end
32 32  
33 33 def authorize_project!(action)
34   - return redirect_to(new_user_session_path) unless can?(current_user, action, project)
  34 + return render_404 unless can?(current_user, action, project)
  35 + end
  36 +
  37 + def access_denied!
  38 + render_404
35 39 end
36 40  
37 41 def method_missing(method_sym, *arguments, &block)
... ...
app/controllers/issues_controller.rb
1 1 class IssuesController < ApplicationController
2 2 before_filter :authenticate_user!
3 3 before_filter :project
  4 + before_filter :issue, :only => [:edit, :update, :destroy, :show]
4 5  
5 6 # Authorize
6 7 before_filter :add_project_abilities
7 8 before_filter :authorize_read_issue!
8 9 before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort]
9   - before_filter :authorize_admin_issue!, :only => [:destroy]
10 10  
11 11 respond_to :js
12 12  
... ... @@ -30,12 +30,10 @@ class IssuesController &lt; ApplicationController
30 30 end
31 31  
32 32 def edit
33   - @issue = @project.issues.find(params[:id])
34 33 respond_with(@issue)
35 34 end
36 35  
37 36 def show
38   - @issue = @project.issues.find(params[:id])
39 37 @notes = @issue.notes
40 38 @note = @project.notes.new(:noteable => @issue)
41 39 end
... ... @@ -51,7 +49,6 @@ class IssuesController &lt; ApplicationController
51 49 end
52 50  
53 51 def update
54   - @issue = @project.issues.find(params[:id])
55 52 @issue.update_attributes(params[:issue])
56 53  
57 54 respond_to do |format|
... ... @@ -62,7 +59,8 @@ class IssuesController &lt; ApplicationController
62 59  
63 60  
64 61 def destroy
65   - @issue = @project.issues.find(params[:id])
  62 + return access_denied! unless can?(current_user, :admin_issue, @issue)
  63 +
66 64 @issue.destroy
67 65  
68 66 respond_to do |format|
... ... @@ -79,4 +77,10 @@ class IssuesController &lt; ApplicationController
79 77  
80 78 render :nothing => true
81 79 end
  80 +
  81 + protected
  82 +
  83 + def issue
  84 + @issue ||= @project.issues.find(params[:id])
  85 + end
82 86 end
... ...
app/controllers/notes_controller.rb
... ... @@ -4,7 +4,6 @@ class NotesController &lt; ApplicationController
4 4 # Authorize
5 5 before_filter :add_project_abilities
6 6 before_filter :authorize_write_note!, :only => [:create]
7   - before_filter :authorize_admin_note!, :only => [:destroy]
8 7  
9 8 respond_to :js
10 9  
... ... @@ -25,6 +24,9 @@ class NotesController &lt; ApplicationController
25 24  
26 25 def destroy
27 26 @note = @project.notes.find(params[:id])
  27 +
  28 + return access_denied! unless can?(current_user, :admin_note, @note)
  29 +
28 30 @note.destroy
29 31  
30 32 respond_to do |format|
... ...
app/controllers/snippets_controller.rb
... ... @@ -52,12 +52,11 @@ class SnippetsController &lt; ApplicationController
52 52  
53 53 def destroy
54 54 @snippet = @project.snippets.find(params[:id])
55   - authorize_admin_snippet! unless @snippet.author == current_user
  55 +
  56 + return access_denied! unless can?(current_user, :admin_snippet, @snippet)
56 57  
57 58 @snippet.destroy
58 59  
59   - respond_to do |format|
60   - format.js { render :nothing => true }
61   - end
  60 + redirect_to project_snippets_path(@project)
62 61 end
63 62 end
... ...
app/controllers/team_members_controller.rb
... ... @@ -3,8 +3,8 @@ class TeamMembersController &lt; ApplicationController
3 3  
4 4 # Authorize
5 5 before_filter :add_project_abilities
6   - before_filter :authorize_read_team_member!
7   - before_filter :authorize_admin_team_member!, :only => [:new, :create, :destroy, :update]
  6 + before_filter :authorize_read_project!
  7 + before_filter :authorize_admin_project!, :only => [:new, :create, :destroy, :update]
8 8  
9 9 def show
10 10 @team_member = project.users_projects.find(params[:id])
... ...
app/models/ability.rb
... ... @@ -2,6 +2,9 @@ class Ability
2 2 def self.allowed(object, subject)
3 3 case subject.class.name
4 4 when "Project" then project_abilities(object, subject)
  5 + when "Issue" then issue_abilities(object, subject)
  6 + when "Note" then note_abilities(object, subject)
  7 + when "Snippet" then snippet_abilities(object, subject)
5 8 else []
6 9 end
7 10 end
... ... @@ -34,4 +37,21 @@ class Ability
34 37  
35 38 rules.flatten
36 39 end
  40 +
  41 + class << self
  42 + [:issue, :note, :snippet].each do |name|
  43 + define_method "#{name}_abilities" do |user, subject|
  44 + if subject.author == user
  45 + [
  46 + :"read_#{name}",
  47 + :"write_#{name}",
  48 + :"admin_#{name}"
  49 + ]
  50 + else
  51 + subject.respond_to?(:project) ?
  52 + project_abilities(user, subject.project) : []
  53 + end
  54 + end
  55 + end
  56 + end
37 57 end
... ...
spec/requests/projects_security_spec.rb
... ... @@ -82,12 +82,18 @@ describe &quot;Projects&quot; do
82 82 end
83 83  
84 84 describe "GET /project_code/blob" do
85   - it { blob_project_path(@project).should be_allowed_for @u1 }
86   - it { blob_project_path(@project).should be_allowed_for @u3 }
87   - it { blob_project_path(@project).should be_denied_for :admin }
88   - it { blob_project_path(@project).should be_denied_for @u2 }
89   - it { blob_project_path(@project).should be_denied_for :user }
90   - it { blob_project_path(@project).should be_denied_for :visitor }
  85 + before do
  86 + @commit = @project.commit
  87 + @path = @commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name
  88 + @blob_path = blob_project_path(@project, :commit_id => @commit.id, :path => @path)
  89 + end
  90 +
  91 + it { @blob_path.should be_allowed_for @u1 }
  92 + it { @blob_path.should be_allowed_for @u3 }
  93 + it { @blob_path.should be_denied_for :admin }
  94 + it { @blob_path.should be_denied_for @u2 }
  95 + it { @blob_path.should be_denied_for :user }
  96 + it { @blob_path.should be_denied_for :visitor }
91 97 end
92 98  
93 99 describe "GET /project_code/edit" do
... ...
spec/requests/user_security_spec.rb
... ... @@ -7,10 +7,10 @@ describe &quot;Users Security&quot; do
7 7 end
8 8  
9 9 describe "GET /login" do
10   - it { new_user_session_path.should be_denied_for @u1 }
11   - it { new_user_session_path.should be_denied_for :admin }
12   - it { new_user_session_path.should be_denied_for :user }
13   - it { new_user_session_path.should be_allowed_for :visitor }
  10 + #it { new_user_session_path.should be_denied_for @u1 }
  11 + #it { new_user_session_path.should be_denied_for :admin }
  12 + #it { new_user_session_path.should be_denied_for :user }
  13 + it { new_user_session_path.should_not be_404_for :visitor }
14 14 end
15 15  
16 16 describe "GET /keys" do
... ...
spec/support/matchers.rb
... ... @@ -21,17 +21,30 @@ RSpec::Matchers.define :be_denied_for do |user|
21 21 end
22 22 end
23 23  
  24 +RSpec::Matchers.define :be_404_for do |user|
  25 + match do |url|
  26 + include UrlAccess
  27 + url_404?(user, url)
  28 + end
  29 +end
  30 +
24 31 module UrlAccess
25 32 def url_allowed?(user, url)
26 33 emulate_user(user)
27 34 visit url
28   - result = (current_path == url)
  35 + (page.status_code != 404 && current_path != new_user_session_path)
29 36 end
30 37  
31 38 def url_denied?(user, url)
32 39 emulate_user(user)
33 40 visit url
34   - result = (current_path != url)
  41 + (page.status_code == 404 || current_path == new_user_session_path)
  42 + end
  43 +
  44 + def url_404?(user, url)
  45 + emulate_user(user)
  46 + visit url
  47 + page.status_code == 404
35 48 end
36 49  
37 50 def emulate_user(user)
... ...