Commit 62ace459 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'hooks_checkbox' into 'master'

Git hooks for email checking

https://dev.gitlab.org/gitlab/gitlab-ee/issues/165

https://dev.gitlab.org/gitlab/gitlab-ee/issues/167

See merge request !228
parents e180e6d5 a7f0160f
v 7.5.0
- Added an ability to check each author commit's email by regex
- Added an abulity to restrict commit authors to existing Gitlab users
v 7.4.0 v 7.4.0
- Support for multiple LDAP servers - Support for multiple LDAP servers
- Skip AD specific LDAP checks - Skip AD specific LDAP checks
......
...@@ -27,6 +27,7 @@ class Projects::GitHooksController < Projects::ApplicationController ...@@ -27,6 +27,7 @@ class Projects::GitHooksController < Projects::ApplicationController
# Only allow a trusted parameter "white list" through. # Only allow a trusted parameter "white list" through.
def git_hook_params def git_hook_params
params.require(:git_hook).permit(:deny_delete_tag, :delete_branch_regex, :commit_message_regex, :force_push_regex) params.require(:git_hook).permit(:deny_delete_tag, :delete_branch_regex,
:commit_message_regex, :force_push_regex, :author_email_regex, :member_check)
end end
end end
...@@ -13,4 +13,8 @@ class GitHook < ActiveRecord::Base ...@@ -13,4 +13,8 @@ class GitHook < ActiveRecord::Base
true true
end end
end end
def commit_validation?
commit_message_regex.present? || author_email_regex.present? || member_check
end
end end
...@@ -213,6 +213,10 @@ class User < ActiveRecord::Base ...@@ -213,6 +213,10 @@ class User < ActiveRecord::Base
User.where(name: name).first User.where(name: name).first
end end
def existing_member?(email)
User.where(email: email).any? || Email.where(email: email).any?
end
def filter(filter_name) def filter(filter_name)
case filter_name case filter_name
when "admins"; self.admins when "admins"; self.admins
......
...@@ -13,13 +13,23 @@ ...@@ -13,13 +13,23 @@
.form-group .form-group
= f.label :deny_delete_tag, "Prevent tag removal", class: 'control-label' = f.label :deny_delete_tag, "Prevent tag removal", class: 'control-label'
.col-sm-10 .col-sm-10
.checkbox %label
= f.check_box :deny_delete_tag .checkbox
%span.descr = f.check_box :deny_delete_tag
Do not allow users to remove git tags with %span.descr
= succeed '.' do Do not allow users to remove git tags with
%code git push = succeed '.' do
Tags can still be deleted through the web UI. %code git push
Tags can still be deleted through the web UI.
.form-group
= f.label :member_check, "Restrict commit authors to existing Gitlab users", class: 'control-label'
.col-sm-10
%label
.checkbox
= f.check_box :member_check
%span.descr
Check whether author is a GitLab member
-#.form-group -#.form-group
= f.label :force_push_regex, "Force push", class: 'control-label' = f.label :force_push_regex, "Force push", class: 'control-label'
...@@ -44,5 +54,15 @@ ...@@ -44,5 +54,15 @@
If this field is empty it allows any commit message. If this field is empty it allows any commit message.
For example you can require that an issue number is always mentioned in the commit message. For example you can require that an issue number is always mentioned in the commit message.
.form-group
= f.label :author_email_regex, "Commit author's email", class: 'control-label'
.col-sm-10
= f.text_field :author_email_regex, class: "form-control", placeholder: 'Example: Fixes @my-company.com$'
%p.hint
All commit author's email must match this
= link_to 'Ruby regular expression', 'http://www.ruby-doc.org/core-2.1.1/Regexp.html'
to be pushed.
If this field is empty it allows any email.
.form-actions .form-actions
= f.submit "Save Git hooks", class: "btn btn-create" = f.submit "Save Git hooks", class: "btn btn-create"
class AddAuthorEmailRegexToGitHook < ActiveRecord::Migration
def change
add_column :git_hooks, :author_email_regex, :string
end
end
class AddMemberCheckToGitHooks < ActiveRecord::Migration
def change
add_column :git_hooks, :member_check, :boolean, default: false, null: false
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141010132608) do ActiveRecord::Schema.define(version: 20141030133853) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -91,6 +91,8 @@ ActiveRecord::Schema.define(version: 20141010132608) do ...@@ -91,6 +91,8 @@ ActiveRecord::Schema.define(version: 20141010132608) do
t.integer "project_id" t.integer "project_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "author_email_regex"
t.boolean "member_check", default: false, null: false
end end
create_table "issues", force: true do |t| create_table "issues", force: true do |t|
......
Feature: Git Hooks
Background:
Given I sign in as a user
And I own project "Shop"
Scenario: I should see git hook form
When I visit project git hooks page
Then I should see git hook form
\ No newline at end of file
require 'webmock'
class Spinach::Features::GitHooks < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
include RSpec::Matchers
include RSpec::Mocks::ExampleMethods
include WebMock::API
step 'I should see git hook form' do
page.should have_selector('input#git_hook_commit_message_regex')
page.should have_content "Commit message"
page.should have_content "Commit author's email"
end
end
...@@ -228,6 +228,10 @@ module SharedPaths ...@@ -228,6 +228,10 @@ module SharedPaths
visit project_hooks_path(@project) visit project_hooks_path(@project)
end end
step 'I visit project git hooks page' do
visit project_git_hooks_path(@project)
end
step 'I visit project deploy keys page' do step 'I visit project deploy keys page' do
visit project_deploy_keys_path(@project) visit project_deploy_keys_path(@project)
end end
......
...@@ -109,11 +109,24 @@ module Gitlab ...@@ -109,11 +109,24 @@ module Gitlab
end end
# Check commit messages unless its branch removal # Check commit messages unless its branch removal
if git_hook.commit_message_regex.present? && newrev !~ /00000000/ if git_hook.commit_validation? && newrev !~ /00000000/
commits = project.repository.commits_between(oldrev, newrev) commits = project.repository.commits_between(oldrev, newrev)
commits.each do |commit| commits.each do |commit|
unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex) if git_hook.commit_message_regex.present?
return false return false unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex)
end
if git_hook.author_email_regex.present?
return false unless commit.committer_email =~ Regexp.new(git_hook.author_email_regex)
return false unless commit.author_email =~ Regexp.new(git_hook.author_email_regex)
end
# Check whether author is a GitLab member
if git_hook.member_check
return false unless User.existing_member?(commit.author_email)
if commit.author_email != commit.committer_email
return false unless User.existing_member?(commit.committer_email)
end
end end
end end
end end
...@@ -144,5 +157,6 @@ module Gitlab ...@@ -144,5 +157,6 @@ module Gitlab
nil nil
end end
end end
end end
end end
...@@ -449,6 +449,27 @@ describe User do ...@@ -449,6 +449,27 @@ describe User do
end end
end end
describe "#existing_member?" do
it "returns true for exisitng user" do
create :user, email: "bruno@example.com"
expect(User.existing_member?("bruno@example.com")).to be_true
end
it "returns false for unknown exisitng user" do
create :user, email: "bruno@example.com"
expect(User.existing_member?("rendom@example.com")).to be_false
end
it "returns true if additional email exists" do
user = create :user
user.emails.create(email: "bruno@example.com")
expect(User.existing_member?("bruno@example.com")).to be_true
end
end
describe "#sort" do describe "#sort" do
before do before do
User.delete_all User.delete_all
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment