ProtectedBranches model, Master permission for repo\n Allow push to protected branch for masters only
This commit is contained in:
parent
3a9e5a9357
commit
37224dc9c1
14 changed files with 229 additions and 53 deletions
23
app/controllers/protected_branches_controller.rb
Normal file
23
app/controllers/protected_branches_controller.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
class ProtectedBranchesController < ApplicationController
|
||||
before_filter :project
|
||||
|
||||
# Authorize
|
||||
before_filter :add_project_abilities
|
||||
before_filter :authorize_read_project!
|
||||
before_filter :require_non_empty_project
|
||||
|
||||
layout "project"
|
||||
|
||||
def index
|
||||
@branches = @project.protected_branches.all
|
||||
@protected_branch = @project.protected_branches.new
|
||||
end
|
||||
|
||||
def create
|
||||
@project.protected_branches.create(params[:protected_branch])
|
||||
redirect_to project_protected_branches_path(@project)
|
||||
end
|
||||
|
||||
def destroy
|
||||
end
|
||||
end
|
|
@ -16,6 +16,7 @@ class Project < ActiveRecord::Base
|
|||
has_many :snippets, :dependent => :destroy
|
||||
has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key"
|
||||
has_many :web_hooks, :dependent => :destroy
|
||||
has_many :protected_branches, :dependent => :destroy
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
|
@ -138,6 +139,15 @@ class Project < ActiveRecord::Base
|
|||
data
|
||||
end
|
||||
|
||||
def open_branches
|
||||
if protected_branches.empty?
|
||||
self.repo.heads
|
||||
else
|
||||
pnames = protected_branches.map(&:name)
|
||||
self.repo.heads.reject { |h| pnames.include?(h.name) }
|
||||
end.sort_by(&:name)
|
||||
end
|
||||
|
||||
def team_member_by_name_or_email(email = nil, name = nil)
|
||||
user = users.where("email like ? or name like ?", email, name).first
|
||||
users_projects.find_by_user_id(user.id) if user
|
||||
|
@ -210,6 +220,12 @@ class Project < ActiveRecord::Base
|
|||
keys.map(&:identifier)
|
||||
end
|
||||
|
||||
def repository_masters
|
||||
keys = Key.joins({:user => :users_projects}).
|
||||
where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_MASTER)
|
||||
keys.map(&:identifier)
|
||||
end
|
||||
|
||||
def readers
|
||||
@readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user)
|
||||
end
|
||||
|
@ -235,7 +251,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def allow_pull_for?(user)
|
||||
!users_projects.where(:user_id => user.id, :repo_access => [Repository::REPO_R, Repository::REPO_RW]).empty?
|
||||
!users_projects.where(:user_id => user.id, :repo_access => [Repository::REPO_R, Repository::REPO_RW, Repository::REPO_MASTER]).empty?
|
||||
end
|
||||
|
||||
def root_ref
|
||||
|
@ -350,5 +366,8 @@ end
|
|||
# code :string(255)
|
||||
# owner_id :integer
|
||||
# default_branch :string(255) default("master"), not null
|
||||
# issues_enabled :boolean default(TRUE), not null
|
||||
# wall_enabled :boolean default(TRUE), not null
|
||||
# merge_requests_enabled :boolean default(TRUE), not null
|
||||
#
|
||||
|
||||
|
|
29
app/models/protected_branch.rb
Normal file
29
app/models/protected_branch.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
class ProtectedBranch < ActiveRecord::Base
|
||||
belongs_to :project
|
||||
validates_presence_of :project_id
|
||||
validates_presence_of :name
|
||||
|
||||
after_save :update_repository
|
||||
after_destroy :update_repository
|
||||
|
||||
def update_repository
|
||||
Gitlabhq::GitHost.system.new.configure do |c|
|
||||
c.update_project(project.path, project)
|
||||
end
|
||||
end
|
||||
|
||||
def commit
|
||||
project.commit(self.name)
|
||||
end
|
||||
end
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: protected_branches
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer not null
|
||||
# name :string(255) not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
|
@ -4,6 +4,7 @@ class Repository
|
|||
REPO_N = 0
|
||||
REPO_R = 1
|
||||
REPO_RW = 2
|
||||
REPO_MASTER = 3
|
||||
|
||||
attr_accessor :project
|
||||
|
||||
|
@ -15,7 +16,8 @@ class Repository
|
|||
{
|
||||
"Denied" => REPO_N,
|
||||
"Pull" => REPO_R,
|
||||
"Pull & Push" => REPO_RW
|
||||
"Pull & Push" => REPO_RW,
|
||||
"Master" => REPO_MASTER
|
||||
}
|
||||
end
|
||||
|
||||
|
|
39
app/views/protected_branches/index.html.haml
Normal file
39
app/views/protected_branches/index.html.haml
Normal file
|
@ -0,0 +1,39 @@
|
|||
= render "repositories/branches_head"
|
||||
|
||||
= form_for [@project, @protected_branch] do |f|
|
||||
-if @protected_branch.errors.any?
|
||||
.alert-message.block-message.error
|
||||
%ul
|
||||
- @protected_branch.errors.full_messages.each do |msg|
|
||||
%li= msg
|
||||
|
||||
.clearfix
|
||||
= f.label :name
|
||||
.input= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , { :include_blank => "Select branch" }, { :style => "width:300px" })
|
||||
.actions
|
||||
= f.submit 'Add', :class => "primary btn"
|
||||
|
||||
|
||||
- unless @branches.empty?
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th Name
|
||||
%th Last commit
|
||||
%tbody
|
||||
- @branches.each do |branch|
|
||||
%tr
|
||||
%td
|
||||
= link_to project_commits_path(@project, :ref => branch.name) do
|
||||
%strong= branch.name
|
||||
- if branch.name == @project.root_ref
|
||||
%span.label default
|
||||
%td
|
||||
= link_to project_commits_path(@project, branch.commit.id) do
|
||||
= truncate branch.commit.id.to_s, :length => 10
|
||||
= time_ago_in_words(branch.commit.committed_date)
|
||||
ago
|
||||
|
||||
|
||||
:javascript
|
||||
$('select#protected_branch_name').chosen();
|
9
app/views/repositories/_branches_head.html.haml
Normal file
9
app/views/repositories/_branches_head.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
|||
= render "repositories/head"
|
||||
%ul.pills
|
||||
%li{:class => ("active" if current_page?(branches_project_repository_path(@project)))}
|
||||
= link_to branches_project_repository_path(@project) do
|
||||
All
|
||||
%li{:class => ("active" if current_page?(project_protected_branches_path(@project)))}
|
||||
= link_to project_protected_branches_path(@project) do
|
||||
Protected
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
= link_to project_repository_path(@project) do
|
||||
%span
|
||||
Activities
|
||||
%li{:class => "#{'active' if current_page?(branches_project_repository_path(@project)) }"}
|
||||
%li{:class => "#{'active' if current_page?(branches_project_repository_path(@project)) || current_page?(project_protected_branches_path(@project)) }"}
|
||||
= link_to branches_project_repository_path(@project) do
|
||||
%span
|
||||
Branches
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
= render "head"
|
||||
= render "repositories/branches_head"
|
||||
- unless @branches.empty?
|
||||
%table
|
||||
%thead
|
||||
|
|
|
@ -62,6 +62,7 @@ Gitlab::Application.routes.draw do
|
|||
end
|
||||
|
||||
resources :deploy_keys
|
||||
resources :protected_branches, :only => [:index, :create, :destroy]
|
||||
|
||||
resources :refs, :only => [], :path => "/" do
|
||||
collection do
|
||||
|
|
10
db/migrate/20120215182305_create_protected_branches.rb
Normal file
10
db/migrate/20120215182305_create_protected_branches.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class CreateProtectedBranches < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :protected_branches do |t|
|
||||
t.integer :project_id, :null => false
|
||||
t.string :name, :null => false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
21
db/schema.rb
21
db/schema.rb
|
@ -11,7 +11,19 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20120206170141) do
|
||||
ActiveRecord::Schema.define(:version => 20120215182305) do
|
||||
|
||||
create_table "features", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "branch_name"
|
||||
t.integer "assignee_id"
|
||||
t.integer "author_id"
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "version"
|
||||
t.integer "status", :default => 0, :null => false
|
||||
end
|
||||
|
||||
create_table "issues", :force => true do |t|
|
||||
t.string "title"
|
||||
|
@ -82,6 +94,13 @@ ActiveRecord::Schema.define(:version => 20120206170141) do
|
|||
t.boolean "merge_requests_enabled", :default => true, :null => false
|
||||
end
|
||||
|
||||
create_table "protected_branches", :force => true do |t|
|
||||
t.integer "project_id", :null => false
|
||||
t.string "name", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "snippets", :force => true do |t|
|
||||
t.string "title"
|
||||
t.text "content"
|
||||
|
|
|
@ -64,19 +64,7 @@ module Gitlabhq
|
|||
def update_project(repo_name, project)
|
||||
ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
|
||||
conf = ga_repo.config
|
||||
|
||||
repo = if conf.has_repo?(repo_name)
|
||||
conf.get_repo(repo_name)
|
||||
else
|
||||
::Gitolite::Config::Repo.new(repo_name)
|
||||
end
|
||||
|
||||
name_readers = project.repository_readers
|
||||
name_writers = project.repository_writers
|
||||
|
||||
repo.clean_permissions
|
||||
repo.add_permission("R", "", name_readers) unless name_readers.blank?
|
||||
repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
|
||||
repo = update_project_config(project, conf)
|
||||
conf.add_repo(repo, true)
|
||||
|
||||
ga_repo.save
|
||||
|
@ -89,6 +77,14 @@ module Gitlabhq
|
|||
conf = ga_repo.config
|
||||
|
||||
projects.each do |project|
|
||||
repo = update_project_config(project, conf)
|
||||
conf.add_repo(repo, true)
|
||||
end
|
||||
|
||||
ga_repo.save
|
||||
end
|
||||
|
||||
def update_project_config(project, conf)
|
||||
repo_name = project.path
|
||||
|
||||
repo = if conf.has_repo?(repo_name)
|
||||
|
@ -99,15 +95,25 @@ module Gitlabhq
|
|||
|
||||
name_readers = project.repository_readers
|
||||
name_writers = project.repository_writers
|
||||
name_masters = project.repository_masters
|
||||
|
||||
pr_br = project.protected_branches.map(&:name).join(" ")
|
||||
|
||||
repo.clean_permissions
|
||||
|
||||
# Deny access to protected branches for writers
|
||||
unless name_writers.blank? || pr_br.blank?
|
||||
repo.add_permission("-", pr_br, name_writers)
|
||||
end
|
||||
|
||||
# Add read permissions
|
||||
repo.add_permission("R", "", name_readers) unless name_readers.blank?
|
||||
|
||||
# Add write permissions
|
||||
repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
|
||||
conf.add_repo(repo, true)
|
||||
end
|
||||
repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
|
||||
|
||||
ga_repo.save
|
||||
repo
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -300,5 +300,8 @@ end
|
|||
# code :string(255)
|
||||
# owner_id :integer
|
||||
# default_branch :string(255) default("master"), not null
|
||||
# issues_enabled :boolean default(TRUE), not null
|
||||
# wall_enabled :boolean default(TRUE), not null
|
||||
# merge_requests_enabled :boolean default(TRUE), not null
|
||||
#
|
||||
|
||||
|
|
16
spec/models/protected_branch_spec.rb
Normal file
16
spec/models/protected_branch_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: protected_branches
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer not null
|
||||
# name :string(255) not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe ProtectedBranch do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in a new issue