Commit cb021e58314791c1c9eb8035ed01349876d246a1

Authored by Dmitriy Zaporozhets
1 parent 2ca00bdb

repo & project access separated. critical gitolite bugfix

app/controllers/team_members_controller.rb
... ... @@ -25,15 +25,10 @@ class TeamMembersController < ApplicationController
25 25 @team_member = project.users_projects.find(params[:id])
26 26 @team_member.update_attributes(params[:team_member])
27 27  
28   - respond_to do |format|
29   - format.js
30   - format.html do
31   - unless @team_member.valid?
32   - flash[:alert] = "User should have at least one role"
33   - end
34   - redirect_to team_project_path(@project)
35   - end
  28 + unless @team_member.valid?
  29 + flash[:alert] = "User should have at least one role"
36 30 end
  31 + redirect_to team_project_path(@project)
37 32 end
38 33  
39 34 def destroy
... ...
app/models/key.rb
... ... @@ -23,7 +23,7 @@ class Key < ActiveRecord::Base
23 23 c.update_keys(identifier, key)
24 24  
25 25 projects.each do |project|
26   - c.update_project(project.path, project.repository_writers)
  26 + c.update_project(project.path, project)
27 27 end
28 28 end
29 29 end
... ... @@ -33,7 +33,7 @@ class Key < ActiveRecord::Base
33 33 c.delete_key(identifier)
34 34  
35 35 projects.each do |project|
36   - c.update_project(project.path, project.repository_writers)
  36 + c.update_project(project.path, project)
37 37 end
38 38 end
39 39 end
... ...
app/models/project.rb
1 1 require "grit"
2 2  
3 3 class Project < ActiveRecord::Base
  4 + PROJECT_N = 0
  5 + PROJECT_R = 1
  6 + PROJECT_RW = 2
  7 + PROJECT_RWA = 3
  8 +
4 9 belongs_to :owner, :class_name => "User"
5 10  
6 11 has_many :merge_requests, :dependent => :destroy
... ... @@ -47,6 +52,16 @@ class Project &lt; ActiveRecord::Base
47 52  
48 53 scope :public_only, where(:private_flag => false)
49 54  
  55 +
  56 + def self.access_options
  57 + {
  58 + "Denied" => PROJECT_N,
  59 + "Read" => PROJECT_R,
  60 + "Report" => PROJECT_RW,
  61 + "Admin" => PROJECT_RWA
  62 + }
  63 + end
  64 +
50 65 def repository
51 66 @repository ||= Repository.new(self)
52 67 end
... ... @@ -109,21 +124,28 @@ class Project &lt; ActiveRecord::Base
109 124 users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
110 125 end
111 126  
112   - def writers
113   - @writers ||= users_projects.includes(:user).where(:write => true).map(&:user)
  127 + def repository_readers
  128 + keys = Key.joins({:user => :users_projects}).
  129 + where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_R)
  130 + keys.map(&:identifier)
114 131 end
115 132  
116 133 def repository_writers
117   - keys = Key.joins({:user => :users_projects}).where("users_projects.project_id = ? AND users_projects.write = ?", id, true)
  134 + keys = Key.joins({:user => :users_projects}).
  135 + where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_RW)
118 136 keys.map(&:identifier)
119 137 end
120 138  
121 139 def readers
122   - @readers ||= users_projects.includes(:user).where(:read => true).map(&:user)
  140 + @readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user)
  141 + end
  142 +
  143 + def writers
  144 + @writers ||= users_projects.includes(:user).where(:project_access => [PROJECT_RW, PROJECT_RWA]).map(&:user)
123 145 end
124 146  
125 147 def admins
126   - @admins ||=users_projects.includes(:user).where(:admin => true).map(&:user)
  148 + @admins ||= users_projects.includes(:user).where(:project_access => PROJECT_RWA).map(&:user)
127 149 end
128 150  
129 151 def root_ref
... ...
app/models/repository.rb
1 1 require File.join(Rails.root, "lib", "gitlabhq", "git_host")
2 2  
3 3 class Repository
  4 + REPO_N = 0
  5 + REPO_R = 1
  6 + REPO_RW = 2
  7 +
4 8 attr_accessor :project
5 9  
6 10 def self.default_ref
7 11 "master"
8 12 end
9 13  
  14 + def self.access_options
  15 + {
  16 + "Denied" => REPO_N,
  17 + "Pull" => REPO_R,
  18 + "Pull & Push" => REPO_RW
  19 + }
  20 + end
  21 +
10 22 def initialize(project)
11 23 @project = project
12 24 end
... ... @@ -33,7 +45,7 @@ class Repository
33 45  
34 46 def update_repository
35 47 Gitlabhq::GitHost.system.new.configure do |c|
36   - c.update_project(path, project.repository_writers)
  48 + c.update_project(path, project)
37 49 end
38 50 end
39 51  
... ...
app/models/users_project.rb
... ... @@ -4,25 +4,20 @@ class UsersProject &lt; ActiveRecord::Base
4 4  
5 5 attr_protected :project_id, :project
6 6  
7   - after_commit :update_repository
  7 + after_save :update_repository
  8 + after_destroy :update_repository
8 9  
9 10 validates_uniqueness_of :user_id, :scope => [:project_id]
10 11 validates_presence_of :user_id
11 12 validates_presence_of :project_id
12   - validate :user_has_a_role_selected
13 13  
14 14 delegate :name, :email, :to => :user, :prefix => true
15 15  
16 16 def update_repository
17   - Gitosis.new.configure do |c|
18   - c.update_project(project.path, project.repository)
  17 + Gitlabhq::GitHost.system.new.configure do |c|
  18 + c.update_project(project.path, project)
19 19 end
20 20 end
21   -
22   - def user_has_a_role_selected
23   - errors.add(:base, "Please choose at least one Role in the Access list") unless read || write || admin
24   - end
25   -
26 21 end
27 22 # == Schema Information
28 23 #
... ...
app/views/projects/_team.html.haml
... ... @@ -5,14 +5,19 @@
5 5 %table.round-borders#team-table
6 6 %thead
7 7 %th Name
8   - %th Web
9   - %th Git
10   - %th Admin
  8 + %th Project
  9 + %th Repository
11 10 - if can? current_user, :admin_team_member, @project
12 11 %th Actions
13 12 - @project.users_projects.each do |up|
14 13 = render(:partial => 'team_members/show', :locals => {:member => up})
15 14  
16 15 :javascript
  16 + $(function(){
  17 + $('.repo-access-select, .project-access-select').live("change", function() {
  18 + $(this.form).submit();
  19 + });
  20 + })
  21 +
17 22 $('.delete-team-member').live('ajax:success', function() {
18 23 $(this).closest('tr').fadeOut(); });
... ...
app/views/team_members/_show.html.haml
1 1 - user = member.user
  2 +- allow_admin = can? current_user, :admin_project, @project
2 3 %tr{:id => dom_id(member)}
3 4 %td
4 5 = link_to image_tag(gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding:0 5px;"), project_team_member_path(@project, member)
... ... @@ -6,15 +7,13 @@
6 7 = link_to truncate(user.name, :lenght => 24), project_team_member_path(@project, member)
7 8 %br
8 9 .cgray{:style => "padding-top:10px;"}= truncate user.email, :lenght => 24
9   - - if can? current_user, :admin_project, @project
10   - = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f|
11   - %td= f.check_box :read, :onclick => "$(this.form).submit();"
12   - %td= f.check_box :write, :onclick => "$(this.form).submit();"
13   - %td= f.check_box :admin, :onclick => "$(this.form).submit();"
14   - - else
15   - %td= check_box_tag "read", 1, member.read, :disabled => :disabled
16   - %td= check_box_tag "commit", 1, member.write, :disabled => :disabled
17   - %td= check_box_tag "admin", 1, member.admin, :disabled => :disabled
18   - - if can? current_user, :admin_team_member, @project
  10 + %td
  11 + = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f|
  12 + = f.select :project_access, options_for_select(Project.access_options, member.project_access), {}, :class => "project-access-select", :disabled => !allow_admin
  13 + %td
  14 + = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f|
  15 + = f.select :repo_access, options_for_select(Repository.access_options, member.repo_access), {}, :class => "repo-access-select", :disabled => !allow_admin
  16 + - if allow_admin
19 17 %td
20 18 = link_to 'Cancel', project_team_member_path(:project_id => @project, :id => member.id), :confirm => 'Are you sure?', :method => :delete, :class => "grey-button negative delete-team-member", :remote => true
  19 +
... ...
db/migrate/20111206213842_add_advanced_rights_to_team_member.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +class AddAdvancedRightsToTeamMember < ActiveRecord::Migration
  2 + def change
  3 + add_column :users_projects, :repo_access, :integer, :default => 0, :null => false
  4 + add_column :users_projects, :project_access, :integer, :default => 0, :null => false
  5 + end
  6 +end
... ...
db/migrate/20111206222316_migrate_to_new_rights.rb 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +class MigrateToNewRights < ActiveRecord::Migration
  2 + def up
  3 + # Repository access
  4 + UsersProject.update_all("repo_access = 2", :write => true)
  5 + UsersProject.update_all("repo_access = 1", :read => true, :write => false)
  6 +
  7 + # Project access
  8 + UsersProject.update_all("project_access = 1", :read => true, :write => false, :admin => false)
  9 + UsersProject.update_all("project_access = 2", :read => true, :write => true, :admin => false)
  10 + UsersProject.update_all("project_access = 3", :read => true, :write => true, :admin => true)
  11 +
  12 + # Remove old fields
  13 + remove_column :users_projects, :read
  14 + remove_column :users_projects, :write
  15 + remove_column :users_projects, :admin
  16 + end
  17 +
  18 + def down
  19 + end
  20 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20111127155345) do
  14 +ActiveRecord::Schema.define(:version => 20111206222316) do
15 15  
16 16 create_table "features", :force => true do |t|
17 17 t.string "name"
... ... @@ -137,11 +137,10 @@ ActiveRecord::Schema.define(:version =&gt; 20111127155345) do
137 137 create_table "users_projects", :force => true do |t|
138 138 t.integer "user_id", :null => false
139 139 t.integer "project_id", :null => false
140   - t.boolean "read", :default => false
141   - t.boolean "write", :default => false
142   - t.boolean "admin", :default => false
143 140 t.datetime "created_at"
144 141 t.datetime "updated_at"
  142 + t.integer "repo_access", :default => 0, :null => false
  143 + t.integer "project_access", :default => 0, :null => false
145 144 end
146 145  
147 146 end
... ...
lib/gitlabhq/gitolite.rb
... ... @@ -61,7 +61,7 @@ module Gitlabhq
61 61 end
62 62  
63 63 # update or create
64   - def update_project(repo_name, name_writers)
  64 + def update_project(repo_name, project)
65 65 ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
66 66 conf = ga_repo.config
67 67  
... ... @@ -71,8 +71,13 @@ module Gitlabhq
71 71 ::Gitolite::Config::Repo.new(repo_name)
72 72 end
73 73  
  74 + name_readers = project.repository_readers
  75 + name_writers = project.repository_writers
  76 +
  77 + repo.clean_permissions
  78 + repo.add_permission("R", "", name_readers) unless name_readers.blank?
74 79 repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
75   - conf.add_repo(repo)
  80 + conf.add_repo(repo, true)
76 81  
77 82 ga_repo.save
78 83 end
... ...
public/githost_error.html 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <title>We're sorry, but we cant get access to your gitosis</title>
  5 + <style type="text/css">
  6 + body { background-color: #EAEAEA; color: #666; text-align: center; font-family: arial, sans-serif; }
  7 + div.dialog {
  8 + width: 600px;
  9 + padding: 0 4em;
  10 + margin: 4em auto 0 auto;
  11 + }
  12 + h1 { font-size: 48px; color: #444; line-height: 1.5em; }
  13 + h2 { font-size: 24px; color: #666; line-height: 1.5em; }
  14 + </style>
  15 +</head>
  16 +
  17 +<body>
  18 + <!-- This file lives in public/500.html -->
  19 + <div class="dialog">
  20 + <h1>Gitolite Error</h1>
  21 + <h2>We're sorry, but we cant get access to your gitolite system.</h2>
  22 + <h3> 1. Check 'config/gitlab.yml' for correct settings.</h3>
  23 + <h3> 2. Be sure web server user has access to gitolite.</h3>
  24 + </div>
  25 +</body>
  26 +</html>
... ...
public/gitosis_error.html
... ... @@ -1,26 +0,0 @@
1   -<!DOCTYPE html>
2   -<html>
3   -<head>
4   - <title>We're sorry, but we cant get access to your gitosis</title>
5   - <style type="text/css">
6   - body { background-color: #EAEAEA; color: #666; text-align: center; font-family: arial, sans-serif; }
7   - div.dialog {
8   - width: 600px;
9   - padding: 0 4em;
10   - margin: 4em auto 0 auto;
11   - }
12   - h1 { font-size: 48px; color: #444; line-height: 1.5em; }
13   - h2 { font-size: 24px; color: #666; line-height: 1.5em; }
14   - </style>
15   -</head>
16   -
17   -<body>
18   - <!-- This file lives in public/500.html -->
19   - <div class="dialog">
20   - <h1>Gitosis Error</h1>
21   - <h2>We're sorry, but we cant get access to your gitosis.</h2>
22   - <h3> 1. Check 'config/gitosis.yml' for correct settings.</h3>
23   - <h3> 2. Be sure web server user has access to gitosis.</h3>
24   - </div>
25   -</body>
26   -</html>