Commit 4d7b895c authored by Marin Jankovski's avatar Marin Jankovski

Merge branch 'master' into git_hook_api

parents aee56737 da86eace
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
- Add an option for automatic daily LDAP user sync
v 7.4.0
- Support for multiple LDAP servers
- Skip AD specific LDAP checks
......
......@@ -114,6 +114,7 @@ gem "acts-as-taggable-on"
gem 'slim'
gem 'sinatra', require: nil
gem 'sidekiq', '2.17.0'
gem 'sidetiq', '0.6.1'
# HTTP requests
gem "httparty"
......
......@@ -252,6 +252,7 @@ GEM
multi_xml (>= 0.5.2)
httpauth (0.2.1)
i18n (0.6.11)
ice_cube (0.12.1)
ice_nine (0.10.0)
jasmine (2.0.2)
jasmine-core (~> 2.0.0)
......@@ -477,6 +478,10 @@ GEM
json
redis (>= 3.0.4)
redis-namespace (>= 1.3.1)
sidetiq (0.6.1)
celluloid (>= 0.14.1)
ice_cube (~> 0.12.0)
sidekiq (>= 2.16.0)
simple_oauth (0.1.9)
simplecov (0.9.0)
docile (~> 1.1.0)
......@@ -686,6 +691,7 @@ DEPENDENCIES
settingslogic
shoulda-matchers (~> 2.1.0)
sidekiq (= 2.17.0)
sidetiq (= 0.6.1)
simplecov
sinatra
six
......
......@@ -27,6 +27,7 @@ class Projects::GitHooksController < Projects::ApplicationController
# Only allow a trusted parameter "white list" through.
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
......@@ -13,4 +13,8 @@ class GitHook < ActiveRecord::Base
true
end
end
def commit_validation?
commit_message_regex.present? || author_email_regex.present? || member_check
end
end
......@@ -213,6 +213,10 @@ class User < ActiveRecord::Base
User.where(name: name).first
end
def existing_member?(email)
User.where(email: email).any? || Email.where(email: email).any?
end
def filter(filter_name)
case filter_name
when "admins"; self.admins
......
......@@ -13,13 +13,23 @@
.form-group
= f.label :deny_delete_tag, "Prevent tag removal", class: 'control-label'
.col-sm-10
.checkbox
= f.check_box :deny_delete_tag
%span.descr
Do not allow users to remove git tags with
= succeed '.' do
%code git push
Tags can still be deleted through the web UI.
%label
.checkbox
= f.check_box :deny_delete_tag
%span.descr
Do not allow users to remove git tags with
= succeed '.' do
%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
= f.label :force_push_regex, "Force push", class: 'control-label'
......@@ -44,5 +54,15 @@
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.
.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
= f.submit "Save Git hooks", class: "btn btn-create"
class LdapSyncWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
if Gitlab.config.ldap.enabled
HOUR = Gitlab.config.ldap.schedule_sync_hour
MINUTE = Gitlab.config.ldap.schedule_sync_minute
recurrence { daily.hour_of_day(HOUR).minute_of_hour(MINUTE) }
end
def perform
Rails.logger.info "Performing daily LDAP sync task."
User.ldap.find_each(batch_size: 100).each do |ldap_user|
Rails.logger.debug "Syncing user #{ldap_user.username}, #{ldap_user.email}"
Gitlab::LDAP::Access.allowed?(ldap_user)
end
end
end
......@@ -135,6 +135,14 @@ production: &base
# bundle exec rake gitlab:ldap:check RAILS_ENV=production
ldap:
enabled: false
# GitLab EE only.
# In addition to refreshing users when they log in,
# enabling this setting will refresh LDAP user membership once a day.
# Default time of the day when this will happen is at 1:30am server time.
schedule_sync_hour: 1 # Hour of the day. Value from 0-23.
schedule_sync_minute: 30 # Minute of the hour. Value from 0-59.
servers:
main: # 'main' is the GitLab 'provider ID' of this LDAP server
## label
......
......@@ -56,6 +56,8 @@ end
Settings['ldap'] ||= Settingslogic.new({})
Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
Settings.ldap['sync_time'] = 3600 if Settings.ldap['sync_time'].nil?
Settings.ldap['schedule_sync_hour'] = 1 if Settings.ldap['schedule_sync_hour'].nil?
Settings.ldap['schedule_sync_minute'] = 30 if Settings.ldap['schedule_sync_minute'].nil?
# backwards compatibility, we only have one host
if Settings.ldap['enabled'] || Rails.env.test?
......
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 @@
#
# 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
enable_extension "plpgsql"
......@@ -91,6 +91,8 @@ ActiveRecord::Schema.define(version: 20141010132608) do
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "author_email_regex"
t.boolean "member_check", default: false, null: false
end
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
visit project_hooks_path(@project)
end
step 'I visit project git hooks page' do
visit project_git_hooks_path(@project)
end
step 'I visit project deploy keys page' do
visit project_deploy_keys_path(@project)
end
......
......@@ -109,11 +109,24 @@ module Gitlab
end
# 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.each do |commit|
unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex)
return false
if git_hook.commit_message_regex.present?
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
......@@ -144,5 +157,6 @@ module Gitlab
nil
end
end
end
end
......@@ -449,6 +449,27 @@ describe User do
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
before do
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