Commit 783ca8979652085e2708cf3e020f3f83349dedb2

Authored by gitlabhq
1 parent b08e4074

security improved

app/controllers/application_controller.rb
@@ -27,11 +27,15 @@ class ApplicationController < ActionController::Base @@ -27,11 +27,15 @@ class ApplicationController < ActionController::Base
27 end 27 end
28 28
29 def authenticate_admin! 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 end 31 end
32 32
33 def authorize_project!(action) 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 end 39 end
36 40
37 def method_missing(method_sym, *arguments, &block) 41 def method_missing(method_sym, *arguments, &block)
app/controllers/issues_controller.rb
1 class IssuesController < ApplicationController 1 class IssuesController < ApplicationController
2 before_filter :authenticate_user! 2 before_filter :authenticate_user!
3 before_filter :project 3 before_filter :project
  4 + before_filter :issue, :only => [:edit, :update, :destroy, :show]
4 5
5 # Authorize 6 # Authorize
6 before_filter :add_project_abilities 7 before_filter :add_project_abilities
7 before_filter :authorize_read_issue! 8 before_filter :authorize_read_issue!
8 before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort] 9 before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort]
9 - before_filter :authorize_admin_issue!, :only => [:destroy]  
10 10
11 respond_to :js 11 respond_to :js
12 12
@@ -30,12 +30,10 @@ class IssuesController &lt; ApplicationController @@ -30,12 +30,10 @@ class IssuesController &lt; ApplicationController
30 end 30 end
31 31
32 def edit 32 def edit
33 - @issue = @project.issues.find(params[:id])  
34 respond_with(@issue) 33 respond_with(@issue)
35 end 34 end
36 35
37 def show 36 def show
38 - @issue = @project.issues.find(params[:id])  
39 @notes = @issue.notes 37 @notes = @issue.notes
40 @note = @project.notes.new(:noteable => @issue) 38 @note = @project.notes.new(:noteable => @issue)
41 end 39 end
@@ -51,7 +49,6 @@ class IssuesController &lt; ApplicationController @@ -51,7 +49,6 @@ class IssuesController &lt; ApplicationController
51 end 49 end
52 50
53 def update 51 def update
54 - @issue = @project.issues.find(params[:id])  
55 @issue.update_attributes(params[:issue]) 52 @issue.update_attributes(params[:issue])
56 53
57 respond_to do |format| 54 respond_to do |format|
@@ -62,7 +59,8 @@ class IssuesController &lt; ApplicationController @@ -62,7 +59,8 @@ class IssuesController &lt; ApplicationController
62 59
63 60
64 def destroy 61 def destroy
65 - @issue = @project.issues.find(params[:id]) 62 + return access_denied! unless can?(current_user, :admin_issue, @issue)
  63 +
66 @issue.destroy 64 @issue.destroy
67 65
68 respond_to do |format| 66 respond_to do |format|
@@ -79,4 +77,10 @@ class IssuesController &lt; ApplicationController @@ -79,4 +77,10 @@ class IssuesController &lt; ApplicationController
79 77
80 render :nothing => true 78 render :nothing => true
81 end 79 end
  80 +
  81 + protected
  82 +
  83 + def issue
  84 + @issue ||= @project.issues.find(params[:id])
  85 + end
82 end 86 end
app/controllers/notes_controller.rb
@@ -4,7 +4,6 @@ class NotesController &lt; ApplicationController @@ -4,7 +4,6 @@ class NotesController &lt; ApplicationController
4 # Authorize 4 # Authorize
5 before_filter :add_project_abilities 5 before_filter :add_project_abilities
6 before_filter :authorize_write_note!, :only => [:create] 6 before_filter :authorize_write_note!, :only => [:create]
7 - before_filter :authorize_admin_note!, :only => [:destroy]  
8 7
9 respond_to :js 8 respond_to :js
10 9
@@ -25,6 +24,9 @@ class NotesController &lt; ApplicationController @@ -25,6 +24,9 @@ class NotesController &lt; ApplicationController
25 24
26 def destroy 25 def destroy
27 @note = @project.notes.find(params[:id]) 26 @note = @project.notes.find(params[:id])
  27 +
  28 + return access_denied! unless can?(current_user, :admin_note, @note)
  29 +
28 @note.destroy 30 @note.destroy
29 31
30 respond_to do |format| 32 respond_to do |format|
app/controllers/snippets_controller.rb
@@ -52,12 +52,11 @@ class SnippetsController &lt; ApplicationController @@ -52,12 +52,11 @@ class SnippetsController &lt; ApplicationController
52 52
53 def destroy 53 def destroy
54 @snippet = @project.snippets.find(params[:id]) 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 @snippet.destroy 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 end 61 end
63 end 62 end
app/controllers/team_members_controller.rb
@@ -3,8 +3,8 @@ class TeamMembersController &lt; ApplicationController @@ -3,8 +3,8 @@ class TeamMembersController &lt; ApplicationController
3 3
4 # Authorize 4 # Authorize
5 before_filter :add_project_abilities 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 def show 9 def show
10 @team_member = project.users_projects.find(params[:id]) 10 @team_member = project.users_projects.find(params[:id])
app/models/ability.rb
@@ -2,6 +2,9 @@ class Ability @@ -2,6 +2,9 @@ class Ability
2 def self.allowed(object, subject) 2 def self.allowed(object, subject)
3 case subject.class.name 3 case subject.class.name
4 when "Project" then project_abilities(object, subject) 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 else [] 8 else []
6 end 9 end
7 end 10 end
@@ -34,4 +37,21 @@ class Ability @@ -34,4 +37,21 @@ class Ability
34 37
35 rules.flatten 38 rules.flatten
36 end 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 end 57 end
spec/requests/projects_security_spec.rb
@@ -82,12 +82,18 @@ describe &quot;Projects&quot; do @@ -82,12 +82,18 @@ describe &quot;Projects&quot; do
82 end 82 end
83 83
84 describe "GET /project_code/blob" do 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 end 97 end
92 98
93 describe "GET /project_code/edit" do 99 describe "GET /project_code/edit" do
spec/requests/user_security_spec.rb
@@ -7,10 +7,10 @@ describe &quot;Users Security&quot; do @@ -7,10 +7,10 @@ describe &quot;Users Security&quot; do
7 end 7 end
8 8
9 describe "GET /login" do 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 end 14 end
15 15
16 describe "GET /keys" do 16 describe "GET /keys" do
spec/support/matchers.rb
@@ -21,17 +21,30 @@ RSpec::Matchers.define :be_denied_for do |user| @@ -21,17 +21,30 @@ RSpec::Matchers.define :be_denied_for do |user|
21 end 21 end
22 end 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 module UrlAccess 31 module UrlAccess
25 def url_allowed?(user, url) 32 def url_allowed?(user, url)
26 emulate_user(user) 33 emulate_user(user)
27 visit url 34 visit url
28 - result = (current_path == url) 35 + (page.status_code != 404 && current_path != new_user_session_path)
29 end 36 end
30 37
31 def url_denied?(user, url) 38 def url_denied?(user, url)
32 emulate_user(user) 39 emulate_user(user)
33 visit url 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 end 48 end
36 49
37 def emulate_user(user) 50 def emulate_user(user)