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 :snippets, :dependent => :destroy
|
||||||
has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key"
|
has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key"
|
||||||
has_many :web_hooks, :dependent => :destroy
|
has_many :web_hooks, :dependent => :destroy
|
||||||
|
has_many :protected_branches, :dependent => :destroy
|
||||||
|
|
||||||
acts_as_taggable
|
acts_as_taggable
|
||||||
|
|
||||||
|
@ -138,6 +139,15 @@ class Project < ActiveRecord::Base
|
||||||
data
|
data
|
||||||
end
|
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)
|
def team_member_by_name_or_email(email = nil, name = nil)
|
||||||
user = users.where("email like ? or name like ?", email, name).first
|
user = users.where("email like ? or name like ?", email, name).first
|
||||||
users_projects.find_by_user_id(user.id) if user
|
users_projects.find_by_user_id(user.id) if user
|
||||||
|
@ -210,6 +220,12 @@ class Project < ActiveRecord::Base
|
||||||
keys.map(&:identifier)
|
keys.map(&:identifier)
|
||||||
end
|
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
|
def readers
|
||||||
@readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user)
|
@readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user)
|
||||||
end
|
end
|
||||||
|
@ -235,7 +251,7 @@ class Project < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_pull_for?(user)
|
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
|
end
|
||||||
|
|
||||||
def root_ref
|
def root_ref
|
||||||
|
@ -340,15 +356,18 @@ end
|
||||||
#
|
#
|
||||||
# Table name: projects
|
# Table name: projects
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# name :string(255)
|
# name :string(255)
|
||||||
# path :string(255)
|
# path :string(255)
|
||||||
# description :text
|
# description :text
|
||||||
# created_at :datetime
|
# created_at :datetime
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# private_flag :boolean default(TRUE), not null
|
# private_flag :boolean default(TRUE), not null
|
||||||
# code :string(255)
|
# code :string(255)
|
||||||
# owner_id :integer
|
# owner_id :integer
|
||||||
# default_branch :string(255) default("master"), not null
|
# 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_N = 0
|
||||||
REPO_R = 1
|
REPO_R = 1
|
||||||
REPO_RW = 2
|
REPO_RW = 2
|
||||||
|
REPO_MASTER = 3
|
||||||
|
|
||||||
attr_accessor :project
|
attr_accessor :project
|
||||||
|
|
||||||
|
@ -15,7 +16,8 @@ class Repository
|
||||||
{
|
{
|
||||||
"Denied" => REPO_N,
|
"Denied" => REPO_N,
|
||||||
"Pull" => REPO_R,
|
"Pull" => REPO_R,
|
||||||
"Pull & Push" => REPO_RW
|
"Pull & Push" => REPO_RW,
|
||||||
|
"Master" => REPO_MASTER
|
||||||
}
|
}
|
||||||
end
|
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
|
= link_to project_repository_path(@project) do
|
||||||
%span
|
%span
|
||||||
Activities
|
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
|
= link_to branches_project_repository_path(@project) do
|
||||||
%span
|
%span
|
||||||
Branches
|
Branches
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
= render "head"
|
= render "repositories/branches_head"
|
||||||
- unless @branches.empty?
|
- unless @branches.empty?
|
||||||
%table
|
%table
|
||||||
%thead
|
%thead
|
||||||
|
|
|
@ -62,6 +62,7 @@ Gitlab::Application.routes.draw do
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :deploy_keys
|
resources :deploy_keys
|
||||||
|
resources :protected_branches, :only => [:index, :create, :destroy]
|
||||||
|
|
||||||
resources :refs, :only => [], :path => "/" do
|
resources :refs, :only => [], :path => "/" do
|
||||||
collection 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.
|
# 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|
|
create_table "issues", :force => true do |t|
|
||||||
t.string "title"
|
t.string "title"
|
||||||
|
@ -82,6 +94,13 @@ ActiveRecord::Schema.define(:version => 20120206170141) do
|
||||||
t.boolean "merge_requests_enabled", :default => true, :null => false
|
t.boolean "merge_requests_enabled", :default => true, :null => false
|
||||||
end
|
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|
|
create_table "snippets", :force => true do |t|
|
||||||
t.string "title"
|
t.string "title"
|
||||||
t.text "content"
|
t.text "content"
|
||||||
|
|
|
@ -64,21 +64,9 @@ module Gitlabhq
|
||||||
def update_project(repo_name, project)
|
def update_project(repo_name, project)
|
||||||
ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
|
ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
|
||||||
conf = ga_repo.config
|
conf = ga_repo.config
|
||||||
|
repo = update_project_config(project, conf)
|
||||||
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?
|
|
||||||
conf.add_repo(repo, true)
|
conf.add_repo(repo, true)
|
||||||
|
|
||||||
ga_repo.save
|
ga_repo.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -89,25 +77,43 @@ module Gitlabhq
|
||||||
conf = ga_repo.config
|
conf = ga_repo.config
|
||||||
|
|
||||||
projects.each do |project|
|
projects.each do |project|
|
||||||
repo_name = project.path
|
repo = update_project_config(project, conf)
|
||||||
|
|
||||||
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?
|
|
||||||
conf.add_repo(repo, true)
|
conf.add_repo(repo, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
ga_repo.save
|
ga_repo.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_project_config(project, conf)
|
||||||
|
repo_name = project.path
|
||||||
|
|
||||||
|
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
|
||||||
|
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?
|
||||||
|
repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
|
||||||
|
|
||||||
|
repo
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -290,15 +290,18 @@ end
|
||||||
#
|
#
|
||||||
# Table name: projects
|
# Table name: projects
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# name :string(255)
|
# name :string(255)
|
||||||
# path :string(255)
|
# path :string(255)
|
||||||
# description :text
|
# description :text
|
||||||
# created_at :datetime
|
# created_at :datetime
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# private_flag :boolean default(TRUE), not null
|
# private_flag :boolean default(TRUE), not null
|
||||||
# code :string(255)
|
# code :string(255)
|
||||||
# owner_id :integer
|
# owner_id :integer
|
||||||
# default_branch :string(255) default("master"), not null
|
# 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