Commit badfdf66 authored by Valery Sizov's avatar Valery Sizov

Merge remote-tracking branch 'ee/master' into ce-non-conflict

Conflicts:
	app/controllers/projects/merge_requests_controller.rb
	app/helpers/projects_helper.rb
	db/schema.rb
parents 01ab0812 7453e142
......@@ -310,6 +310,9 @@ v 6.9.0
- Labels for merge requests (Drew Blessing)
- Threaded emails by setting a Message-ID (Philip Blatter)
v 6.8.1
- Bump required gitlab-shell version to 1.9.3
v 6.8.0
- Ability to at mention users that are participating in issue and merge req. discussion
- Enabled GZip Compression for assets in example Nginx, make sure that Nginx is compiled with --with-http_gzip_static_module flag (this is default in Ubuntu)
......
v 7.7.0
- Added custom header logo support (Drew Blessing)
- Fixed preview appearance bug
- Improve performance for selectboxes: project share page, admin email users page
v 7.6.2
- Fix failing migrations for MySQL, LDAP
v 7.6.1
- No changes
v 7.6.0
- Added Audit events related to membership changes for groups and projects
- Added option to attempt a rebase before merging merge request
- Dont show LDAP groups settings if LDAP disabled
- Added member lock for groups to disallow membership additions on project level
- Rebase on merge request. Introduced merge request option to rebase before merging
- Better message for failed pushes because of git hooks
- Kerberos support for web interface and git HTTP
v 7.5.3
- Only set up Sidetiq from a Sidekiq server process (fixes Redis::InheritedError)
v 7.5.0
- Added an ability to check each author commit's email by regex
- Added an ability to restrict commit authors to existing Gitlab users
- Add an option for automatic daily LDAP user sync
- Added git hook for preventing tag removal to API
- Added git hook for setting commit message regex to API
- Added an ability to block commits with certain filenames by regex expression
- Improved a jenkins parser
v 7.4.4
- Fix broken ldap migration
v 7.4.0
- Support for multiple LDAP servers
- Skip AD specific LDAP checks
- Do not show ldap users in dropdowns for groups with enabled ldap-sync
- Update the JIRA integration documentation
- Reset the homepage to show the GitLab logo by deleting the custom logo.
v 7.3.0
- Add an option to change the LDAP sync time from default 1 hour
- User will receive an email when unsubscribed from admin notifications
- Show group sharing members on /my/project/team
- Improve explanation of the LDAP permission reset
- Fix some navigation issues
- Added support for multiple LDAP groups per Gitlab group
v 7.2.0
- Improve Redmine integration
- Better logging for the JIRA issue closing service
- Administrators can now send email to all users through the admin interface
- JIRA issue transition ID is now customizable
- LDAP group settings are now visible in admin group show page and group members page
v 7.1.0
- Synchronize LDAP-enabled GitLab administrators with an LDAP group (Marvin Frick, sponsored by SinnerSchrader)
- Synchronize SSH keys with LDAP (Oleg Girko (Jolla) and Marvin Frick (SinnerSchrader))
- Support Jenkins jobs with multiple modules (Marvin Frick, sponsored by SinnerSchrader)
v 7.0.0
- Fix: empty brand images are displayed as empty image_tag on login page (Marvin Frick, sponsored by SinnerSchrader)
v 6.9.4
- Fix bug in JIRA Issue closing triggered by commit messages
- Fix JIRA issue reference bug
v 6.9.3
- Fix check CI status only when CI service is enabled(Daniel Aquino)
v 6.9.2
- Merge community edition changes for version 6.9.2
v 6.9.1
- Merge community edition changes for version 6.9.1
v 6.9.0
- Add support for closing Jira tickets with commits and MR
- Template for Merge Request description can be added in project settings
- Jenkins CI service
- Fix LDAP email upper case bug
v 6.8.0
- Customise sign-in page with custom text and logo
v 6.7.1
- Handle LDAP errors in Adapter#dn_matches_filter?
v 6.7.0
- Improve LDAP sign-in speed by reusing connections
- Add support for Active Directory nested LDAP groups
- Git hooks: Commit message regex
- Git hooks: Deny git tag removal
- Fix group edit in admin area
v 6.5.0
- Add reset permissions button to Group#members page
v 6.4.0
- Respect existing group permissions during sync with LDAP group (d3844662ec7ce816b0a85c8b40f66ee6c5ae90a1)
v 6.3.0
- When looking up a user by DN, use single scope (bc8a875df1609728f1c7674abef46c01168a0d20)
- Try sAMAccountName if omniauth nickname is nil (9b7174c333fa07c44cc53b80459a115ef1856e38)
v 6.2.0
- API: expose ldap_cn and ldap_access group attributes
- Use omniauth-ldap nickname attribute as GitLab username
- Improve group sharing UI for installation with many groups
- Fix empty LDAP group raises exception
- Respect LDAP user filter for git access
......@@ -44,6 +44,7 @@ gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
# LDAP Auth
gem 'gitlab_omniauth-ldap', '1.2.0', require: "omniauth-ldap"
gem 'net-ldap'
# Git Wiki
gem 'gollum-lib', '~> 3.0.0'
......@@ -119,6 +120,7 @@ gem "acts-as-taggable-on"
gem 'slim'
gem 'sinatra', require: nil
gem 'sidekiq', '2.17.8'
gem 'sidetiq', '0.6.1'
# HTTP requests
gem "httparty"
......
......@@ -256,6 +256,7 @@ GEM
httpauth (0.2.1)
httpclient (2.5.3.3)
i18n (0.6.11)
ice_cube (0.12.1)
ice_nine (0.10.0)
jasmine (2.0.2)
jasmine-core (~> 2.0.0)
......@@ -285,7 +286,7 @@ GEM
addressable (~> 2.3)
letter_opener (1.1.2)
launchy (~> 2.2)
libv8 (3.16.14.7)
libv8 (3.16.14.3)
listen (2.3.1)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
......@@ -497,6 +498,10 @@ GEM
json
redis (~> 3.1)
redis-namespace (~> 1.3)
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)
......@@ -674,6 +679,7 @@ DEPENDENCIES
minitest (~> 5.3.0)
mousetrap-rails
mysql2
net-ldap
newrelic_rpm
nprogress-rails
octokit (= 3.7.0)
......@@ -712,6 +718,7 @@ DEPENDENCIES
settingslogic
shoulda-matchers (~> 2.1.0)
sidekiq (= 2.17.8)
sidetiq (= 0.6.1)
simplecov
sinatra
six
......
Copyright (c) 2011-2014 GitLab B.V.
The GitLab Enterprise Edition (EE) license
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Copyright (c) 2013-2014 GitLab B.V.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
This software and associated documentation files (the "Software") can only be
used with a valid GitLab subscription for the correct number of users. You are
free to modify this Software and publish patches. It is forbidden to copy,
merge, publish, distribute, sublicense, and/or sell copies of the Software.
The above copyright notice applies only to the part of this Software that is
not distributed as part of GitLab Community Edition (CE). Any part of this
Software distributed as part of GitLab CE is copyrighted under the MIT Expat
license. The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
......
# ![logo](https://about.gitlab.com/images/gitlab_logo.png) GitLab
## Subscriber onboarding information
Thank you for purchasing a GitLab subscription!
For standard subscribers, please see **emergency contact info and other useful information** in [the Standard subscribers README](https://gitlab.com/standard/standard-subscriber-information/tree/master#README).
If you would like to receive access to GitLab Enterprise Edition please create an account on https://gitlab.com/users/sign_up and send us the username. Note that your user will be visible to other Support Subscribers.
Once your username is added, you can find the repository here:
https://gitlab.com/subscribers/gitlab-ee
Packages:
https://gitlab.com/subscribers/gitlab-ee/blob/master/doc/install/packages.md
Documentation:
http://doc.gitlab.com/ee/
To upgrade from CE, just perform a normal upgrade, but make use of an EE package:
https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md#updating-from-gitlab-6-6-x-and-higher-to-the-latest-version
If you need help with your GitLab installation and for any technical questions please contact us at subscribers@gitlab.com.
For all other questions, contact us at sales@gitlab.com
## Open source software to collaborate on code
![Animated screenshots](https://about.gitlab.com/images/animated/compiled.gif)
......@@ -21,7 +45,7 @@ To get access to the EE and support please [become a subscriber](https://about.g
## Canonical source
- The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
- The source of GitLab Enterprise Edition is [hosted on GitLab.com](https://dev.gitlab.org/gitlab/gitlab-ee/) and acessible only to [subscribers](https://about.gitlab.com/subscription/).
## Code status
......@@ -87,7 +111,7 @@ Instructions on how to start Gitlab and how to run the tests can be found in the
## Documentation
All documentation can be found on [doc.gitlab.com/ce/](http://doc.gitlab.com/ce/).
All documentation can be found on [doc.gitlab.com/ee/](http://doc.gitlab.com/ee/).
## Getting help
......
7.7.0.pre
7.7.0.pre-ee
class @AdminEmailSelect
constructor: ->
$('.ajax-admin-email-select').each (i, select) =>
skip_ldap = $(select).hasClass('skip_ldap')
$(select).select2
placeholder: "Select group or project"
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) ->
group_result = Api.groups query.term, skip_ldap, (groups) ->
groups
project_result = Api.projects query.term, (projects) ->
projects
$.when(project_result, group_result).done (projects, groups) ->
all = {id: "all"}
data = $.merge([all], groups[0], projects[0])
query.callback({ results: data})
id: (object) ->
if object.path_with_namespace
"project-#{object.id}"
else if object.path
"group-#{object.id}"
else
"all"
formatResult: (args...) =>
@formatResult(args...)
formatSelection: (args...) =>
@formatSelection(args...)
dropdownCssClass: "ajax-admin-email-dropdown"
escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
m
formatResult: (object) ->
if object.path_with_namespace
"<div class='project-result'>
<div class='project-name'>#{object.name}</div>
<div class='project-path'>#{object.path_with_namespace}</div>
</div>"
else if object.path
"<div class='group-result'>
<div class='group-name'>#{object.name}</div>
<div class='group-path'>#{object.path}</div>
</div>"
else
"<div class='group-result'>
<div class='group-name'>All</div>
<div class='group-path'>All groups and projects</div>
</div>"
formatSelection: (object) ->
if object.path_with_namespace
"Project: #{object.name}"
else if object.path
"Group: #{object.name}"
else
"All groups and projects"
......@@ -4,8 +4,10 @@
users_path: "/api/:version/users.json"
user_path: "/api/:version/users/:id.json"
notes_path: "/api/:version/projects/:id/notes.json"
ldap_groups_path: "/api/:version/ldap/:provider/groups.json"
namespaces_path: "/api/:version/namespaces.json"
project_users_path: "/api/:version/projects/:id/users.json"
projects_path: "/api/:version/projects.json"
# Get 20 (depends on api) recent notes
# and sort the ascending from oldest to newest
......@@ -39,7 +41,7 @@
# Return users list. Filtered by query
# Only active users retrieved
users: (query, callback) ->
users: (query, skip_ldap, callback) ->
url = Api.buildUrl(Api.users_path)
$.ajax(
......@@ -49,6 +51,7 @@
search: query
per_page: 20
active: true
skip_ldap: skip_ldap
dataType: "json"
).done (users) ->
callback(users)
......@@ -114,3 +117,33 @@
buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version)
# Return LDAP groups list. Filtered by query
ldap_groups: (query, provider, callback) ->
url = Api.buildUrl(Api.ldap_groups_path)
url = url.replace(':provider', provider);
$.ajax(
url: url
data:
private_token: gon.api_token
search: query
per_page: 20
active: true
dataType: "json"
).done (groups) ->
callback(groups)
# Return projects list. Filtered by query
projects: (query, callback) ->
project_url = Api.buildUrl(Api.projects_path)
project_query = $.ajax(
url: project_url
data:
private_token: gon.api_token
search: query
per_page: 20
dataType: "json"
).done (projects) ->
callback(projects)
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
......@@ -79,6 +79,10 @@ class Dispatcher
new ProjectFork()
when 'users:show'
new User()
when 'projects:group_links:index'
new GroupsSelect()
when 'admin:emails:show'
new AdminEmailSelect()
switch path.first()
when 'admin'
......
$ ->
ldapGroupResult = (group) ->
group.cn
groupFormatSelection = (group) ->
group.cn
$('.ajax-ldap-groups-select').each (i, select) ->
$(select).select2
id: (group) ->
group.cn
placeholder: "Search for a LDAP group"
minimumInputLength: 1
query: (query) ->
provider = $('#ldap_group_link_provider').val();
Api.ldap_groups query.term, provider, (groups) ->
data = { results: groups }
query.callback(data)
initSelection: (element, callback) ->
id = $(element).val()
if id isnt ""
callback(cn: id)
formatResult: ldapGroupResult
formatSelection: groupFormatSelection
dropdownCssClass: "ajax-groups-dropdown"
formatNoMatches: (nomatch) ->
"Match not found; try refining your search query."
$('#ldap_group_link_provider').on 'change', ->
$('.ajax-ldap-groups-select').select2('data', null)
\ No newline at end of file
......@@ -17,4 +17,4 @@ class @Project
path = '/'
$.cookie('hide_no_ssh_message', 'false', { path: path })
$(@).parents('.no-ssh-key-message').hide()
e.preventDefault()
e.preventDefault()
\ No newline at end of file
......@@ -23,3 +23,8 @@ class @ProjectNew
$('#project_issues_tracker_id').attr('disabled', 'disabled')
else
$('#project_issues_tracker_id').removeAttr('disabled')
$("#project_merge_requests_enabled").change ->
checked = $(this).prop("checked")
$("#project_merge_requests_template").prop "disabled", not checked
$("#project_merge_requests_rebase_enabled").prop "disabled", not checked
class @UsersSelect
constructor: ->
$('.ajax-users-select').each (i, select) =>
skip_ldap = $(select).hasClass('skip_ldap')
$(select).select2
placeholder: "Search for a user"
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) ->
Api.users query.term, (users) ->
Api.users query.term, skip_ldap, (users) ->
data = { results: users }
query.callback(data)
......@@ -37,4 +39,4 @@ class @UsersSelect
</div>"
formatSelection: (user) ->
user.name
user.name
\ No newline at end of file
......@@ -283,6 +283,15 @@ img.emoji {
margin-bottom: 10px;
}
.group-name {
font-size: 14px;
line-height: 24px;
}
.available-groups form {
margin: 5px 0;
}
table {
td.permission-x {
background: #D9EDF7 !important;
......
......@@ -128,6 +128,15 @@ select {
}
}
.project-result {
.project-name {
font-weight: bold;
}
.project-path {
color: #999;
}
}
.user-result {
.user-image {
float: left;
......
.appearance-logo-preview {
max-width: 400px;
margin-bottom: 20px;
}
.appearance-dark-logo-preview {
background-color: #F1F1F1;
}
.appearance-light-logo-preview {
background-color: #373737;
}
class Admin::AppearancesController < Admin::ApplicationController
before_filter :set_appearance, except: :create
def show
end
def preview
end
def create
@appearance = Appearance.new(appearance_params)
if @appearance.save
redirect_to admin_appearances_path, notice: 'Appearance was successfully created.'
else
render action: 'show'
end
end
def update
if @appearance.update(appearance_params)
redirect_to admin_appearances_path, notice: 'Appearance was successfully updated.'
else
render action: 'show'
end
end
def logo
appearance = Appearance.last
appearance.remove_logo!
appearance.save
redirect_to admin_appearances_path, notice: 'Logo was succesfully removed.'
end
def header_logos
appearance = Appearance.last
appearance.remove_light_logo!
appearance.remove_dark_logo!
appearance.save
redirect_to admin_appearances_path, notice: 'Header logos were succesfully removed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_appearance
@appearance = Appearance.last || Appearance.new
end
# Only allow a trusted parameter "white list" through.
def appearance_params
params.require(:appearance).permit(:title, :description, :logo,
:dark_logo, :light_logo, :updated_by)
end
end
class Admin::EmailsController < Admin::ApplicationController
def show
end
def create
AdminEmailsWorker.perform_async(params[:recipients], params[:subject], params[:body])
redirect_to admin_email_path, notice: 'Email sent'
end
end
......@@ -242,6 +242,12 @@ class ApplicationController < ActionController::Base
end
end
def require_ldap_enabled
unless Gitlab.config.ldap.enabled
render_404 and return
end
end
def set_filters_params
params[:sort] ||= 'newest'
params[:scope] = 'all' if params[:scope].blank?
......
class AuditEventsController < ApplicationController
# Authorize
before_filter :repository, only: :project_log
before_filter :authorize_admin_project!, only: :project_log
before_filter :group, only: :group_log
before_filter :authorize_admin_group!, only: :group_log
layout :determine_layout
def project_log
@events = AuditEvent.where(entity_type: "Project", entity_id: project.id).page(params[:page]).per(20)
end
def group_log
@events = AuditEvent.where(entity_type: "Group", entity_id: group.id).page(params[:page]).per(20)
end
private
def group
@group ||= Group.find_by(path: params[:group_id])
end
def authorize_admin_group!
render_404 unless can?(current_user, :manage_group, group)
end
def determine_layout
if @project
'project_settings'
elsif @group
'group'
end
end
def audit_events_params
params.permit(:project_id, :group_id)
end
end
......@@ -7,21 +7,59 @@ class Groups::GroupMembersController < ApplicationController
layout 'group'
def create
@group.add_users(params[:user_ids].split(','), params[:access_level])
access_level = params[:access_level]
user_ids = params[:user_ids].split(',')
@group.add_users(user_ids, access_level)
users = User.where(id: user_ids).pluck(:id, :name)
users.each do |user|
details = {
add: "user_access",
as: Gitlab::Access.options_with_owner.key(access_level.to_i),
target_id: user[0],
target_type: "User",
target_details: user[1],
}
AuditEventService.new(current_user, @group, details).security_event
end
redirect_to members_group_path(@group), notice: 'Users were successfully added.'
end
def update
@member = @group.group_members.find(params[:id])
@member.update_attributes(member_params)
old_access_level = @member.human_access
if @member.update_attributes(member_params)
details = {
change: "access_level",
from: old_access_level,
to: @member.human_access,
target_id: @member.user_id,
target_type: "User",
target_details: @member.user.name,
}
AuditEventService.new(current_user, @group, details).security_event
end
end
def destroy
@users_group = @group.group_members.find(params[:id])
if can?(current_user, :destroy, @users_group) # May fail if last owner.
@users_group.destroy
user_id = @users_group.id
user_name = @users_group.user.name
if @users_group.destroy
details = {
remove: "user_access",
target_id: user_id,
target_type: "User",
target_details: user_name,
}
AuditEventService.new(current_user, @group, details).security_event
end
respond_to do |format|
format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' }
format.js { render nothing: true }
......
class Groups::LdapGroupLinksController < ApplicationController
before_action :group
before_action :require_ldap_enabled
before_action :authorize_admin_group!
layout 'group'
def index
end
def create
ldap_group_link = @group.ldap_group_links.build(ldap_group_link_params)
if ldap_group_link.save
if request.referer && request.referer.include?('admin')
redirect_to [:admin, @group], notice: 'New LDAP link saved'
else
redirect_to :back, notice: 'New LDAP link saved'
end
else
redirect_to :back, alert: "Could not create new LDAP link: #{ldap_group_link.errors.full_messages * ', '}"
end
end
def destroy
@group.ldap_group_links.where(id: params[:id]).destroy_all
redirect_to :back, notice: 'LDAP link removed'
end
private
def group
@group ||= Group.find_by(path: params[:group_id])
end
def authorize_admin_group!
render_404 unless can?(current_user, :manage_group, group)
end
def ldap_group_link_params
params.require(:ldap_group_link).permit(:cn, :group_access, :provider)
end
end
class Groups::LdapsController < ApplicationController
before_filter :group
before_filter :authorize_admin_group!
def reset_access
LdapGroupResetService.new.execute(group, current_user)
redirect_to members_group_path(@group), notice: 'Access reset complete'
end
private
def group
@group ||= Group.find_by(path: params[:group_id])
end
def authorize_admin_group!
unless can?(current_user, :manage_group, group)
return render_404
end
end
end
......@@ -37,6 +37,8 @@ class GroupsController < ApplicationController
@events = @events.limit(20).offset(params[:offset] || 0)
@last_push = current_user.recent_push if current_user
@shared_projects = @group.shared_projects
respond_to do |format|
format.html
format.json { pager_json("events/_events", @events.count) }
......@@ -147,6 +149,6 @@ class GroupsController < ApplicationController
end
def group_params
params.require(:group).permit(:name, :description, :path, :avatar)
params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock)
end
end
......@@ -5,8 +5,12 @@ class HelpController < ApplicationController
def show
@category = params[:category]
@file = params[:file]
format = params[:format] || 'md'
file_path = Rails.root.join('doc', @category, @file + ".#{format}")
if File.exists?(Rails.root.join('doc', @category, @file + '.md'))
if %w(png jpg jpeg gif).include?(format)
send_file file_path, disposition: 'inline'
elsif File.exists?(file_path)
render 'show'
else
not_found!
......
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
protect_from_forgery except: :kerberos
Gitlab.config.omniauth.providers.each do |provider|
define_method provider['name'] do
handle_omniauth
......
......@@ -26,7 +26,7 @@ class Profiles::KeysController < ApplicationController
def destroy
@key = current_user.keys.find(params[:id])
@key.destroy
@key.destroy unless @key.is_a? LDAPKey
respond_to do |format|
format.html { redirect_to profile_keys_url }
......
class Projects::GitHooksController < Projects::ApplicationController
# Authorize
before_filter :authorize_admin_project!
respond_to :html
layout "project_settings"
def index
project.create_git_hook unless project.git_hook
@pre_receive_hook = project.git_hook
end
def update
@pre_receive_hook = project.git_hook
@pre_receive_hook.update_attributes(git_hook_params)
if @pre_receive_hook.valid?
redirect_to project_git_hooks_path(@project)
else
render :index
end
end
private
# 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, :author_email_regex, :member_check, :file_name_regex)
end
end
class Projects::GroupLinksController < Projects::ApplicationController
layout 'project_settings'
before_filter :authorize_admin_project!
def index
@group_links = project.project_group_links.all
end
def create
link = project.project_group_links.new
link.group_id = params[:link_group_id]
link.group_access = params[:link_group_access]
link.save
redirect_to project_group_links_path(project)
end
def destroy
project.project_group_links.find(params[:id]).destroy
redirect_to project_group_links_path(project)
end
end
......@@ -113,7 +113,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
return access_denied! unless allowed_to_merge?
if @merge_request.open? && @merge_request.can_be_merged?
<<<<<<< HEAD
AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params)
=======
@merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.should_rebase = params[:should_rebase]
@merge_request.automerge!(current_user, params[:commit_message])
>>>>>>> ee/master
@status = true
else
@status = false
......
......@@ -7,6 +7,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
def index
@group = @project.group
@project_members = @project.project_members.order('access_level DESC')
@project_group_links = @project.project_group_links
end
def new
......@@ -15,8 +16,19 @@ class Projects::TeamMembersController < Projects::ApplicationController
def create
users = User.where(id: params[:user_ids].split(','))
@project.team << [users, params[:access_level]]
access_level = params[:access_level]
@project.team << [users, access_level]
users.each do |user|
details = {
add: "user_access",
as: Gitlab::Access.options_with_owner.key(access_level.to_i),
target_id: user.id,
target_type: "User",
target_details: user.name,
}
AuditEventService.new(current_user, @project, details).security_event
end
if params[:redirect_to]
redirect_to params[:redirect_to]
......@@ -27,7 +39,19 @@ class Projects::TeamMembersController < Projects::ApplicationController
def update
@user_project_relation = @project.project_members.find_by(user_id: member)
@user_project_relation.update_attributes(member_params)
old_access_level = @user_project_relation.human_access
if @user_project_relation.update_attributes(member_params)
details = {
change: "access_level",
from: old_access_level,
to: @user_project_relation.human_access,
target_id: @user_project_relation.user_id,
target_type: "User",
target_details: @user_project_relation.user.name,
}
AuditEventService.new(current_user, @project, details).security_event
end
unless @user_project_relation.valid?
flash[:alert] = "User should have at least one role"
......@@ -37,7 +61,18 @@ class Projects::TeamMembersController < Projects::ApplicationController
def destroy
@user_project_relation = @project.project_members.find_by(user_id: member)
@user_project_relation.destroy
user_id = @user_project_relation.user_id
user_name = @user_project_relation.user.name
if @user_project_relation.destroy
details = {
remove: "user_access",
target_id: user_id,
target_type: "User",
target_details: user_name,
}
AuditEventService.new(current_user, @project, details).security_event
end
respond_to do |format|
format.html { redirect_to project_team_index_path(@project) }
......
......@@ -177,7 +177,8 @@ class ProjectsController < ApplicationController
params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :merge_requests_template,
:merge_requests_rebase_enabled
)
end
end
class UnsubscribesController < ApplicationController
skip_before_filter :authenticate_user!,
:reject_blocked, :set_current_user_for_observers,
:add_abilities
layout 'public_users'
def show
@user = get_user
end
def create
@user = get_user
if @user
@user.admin_unsubscribe!
Notify.send_unsubscribed_notification(@user).deliver
end
redirect_to new_user_session_path, notice: 'You have been unsubscribed'
end
protected
def get_user
@email = Base64.urlsafe_decode64(params[:email])
User.where(email: @email).first
end
end
......@@ -37,12 +37,24 @@ class ProjectsFinder
)
else
# User has no access to group or group projects
# or has access through shared project
#
# Return only:
# public projects
# internal projects
#
group.projects.public_and_internal_only
# shared projects
projects_ids = []
ProjectGroupLink.where(project_id: group.projects).each do |shared_project|
if shared_project.group.users.include?(current_user) || shared_project.project.users.include?(current_user)
projects_ids << shared_project.project.id
end
end
group.projects.where(
"projects.id IN (?) OR projects.visibility_level IN (?)",
projects_ids,
Project.public_and_internal_levels
)
end
end
else
......
module AppearancesHelper
def brand_item
nil
end
def brand_title
'GitLab Community Edition'
if brand_item
brand_item.title
else
'GitLab Enterprise Edition'
end
end
def brand_image
nil
if brand_item.logo?
image_tag brand_item.logo
else
nil
end
end
def brand_header_logo
if brand_item.header_logos?
haml_tag(:style) do
# Dark theme/light logo
haml_concat ".dark_theme .app_logo a h1 {" \
"background: url('#{brand_item.light_logo}') " \
"no-repeat center center !important; }"
# Light theme/dark logo
haml_concat ".light_theme .app_logo a h1 {" \
"background: url('#{brand_item.dark_logo}') " \
"no-repeat center center !important; }"
end
end
end
def brand_text
nil
markdown(brand_item.description)
end
def brand_item
@appearance ||= Appearance.first
end
end
module AuditEventsHelper
def human_text(details)
details.map{ |key, value| select_keys(key, value) }.join(" ").humanize
end
def select_keys(key, value)
if key.match(/^target_.*/)
""
else
"#{key.to_s} <strong>#{value}</strong>"
end
end
end
......@@ -19,4 +19,14 @@ module BranchesHelper
current_user.can?(action, project)
end
def can_rebase?(project, branch_name)
if project.protected_branch? branch_name
can?(current_user, :push_code_to_protected_branches, project)
elsif can?(current_user, :push_code, project)
true
else
false
end
end
end
......@@ -36,6 +36,8 @@ module GroupsHelper
def group_settings_page?
if current_controller?('groups')
current_action?('edit') || current_action?('projects')
elsif current_controller?('ldap_group_links') || current_controller?('audit_events')
true
else
false
end
......
......@@ -30,8 +30,15 @@ module MergeRequestsHelper
classes
end
def ci_build_details_path(merge_request)
merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha)
def ci_build_details_path merge_request
build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha)
parsed_url = URI.parse(build_url)
unless parsed_url.userinfo.blank?
parsed_url.userinfo = ''
end
parsed_url.to_s
end
def merge_path_description(merge_request, separator)
......
......@@ -3,6 +3,14 @@ module OauthHelper
Gitlab.config.ldap.enabled
end
def kerberos_enabled?
enabled_oauth_providers.include?(:kerberos)
end
def standard_login_form_only?
ldap_enabled? || kerberos_enabled?
end
def default_providers
[:twitter, :github, :google_oauth2, :ldap]
end
......@@ -13,11 +21,13 @@ module OauthHelper
def enabled_social_providers
enabled_oauth_providers.select do |name|
[:twitter, :github, :google_oauth2].include?(name.to_sym)
[:twitter, :github, :google_oauth2, :kerberos].include?(name.to_sym)
end
end
def additional_providers
enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
enabled_oauth_providers.reject do |provider|
provider.to_s.starts_with?('ldap') || provider == :kerberos
end
end
end
......@@ -257,5 +257,13 @@ module ProjectsHelper
def github_import_enabled?
Gitlab.config.omniauth.enabled && enabled_oauth_providers.include?(:github)
end
def membership_locked?
if @project.group && @project.group.membership_lock
true
else
false
end
end
end
......@@ -2,6 +2,7 @@ module SelectsHelper
def users_select_tag(id, opts = {})
css_class = "ajax-users-select "
css_class << "multiselect " if opts[:multiple]
css_class << "skip_ldap " if opts[:skip_ldap]
css_class << (opts[:class] || '')
value = opts[:selected] || ''
......@@ -18,6 +19,14 @@ module SelectsHelper
hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder, 'data-project-id' => project_id)
end
def ldap_server_select_options
options_from_collection_for_select(
Gitlab::LDAP::Config.servers,
'provider_name',
'label'
)
end
def groups_select_tag(id, opts = {})
css_class = "ajax-groups-select "
css_class << "multiselect " if opts[:multiple]
......@@ -26,4 +35,13 @@ module SelectsHelper
hidden_field_tag(id, value, class: css_class)
end
def admin_email_select_tag(id, opts = {})
css_class = "ajax-admin-email-select "
css_class << "multiselect " if opts[:multiple]
css_class << (opts[:class] || '')
value = opts[:selected] || ''
hidden_field_tag(id, value, class: css_class)
end
end
......@@ -89,8 +89,8 @@ module TabHelper
def project_tab_class
return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
if ['services', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name
"active"
if ['services', 'git_hooks', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name
"active"
end
end
......
module Emails
module AdminNotification
def send_admin_notification(user_id, subject, body)
email = recipient(user_id)
@unsubscribe_url = unsubscribe_url(email: Base64.urlsafe_encode64(email))
@body = body
mail to: email, subject: subject
end
def send_unsubscribed_notification(user_id)
email = recipient(user_id)
mail to: email, subject: "Unsubscribed from GitLab administrator notifications"
end
end
end
class Notify < ActionMailer::Base
include ActionDispatch::Routing::PolymorphicRoutes
include Emails::AdminNotification
include Emails::Issues
include Emails::MergeRequests
include Emails::Notes
......
class Appearance < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
validates :logo, file_size: { maximum: 1000.kilobytes.to_i }
validates :dark_logo, file_size: { maximum: 1000.kilobytes.to_i },
presence: true, if: :light_logo?
validates :light_logo, file_size: { maximum: 1000.kilobytes.to_i },
presence: true, if: :dark_logo?
mount_uploader :logo, AttachmentUploader
mount_uploader :dark_logo, AttachmentUploader
mount_uploader :light_logo, AttachmentUploader
def header_logos?
dark_logo? && light_logo?
end
end
class AuditEvent < ActiveRecord::Base
serialize :details, Hash
belongs_to :user, foreign_key: :author_id
validates :author_id, presence: true
validates :entity_id, presence: true
validates :entity_type, presence: true
after_initialize :initialize_details
def initialize_details
self.details = {} if details.nil?
end
def author_name
self.user.name
end
end
class GitHook < ActiveRecord::Base
belongs_to :project
validates :project, presence: true
def commit_message_allowed?(message)
if commit_message_regex.present?
if message =~ Regexp.new(commit_message_regex)
true
else
false
end
else
true
end
end
def commit_validation?
commit_message_regex.present? || author_email_regex.present? || member_check || file_name_regex.present?
end
end
......@@ -19,6 +19,9 @@ require 'file_size_validator'
class Group < Namespace
has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember'
has_many :users, through: :group_members
has_many :project_group_links, dependent: :destroy
has_many :shared_projects, through: :project_group_links, source: :project
has_many :ldap_group_links, foreign_key: 'group_id', dependent: :destroy
validate :avatar_type, if: ->(user) { user.avatar_changed? }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
......@@ -70,10 +73,27 @@ class Group < Namespace
end
end
def human_ldap_access
Gitlab::Access.options_with_owner.key ldap_access
end
def public_profile?
projects.public_only.any?
end
# NOTE: Backwards compatibility with old ldap situation
def ldap_cn
ldap_group_links.first.try(:cn)
end
def ldap_access
ldap_group_links.first.try(:group_access)
end
def ldap_synced?
ldap_cn.present?
end
class << self
def search(query)
where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%")
......
class JiraIssue
def initialize(issue_identifier)
@issue_identifier = issue_identifier
end
def to_s
@issue_identifier.to_s
end
def id
@issue_identifier.to_s
end
def iid
@issue_identifier.to_s
end
def ==(other)
other.is_a?(self.class) && (to_s == other.to_s)
end
end
......@@ -25,6 +25,8 @@ class Key < ActiveRecord::Base
validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
scope :ldap, -> { where(type: 'LDAPKey') }
delegate :name, :email, to: :user, prefix: true
after_create :add_to_shell
......
class LdapGroupLink < ActiveRecord::Base
include Gitlab::Access
belongs_to :group
validates :cn, :group_access, :group_id, presence: true
validates :cn, uniqueness: { scope: [:group_id, :provider] }
validates :group_access, inclusion: { in: Gitlab::Access.all_values }
scope :with_provider, ->(provider) { where(provider: provider) }
def access_field
group_access
end
def config
Gitlab::LDAP::Config.new(provider)
rescue Gitlab::LDAP::Config::InvalidProvider
nil
end
# default to the first LDAP server
def provider
read_attribute(:provider) || Gitlab::LDAP::Config.providers.first
end
def provider_label
config.label
end
end
# == Schema Information
#
# Table name: keys
#
# id :integer not null, primary key
# user_id :integer
# created_at :datetime
# updated_at :datetime
# key :text
# title :string(255)
# identifier :string(255)
# type :string(255)
#
class LDAPKey < Key
end
......@@ -26,6 +26,7 @@ class GroupMember < Member
scope :with_group, ->(group) { where(source_id: group.id) }
scope :with_user, ->(user) { where(user_id: user.id) }
scope :with_ldap_dn, -> { joins(user: :identities).where("identities.provider LIKE ?", 'ldap%') }
after_create :notify_create
after_update :notify_update
......
......@@ -40,6 +40,9 @@ class MergeRequest < ActiveRecord::Base
attr_accessor :should_remove_source_branch
# If true, merge request should rebase before merging
attr_accessor :should_rebase
# When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests
attr_accessor :allow_broken
......
......@@ -51,6 +51,7 @@ class Project < ActiveRecord::Base
belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id"
belongs_to :namespace
has_one :git_hook, dependent: :destroy
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
# Project services
......@@ -64,10 +65,13 @@ class Project < ActiveRecord::Base
has_one :assembla_service, dependent: :destroy
has_one :gemnasium_service, dependent: :destroy
has_one :slack_service, dependent: :destroy
has_one :jira_service, dependent: :destroy
has_one :jenkins_service, dependent: :destroy
has_one :buildbox_service, dependent: :destroy
has_one :bamboo_service, dependent: :destroy
has_one :teamcity_service, dependent: :destroy
has_one :pushover_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link
# Merge Requests for target project should be removed with it
......@@ -90,6 +94,9 @@ class Project < ActiveRecord::Base
has_many :users_star_projects, dependent: :destroy
has_many :starrers, through: :users_star_projects, source: :user
has_many :project_group_links, dependent: :destroy
has_many :invited_groups, through: :project_group_links, source: :group
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
......@@ -316,7 +323,7 @@ class Project < ActiveRecord::Base
def available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla
emails_on_push gemnasium slack pushover buildbox bamboo teamcity)
emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira jenkins)
end
def gitlab_ci?
......@@ -331,6 +338,19 @@ class Project < ActiveRecord::Base
@ci_service ||= ci_services.select(&:activated?).first
end
def jira_tracker?
self.issues_tracker == "jira"
end
def redmine_tracker?
self.issues_tracker == "redmine"
end
# For compatibility with old code
def code
path
end
def items_for(entity)
case entity
when 'issue' then
......@@ -582,6 +602,14 @@ class Project < ActiveRecord::Base
merge_requests.where(source_project_id: self.id)
end
def group_ldap_synced?
if group
group.ldap_synced?
else
false
end
end
def create_repository
if gitlab_shell.add_repository(path_with_namespace)
true
......
class ProjectGroupLink < ActiveRecord::Base
GUEST = 10
REPORTER = 20
DEVELOPER = 30
MASTER = 40
belongs_to :project
belongs_to :group
validates :project_id, presence: true
validates :group_id, presence: true
validates :group_id, uniqueness: { scope: [:project_id], message: "already shared with this group" }
validates :group_access, presence: true
validates :group_access, inclusion: { in: Gitlab::Access.values }, presence: true
def self.access_options
Gitlab::Access.options
end
def self.default_access
DEVELOPER
end
def human_access
self.class.access_options.key(self.group_access)
end
end
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class JenkinsService < CiService
prop_accessor :project_url
validates :project_url, presence: true, if: :activated?
delegate :execute, to: :service_hook, prefix: nil
after_save :compose_service_hook, if: :activated?
def compose_service_hook
hook = service_hook || build_service_hook
jenkins_url = project_url.sub(/job\/.*/, '')
hook.url = jenkins_url + "/gitlab/build_now"
hook.save
end
def title
'Jenkins CI'
end
def description
'An extendable open source continuous integration server'
end
def help
'You must have installed GitLab Hook plugin into Jenkins.'
end
def to_param
'jenkins'
end
def fields
[
{ type: 'text', name: 'project_url', placeholder: 'Jenkins project URL like http://jenkins.example.com/job/my-project/' }
]
end
def build_page sha
project_url + "/scm/bySHA1/#{sha}"
end
def commit_status sha
parsed_url = URI.parse(build_page(sha))
if parsed_url.userinfo.blank?
response = HTTParty.get(build_page(sha), verify: false)
else
get_url = build_page(sha).gsub("#{parsed_url.userinfo}@", "")
auth = {
username: URI.decode(parsed_url.user),
password: URI.decode(parsed_url.password),
}
response = HTTParty.get(get_url, verify: false, basic_auth: auth)
end
if response.code == 200
# img.build-caption-status-icon for old jenkins version
src = Nokogiri.parse(response).css('img.build-caption-status-icon,.build-caption>img').first.attributes['src'].value
if src =~ /blue\.png$/
'success'
elsif src =~ /(red\.png|aborted\.png)$/
'failed'
elsif src =~ /anime\.gif$/
'running'
else
'pending'
end
else
:error
end
end
end
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class JiraService < Service
include HTTParty
prop_accessor :project_url, :username, :password,
:api_version, :jira_issue_transition_id
validates :username, :password, presence: true, if: :activated?
before_validation :set_api_version
def title
'JIRA'
end
def description
'Bug, issue tracking, and project management system'
end
def to_param
'jira'
end
def fields
[
{ type: 'text', name: 'project_url', placeholder: 'Url to JIRA, http://jira.example' },
{ type: 'text', name: 'username', placeholder: '' },
{ type: 'password', name: 'password', placeholder: '' },
{ type: 'text', name: 'api_version', placeholder: '2' },
{ type: 'text', name: 'jira_issue_transition_id', placeholder: '2' }
]
end
def set_api_version
self.api_version = "2"
end
def execute(push, issue = nil)
close_issue(push, issue) if issue
end
private
def close_issue(push_data, issue_name)
url = close_issue_url(issue_name)
commit_url = push_data[:commits].first[:url]
message = {
'update' => {
'comment' => [{
'add' => {
'body' => "Issue solved with #{commit_url}"
}
}]
},
'transition' => {
'id' => jira_issue_transition_id
}
}
json_body = message.to_json
Rails.logger.info("#{self.class.name}: sending POST with body #{json_body} to #{url}")
JiraService.post(
url,
body: json_body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Basic #{auth}"
}
)
end
def close_issue_url(issue_name)
"#{self.project_url.chomp("/")}/rest/api/#{self.api_version}/issue/#{issue_name}/transitions"
end
def auth
require 'base64'
Base64.urlsafe_encode64("#{self.username}:#{self.password}")
end
end
......@@ -52,6 +52,7 @@ class ProjectTeam
end
def add_users_ids(user_ids, access)
return false if group_member_lock
ProjectMember.add_users_into_projects(
[project.id],
user_ids,
......@@ -145,14 +146,63 @@ class ProjectTeam
access << group.group_members.find_by(user_id: user_id).try(:access_field)
end
if project.invited_groups.any?
access << max_invited_level(user_id)
end
access.compact.max
end
def max_invited_level(user_id)
project.project_group_links.map do |group_link|
invited_group = group_link.group
access = invited_group.group_members.find_by(user_id: user_id).try(:access_field)
# If group member has higher access level we should restrict it
# to max allowed access level
if access && access > group_link.group_access
access = group_link.group_access
end
access
end.compact.max
end
private
def fetch_members(level = nil)
project_members = project.project_members
group_members = group ? group.group_members : []
invited_members = []
if project.invited_groups.any?
project.project_group_links.each do |group_link|
invited_group = group_link.group
im = invited_group.group_members
if level
int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize]
# Skip group members if we ask for masters
# but max group access is developers
next if int_level > group_link.group_access
# If we ask for developers and max
# group access is developers we need to provide
# both group master, developers as devs
if int_level == group_link.group_access
im.where("access_level >= ?)", group_link.group_access)
else
im.send(level)
end
end
invited_members << im
end
invited_members = invited_members.flatten.compact
end
if level
project_members = project_members.send(level)
......@@ -160,6 +210,7 @@ class ProjectTeam
end
user_ids = project_members.pluck(:user_id)
user_ids += invited_members.map(&:user_id) if invited_members.any?
user_ids += group_members.pluck(:user_id) if group
User.where(id: user_ids)
......@@ -168,4 +219,8 @@ class ProjectTeam
def group
project.group
end
def group_member_lock
group && group.membership_lock
end
end
class SecurityEvent < AuditEvent
end
......@@ -180,6 +180,8 @@ class User < ActiveRecord::Base
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
scope :subscribed_for_admin_email, -> { where(admin_email_unsubscribed_at: nil) }
scope :ldap, -> { joins(:identities).where('identities.provider LIKE ?', 'ldap%') }
scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active }
#
......@@ -213,6 +215,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
......@@ -299,7 +305,8 @@ class User < ActiveRecord::Base
@authorized_projects ||= begin
project_ids = personal_projects.pluck(:id)
project_ids += groups_projects.pluck(:id)
project_ids += projects.pluck(:id).uniq
project_ids += projects.pluck(:id)
project_ids += groups.joins(:shared_projects).pluck(:project_id)
Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC')
end
end
......@@ -434,7 +441,7 @@ class User < ActiveRecord::Base
if !Gitlab.config.ldap.enabled
false
elsif ldap_user?
!last_credential_check_at || (last_credential_check_at + 1.hour) < Time.now
!last_credential_check_at || (last_credential_check_at + Gitlab.config.ldap['sync_time']) < Time.now
else
false
end
......@@ -543,6 +550,10 @@ class User < ActiveRecord::Base
SystemHooksService.new
end
def admin_unsubscribe!
update_column :admin_email_unsubscribed_at, Time.now
end
def starred?(project)
starred_projects.exists?(project)
end
......
class AuditEventService
def initialize(author, entity, details = {})
@author, @entity, @details = author, entity, details
end
def security_event
SecurityEvent.create(
author_id: @author.id,
entity_id: @entity.id,
entity_type: @entity.class.name,
details: @details
)
end
end
......@@ -13,5 +13,9 @@ module Files
def repository
project.repository
end
def git_hook
project.git_hook
end
end
end
......@@ -17,6 +17,10 @@ module Files
return error("You can only create files if you are on top of a branch")
end
if git_hook && !git_hook.commit_message_allowed?(params[:commit_message])
return error("Commit message must match next format: #{git_hook.commit_message_regex}")
end
file_name = File.basename(path)
file_path = path
......
......@@ -17,6 +17,10 @@ module Files
return error("You can only create files if you are on top of a branch")
end
if git_hook && !git_hook.commit_message_allowed?(params[:commit_message])
return error("Commit message must match next format: #{git_hook.commit_message_regex}")
end
blob = repository.blob_at_branch(ref, path)
unless blob
......
......@@ -17,6 +17,10 @@ module Files
return error("You can only create files if you are on top of a branch")
end
if git_hook && !git_hook.commit_message_allowed?(params[:commit_message])
return error("Commit message must match next format: #{git_hook.commit_message_regex}")
end
blob = repository.blob_at_branch(ref, path)
unless blob
......
......@@ -82,7 +82,11 @@ class GitPushService
author ||= commit_user(commit)
issues_to_close.each do |issue|
Issues::CloseService.new(project, author, {}).execute(issue, commit)
if project.jira_tracker? && project.jira_service.active
project.jira_service.execute(push_data, issue)
else
Issues::CloseService.new(project, author, {}).execute(issue, commit)
end
end
end
......
class LdapGroupResetService
def execute(group, current_user)
# Only for ldap connected users
# reset last_credential_check_at to force LDAP::Access::update_permissions
# set Gitlab::Access::Guest to later on upgrade the access of a user
# trigger the lowest access possible for all LDAP connected users
a = group.members.with_ldap_dn.map do |member|
# don't unauthorize the current user
next if current_user == member.user
member.update_attribute :access_level, Gitlab::Access::GUEST
end
group.users.ldap.update_all last_credential_check_at: nil
end
end
......@@ -19,6 +19,9 @@ module MergeRequests
# Generate suggested MR title based on source branch name
merge_request.title = merge_request.source_branch.titleize.humanize
# Set MR description based on project template
merge_request.description = merge_request.target_project.merge_requests_template
compare_result = CompareService.new.execute(
current_user,
merge_request.source_project,
......
= form_for @appearance, url: admin_appearances_path, html: { class: 'form-horizontal'} do |f|
- if @appearance.errors.any?
.alert.alert-danger
- @appearance.errors.full_messages.each do |msg|
%p= msg
%fieldset.sign-in
%legend
Sign in/Sign up pages:
.form-group
= f.label :title, class: 'control-label'
.col-sm-10
= f.text_field :title, class: "form-control"
.form-group
= f.label :description, class: 'control-label'
.col-sm-10
= f.text_area :description, class: "form-control", rows: 10
.hint
Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('markdown', 'markdown'), target: '_blank'}.
.form-group
= f.label :logo, class: 'control-label'
.col-sm-10
- if @appearance.logo?
= image_tag @appearance.logo, class: 'appearance-logo-preview'
%br
= link_to 'Remove logo', logo_admin_appearances_path, data: { confirm: "Logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-logo"
%hr
= f.file_field :logo, class: ""
.hint
Maximum logo size is 1MB, page optimized for logo size 640x360px
%fieldset.app_logo
%legend
Navigation bar:
.form-group
= f.label :dark_logo, class: 'control-label'
.col-sm-10
- if @appearance.dark_logo?
= image_tag @appearance.dark_logo, class: 'appearance-dark-logo-preview'
= f.file_field :dark_logo, class: ""
.hint
Maximum size is 1MB, page optimized for logo size 40x40px
= f.label :light_logo, class: 'control-label'
.col-sm-10
- if @appearance.light_logo?
= image_tag @appearance.light_logo, class: 'appearance-light-logo-preview'
= f.file_field :light_logo, class: ""
.hint
Maximum size is 1MB, page optimized for logo size 41x41px
-if @appearance.light_logo? || @appearance.dark_logo?
%br
= link_to 'Remove header logos', header_logos_admin_appearances_path, data: { confirm: "Header logos will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-logo"
.form-actions
= f.submit 'Save', class: 'btn btn-save'
- if @appearance.persisted?
= link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank'
- if @appearance.updated_at
%span.pull-right
Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
%h3.page-title
Appearance settings - Preview
%hr
.ui-box
.title
Sign-in page
%div
.login-page
.container
.content
.login-title
%h1= brand_title
%hr
.container
.content
.row
.col-sm-7
.brand-image
= brand_image
.brand_text
= brand_text
.col-sm-4
.login-box
%h3.page-title Sign in
= text_field_tag :login, nil, class: "form-control top", placeholder: "Username or Email"
= password_field_tag :password, nil, class: "form-control bottom", placeholder: "Password"
= button_tag "Sign in", class: "btn-create btn"
%h3.page-title
Appearance settings
%p.light
You can modify the look and feel of GitLab here
= render 'form'
%h3.page-title
Send email notication
%p.light
You can notify the app / group or a project by sending them an email notification
= form_tag admin_email_path, class: 'form-horizontal', id: 'new-admin-email' do
.form-group
%label.control-label{for: :subject} Subject
.col-sm-10
= text_field_tag :subject, '', class: 'form-control', required: true
.form-group
%label.control-label{for: :body} Body
.col-sm-10
= text_area_tag :body, '', class: 'form-control', rows: 15, required: true
.form-group
%label.control-label{for: :recipients} Recipient group
.col-sm-10
= admin_email_select_tag(:recipients)
.form-actions
= submit_tag 'Send message', class: 'btn btn-create'
......@@ -25,3 +25,7 @@
= f.submit 'Save changes', class: "btn btn-primary"
= link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel"
- if @group.persisted?
%h3.page-title Linked LDAP groups
= render 'ldap_group_links/form', group: @group
= render 'ldap_group_links/ldap_group_links', group: @group
......@@ -31,6 +31,17 @@
%strong
= @group.created_at.stamp("March 1, 1999")
.panel.panel-default
.panel-heading Linked LDAP groups
%ul.well-list
- if @group.ldap_group_links.any?
- @group.ldap_group_links.each do |ldap_group_link|
%li
cn:
%strong= ldap_group_link.cn
as
%strong= ldap_group_link.human_access
.panel.panel-default
.panel-heading
%h3.panel-title
......@@ -49,6 +60,22 @@
.panel-footer
= paginate @projects, param_name: 'projects_page', theme: 'gitlab'
- if @group.shared_projects.any?
.panel.panel-default
.panel-heading
Projects shared with #{@group.name}
%span.badge
#{@group.shared_projects.count}
%ul.well-list
- @group.shared_projects.sort_by(&:name).each do |project|
%li
%strong
= link_to project.name_with_namespace, [:admin, project]
%span.label.label-gray
= repository_size(project)
%span.pull-right.light
%span.monospace= project.path_with_namespace + ".git"
.col-md-6
.panel.panel-default
.panel-heading
......@@ -60,7 +87,7 @@
= form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
%div
= users_select_tag(:user_ids, multiple: true)
= users_select_tag(:user_ids, { multiple: true, skip_ldap: @group.ldap_synced? })
%div.prepend-top-10
= select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2"
%hr
......
......@@ -32,6 +32,7 @@
.panel-heading
Users (#{@users.total_count})
.panel-head-actions
= link_to 'Send email to users', admin_email_path, class: 'btn btn-info'
.dropdown.inline
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort:
......
- if defined?(events)
%table.table#audits
%thead
%tr
%th Author
%th Action
%th Target
%th At
%tbody
- events.each do |event|
%tr
%td #{event.author_name}
%td
%span
#{raw human_text(event.details)}
%td #{event.details[:target_details]}
%td #{event.created_at}
= paginate events, theme: "gitlab"
%h3.page-title Group Audit Events
%p.light Events in #{@group.name}
= render 'event_table', events: @events
%h3.page-title Project Audit Events
%p.light Events in #{@project.path_with_namespace}
= render 'event_table', events: @events
= form_tag(user_omniauth_callback_path(provider), id: 'new_kerberos_user' ) do
= text_field_tag :username, nil, {class: "form-control top", placeholder: "Kerberos Login", autofocus: "autofocus"}
= password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
%br/
= button_tag "Kerberos Sign in", class: "btn-save btn"
\ No newline at end of file
......@@ -7,6 +7,9 @@
- @ldap_servers.each_with_index do |server, i|
%li{class: (:active if i.zero?)}
= link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
- if kerberos_enabled?
%li{class: (:active unless ldap_enabled?)}
= link_to "Kerberos", "#tab-kerberos", 'data-toggle' => 'tab'
- if signin_enabled?
%li
= link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
......@@ -14,6 +17,9 @@
- @ldap_servers.each_with_index do |server, i|
%div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)}
= render 'devise/sessions/new_ldap', provider: server['provider_name']
- if kerberos_enabled?
%div#tab-kerberos.tab-pane{class: (:active unless ldap_enabled?)}
= render 'devise/sessions/new_kerberos', provider: :kerberos
- if signin_enabled?
%div#tab-signin.tab-pane
= render 'devise/sessions/new_base'
......
= form_for @users_group, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
.form-group
= f.label :user_ids, "People", class: 'control-label'
.col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large')
.col-sm-10= users_select_tag(:user_ids, { multiple: true, skip_ldap: @group.ldap_synced? , class: 'input-large' })
.form-group
= f.label :access_level, "Group Access", class: 'control-label'
......
......@@ -9,3 +9,14 @@
%i.fa.fa-folder
%span
Projects
- if ldap_enabled?
= nav_link(controller: :ldap_group_links) do
= link_to group_ldap_group_links_path(@group) do
%i.fa.fa-exchange
%span
LDAP Groups
= nav_link(controller: :audit_events) do
= link_to group_audit_events_path(@group) do
%i.fa.fa-file-text-o
%span
Audit Events
- if projects.present?
.panel.panel-default
.panel-heading
Projects shared with
%strong #{@group.name}
(#{projects.count})
%ul.well-list
- projects.each do |project|
%li.project-row
= link_to project_path(project), class: dom_class(project) do
%span.namespace-name
- if project.namespace
= project.namespace.human_name
\/
%span.project-name
= truncate(project.name, length: 25)
%span.arrow
%i.icon-angle-right
......@@ -23,6 +23,15 @@
%hr
= link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
.form-group
%hr
= f.label :name, class: 'control-label' do
Member lock
.col-sm-10
.checkbox
= f.check_box :membership_lock
%span.descr Prevent adding new members to project membership within this group
.form-actions
= f.submit 'Save group', class: "btn btn-save"
......@@ -33,5 +42,4 @@
Removing group will cause all child projects and resources to be removed.
%br
%strong Removed group can not be restored!
= link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove"
%h3.page-title Linked LDAP groups
= render 'ldap_group_links/form', group: @group
= render 'ldap_group_links/ldap_group_links', group: @group
......@@ -17,6 +17,10 @@
- if current_user && current_user.can?(:manage_group, @group)
.pull-right
- if ldap_enabled? && @group.ldap_group_links.any?
= link_to reset_access_group_ldap_path(@group), class: 'btn btn-grouped', data: { confirm: "Force GitLab to do LDAP permission checks for all group members? All members besides yourself will be reduced to 'Guest' access until their next interaction with GitLab." }, method: :put do
Clear LDAP permission cache
= link_to '#', class: 'btn btn-new js-toggle-button' do
Add members
%i.fa.fa-chevron-down
......@@ -24,6 +28,19 @@
.js-toggle-content.hide.new-group-member-holder
= render "new_group_member"
- if ldap_enabled? && @group.ldap_group_links.any?
.bs-callout.bs-callout-info
The members of this group are sync with LDAP.
Because LDAP permissions in GitLab get updated one user at a time and because GitLab caches LDAP check results, changes on your LDAP server or in this group's LDAP sync settings may take up to #{Gitlab.config.ldap['sync_time']}s to show in the list below.
%ul
- @group.ldap_group_links.each do |ldap_group_link|
%li
People in cn
%code= ldap_group_link.cn
are given
%code= ldap_group_link.human_access
access.
.panel.panel-default.prepend-top-20
.panel-heading
%strong #{@group.name}
......
......@@ -20,3 +20,5 @@
= spinner
%aside.side.col-md-4
= render "projects", projects: @projects
%br
= render "shared_projects", projects: @shared_projects
%div
%h1
GitLab
%span.light Enterprise Edition
%span= Gitlab::VERSION
%small= Gitlab::REVISION
%p.slead
......
......@@ -7,7 +7,7 @@
-# https://github.com/gitlabhq/gitlabhq/pull/5958#issuecomment-45397555
- if controller_name == 'projects' && action_name == 'show'
%meta{name: "go-import", content: "#{@project.web_url_without_protocol} git #{@project.web_url}.git"}
%meta{content: "GitLab Community Edition", name: "description"}
%meta{content: "GitLab Enterprise Edition", name: "description"}
%title
= "#{title} | " if defined?(title)
......
......@@ -2,6 +2,7 @@
.navbar-inner
.container
%div.app_logo
- brand_header_logo if brand_item
= link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do
%h1 GITLAB
%h1.title= title
......
......@@ -39,7 +39,11 @@
%i.fa.fa-cog
%span
Background Jobs
= nav_link(controller: :appearances) do
= link_to admin_appearances_path do
%i.fa.fa-image
%span
Appearance
= nav_link(controller: :application_settings) do
= link_to admin_application_settings_path do
%i.fa.fa-cogs
......
%section.ldap-group-links
= form_for [group, LdapGroupLink.new] do |f|
%fieldset
%legend
%div.form-holder
.form-group.clearfix
= f.label :cn, class: 'control-label' do
LDAP Server
.col-sm-10
= f.select :provider, ldap_server_select_options
.form-group.clearfix
= f.label :cn, class: 'control-label' do
LDAP Group cn
.col-sm-10
= f.hidden_field :cn, placeholder: "Ex. QA group", class: "xxlarge ajax-ldap-groups-select input-mn-300"
.help-block
Synchronize #{group.name}'s members with this LDAP group.
%br
If you select an LDAP group you do not belong to you will lose ownership of #{group.name}.
.form-group.clearfix
= f.label :group_access, class: 'control-label' do
LDAP Access
.col-sm-10
= f.select :group_access, options_for_select(GroupMember.access_level_roles)
.help-block
Default, minimum permission level for LDAP group members of #{group.name}.
%br
You can manage permission levels for individual group members in the Members tab.
.form-actions
= f.submit 'Add synchronization', class: "btn btn-create"
%li
%h4= ldap_group_link.cn
.pull-right
= link_to group_ldap_group_link_path(group, ldap_group_link), method: :delete, class: 'btn btn-danger btn-small' do
= fa_icon('unlink', text: 'unlink')
- if ldap_group_link.config
%p.light
As
%strong #{ldap_group_link.human_access}
on
%strong #{ldap_group_link.provider_label}
server
- else
%p.cred
%i.fa.fa-warning
Config for
%code #{ldap_group_link.provider}
does not present in GitLab
.panel.panel-default
.panel-heading
%h4.panel-title
Linked LDAP groups
== (#{group.ldap_group_links.count})
- if group.ldap_group_links.any?
%ul.well-list
= render collection: group.ldap_group_links, partial: 'ldap_group_links/ldap_group_link', locals: { group: group }
- else
.panel-body
No linked LDAP groups
= simple_format @body
\----
%p
Don't want to receive updates from GitLab administrators?
= link_to 'Unsubscribe', @unsubscribe_url
\ No newline at end of file
= h @body
\-----
Don't want to receive updates from GitLab administrators?
== Unsubscribe here: #{@unsubscribe_url}
\ No newline at end of file
%p
You have been unsubscribed from receiving GitLab administrator notifications.
You have been unsubscribed from receiving GitLab administrator notifications.
......@@ -9,4 +9,5 @@
%span.cgray
added #{time_ago_with_tooltip(key.created_at)}
%td
= link_to 'Remove', path_to_key(key, is_admin), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
- unless key.is_a? LDAPKey
= link_to 'Remove', path_to_key(key, is_admin), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
......@@ -19,4 +19,5 @@
%pre.well-pre
= @key.key
.pull-right
= link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
- unless @key.is_a? LDAPKey
= link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
......@@ -9,6 +9,11 @@
%i.fa.fa-users
%span
Members
= nav_link(controller: :group_links) do
= link_to project_group_links_path(@project) do
%i.fa.fa-share-square-o
%span
Groups
= nav_link(controller: :deploy_keys) do
= link_to project_deploy_keys_path(@project) do
%i.fa.fa-key
......@@ -19,6 +24,11 @@
%i.fa.fa-link
%span
Web Hooks
= nav_link(controller: :git_hooks) do
= link_to project_git_hooks_path(@project) do
%i.fa.fa-git-square
%span
Git Hooks
= nav_link(controller: :services) do
= link_to project_services_path(@project) do
%i.fa.fa-cogs
......@@ -29,3 +39,8 @@
%i.fa.fa-lock
%span
Protected branches
= nav_link(controller: :audit_events) do
= link_to project_audit_events_path(@project) do
%i.fa.fa-file-text-o
%span
Audit Events
......@@ -66,6 +66,20 @@
= f.check_box :merge_requests_enabled
%span.descr Submit changes to be merged upstream.
.form-group
= f.label :merge_requests_rebase_enabled, "Merge Requests Rebase", class: 'control-label'
.col-sm-10
.checkbox
= f.check_box :merge_requests_rebase_enabled
%span.descr Allows rebasing of merge requests before merging.
.form-group
= f.label :merge_requests_template, class: 'control-label' do
Merge request template
%span.light (optional)
.col-sm-10
= f.text_area :merge_requests_template, placeholder: "This MR should have: *", disabled: !@project.merge_requests_enabled, class: "form-control", rows: 3
.form-group
= f.label :wiki_enabled, "Wiki", class: 'control-label'
.col-sm-10
......
%h3.page-title
Git hooks
%p.light
Rules that define what git pushes are accepted for this project
%hr.clearfix
= form_for [@project, @pre_receive_hook], html: { class: 'form-horizontal' } do |f|
-if @pre_receive_hook.errors.any?
.alert.alert-danger
- @pre_receive_hook.errors.full_messages.each do |msg|
%p= msg
.form-group
= f.label :deny_delete_tag, "Prevent tag removal", class: 'control-label'
.col-sm-10
%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 commits by author(email) 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 user
-#.form-group
= f.label :force_push_regex, "Force push", class: 'control-label'
.col-sm-10
= f.text_field :force_push_regex, class: "form-control"
%p.hint Regular expression that finds branches that you can force push to. If this field is empty it allows force pushes to any branch.
-#.form-group
= f.label :delete_branch_regex, "Branch removal", class: 'control-label'
.col-sm-10
= f.text_field :delete_branch_regex, class: "form-control"
%p.hint Regular expression that finds branches that can be removed. If this field is empty it allows removal of all branches.
.form-group
= f.label :commit_message_regex, "Commit message", class: 'control-label'
.col-sm-10
= f.text_field :commit_message_regex, class: "form-control", placeholder: 'Example: Fixes \d+\..*'
%p.hint
All commit messages 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 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-group
= f.label :file_name_regex, "Prohibited file names", class: 'control-label'
.col-sm-10
= f.text_field :file_name_regex, class: "form-control", placeholder: 'Example: (jar|exe)$'
%p.hint
All commited filenames must not 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 filenames.
.form-actions
= f.submit "Save Git hooks", class: "btn btn-create"
%h3.page_title Share project with other groups
%p.light
Projects can be stored in only one group at once. However you can share a project with other groups here.
%hr
- if @group_links.present?
.enabled-groups.append-bottom-20
%h4
Already shared with
%ul.bordered-list
- @group_links.each do |group_link|
- group = group_link.group
%li
%h4
= link_to group do
%i.icon-folder-open
= group.name
%small.light up to #{group_link.human_access}
.pull-right
= link_to project_group_link_path(@project, group_link), method: :delete, class: 'btn btn-small append-right-10' do
%i.icon-remove
disable sharing
.available-groups
%h4
Can be shared with
%div
= form_tag project_group_links_path(@project), method: :post, class: 'form-horizontal' do
.form-group
= label_tag :link_group_id, 'Group', class: 'control-label'
.col-sm-10
= groups_select_tag(:link_group_id)
.form-group
= label_tag :link_group_access, 'Max access level', class: 'control-label'
.col-sm-10
= select_tag :link_group_access, options_for_select(ProjectGroupLink.access_options, ProjectGroupLink.default_access), class: "form-control"
.form-actions
= submit_tag "Share", class: "btn btn-create"
......@@ -21,6 +21,11 @@
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch
Remove source-branch
- if @merge_request.target_project.merge_requests_rebase_enabled && can_rebase?(@merge_request.target_project, @merge_request.target_branch)
.accept-control.remove_branch_holder
= label_tag :should_rebase, class: "checkbox" do
= check_box_tag :should_rebase
Rebase before merge
.accept-control
= link_to "#", class: "modify-merge-commit-link js-toggle-button", title: "Modify merge commit message" do
%i.fa.fa-edit
......
......@@ -43,6 +43,8 @@
= f.text_area name, rows: 5, class: "form-control", placeholder: placeholder
- elsif type == 'checkbox'
= f.check_box name
- elsif type == 'password'
= f.password_field name, class: "form-control"
- elsif type == 'select'
= f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
- elsif type == 'password'
......
......@@ -12,7 +12,7 @@
.form-group
= f.label :user_ids, "People", class: 'control-label'
.col-sm-10
= users_select_tag(:user_ids, multiple: true)
= users_select_tag(:user_ids, { multiple: true })
%p 2. Set access level for them
.form-group
......
- @project_group_links.each do |group_links|
- shared_group = group_links.group
- shared_group_users_count = group_links.group.group_members.count
.panel.panel-default
.panel-heading
Shared with
%strong #{shared_group.name}
group, members with
%strong #{group_links.human_access}
role (#{shared_group_users_count})
.pull-right
= link_to members_group_path(shared_group), class: 'btn btn-small' do
%i.icon-edit
%ul.well-list
- shared_group.group_members.order('access_level DESC').limit(20).each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: false, show_roles: false
- if shared_group_users_count > 20
%li
and #{shared_group_users_count - 20} more. For full list visit #{link_to 'group members page', members_group_path(shared_group)}
......@@ -13,5 +13,3 @@
%p
%strong= user.name
%span.cgray= user.username
%h3.page-title
Users with access to this project
- if can? current_user, :admin_team_member, @project
%span.pull-right
= link_to new_project_team_member_path(@project), class: "btn btn-new btn-grouped", title: "New project member" do
New project member
= link_to import_project_team_members_path(@project), class: "btn btn-grouped", title: "Import members from another project" do
Import members
- unless membership_locked?
- if can?(current_user, :admin_team_member, @project)
%span.pull-right
= link_to new_project_team_member_path(@project), class: "btn btn-new btn-grouped", title: "New project member" do
New project member
= link_to import_project_team_members_path(@project), class: "btn btn-grouped", title: "Import members from another project" do
Import members
%p.light
Read more about project permissions
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
- if membership_locked?
%span.pull-right
Adding new users is disabled at group level
= render "team", members: @project_members
- if @group
= render "group_members"
- if @project_group_links.any?
= render "shared_group_members"
%h3.page-title Unsubscribe from Admin notifications
%hr
= form_tag unsubscribe_path(Base64.urlsafe_encode64(@email)) do
%p
Yes, I want to unsubscribe
%strong= @email
from any further admin emails.
.form-actions
= submit_tag 'Unsubscribe', class: 'btn btn-create'
class AdminEmailsWorker
include Sidekiq::Worker
def perform(recipient_id, subject, body)
recipient_list(recipient_id).pluck(:id).each do |user_id|
Notify.send_admin_notification(user_id, subject, body).deliver
end
end
private
def recipient_list(recipient_id)
case recipient_id
when 'all'
User.subscribed_for_admin_email
when /group-(\d+)\z/
Group.find($1).users.subscribed_for_admin_email
when /project-(\d+)\z/
Project.find($1).team.users.subscribed_for_admin_email
end
end
end
class LdapSyncWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
# We check if we are in a Sidekiq server process because of a bug in Sidetiq
# 0.6.1 which was giving Unicorn trouble (throwing a Redis::InheritedError).
if Gitlab.config.ldap.enabled && Sidekiq.server?
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
......@@ -77,7 +77,7 @@ production: &base
# This happens when the commit is pushed or merged into the default branch of a project.
# When not specified the default issue_closing_pattern as specified below will be used.
# Tip: you can test your closing pattern at http://rubular.com
# issue_closing_pattern: '([Cc]lose[sd]|[Ff]ixe[sd]) #(\d+)'
# issue_closing_pattern: '([Cc]lose[sd]|[Ff]ixe[sd]) (#\d+|([A-Z\-]+-)\d+)'
## Default project features settings
default_projects_features:
......@@ -142,6 +142,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
......@@ -190,6 +198,33 @@ production: &base
#
user_filter: ''
# This setting controls the amount of time between LDAP permission checks for each user.
# After this time has expired for a given user, their next interaction with GitLab (a click in the web UI, a git pull etc.) will be slower because the LDAP permission check is being performed.
# How much slower depends on your LDAP setup, but it is not uncommon for this check to add seconds of waiting time.
# The default value is to have a 'slow click' once every 3600 seconds, i.e. once per hour.
#
# Warning: if you set this value too low, every click in GitLab will be a 'slow click' for all of your LDAP users.
# sync_time: 3600
# Base where we can search for groups
#
# Ex. ou=Groups,dc=gitlab,dc=example
#
group_base: ''
# LDAP group of users who should be admins in GitLab
#
# Ex. GLAdmins
#
admin_group: ''
# Name of attribute which holds a ssh public key of the user object.
# If false or nil, SSH key syncronisation will be disabled.
#
# Ex. sshpublickey
#
sync_ssh_keys: false
# GitLab EE only: add more LDAP servers
# Choose an ID made of a-z and 0-9 . This ID will be stored in the database
# so that GitLab can remember which LDAP server a user belongs to.
......@@ -198,7 +233,6 @@ production: &base
# host:
# ....
## OmniAuth settings
omniauth:
# Allow login via Twitter, Google, etc. using OmniAuth providers
......
......@@ -52,15 +52,19 @@ class Settings < Settingslogic
end
end
# Default settings
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?
if Settings.ldap['host'].present?
server = Settings.ldap.except('sync_time')
server = Settingslogic.new(server)
server['label'] = 'LDAP'
server['provider_name'] = 'ldap'
Settings.ldap['servers'] = {
'ldap' => server
......@@ -68,11 +72,14 @@ if Settings.ldap['enabled'] || Rails.env.test?
end
Settings.ldap['servers'].each do |key, server|
server = Settingslogic.new(server)
server['label'] ||= 'LDAP'
server['allow_username_or_email_login'] = false if server['allow_username_or_email_login'].nil?
server['active_directory'] = true if server['active_directory'].nil?
server['provider_name'] ||= "ldap#{key}".downcase
server['sync_time'] = 3600 if server['sync_time'].nil?
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
Settings.ldap['servers'][key] = server
end
end
......@@ -109,7 +116,7 @@ Settings.gitlab['signup_enabled'] ||= false
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '([Cc]lose[sd]|[Ff]ixe[sd]) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['issue_closing_pattern'] = '([Cc]lose[sd]|[Ff]ixe[sd]) (#\d+|([A-Z\-]+-)\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil?
......
if Gitlab::LDAP::Config.enabled?
module OmniAuth::Strategies
server = Gitlab.config.ldap.servers.values.first
klass = server['provider_class']
const_set(klass, Class.new(LDAP)) unless klass == 'LDAP'
Gitlab::LDAP::Config.servers.each do |server|
# do not redeclare LDAP
next if server['provider_name'] == 'ldap'
const_set(server['provider_class'], Class.new(LDAP))
end
end
OmniauthCallbacksController.class_eval do
server = Gitlab.config.ldap.servers.values.first
alias_method server['provider_name'], :ldap
Gitlab::LDAP::Config.servers.each do |server|
alias_method server['provider_name'], :ldap
end
end
end
\ No newline at end of file
end
......@@ -205,7 +205,7 @@ Devise.setup do |config|
# end
if Gitlab::LDAP::Config.enabled?
Gitlab.config.ldap.servers.values.each do |server|
Gitlab::LDAP::Config.servers.each do |server|
if server['allow_username_or_email_login']
email_stripping_proc = ->(name) {name.gsub(/@.*$/,'')}
else
......
......@@ -39,6 +39,7 @@ Gitlab::Application.routes.draw do
get 'help' => 'help#index'
get 'help/:category/:file' => 'help#show', as: :help_page
get 'help/:category/*file' => 'help#show'
get 'help/shortcuts'
#
......@@ -110,6 +111,7 @@ Gitlab::Application.routes.draw do
resources :broadcast_messages, only: [:index, :create, :destroy]
resource :logs, only: [:show]
resource :background_jobs, controller: 'background_jobs', only: [:show]
resource :email, only: [:show, :create]
resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do
member do
......@@ -117,8 +119,15 @@ Gitlab::Application.routes.draw do
end
end
resource :application_settings, only: [:show, :update]
resource :appearances, path: 'appearance' do
member do
get :preview
delete :logo
delete :header_logos
end
end
resource :application_settings, only: [:show, :update]
root to: "dashboard#index"
end
......@@ -180,12 +189,25 @@ Gitlab::Application.routes.draw do
end
scope module: :groups do
resource :ldap, only: [] do
member do
put :reset_access
end
end
end
scope module: :groups do
resources :ldap_group_links, only: [:index, :create, :destroy]
resources :group_members, only: [:create, :update, :destroy]
resource :avatar, only: [:destroy]
resources :milestones
end
get "/audit_events" => "audit_events#group_log"
end
get 'unsubscribes/:email', to: 'unsubscribes#show', as: :unsubscribe
post 'unsubscribes/:email', to: 'unsubscribes#create'
resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords, sessions: :sessions, confirmations: :confirmations }
......@@ -308,6 +330,8 @@ Gitlab::Application.routes.draw do
end
end
resources :git_hooks, constraints: {id: /\d+/}
resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
member do
get :test
......@@ -345,12 +369,16 @@ Gitlab::Application.routes.draw do
end
end
resources :group_links, only: [:index, :create, :destroy], constraints: {id: /\d+/}
resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do
member do
delete :delete_attachment
end
end
end
get "/audit_events" => "audit_events#project_log"
end
get ':id' => "namespaces#show", constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
......
class CreateProjectGroupLinks < ActiveRecord::Migration
def change
create_table :project_group_links do |t|
t.integer :project_id, null: false
t.integer :group_id, null: false
t.timestamps
end
end
end
class AddLdapSettingsToGroup < ActiveRecord::Migration
def change
add_column :namespaces, :ldap_cn, :string, null: true
end
end
class AddLdapAccessToGroup < ActiveRecord::Migration
def change
add_column :namespaces, :ldap_access, :integer, null: true
end
end
class AddAccessToProjectGroupLink < ActiveRecord::Migration
def change
add_column :project_group_links, :group_access, :integer, null: false, default: ProjectGroupLink.default_access
end
end
class CreateGitHooks < ActiveRecord::Migration
def change
create_table :git_hooks do |t|
t.string :force_push_regex
t.string :delete_branch_regex
t.string :commit_message_regex
t.boolean :deny_delete_tag
t.integer :project_id
t.timestamps
end
end
end
class CreateAppearances < ActiveRecord::Migration
def change
create_table :appearances do |t|
t.string :title
t.text :description
t.string :logo
t.integer :updated_by
t.timestamps
end
end
end
class AddMrTemplateToProject < ActiveRecord::Migration
def change
add_column :projects, :merge_requests_template, :text
end
end
class AddUsernamePasswordApiVersionToServices < ActiveRecord::Migration
def change
add_column :services, :username, :string
add_column :services, :password, :string
add_column :services, :api_version, :string
end
end
class AddUnsubscribedAtFieldToUsers < ActiveRecord::Migration
def change
add_column :users, :admin_email_unsubscribed_at, :datetime
end
end
class AddJiraIssueTransitionIdToServices < ActiveRecord::Migration
def up
add_column :services, :jira_issue_transition_id, :string, default: '2'
Service.reset_column_information
Service.where(jira_issue_transition_id: nil).update_all jira_issue_transition_id: '2'
end
def down
remove_column :services, :jira_issue_transition_id
end
end
class AddLdapGroupsTable < ActiveRecord::Migration
def up
create_table :ldap_groups do |t|
t.string :cn, null: false
t.integer :group_access, null: false
t.references :group, null: false
t.timestamps
end
end
def down
drop_table :ldap_groups
end
end
class RenameLdapGroupToLdapGroupLink < ActiveRecord::Migration
def up
rename_table :ldap_groups, :ldap_group_links
# NOTE: we use the old_ methods because the new methods are overloaded
# for backwards compatibility
time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
execute "INSERT INTO ldap_group_links ( group_access, cn, group_id, created_at, updated_at )
SELECT ldap_access, ldap_cn, id, DATE('#{time}'), DATE('#{time}') FROM namespaces
WHERE ldap_cn IS NOT NULL;"
end
def down
rename_table :ldap_group_links, :ldap_groups
end
end
class RemoveColumnsForServices < ActiveRecord::Migration
def change
remove_column :services, :username, :string
remove_column :services, :password, :string
remove_column :services, :jira_issue_transition_id, :string
remove_column :services, :api_version, :string
end
end
class AddProviderToLdapGroupLinks < ActiveRecord::Migration
def change
add_column :ldap_group_links, :provider, :string
end
end
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
class AddFileNameRegexToGitHooks < ActiveRecord::Migration
def change
add_column :git_hooks, :file_name_regex, :string
end
end
class AddAuditEvent < ActiveRecord::Migration
def change
create_table :audit_events do |t|
t.integer :author_id, null: false
t.string :type, null: false
# "Namespace" where the change occurs
# eg. On a project, group or user
t.integer :entity_id, null: false
t.string :entity_type, null: false
# Details for the event
t.text :details
t.timestamps
end
add_index :audit_events, :author_id
add_index :audit_events, :type
add_index :audit_events, [:entity_id, :entity_type]
end
end
class AddMergeRequestRebaseEnabledToProjects < ActiveRecord::Migration
def change
add_column :projects, :merge_requests_rebase_enabled, :boolean, default: false
end
end
class AddGroupMembershipLock < ActiveRecord::Migration
def change
add_column :namespaces, :membership_lock, :boolean, default: false
end
end
class AddHeaderLogosToAppearances < ActiveRecord::Migration
def change
add_column :appearances, :dark_logo, :string
add_column :appearances, :light_logo, :string
end
end
class RemoveOldFieldsFromNamespace < ActiveRecord::Migration
def up
remove_column :namespaces, :ldap_cn
remove_column :namespaces, :ldap_access
end
def down
add_column :namespaces, :ldap_cn, :string, null: true
add_column :namespaces, :ldap_access, :integer, null: true
end
end
......@@ -16,6 +16,31 @@ ActiveRecord::Schema.define(version: 20150108073740) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "appearances", force: true do |t|
t.string "title"
t.text "description"
t.string "logo"
t.integer "updated_by"
t.datetime "created_at"
t.datetime "updated_at"
t.string "dark_logo"
t.string "light_logo"
end
create_table "audit_events", force: true do |t|
t.integer "author_id", null: false
t.string "type", null: false
t.integer "entity_id", null: false
t.string "entity_type", null: false
t.text "details"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "audit_events", ["author_id"], name: "index_audit_events_on_author_id", using: :btree
add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree
create_table "application_settings", force: true do |t|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
......@@ -84,6 +109,19 @@ ActiveRecord::Schema.define(version: 20150108073740) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "git_hooks", force: true do |t|
t.string "force_push_regex"
t.string "delete_branch_regex"
t.string "commit_message_regex"
t.boolean "deny_delete_tag"
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
t.string "file_name_regex"
end
create_table "identities", force: true do |t|
t.string "extern_uid"
t.string "provider"
......@@ -148,6 +186,15 @@ ActiveRecord::Schema.define(version: 20150108073740) do
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
create_table "ldap_group_links", force: true do |t|
t.string "cn", null: false
t.integer "group_access", null: false
t.integer "group_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "provider"
end
create_table "members", force: true do |t|
t.integer "access_level", null: false
t.integer "source_id", null: false
......@@ -220,14 +267,15 @@ ActiveRecord::Schema.define(version: 20150108073740) do
add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
create_table "namespaces", force: true do |t|
t.string "name", null: false
t.string "path", null: false
t.string "name", null: false
t.string "path", null: false
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "type"
t.string "description", default: "", null: false
t.string "description", default: "", null: false
t.string "avatar"
t.boolean "membership_lock", default: false
end
add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree
......@@ -302,6 +350,14 @@ ActiveRecord::Schema.define(version: 20150108073740) do
add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree
add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
create_table "project_group_links", force: true do |t|
t.integer "project_id", null: false
t.integer "group_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "group_access", default: 30, null: false
end
create_table "projects", force: true do |t|
t.string "name"
t.string "path"
......@@ -309,23 +365,25 @@ ActiveRecord::Schema.define(version: 20150108073740) do
t.datetime "created_at"
t.datetime "updated_at"
t.integer "creator_id"
t.boolean "issues_enabled", default: true, null: false
t.boolean "wall_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false
t.boolean "issues_enabled", default: true, null: false
t.boolean "wall_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false
t.integer "namespace_id"
t.string "issues_tracker", default: "gitlab", null: false
t.string "issues_tracker", default: "gitlab", null: false
t.string "issues_tracker_id"
t.boolean "snippets_enabled", default: true, null: false
t.boolean "snippets_enabled", default: true, null: false
t.datetime "last_activity_at"
t.string "import_url"
t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false
t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false
t.string "import_status"
t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
t.string "import_type"
t.string "import_source"
t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
t.text "merge_requests_template"
t.boolean "merge_requests_rebase_enabled", default: false
end
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
......@@ -392,12 +450,12 @@ ActiveRecord::Schema.define(version: 20150108073740) do
end
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0
t.integer "sign_in_count", default: 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
......@@ -405,22 +463,22 @@ ActiveRecord::Schema.define(version: 20150108073740) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.boolean "admin", default: false, null: false
t.integer "projects_limit", default: 10
t.string "skype", default: "", null: false
t.string "linkedin", default: "", null: false
t.string "twitter", default: "", null: false
t.boolean "admin", default: false, null: false
t.integer "projects_limit", default: 10
t.string "skype", default: "", null: false
t.string "linkedin", default: "", null: false
t.string "twitter", default: "", null: false
t.string "authentication_token"
t.integer "theme_id", default: 1, null: false
t.integer "theme_id", default: 1, null: false
t.string "bio"
t.integer "failed_attempts", default: 0
t.integer "failed_attempts", default: 0
t.datetime "locked_at"
t.string "username"
t.boolean "can_create_group", default: true, null: false
t.boolean "can_create_team", default: true, null: false
t.boolean "can_create_group", default: true, null: false
t.boolean "can_create_team", default: true, null: false
t.string "state"
t.integer "color_scheme_id", default: 1, null: false
t.integer "notification_level", default: 1, null: false
t.integer "color_scheme_id", default: 1, null: false
t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at"
t.integer "created_by_id"
t.string "avatar"
......@@ -428,10 +486,11 @@ ActiveRecord::Schema.define(version: 20150108073740) do
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false
t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at"
t.string "github_access_token"
t.datetime "admin_email_unsubscribed_at"
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
......@@ -20,6 +20,11 @@
- [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed.
- [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
- [Update](update/README.md) Update guides to upgrade your installation.
- [Audit Events](administration/audit_events.md) Check how user access changed in projects and groups.
- [Branded login page](customization/branded_login_page.md) Change the login page appearance for your GitLab instance.
- [Git Hooks](git_hooks/git_hooks.md) Advanced push rules for your project.
- [Email](tools/email.md) Email GitLab users from GitLab
- [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page.
- [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
- [Libravatar](customization/libravatar.md) Use Libravatar for user avatars.
......
# Audit Events
GitLab Enterprise Edition offers a way to view the changes made within the GitLab server as a help to system administrators.
# Security Events
| Security Event | Description |
|--------------------------------|--------------------------------------------------------------------------------------------------|
| User added to group or project | Notes the author of the change, target user |
| User permission changed | Notes the author of the change, original permission and new permission, target user |
# Audit Events in Project
To view the Audit Events user needs to have enough permissions to view the project Settings page.
Navigate to Project->Settings->Audit Events to view the Audit Events:
![audit events project](audit_events_project.png)
# Audit Events in Group
To view the Audit Events user needs to have enough permissions to view the group Settings page.
Navigate to Group->Settings->Audit Events to view the Audit Events:
![audit events group](audit_events_group.png)
......@@ -636,3 +636,72 @@ Parameters:
- `page` (optional) - the page to retrieve
- `order_by` (optional) - Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields
- `sort` (optional) - Return requests sorted in `asc` or `desc` order
## Git Hooks (EE only)
### Show project git hooks
Get a project git hook.
```
GET /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
```json
{
"id": 1,
"project_id": 3,
"commit_message_regex": "Fixes \d +\",
"deny_delete_tag": false,
"created_at": "2012-10-12T17:04:47Z"
}
```
### Add project git hook
Adds a git hook to a specified project.
```
POST /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
- `deny_delete_tag` - Do not allow users to remove git tags with git push
- `commit_message_regex` - Commit message regex
### Edit project git hook
Edits a git hook for a specified project.
```
PUT /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
- `deny_delete_tag` - Do not allow users to remove git tags with git push
- `commit_message_regex` - Commit message regex
### Delete project git hook
Removes a git hook from a project. This is an idempotent method and can be called multiple times.
Either the git hook is available or not.
```
DELETE /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
Note the JSON response differs if the hook is available or not. If the project hook
is available before it is returned in the JSON response or an empty response is returned.
# Branded Login Page
GitLab Enterprise Edition offers a way to put your company recognizible identity on the login page of your GitLab server.
By default, Enterprise Edition page shows GitLab logo and description
![default_login_page](branded_login_page/default_login_page.png)
## Changing the appearance of the login page
Navigate to the ![admin area](branded_login_page/admin_area.png) and go to the Appearance page.
Fill in the required details like Title, Description and upload the company logo.
![appearance](branded_login_page/appearance.png)
After saving the page, your GitLab login page will have the details you filled in:
![company_login_page](branded_login_page/company_login_page.png)
\ No newline at end of file
# Guidelines for implementing Enterprise Edition feature
## Write the code and the tests
Implement the wanted feature.
Implemented feature needs to have the full test coverage.
For now, exception is the code that needs to query a LDAP server.
## Write the documentation
Any feature needs to be well documented. Add the documentation to `/doc` directory, describe the main use of the newly implemented feature and, if applicable, add screenshots.
## Submit the MR to `about.gitlab.com`
Submit the MR to [about.gitlab.com site repository](https://gitlab.com/gitlab-com/www-gitlab-com) to add the new feature to the [EE feature comparison page](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/gitlab-ee/index.html)
# Git Hooks
Sometimes you need additional control over pushes to your repository.
GitLab already offers protected branches.
But there are cases when you need some specific rules like preventing git tag removal or enforcing a special format for commit messages.
GitLab Enterprise Edition offers a user-friendly interface for such cases.
Git hooks are defined per project so you can have different rules applied to different projects depends on your needs.
Git hooks settings can be found at Project settings -> Git Hooks page.
## How to use
Let's assume you have the following requirements for your workflow:
* every commit should reference a reference JIRA issue. For example: `Refactored css. Fixes JIRA-123. `
* users should not be able to remove git tags with `git push`
All you need to do is write simple regular expression that requires mention of JIRA issue in a commit message.
It can be something like this `/JIRA\-\d+/`.
Just paste regular expression into commit message textfield(without start and ending slash) and save changes.
See the screenshot below:
![screenshot](git_hooks.png)
Now when a user tries to push a commit like `Bugfix` - their push will be declined.
And pushing commit with message like `Bugfix according to JIRA-123` will be accepted.
\ No newline at end of file
......@@ -4,3 +4,4 @@
- [Requirements](requirements.md)
- [Structure](structure.md)
- [Database MySQL](database_mysql.md)
- [LDAP](ldap.md)
......@@ -181,9 +181,11 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
### Clone the Source
# Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-6-stable gitlab
sudo -u git -H git clone https://gitlab.com/subscribers/gitlab-ee.git -b 7-6-stable-ee gitlab
**Note:** You can change `7-6-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `7-6-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
......
# Link LDAP Groups
You can link LDAP groups with GitLab groups.
It gives you ability to automatically add/remove users from GitLab groups based on LDAP groups membership.
How it works:
1. We retrieve user ldap groups
2. We find corresponding GitLab groups
3. We add user to GitLab groups
4. We remove user from GitLab groups if user has no membership in LDAP groups
In order to use LDAP groups feature:
1. Edit gitlab.yml config LDAP sections.
2. Visti group settings -> LDAP tab
3. Edit LDAP cn and access level for gitlab group
4. Setup LDAP group members
Example of LDAP section from gitlab.yml
```
#
# 2. Auth settings
# ==========================
## LDAP settings
ldap:
enabled: true
host: 'localhost'
base: 'ou=People,dc=gitlab,dc=local'
group_base: 'ou=Groups,dc=gitlab,dc=local'
port: 389
uid: 'uid'
```
# Test whether LDAP group functionality is configured correctly
You need a non-LDAP admin user (such as the default admin@local.host), an LDAP user (e.g. Mary) and an LDAP group to which Mary belongs (e.g. Developers).
1. As the admin, create a new group 'Developers' in GitLab and associate it with the Developers LDAP group at gitlab.example.com/admin/groups/developers/edit .
2. Log in as Mary.
3. Verify that Mary is now a member of the Developers group in GitLab.
If you get an error message when logging in as Mary, double-check your `group_base` setting in `config/gitlab.yml`.
# Debug LDAP user filter with ldapsearch
This example uses [ldapsearch](http://www.openldap.org/software/man.cgi?query=ldapsearch&apropos=0&sektion=0&manpath=OpenLDAP+2.0-Release&format=html) and assumes you are using ActiveDirectory.
The following query returns the login names of the users that will be allowed to log in to GitLab if you configure your own `user_filter`.
```bash
ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$base" "(&(ObjectClass=User)($user_filter))" sAMAccountName
```
- `$var` refers to a variable from the `ldap` section of your `config/gitlab.yml` https://gitlab.com/subscribers/gitlab-ee/blob/master/config/gitlab.yml.example#L100;
- Replace `ldaps://` with `ldap://` if you are using the `plain` authentication method;
- We are assuming the password for the `bind_dn` user is in `bind_dn_password.txt`.
# GitLab EE Omnibus packages
Below are the [gitlab-omnibus packages](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) for GitLab Enterprise Edition.
Installation instructions are similar to the [CE Omnibus package instructions](https://about.gitlab.com/downloads/) after choosing an OS (of course your package name is different).
[Update instructions](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md) can be found in the GitLab Omnibus documentation.
The [GitLab Omnibus Readme](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) contains troubleshooting information and configuration options.
Please contact <subscribers@gitlab.com> if you have any questions.
## RPM 'package is already installed' error
If you are using RPM and you are upgrading from GitLab Community Edition you may get an error like this:
```
package gitlab-7.6.3_omnibus.5.3.0.ci-1.el7.x86_64 (which is newer than gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el7.x86_64) is already installed
```
You can override this version check with the `--oldpackage` option:
```
rpm -Uvh --oldpackage gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm
```
### GitLab 7.6.3 Enterprise Edition
- Ubuntu 14.04 64-bit - 7.6.3-ee/CI 5.3.0 [gitlab_7.6.3-ee.omnibus.5.3.0.ci.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/c6a3515ca1bafff7fbb28f4f0eb4923fea45c230/ubuntu-14.04/gitlab_7.6.3-ee.omnibus.5.3.0.ci.1-1_amd64.deb)
+ SHA256: 8b038ac879653a3187f5bd282b455afc0054bf6d486835bb334631295a286ffb
- Ubuntu 12.04 64-bit - 7.6.3-ee/CI 5.3.0 [gitlab_7.6.3-ee.omnibus.5.3.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/8d3dc83883a7cb777ab576750c189dd90ba392f6/ubuntu-12.04/gitlab_7.6.3-ee.omnibus.5.3.0.ci.1-1_amd64.deb)
+ SHA256: ab761a0b650b62d21ad0e9a29955907a5f9efcc108b0af115e8846d713760f11
- Debian 7 64-bit - 7.6.3-ee/CI 5.3.0 [gitlab_7.6.3-ee.omnibus.5.3.0.ci.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/d87605a1df241e695bdd9b4cb8591838096a8427/debian-7.7/gitlab_7.6.3-ee.omnibus.5.3.0.ci.1-1_amd64.deb)
+ SHA256: c05aac681e578d3c65d0fbfc7911c5af2abdb88fd7162f50bb8b33b953e2c580
- CentOS 6 64-bit - 7.6.3-ee/CI 5.3.0 [gitlab-7.6.3_ee.omnibus.5.3.0.ci.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/99cf1d877e29773427a096abb5fcb78edac73b02/centos-6.6/gitlab-7.6.3_ee.omnibus.5.3.0.ci.1-1.el6.x86_64.rpm)
+ SHA256: cb2a675b26eebca43a74c34c656fba8c71b4fe21360f38245c9bd6d3c7a0d4bc
- CentOS 7 64-bit - 7.6.3-ee/CI 5.3.0 [gitlab-7.6.3_ee.omnibus.5.3.0.ci.1-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/47d608b352338f5b878a38ddc1eb88e049b7a051/centos-7.0.1406/gitlab-7.6.3_ee.omnibus.5.3.0.ci.1-1.el7.x86_64.rpm)
+ SHA256: 0d22124a7cba2d5b9a7fb3bfa288a9d267e574f53ada27999f5dfdfe870278ed
### GitLab 7.6.2 Enterprise Edition
- 7.6.2-ee/CI 5.3.0 - Ubuntu 14.04 64-bit [gitlab_7.6.2-ee.omnibus.5.3.0.ci.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/44449a1cd473eb3f6f79dd88e57d5b8254c4a16d/ubuntu-14.04/gitlab_7.6.2-ee.omnibus.5.3.0.ci.1-1_amd64.deb)
+ SHA256: 3254c613e356b58b040aa2695af78f036dde83d05150ccae1d3021e223709210
- 7.6.2-ee/CI 5.3.0 - Ubuntu 12.04 64-bit [gitlab_7.6.2-ee.omnibus.5.3.0.ci.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/4dffcf1fe07b5825f9c94c9efc02c675757057e3/ubuntu-12.04/gitlab_7.6.2-ee.omnibus.5.3.0.ci.1-1_amd64.deb)
+ SHA256: 92af46677254b58ec33a333eb6c2915fd80724165b4b732e1660ee3b129c7c8d
- 7.6.2-ee/CI 5.3.0 - Debian 7 64-bit [gitlab_7.6.2-ee.omnibus.5.3.0.ci.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/1b7f1f2e0726908205abfffee87315c3a40e1e08/debian-7.7/gitlab_7.6.2-ee.omnibus.5.3.0.ci.1-1_amd64.deb)
+ SHA256: 4fd62c0ce1db6bd5bdce8b64e236cb8f7d2bc251a20f853a9bf3a407858748af
- 7.6.2-ee/CI 5.3.0 - CentOS 6 64-bit [gitlab-7.6.2_ee.omnibus.5.3.0.ci.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/455b87ddd5459b8bdbd86cdabdb5e1c6783c3592/centos-6.6/gitlab-7.6.2_ee.omnibus.5.3.0.ci.1-1.el6.x86_64.rpm)
+ SHA256: 64110aaad20ba52f81dd5011bfadb960b6e1047bb2aaa8c8e39dd0d5a1475efc
- 7.6.2-ee/CI 5.3.0 - CentOS 7 64-bit [gitlab-7.6.2_ee.omnibus.5.3.0.ci.1-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/8f9278f7796b060acc0a116b6bc424cbcfd64698/centos-7.0.1406/gitlab-7.6.2_ee.omnibus.5.3.0.ci.1-1.el7.x86_64.rpm)
+ SHA256: 073385056fd0659c4f15ffd368b8b9e9f2b80a3fb211adfd06203811de082bf4
### GitLab 7.6.0 Enterprise Edition
- 7.6.0-ee/CI 5.3.0 - Ubuntu 14.04 64-bit [gitlab_7.6.0-ee.omnibus.5.3.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/fadbb1570f35a76e8b57435bb9f3bfc321b59956/ubuntu-14.04/gitlab_7.6.0-ee.omnibus.5.3.0.ci-1_amd64.deb)
+ SHA256: 72e961070688763391aafd28a94ca893b74a2f612b64f9e2d5c7aa3b972ee6ed
- 7.6.0-ee/CI 5.3.0 - Ubuntu 12.04 64-bit [gitlab_7.6.0-ee.omnibus.5.3.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/0af6270fbc92e3fc2ff621547187b852f2a0be7a/ubuntu-12.04/gitlab_7.6.0-ee.omnibus.5.3.0.ci-1_amd64.deb)
+ SHA256: 306205a5f4ebab40f423f02957d0ca1a6a899d50aaabfceac121e76bfba2e775
- 7.6.0-ee/CI 5.3.0 - Debian 7 64-bit [gitlab_7.6.0-ee.omnibus.5.3.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/5d7f757633a09bb172c5e55b0a7efc7a729927e1/debian-7.7/gitlab_7.6.0-ee.omnibus.5.3.0.ci-1_amd64.deb)
+ SHA256: 2da8df98000ea4e217e08533911f28ade2c278f8c5d7717f7a8bc9911c810530
- 7.6.0-ee/CI 5.3.0 - CentOS 6 64-bit [gitlab-7.6.0_ee.omnibus.5.3.0.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/9ff0148bbf7b3f327c05ce0e4b5fdc938eb1bd7c/centos-6.6/gitlab-7.6.0_ee.omnibus.5.3.0.ci-1.el6.x86_64.rpm)
+ SHA256: fcc92c8b3723217dcad8677cea3d2f2b54cade6c235668a0bc2b11773fd3c052
#### Note: GitLab 7.6 EE for Centos 7 will be released later today
- 7.5.3-ee/CI 5.2.1 - CentOS 7 64-bit [gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/f08d577a156a0bf4ef06f4b42586a94707d2e456/centos-7.0.1406/gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm)
+ SHA256: d3e734f37841b38f37892ea5557a7c707f0e7bba8bf5f70869f309bd8f21120a
## Previous versions
### Ubuntu 14.04 64-bit
- 7.5.3-ee/CI 5.2.1 - Ubuntu 14.04 64-bit [gitlab_7.5.3-ee.omnibus.5.2.1.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/05998bb8ba9cca0ef22c90f4529c875003c51f23/ubuntu-14.04/gitlab_7.5.3-ee.omnibus.5.2.1.ci-1_amd64.deb)
+ SHA256: 5aa2e0c7ff9b48344d2d5bf62dd4fbff09ccd95c010331e12da78e2cd73cf430
- 7.5.2-ee/CI 5.2.1 - Ubuntu 14.04 64-bit [gitlab_7.5.2-ee.omnibus.5.2.1.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e864efcad31bc4ede2c1e1fc8bba8951e4468e5f/ubuntu-14.04/gitlab_7.5.2-ee.omnibus.5.2.1.ci-1_amd64.deb)
+ SHA256: 70e04525b4c55eb55567f2c45b09a2ce31a1d5a59296947d86706656e79f8ae3
- 7.5.1-ee/CI 5.2.0 - Ubuntu 14.04 64-bit [gitlab_7.5.1-ee.omnibus.5.2.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/3da7e4fb16f1a15de137a5ac5d4cb4a39cef536c/ubuntu-14.04/gitlab_7.5.1-ee.omnibus.5.2.0.ci-1_amd64.deb)
+ SHA256: 834e9478e7dd6862cd9ce61c7179eb765b66d7ebe61c493ffd44e15b79f287b8
- 7.4.5-ee/CI 5.1.0 - Ubuntu 14.04 64-bit [gitlab_7.4.5-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/9ac1901f0e346f5c795262368450fda9b1f7bbb9/ubuntu-14.04/gitlab_7.4.5-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ SHA256: 8e44f7cc87a73f007c882f5f9147294073a7ea58a805d9a3cb43d1ed1e0d9dfe
- 7.4.4-ee/CI 5.1.0 - Ubuntu 14.04 64-bit [gitlab_7.4.4-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/2a880962cd18293a9da61ab884c29cbdd7eebdba/ubuntu-14.04/gitlab_7.4.4-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ MD5: d549fdaa96e53a2a98cb91676076259a
- 7.4.3-ee/CI 5.1.0 - Ubuntu 14.04 64-bit [gitlab_7.4.3-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/fca7e66f323d8fbffbd86fbb26a6f60eab891dc9/ubuntu-14.04/gitlab_7.4.3-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ MD5: 7bd15c589f9fb81750c5fc77d3f9881f
- 7.4.3-ee - Ubuntu 14.04 64-bit [gitlab_7.4.3-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/7ebaadae0ea2ca05971a80e5000877943bb1fbfc/ubuntu-14.04/gitlab_7.4.3-ee.omnibus.1-1_amd64.deb)
+ MD5: 639e9519a9cd0629685ac16db8d68b5c
- 7.4.2-ee - Ubuntu 14.04 64-bit [gitlab_7.4.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e38dad05abb276453da95d78fa1eaa41d783f390/ubuntu-14.04/gitlab_7.4.2-ee.omnibus-1_amd64.deb)
+ MD5: 7a28adaf0fc96e86fafe4a363484fe07
- 7.4.1-ee - Ubuntu 14.04 64-bit [gitlab_7.4.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/d6e0332c065645b2ac380890f8406224377cbcfc/ubuntu-14.04/gitlab_7.4.1-ee.omnibus-1_amd64.deb)
+ MD5: aa39962db5c6e9b5f56a6c592927d338
- 7.4.0-ee - Ubuntu 14.04 64-bit [gitlab_7.4.0-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/7839c59170801447b308694628378151a988ce75/ubuntu-14.04/gitlab_7.4.0-ee.omnibus.2-1_amd64.deb)
+ MD5: e091774fdd2649f3a839bef1c608399f
- 7.3.2-ee - Ubuntu 14.04 64-bit [gitlab_7.3.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/b4d37ee804679cdd21b3cf5c83c43ca0f40ae2a6/ubuntu-14.04/gitlab_7.3.2-ee.omnibus-1_amd64.deb)
+ MD5: 53539f5f7833a760a9918633ca8c9be5
- 7.3.1-ee - Ubuntu 14.04 64-bit [gitlab_7.3.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/50d2c5178c423a141f316f52e3447aefc017c77b/ubuntu-14.04/gitlab_7.3.1-ee.omnibus-1_amd64.deb)
+ MD5: e4342b4a4d7192f8f7eb04816eba6c29
- 7.3.0-ee - Ubuntu 14.04 64-bit [gitlab_7.3.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/bb2502342d24cc9ffd773946f7f3027be60cf612/ubuntu-14.04/gitlab_7.3.0-ee.omnibus-1_amd64.deb)
+ MD5: 6d46e3ec4051fe2fa616baf6bdf7d594
- 7.2.2-ee - Ubuntu 14.04 64-bit [gitlab_7.2.2-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e542352a629ad69f12d29476c85f6abb27202136/ubuntu-14.04/gitlab_7.2.2-ee.omnibus-1_amd64.deb)
+ MD5: 1612bc8b722e9e01d27845f0e1102758
- 7.2.1-ee - Ubuntu 14.04 64-bit [gitlab_7.2.1-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/b88dc7319205954b71fe53e15e0cee5211e399d3/ubuntu-14.04/gitlab_7.2.1-ee.omnibus.2-1_amd64.deb)
+ MD5: 22b3120d14b29495741a6c04dbc88f7d
- 7.2.0-ee - Ubuntu 14.04 64-bit [gitlab_7.2.0-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/f8bfb6cafa08687822786ff5be822c8b36a656f5/ubuntu-14.04/gitlab_7.2.0-ee.omnibus.2-1_amd64.deb)
+ MD5: 356263bdfe56c9bed04096c40ca3a8a2
- 7.1.1-ee - Ubuntu 14.04 64-bit [gitlab_7.1.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/fe636f5b18be2a47198278337547124405e05051/ubuntu-14.04/gitlab_7.1.1-ee.omnibus-1_amd64.deb)
+ MD5: 4b005d4f7e92538663e993f97e9f94be
- 7.1.0-ee - Ubuntu 14.04 64-bit [gitlab_7.1.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/2b86ee72a2b5f469a453d4dcb2e7a54dd6d1945d/ubuntu-14.04/gitlab_7.1.0-ee.omnibus-1_amd64.deb)
+ MD5: 46372eb1f620985d199b7c364d211625
- 7.0.1-ee - Ubuntu 14.04 64-bit [gitlab_7.0.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/0c687476e83a80fa4fa717ad5881f41e31a41eb0/ubuntu-14.04/gitlab_7.0.1-ee.omnibus-1_amd64.deb)
+ MD5: 547d15f7a6bb05ce0b3b0776c99eb40c
- 7.0.0-ee - Ubuntu 14.04 64-bit [gitlab_7.0.0-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/7e416d0421a055dc87c471d9be981c8959615406/ubuntu-14.04/gitlab_7.0.0-ee.omnibus.1-1_amd64.deb)
- MD5: 0a0a821a166dc08499359a72daf2aa88
### Ubuntu 12.04 64-bit
- 7.5.3-ee/CI 5.2.1 - Ubuntu 12.04 64-bit [gitlab_7.5.3-ee.omnibus.5.2.1.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/b8b21efced5fb783a8fdb67f6e62abe9b4a355f5/ubuntu-12.04/gitlab_7.5.3-ee.omnibus.5.2.1.ci-1_amd64.deb)
+ SHA256: a502347f3cde250e875dd378d83dd180ecaf02adb997c89401209b779b8f3764
- 7.5.2-ee/CI 5.2.1 - Ubuntu 12.04 64-bit [gitlab_7.5.2-ee.omnibus.5.2.1.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/3d414be81496a7c8e7ca5643a23d49787055241e/ubuntu-12.04/gitlab_7.5.2-ee.omnibus.5.2.1.ci-1_amd64.deb)
+ SHA256: abc84afdcfae11325944c037e9b070d6fd63e630d8a64627316aa056a2f1dfaa
- 7.5.1-ee/CI 5.2.0 - Ubuntu 12.04 64-bit [gitlab_7.5.1-ee.omnibus.5.2.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/d657214f75cfafb1e6e47f179fca394fd8c3c34e/ubuntu-12.04/gitlab_7.5.1-ee.omnibus.5.2.0.ci-1_amd64.deb)
+ SHA256: 843e177375f8d2f2b149405dfbd65f023952938cf017d4f8946b7badf98220a2
- 7.4.5-ee/CI 5.1.0 - Ubuntu 12.04 64-bit [gitlab_7.4.5-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/16e535efc9f100d6acafa651e28180c6573197f3/ubuntu-12.04/gitlab_7.4.5-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ SHA256: 92fa8eb59efc6ae901a13ad47712061edd468d111e197517a7d96309a6798152
- 7.4.4-ee/CI 5.1.0 - Ubuntu 12.04 64-bit [gitlab_7.4.4-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e99bcfc0601b020fc7d218bcd2e76fbcbc66c9d8/ubuntu-12.04/gitlab_7.4.4-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ MD5: 61cc01a792a0b649e5bfb51bd63adb12
- 7.4.3-ee/CI 5.1.0 - Ubuntu 12.04 64-bit [gitlab_7.4.3-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e48726116808fc8b4e859aacf32bd7f12a569eab/ubuntu-12.04/gitlab_7.4.3-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ MD5: fcc033b7db38f5afc5bd21b991227ef1
- 7.4.3-ee - Ubuntu 12.04 64-bit [gitlab_7.4.3-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/d6cdce3171b469c3198828a6167f49d380817d18/ubuntu-12.04/gitlab_7.4.3-ee.omnibus.1-1_amd64.deb)
+ MD5: 1f01c05c238f380c546ffe8a767e5d48
- 7.4.2-ee - Ubuntu 12.04 64-bit [gitlab_7.4.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/cd86d1cb6d76231403ca0fba4ded395a6c753b9b/ubuntu-12.04/gitlab_7.4.2-ee.omnibus-1_amd64.deb)
+ MD5: 4851d59c5b304570eafd7ca1c4ce1617
- 7.4.1-ee - Ubuntu 12.04 64-bit [gitlab_7.4.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/fe8289d8a2ca90b5839012296ff1a89c4c58c5bd/ubuntu-12.04/gitlab_7.4.1-ee.omnibus-1_amd64.deb)
+ MD5: ee324001283b52d2d0dfd8ccba71d77e
- 7.4.0-ee - Ubuntu 12.04 64-bit [gitlab_7.4.0-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/417446d069cba775a883d22ea22955ac3e93d24a/ubuntu-12.04/gitlab_7.4.0-ee.omnibus.2-1_amd64.deb)
+ MD5: 879a821076353bc92add2e539ea0f6d1
- 7.3.2-ee - Ubuntu 12.04 64-bit [gitlab_7.3.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/c58e302c165ff0ee6eec240b6b6b15d02d82cd18/ubuntu-12.04/gitlab_7.3.2-ee.omnibus-1_amd64.deb)
+ MD5: 9b75edcb5c066bee223d69a3abd62256
- 7.3.1-ee - Ubuntu 12.04 64-bit [gitlab_7.3.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/84b514bea64be8ee065c222d318d7d37c237985e/ubuntu-12.04/gitlab_7.3.1-ee.omnibus-1_amd64.deb)
+ MD5: 35c573d2005f7bb7aa8406405f1a8e9d
- 7.3.0-ee - Ubuntu 12.04 64-bit [gitlab_7.3.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/5959588d95a915ee061daee467d1bc55a6316f7e/ubuntu-12.04/gitlab_7.3.0-ee.omnibus-1_amd64.deb)
+ MD5: e7fee9727ba8bf79aeb94afd5b219510
- 7.2.2-ee - Ubuntu 12.04 64-bit [gitlab_7.2.2-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/c55c6cbc34ea446e68382ac35d96c8722d2a87cd/ubuntu-12.04/gitlab_7.2.2-ee.omnibus-1_amd64.deb)
+ MD5: b4238977da83164e56772c17ea4e9d2c
- 7.2.1-ee - Ubuntu 12.04 64-bit [gitlab_7.2.1-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/c64e66c88063395e407f75174dfcdc9e833f7cc8/ubuntu-12.04/gitlab_7.2.1-ee.omnibus.2-1_amd64.deb)
+ MD5: 640703e4ff1a92ff912f56e869e4a38a
- 7.2.0-ee - Ubuntu 12.04 64-bit [gitlab_7.2.0-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/3173c5075e937a0f7940ceaba9f48c2249c07a7c/ubuntu-12.04/gitlab_7.2.0-ee.omnibus.2-1_amd64.deb)
+ MD5: aa9b5fb8defd6d4ed77fb7e5451442d8
- 7.1.1-ee - Ubuntu 12.04 64-bit [gitlab_7.1.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/71e1c0e770458056dc40709bf8b986ba83c0296d/ubuntu-12.04/gitlab_7.1.1-ee.omnibus-1_amd64.deb)
+ MD5: f6b84bc60b10556344e16175a19719ef
- 7.1.0-ee - Ubuntu 12.04 64-bit [gitlab_7.1.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/a4416b7b2ab2a50b74062471b7969f127ae01e03/ubuntu-12.04/gitlab_7.1.0-ee.omnibus-1_amd64.deb)
+ MD5: 07271fafd97f61a2fce5343970f4b4cc
- 7.0.1-ee - Ubuntu 12.04 64-bit [gitlab_7.0.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e52f5de30db26d895438b81ea13ce6a89a22b3cc/ubuntu-12.04/gitlab_7.0.1-ee.omnibus-1_amd64.deb)
+ MD5: fc32a7de460dbfb3f0249cf3e1c56056
- 7.0.0-ee - Ubuntu 12.04 64-bit [gitlab_7.0.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/1ad8765351d114afdc9b96f1044551d209e6742c/ubuntu-12.04/gitlab_7.0.0-ee.omnibus-1_amd64.deb)
- MD5: 4d243a7d075d940963ad0909e60e18e5
- 6.9.4-ee - Ubuntu 12.04 64-bit [gitlab_6.9.4-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/c0139737a5ffc2725eb5f72316c1d0f1d34d8944/ubuntu-12.04/gitlab_6.9.4-ee.omnibus.1-1_amd64.deb)
- MD5: 85c7879a5e3c368c7d9d8b5c0bd8eed0
- 6.9.3-ee - Ubuntu 12.04 64-bit [gitlab_6.9.3-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/4cc3c248f50ecfc8048209da908e5ea62252190b/ubuntu-12.04/gitlab_6.9.3-ee.omnibus.1-1_amd64.deb)
- MD5: d5a92e909e157638f8616041de1e9ff8
- 6.9.2-ee - Ubuntu 12.04 64-bit [gitlab_6.9.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/513969c5bd4ae079c27b61c792a86217eeb2c443/ubuntu-12.04/gitlab_6.9.2-ee.omnibus-1_amd64
- MD5: 074fc4c035837c5671de5fea10ecfcec
- 6.9.1-ee - Ubuntu 12.04 64-bit [gitlab_6.9.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/f1b162213022e7c5def15ed773e2bfdf7d420590/ubuntu-12.04/gitlab_6.9.1-ee.omnibus-1_amd64.deb)
- MD5: 52481cfaf8c555fb296c15facaf39900
- 6.9.0-ee - Ubuntu 12.04 64-bit [gitlab_6.9.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/f4bfa95fe308a10298178316aa140f5623536432/ubuntu-12.04/gitlab_6.9.0-ee.omnibus-1_amd64.deb)
- MD5: 022feef5454b35ad49b9485149122c2e
- 6.8.1-ee - Ubuntu 12.04 64-bit [gitlab_6.8.1-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/aad7786fc512593733cc3351ebf515fb6f0d0462/ubuntu-12.04/gitlab_6.8.1-ee.omnibus.1-1_amd64.deb)
- MD5: 4b7b3487f3631a261d56dc58e1922a11
- 6.8.0-ee - Ubuntu 12.04 64-bit [gitlab_6.8.0-ee.omnibus.4-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/788d9b718e820d3196295f2801b0bbec307e68a7/ubuntu-12.04/gitlab_6.8.0-ee.omnibus.4-1_amd64.deb)
- MD5: 9a8a99ef147f30aa92ef5dddf85dfa97
- 6.7.4-ee - Ubuntu 12.04 64-bit [gitlab_6.7.4-ee.omnibus-1.ubuntu.12.04_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e27eb70aac3619b17ba7ade0e6bfc48e896b057f/gitlab_6.7.4-ee.omnibus-1.ubuntu.12.04_amd64.deb)
- MD5: 16d0c4ab627638cc6d612042af4498da
- 6.7.3-ee - Ubuntu 12.04 64-bit [gitlab_6.7.3-ee.omnibus.1-1.ubuntu.12.04_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/43c6dec1146d6335c6ca90fa8679d4e63962732e/gitlab_6.7.3-ee.omnibus.1-1.ubuntu.12.04_amd64.deb)
- MD5: 527561c7b817f3375598778368530e9a
- 6.7.2-ee - Ubuntu 12.04 64-bit [gitlab_6.7.2-ee.omnibus.2-1.ubuntu.12.04_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/91692a0c3730d22621af07670b832e3ec1df7ee9/gitlab_6.7.2-ee.omnibus.2-1.ubuntu.12.04_amd64.deb)
- MD5: 1deb3ac65cb2f25b00b489e52bf800e6
- 6.7.2-ee - Ubuntu 12.04 64-bit [gitlab_6.7.2-ee.omnibus-1.ubuntu.12.04_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/66e5962a62e403f30b63a6a709a894fdf6f8bc33/gitlab_6.7.2-ee.omnibus-1.ubuntu.12.04_amd64.deb)
- MD5: 24d9618767217acd39c37cb7e0ae1881
- 6.7.1-ee Ubuntu 12.04 64-bit [gitlab_6.7.1-ee.omnibus-1.ubuntu.12.04_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/6d24b1dfb3a0ac4c80a7301bd42a32faf1e9d650/gitlab_6.7.1-ee.omnibus-1.ubuntu.12.04_amd64.deb)
- MD5: cafba48596583b023758f35eaaaf98fa
- 6.6.3-ee Ubuntu 12.04 64-bit [gitlab_6.6.3-ee.omnibus.2-1.ubuntu.12.04_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/a7dcf16bd7948d5415a9c53176f2078375dac12e/gitlab_6.6.3-ee.omnibus.2-1.ubuntu.12.04_amd64.deb)
- MD5: cbd2a9086691f0ea2ebe47b374e84151
- 6.6.3-ee Ubuntu 12.04 64-bit [gitlab_6.6.3-ee.omnibus-1.ubuntu.12.04_amd64.deb](https://downloads-packages.s3.amazonaws.com/2601c69af9247a47334c21cb9c9e4267d21eb8e7/gitlab_6.6.3-ee.omnibus-1.ubuntu.12.04_amd64.deb)
- MD5: de0a2cf1b9876b9c07256aa7f5692677
### CentOS 6 64-bit
- 7.5.3-ee/CI 5.2.1 - CentOS 6 64-bit [gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/09755469e681f852c4a81794c6ec640ed20a7f82/centos-6.6/gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el6.x86_64.rpm)
+ SHA256: 208b46fea67029cb3bbdfca593cd5866845b1a5b68cbd0b3d1f6201d9169ae00
- 7.5.2-ee/CI 5.2.1 - CentOS 6 64-bit [gitlab-7.5.2_ee.omnibus.5.2.1.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/91595f2a0207e8456e9b7d86e4e529c80dc2f998/centos-6.6/gitlab-7.5.2_ee.omnibus.5.2.1.ci-1.el6.x86_64.rpm)
+ SHA256: 79d8d3c954466a539d4e33c4ba43bda090eae73fb3738ea98aaf281869fe80ac
- 7.5.1-ee/CI 5.2.0 - CentOS 6 64-bit [gitlab-7.5.1_ee.omnibus.5.2.0.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/52cf99f7a5d7ab1ee9414b95d7875afce4c30525/centos-6.6/gitlab-7.5.1_ee.omnibus.5.2.0.ci-1.el6.x86_64.rpm)
+ SHA256: e50d86c483211734bc60ba039ce63b5e44d444f286759f119bd9899b1715df43
- 7.4.5-ee/CI 5.1.0 - CentOS 6 64-bit [gitlab-7.4.5_ee.omnibus.5.1.0.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/db1bf2b0be4947b23bc3e9ff22a7059720ccfc3a/centos-6.6/gitlab-7.4.5_ee.omnibus.5.1.0.ci-1.el6.x86_64.rpm)
+ SHA256: 4fa6e9f4ef399833fd4e38194fc5acfc5914cc9f90adfa75ff674e7e054c5d83
- 7.4.4-ee/CI 5.1.0 - CentOS 6 64-bit [gitlab-7.4.4_ee.omnibus.5.1.0.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/8cdc5c7ae898c51845669dacc09d844614e46f90/centos-6.5/gitlab-7.4.4_ee.omnibus.5.1.0.ci-1.el6.x86_64.rpm)
+ MD5: be5c4d977b647459c28ea587de1b82c4
- 7.4.3-ee/CI 5.1.0 - CentOS 6 64-bit [gitlab-7.4.3_ee.omnibus.5.1.0.ci-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/268e1049c800baeebaa6a2bbcec1b520d52c9587/centos-6.5/gitlab-7.4.3_ee.omnibus.5.1.0.ci-1.el6.x86_64.rpm)
+ MD5: 3e9753ce5d4580900a809da99c4b91de
- 7.4.3-ee - CentOS 6 64-bit [gitlab-7.4.3_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/0de6a7cef7e1c4b81dfb41b3aed5b29245521241/centos-6.5/gitlab-7.4.3_ee.omnibus.1-1.el6.x86_64.rpm)
+ MD5: 03fda4571bc087059214511c988819c5
- 7.4.2-ee - CentOS 6 64-bit [gitlab-7.4.2_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/0cacc003ce7d724eae04610af9adc8cf2c47f6cc/centos-6.5/gitlab-7.4.2_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: ab9c5fa50eaa337d6fcb13dadf83c7c7
- 7.4.1-ee - CentOS 6 64-bit [gitlab-7.4.1_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/0e35c2a4c7174facb186a892a5260cad168a6167/centos-6.5/gitlab-7.4.1_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: 6909bbb98071974a4ab9808c63e15f19
- 7.4.0-ee - CentOS 6 64-bit [gitlab-7.4.0_ee.omnibus.2-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/f26f3f667c432fb7d901cb8ec6d9933b6682f023/centos-6.5/gitlab-7.4.0_ee.omnibus.2-1.el6.x86_64.rpm)
+ MD5: 5fe5843b33d244edb7e53a65f1dddd46
- 7.3.2-ee - CentOS 6 64-bit [gitlab-7.3.2_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/e951c9049fdcb4719b62d32da4b5b20fb4ac06ba/centos-6.5/gitlab-7.3.2_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: 66dc5db39a230149bd6b4fa3543c1704
- 7.3.1-ee - CentOS 6 64-bit [gitlab-7.3.1_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/31cd8285078211e0c586e3ca55de835fbb4bd641/centos-6.5/gitlab-7.3.1_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: 1bb944331915bd1ab024f26f5363d5ac
- 7.3.0-ee - CentOS 6 64-bit [gitlab-7.3.0_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/e96783668115d01b2c11e7a68fe174055f2fa409/centos-6.5/gitlab-7.3.0_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: 3f79fd3a8df8c3f14b7731be0e71a0ce
- 7.2.2-ee - CentOS 6 64-bit [gitlab-7.2.2_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/0f1f8d86c7d33d063066e078d2f46d38199471a6/centos-6.5/gitlab-7.2.2_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: aac87719e12b89a8b7fbb8e76d08cf10
- 7.2.1-ee - CentOS 6 64-bit [gitlab-7.2.1_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/bfecfa9854037cf7c8d3d17c9fadebe06a30c908/centos-6.5/gitlab-7.2.1_ee.omnibus.1-1.el6.x86_64.rpm)
+ MD5: 6242e0715620d34e2f5329ba9bd74e23
- 7.2.0-ee - CentOS 6 64-bit [gitlab-7.2.0_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/2f0192626cfa99c6c86eeb9d340a7a5969d7943a/centos-6.5/gitlab-7.2.0_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: e2db09cfc46542fd4c53a669d4159b68
- 7.1.1-ee - CentOS 6 64-bit [gitlab-7.1.0_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/ba1aa90ff5662e790fd3eecfd6653e4377cada95/centos-6.5/gitlab-7.1.1_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: cee4f447c7ae99afd2bd6634a8a48000
- 7.1.0-ee - CentOS 6 64-bit [gitlab-7.1.0_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/de9f52c1c4cf611db78ad0548275c574d85cb220/centos-6.5/gitlab-7.1.0_ee.omnibus-1.el6.x86_64.rpm)
+ MD5: 35311bc3ae636b370c142aa10217d702
- 7.0.1-ee - CentOS 6 64-bit [gitlab-7.0.1_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/09a89ba7f0fe28ba9c4b52a492d02135e5a39a9c/centos-6.5/gitlab-7.0.1_ee.omnibus.1-1.el6.x86_64.rpm)
+ MD5: d9b518df79b2abd63ce70f1d028f5c30
- 7.0.0-ee - CentOS 6 64-bit [gitlab-7.0.0_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/6232e9f5ee819537011a57d3f8eb40c149795052/centos-6.5/gitlab-7.0.0_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 49a9eb63daba98bec85d3dbc175bac9d
- 6.9.4-ee - CentOS 6 64-bit [gitlab-6.9.4_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/60dc935248ddfdc182703f770ac8b55718b7bf94/centos-6.5/gitlab-6.9.4_ee.omnibus.1-1.el6.x86_64.rpm)
- MD5: 17c358ff5edf868ccf3f07158b0ef382
- 6.9.3-ee - CentOS 6 64-bit [gitlab-6.9.3_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/2309ffd68483e2d74ef1b96566e7b68934abd99f/centos-6.5/gitlab-6.9.3_ee.omnibus.1-1.el6.x86_64.rpm)
- MD5: 2e716a56643b93f0ee8d8c6cb5457952
- 6.9.2-ee - CentOS 6 64-bit [gitlab-6.9.2_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/8f0bde82158c3d542357f5ae5658bc4939f9d006/centos-6.5/gitlab-6.9.2_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 696c861da0a8a71d7df22c431ddb9619
- 6.9.1-ee - CentOS 6 64-bit [gitlab-6.9.1_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/c5bddcb7e781a16eca3bd5d6418f200cdfcdd311/centos-6.5/gitlab-6.9.1_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 4728394d750f28827c445ddc01f53580
- 6.9.0-ee - CentOS 6 64-bit [gitlab-6.9.0_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/f86f29bac6fa3e7cd96315550c362816fc04cdb4/centos-6.5/gitlab-6.9.0_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 18bd1bea069b968935eea489e4a24b50
- 6.8.1-ee - CentOS 6 64-bit [gitlab-6.8.1_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/e8f63c2a21cae7e9842c16b20d76b9de25d3130b/centos-6.5/gitlab-6.8.1_ee.omnibus.1-1.el6.x86_64.rpm)
- MD5: 31895155f8f694ded61a04976a06baeb
- 6.8.0-ee - CentOS 6 64-bit [gitlab-6.8.0_ee.omnibus.4-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/0a6d0e42b82d64a4c4ec6bbe448ffc0a5cfb70ab/centos-6.5/gitlab-6.8.0_ee.omnibus.4-1.el6.x86_64.rpm)
- MD5: 6648d41b02712c1d701d8361490126e7
- 6.7.4-ee - CentOS 6 64-bit [gitlab-6.7.4_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/e9394ffe2dd9cba518ab6d43510fb0fb6acc4ff6/gitlab-6.7.4_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 5004af120eb457fe7eefbaa5f47429dc
- 6.7.3-ee - CentOS 6 64-bit [gitlab-6.7.3_ee.omnibus.1-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/4a83046ae506fe84158c1bc433d8fa85a886abba/gitlab-6.7.3_ee.omnibus.1-1.el6.x86_64.rpm)
- MD5: 6335719321acc8edc2f718570960c832
- 6.7.2-ee CentOS 6 64-bit [gitlab-6.7.2_ee.omnibus.2-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/e13ccafca35955ad754ea501798875d99e0cce4c/gitlab-6.7.2_ee.omnibus.2-1.el6.x86_64.rpm)
- MD5: 36347c81013c4215226a3cb30f6ac1b4
- 6.7.2-ee - CentOS 6 64-bit [gitlab-6.7.2_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/d8fd3ffca4c88ec2cd056cf0abb76fa5fc2c9236/gitlab-6.7.2_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 783db81d088e1fa679e8608672e83adb
- 6.7.1-ee - CentOS 6 64-bit [gitlab-6.7.1_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/bc91ee44fe1d23d9816e2497ff2fb23ad5efbbd4/gitlab-6.7.1_ee.omnibus-1.el6.x86_64.rpm)
- MD5: 5271918a5610f972b6c10225b151ad81
- 6.6.3-ee - CentOS 6 64-bit [gitlab-6.6.3_ee.omnibus.2-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/9fdbc4650df67d3a55c94fe7dced4fb9161aa056/gitlab-6.6.3_ee.omnibus.2-1.el6.x86_64.rpm)
- MD5: e7f8e1bfe3f6f8173fce204e3903672c
- 6.6.2-ee - CentOS 6 64-bit [gitlab-6.6.2_ee.omnibus-1.el6.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/32f814ce19709276846c281cac23b934f91beb06/gitlab-6.6.2_ee.omnibus-1.el6.x86_64.rpm)
- MD5: e4414bf4c4b13e30a35c8578943bb7a1
### CentOS 7 64-bit
- 7.5.3-ee/CI 5.2.1 - CentOS 7 64-bit [gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/f08d577a156a0bf4ef06f4b42586a94707d2e456/centos-7.0.1406/gitlab-7.5.3_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm)
+ SHA256: d3e734f37841b38f37892ea5557a7c707f0e7bba8bf5f70869f309bd8f21120a
- 7.5.2-ee/CI 5.2.1 - CentOS 7 64-bit [gitlab-7.5.2_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/01fe47e4a0b4f27da31edfc40e8bb2c695fa1647/centos-7.0.1406/gitlab-7.5.2_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm)
+ SHA256: 0543dcfccd229d37934a069cb151b14bf61f2f8a6dcb78e8aeb14cfdb0fecb47
- 7.5.1-ee/CI 5.2.0 - CentOS 7 64-bit [gitlab-7.5.1_ee.omnibus.5.2.0.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/cbe0e6ef39dc93d791707f5f715d4009034f74fc/centos-7.0.1406/gitlab-7.5.1_ee.omnibus.5.2.0.ci-1.el7.x86_64.rpm)
+ SHA256: e184d321f2d3bff994be9b7a66a76a4ec84fc88fb299b22a66d1ce90d551a970
- 7.4.5-ee/CI 5.1.0 - CentOS 7 64-bit [gitlab-7.4.5_ee.omnibus.5.1.0.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/9cb022483de75b25e9ed55f0a89b8f6de01da8d8/centos-7.0.1406/gitlab-7.4.5_ee.omnibus.5.1.0.ci-1.el7.x86_64.rpm)
+ SHA256: 50aebcda2b2a0b65527636b7ed4deded23e20dfeb6049d8fc167a441654af5e8
- 7.4.4-ee/CI 5.1.0 - CentOS 7 64-bit [gitlab-7.4.4_ee.omnibus.5.1.0.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/b5a6e03222854e741d1c0e0cf37748d5b79beac5/centos-7.0.1406/gitlab-7.4.4_ee.omnibus.5.1.0.ci-1.el7.x86_64.rpm)
+ MD5: 88d34e3705ca8317e61a2cf91ef101af
- 7.4.3-ee/CI 5.1.0 - CentOS 7 64-bit [gitlab-7.4.3_ee.omnibus.5.1.0.ci-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/f4535b85fe82f08ed758d77284572db0f5a8c141/centos-7.0.1406/gitlab-7.4.3_ee.omnibus.5.1.0.ci-1.el7.x86_64.rpm)
+ MD5: 9a1da05ff685348edc44ab2bcf419401
- 7.4.3-ee - CentOS 7 64-bit [gitlab-7.4.3_ee.omnibus.1-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/6fb497096e614fc9e06a97e2340c42c6eff902a7/centos-7.0.1406/gitlab-7.4.3_ee.omnibus.1-1.el7.x86_64.rpm)
+ MD5: 4437aa26a37e6755741cd17cf8b0ace1
- 7.4.2-ee - CentOS 7 64-bit [gitlab-7.4.2_ee.omnibus-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/34271e331e786ffb2ea436ba2f872be091d9a985/centos-7.0.1406/gitlab-7.4.2_ee.omnibus-1.el7.x86_64.rpm)
+ MD5: 54cbef1653422906aa912925c4821e80
- 7.4.1-ee - CentOS 7 64-bit [gitlab-7.4.1_ee.omnibus-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/7fec37a0e4f36281269260bdbd0b911acfb8593b/centos-7.0.1406/gitlab-7.4.1_ee.omnibus-1.el7.x86_64.rpm)
+ MD5: 6d5e0c2be3ab694a17536c7ff93e88c4
- 7.4.0-ee - CentOS 7 64-bit [gitlab-7.4.0_ee.omnibus.2-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/9b33aa1758a695f38898818a4fdd79529d123dc6/centos-7.0.1406/gitlab-7.4.0_ee.omnibus.2-1.el7.x86_64.rpm)
+ MD5: 9489913a4250df7691f6037dc5f26c3e
- 7.3.2-ee - CentOS 7 64-bit [gitlab-7.3.2_ee.omnibus-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/e5c37348729adcb27801dd2bd6c580f88b49e6ad/centos-7.0.1406/gitlab-7.3.2_ee.omnibus-1.el7.x86_64.rpm)
+ MD5: 123e637a7e75ff8506bb95b2727a5a97
- 7.3.1-ee - CentOS 7 64-bit [gitlab-7.3.1_ee.omnibus-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/3050e92537dea21bfe91a5c81037d778a00f19aa/centos-7.0.1406/gitlab-7.3.1_ee.omnibus-1.el7.x86_64.rpm)
+ MD5: fb1baf16e1937634359961656ac3d18c
- 7.3.0-ee - CentOS 7 64-bit [gitlab-7.3.0_ee.omnibus-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/18ad7ed255618bf1d3d1a26e0eaff324f609e8a2/centos-7.0.1406/gitlab-7.3.0_ee.omnibus-1.el7.x86_64.rpm)
+ MD5: c75673bed7add69c032606db9581b13f
- 7.2.2-ee - CentOS 7 64-bit [gitlab-7.2.2_ee.omnibus.1-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/8ec5d93f4c7b6884a85fe3a0b4f6e4f1ab561de4/centos-7.0.1406/gitlab-7.2.2_ee.omnibus-1.el7.x86_64.rpm)
+ MD5: d9122c6afb70f059c8c9d63691db6bb7
- 7.2.1-ee - CentOS 7 64-bit [gitlab-7.2.1_ee.omnibus.1-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/3769df612d984a89472ddd55a1c7edd76ba5d245/centos-7.0.1406/gitlab-7.2.1_ee.omnibus.1-1.el7.x86_64.rpm)
+ MD5: 1d3cee97374e1b4e9eda9afad7e75057
- 7.2.0-ee - CentOS 7 64-bit [gitlab-7.2.0_ee.omnibus.1-1.el7.x86_64.rpm](https://s3-eu-west-1.amazonaws.com/downloads-packages/74a4d7a4e9406253f7ba7fff1e83c67122d7f12d/centos-7.0.1406/gitlab-7.2.0_ee.omnibus.1-1.el7.x86_64.rpm)
+ MD5: 77b343220a36d39a1c167355ccb7c8fc
### Debian 7 64-bit
- 7.5.3-ee/CI 5.2.1 - Debian 7 64-bit [gitlab_7.5.3-ee.omnibus.5.2.1.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/9e2aa73766f581642ff10daac1dcbdaff44f6040/debian-7.6/gitlab_7.5.3-ee.omnibus.5.2.1.ci-1_amd64.deb)
+ SHA256: f370fe69342c36a84080a19ccc2f9dfce5c70cdf99922b5381fabf126b0c203e
- 7.5.2-ee/CI 5.2.1 - Debian 7 64-bit [gitlab_7.5.2-ee.omnibus.5.2.1.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/9e4146057f068039938937722a26ed9b3eef755b/debian-7.6/gitlab_7.5.2-ee.omnibus.5.2.1.ci-1_amd64.deb)
+ SHA256: 8a60a952e400cba552356613e4bd299eb8e23f982de6494d7c4207e3708a3a27
- 7.5.1-ee/CI 5.2.0 - Debian 7 64-bit [gitlab_7.5.1-ee.omnibus.5.2.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/4cd93dae8f910df1ffcc2e13dca77c6e99f6262e/debian-7.6/gitlab_7.5.1-ee.omnibus.5.2.0.ci-1_amd64.deb)
+ SHA256: 4e5812b72518dd911024c578c3abd827ae0b112781ab21d0f5821a004ba66007
- 7.4.5-ee/CI 5.1.0 - Debian 7 64-bit [gitlab_7.4.5-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/263e437825ad04d972b8a29fd1b95e3fa9d2eca5/debian-7.6/gitlab_7.4.5-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ SHA256: 16cef31906a1508869b91565fc71c1dfb9c712789e56554c3177341bd1f8903e
- 7.4.4-ee/CI 5.1.0 - Debian 7 64-bit [gitlab_7.4.4-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/57faf07036cda6780f9c55da6aaefad97218f835/debian-7.6/gitlab_7.4.4-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ MD5: 0690cc175b8563239a374c5d2001254c
- 7.4.3-ee/CI 5.1.0 - Debian 7 64-bit [gitlab_7.4.3-ee.omnibus.5.1.0.ci-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/312e79a2724f10353c68c4e4ebc68d7c706939ae/debian-7.6/gitlab_7.4.3-ee.omnibus.5.1.0.ci-1_amd64.deb)
+ MD5: d4ddb61274bca6d7268d2e3613ea5654
- 7.4.3-ee - Debian 7 64-bit [gitlab_7.4.3-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/15a6fd75f742b239a4589aa54dad7cd382d46e00/debian-7.6/gitlab_7.4.3-ee.omnibus.1-1_amd64.deb)
+ MD5: e513fba07fdc84ab0e4f8bc10f9b4a90
- 7.4.2-ee - Debian 7 64-bit [gitlab_7.4.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/93b1781f1ef5bf910075fa23bd609d504c5875a0/debian-7.6/gitlab_7.4.2-ee.omnibus-1_amd64.deb)
+ MD5: 21f097081c2c94edf91bc2d35fc5821a
- 7.4.1-ee - Debian 7 64-bit [gitlab_7.4.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/aded923f200d89ec22f70e2edc6c12146f3e605a/debian-7.6/gitlab_7.4.1-ee.omnibus-1_amd64.deb)
+ MD5: 901115747079fbab658078f268991596
- 7.4.0-ee - Debian 7 64-bit [gitlab_7.4.0-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/22be93e9b1d13b05c94dfa5c77ac1210932b92e1/debian-7.6/gitlab_7.4.0-ee.omnibus.2-1_amd64.deb)
+ MD5: b887551f922d97b41f5c9fbd0814ef3f
- 7.3.2-ee - Debian 7 64-bit [gitlab_7.3.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/daf694d5de05b57c2fd1ecb05f8bd49b4ae8dd5b/debian-7.6/gitlab_7.3.2-ee.omnibus-1_amd64.deb)
+ MD5: b57dc8b083680aa30b6ad5c4186a5194
- 7.3.1-ee - Debian 7 64-bit [gitlab_7.3.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/e89bc59a8001adf3349a89913c9ea4f25c217d59/debian-7.6/gitlab_7.3.1-ee.omnibus-1_amd64.deb)
+ MD5: 51d8206aaee69d3d3a1236bf61cc4b8a
- 7.3.0-ee - Debian 7 64-bit [gitlab_7.3.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/37b500c5c99269354366f74ee6f4558dd5aa7fe1/debian-7.6/gitlab_7.3.0-ee.omnibus-1_amd64.deb)
+ MD5: 4488f302d1f1c5278282b199f8246490
- 7.2.2-ee - Debian 7 64-bit [gitlab_7.2.2-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/f3ce6ab1750ab3cf54fa4685d83b2c0cdb846867/debian-7.6/gitlab_7.2.2-ee.omnibus-1_amd64.deb)
+ MD5: 392815a9b63e2f4c1ba69111ad509264
- 7.2.1-ee - Debian 7 64-bit [gitlab_7.2.1-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/f5508877220d49dc7abf9bdb6b5f016fa4deb46a/debian-7.6/gitlab_7.2.1-ee.omnibus.2-1_amd64.deb)
+ MD5: 8fbcb93fcb2c6a09a3a8b5d86d2b8d85
- 7.2.0-ee - Debian 7 64-bit [gitlab_7.2.0-ee.omnibus.2-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/49ca44c4b6a815993d878d8a42a653fb71672f0c/debian-7.6/gitlab_7.2.0-ee.omnibus.2-1_amd64.deb)
+ MD5: 36166f60d990afd1d76217ad23bd9e5d
- 7.1.1-ee - Debian 7 64-bit [gitlab_7.1.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/15e4d859ee875474aed4d28e85ab363513ab9967/debian-7.5/gitlab_7.1.1-ee.omnibus-1_amd64.deb)
- MD5: b25110d4dd807c968aa593afd2c9ea8b
- 7.1.0-ee - Debian 7 64-bit [gitlab_7.1.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/f25023e63a9c8782c05a1f3bcc3ed45cd8e15136/debian-7.5/gitlab_7.1.0-ee.omnibus-1_amd64.deb)
- MD5: 800b904ab58a66c95b4b9e2771233a81
- 7.0.1-ee - Debian 7 64-bit [gitlab_7.0.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/c0190e8bf1fc0b61f27c3482e26ccc8adc58e82e/debian-7.5/gitlab_7.0.1-ee.omnibus-1_amd64.deb)
- MD5: 572866c64e3dc2bead15566abd1590c2
- 7.0.0-ee - Debian 7 64-bit [gitlab_7.0.0-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/0abbb828dccfc70557caf9fd07ea302e14cc07dd/debian-7.5/gitlab_7.0.0-ee.omnibus-1_amd64.deb)
- MD5: 823ff3cf365aead9a641169c43171ea9
- 6.9.4-ee - Debian 7 64-bit [gitlab_6.9.4-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/1b5bc6d0d291eef9a6399383d6a8f13b01c09e47/debian-7.5/gitlab_6.9.4-ee.omnibus.1-1_amd64.deb)
- MD5: c31b66def74400dcc95625b6cc886191
- 6.9.3-ee - Debian 7 64-bit [gitlab_6.9.3-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/029b026311e688f1865ba9e8f7c9e4b4d01fbdc2/debian-7.5/gitlab_6.9.3-ee.omnibus.1-1_amd64.deb)
- MD5: 643e6d26d31b5b1166b9f67de299b450
- 6.9.2-ee - Debian 7 64-bit [gitlab_6.9.2-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/d33ef3d41af88acd847d0199678a1e3503fbbaa0/debian-7.4/gitlab_6.9.2-ee.omnibus-1_amd64.deb)
- MD5: 8027344d00d3d26abbd87b754a42fe2c
- 6.9.1-ee - Debian 7 64-bit [gitlab_6.9.1-ee.omnibus-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/0a8357d7282de4350c45ebdcc109ab653978a03d/debian-7.4/gitlab_6.9.1-ee.omnibus-1_amd64.deb)
- MD5: 8ea5d343bc60b984ef44325d03180f27
- 6.9.0-ee - Debian 7 64-bit [gitlab_6.9.0-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/9a604b7d3f4b57d7ebf34c26e034fb99dbe90ebf/debian-7.4/gitlab_6.9.0-ee.omnibus.1-1_amd64.deb)
- MD5: 4831a0b7dff2abf7982aaefae88a66f4
- 6.8.1-ee - Debian 7 64-bit [gitlab_6.8.1-ee.omnibus.1-1_amd64.deb](https://s3-eu-west-1.amazonaws.com/downloads-packages/42982fb41464911692bcf98692bb5858a0bba009/debian-7.4/gitlab_6.8.1-ee.omnibus.1-1_amd64.deb)
- MD5: fb0510d75a2672b605575439e4107ce9
......@@ -4,12 +4,13 @@ GitLab integrates with multiple third-party services to allow external issue tra
See the documentation below for details on how to configure these services.
- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
- [Jira](jira.md) Integrate with the JIRA issue tracker
- [External issue tracker](external-issue-tracker.md) Redmine, bugzilla, etc.
- [LDAP](ldap.md) Set up sign in via LDAP
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth.
- [Jenkins](jenkins.md) Integrate with the Jenkins CI
- [Slack](slack.md) Integrate with the Slack chat service
Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html).
- [Kerberos](kerberos.md) Integrate with Kerberos
## Project services
......
......@@ -9,5 +9,3 @@ GitLab has a great issue tracker but you can also use an external issue tracker
![jira screenshot](jira-integration-points.png)
You can configure the integration in the gitlab.yml configuration file.
Support to add your commits to the Jira ticket automatically is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jira.html).
# Jenkins CI integration
GitLab can be configured to interact with Jenkins
Integration includes:
* Trigger Jenkins build after push to repo
* Show build status on Merge Request page
Requirements:
* Jenkins GitLab Hook plugin
* git clone access for Jenkins from GitLab repo (via ssh key)
## Jenkins
1. Install GitLab Hook plugin
2. Setup jenkins project
![screen](jenkins_project.png)
## GitLab
### Read access to repository
Jenkins need read access to GitLab repository. We already specified private key to use in Jenkins. Now we need to add public key to GitLab project
![screen](jenkins_gitlab_deploy.png)
### Jenkins service
Now navigate to GitLab services page and activate Jenkins
![screen](jenkins_gitlab_service.png)
Done! Now when you push to GitLab - it will create a build for Jenkins.
And also you will be able to see merge request build status with a link to the Jenkins build.
## Development
An explanation of how this works in case anyone want to improve it or develop this service for another CI tool.
In GitLab there is no database table that lists the commits, these are always read from the repository.
Therefore it is not possible to mark the build status of a commit in GitLab.
Actually we believe this information should be stored in a single place, the CI tool itself.
To show this information in a merge request you make a project service in GitLab.
This project service does a (JSON) query to a url of the CI tool with the SHA1 of the commit.
The project service builds this url and payload based on project service settings and knowlegde of the CI tool.
The response is parsed to give a response in GitLab (success/failed/pending).
All this happens with AJAX requests on the merge request page.
The Jenkins project service code is only available in GitLab EE.
The GitLab CI project service code is available in the GitLab CE codebase.
# GitLab JIRA integration
GitLab can be configured to interact with JIRA
*Note* Directions below are for JIRA v6.x and GitLab v6.x
## Configuring JIRA
We need to create a user in JIRA which will have access to all projects that need to integrate with GitLab.
Login to your JIRA instance as admin and under Administration -> User Management create a new user.
For example, let's create user `gitlab`. We've also added `gitlab` user to group `jira-developers` which grants it access to projects.
## Configuring GitLab
In `gitlab.yml` enable [JIRA issue tracker section by uncommenting the lines](https://gitlab.com/subscribers/gitlab-ee/blob/6-8-stable-ee/config/gitlab.yml.example#L111-115).
This will make sure that all issues within GitLab are pointing to the JIRA issue tracker.
We can also enable JIRA service that will allow us to interact with JIRA issues.
For example, we can close issues in JIRA by a commit in GitLab.
Go to project settings page and fill in the project name for the JIRA project:
![Set the JIRA project name in GitLab to 'NEW'](jira_project_name.png)
Next, go to the services page and find JIRA.
![Jira services page](jira_service.png)
1. Tick the active check box to enable the service.
1. Supply the url to JIRA server, for example http://jira.sample
1. Supply the username of a user we created under `Configuring JIRA` section, for example `gitlab`
1. Supply the password of the user
1. Optional: supply the JIRA api version, default is version
1. Optional: supply the JIRA issue transition ID (issue transition to closed). This is dependant on JIRA settings, default is 2
1. Save
Now we should be able to interact with JIRA issues, for example we can close a JIRA issue by commiting to our GitLab repository and referencing the JIRA issue( in the format of JIRAPROJECT-123).
For example, for project named NEW we commit with a commit message `Add new file fixes NEW-1`:
![A Git commit that causes the JIRA issue to be closed](jira_service_commit.png)
That will close an issue NEW-1 in JIRA and add a comment with a link to the commit that closed the issue:
![The GitLab integration user leaves a comment on JIRA](jira_service_close_issue.png)
# Kerberos integration
GitLab can be configured to allow your users to sign with their Kerberos credentials.
Kerberos integration can be enabled as a regular omniauth provider, edit [gitlab.rb (omnibus-gitlab)`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#omniauth-google-twitter-github-login) or [gitlab.yml (source installations)](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example) on your GitLab server and restart GitLab. You only need to specify the provider name. For example:
```
{ name: 'kerberos'}
```
You still need to configure your system for Kerberos usage, such as specifying realms. GitLab will make use of the system's Kerberos settings.
The first time a user signs in with Kerberos credentials, GitLab will create a new GitLab user associated with the email, which is built from the kerberos username and realm. Existing GitLab users can go to profile > account and attach a Kerberos account.
### HTTP git access
A linked Kerberos account enables you to `git pull` and `git push` using your Kerberos account, as well as your standard GitLab credentials.
### Helpful links to setup development kerberos environment.
https://help.ubuntu.com/community/Kerberos
http://blog.manula.org/2012/04/setting-up-kerberos-server-with-debian.html
\ No newline at end of file
# GitLab LDAP integration
GitLab can be configured to allow your users to sign with their LDAP credentials to integrate with e.g. Active Directory.
To enable LDAP integration, edit [gitlab.rb (omnibus-gitlab)`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#setting-up-ldap-sign-in) or [gitlab.yml (source installations)](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example) on your GitLab server and restart GitLab.
The first time a user signs in with LDAP credentials, GitLab will create a new GitLab user associated with the LDAP Distinguished Name (DN) of the LDAP user.
......@@ -107,6 +108,98 @@ GitLab recognizes the following LDAP attributes as email addresses: `mail`, `ema
If multiple LDAP email attributes are present, e.g. `mail: foo@bar.com` and `email: foo@example.com`, then the first attribute found wins -- in this case `foo@bar.com`.
## LDAP group synchronization (GitLab Enterprise Edition)
LDAP group synchronization in GitLab Enterprise Edition allows you to synchronize the members of a GitLab group with one or more LDAP groups.
### Setting up LDAP group synchronization
Suppose we want to synchronize the GitLab group 'example group' with the LDAP group 'Engineering'.
1. As an owner, go to the group settings page for 'example group'.
![LDAP group settings](ldap/select_group_cn.png)
As an admin you can also go to the group edit page in the admin area.
![LDAP group settings for admins](ldap/select_group_cn_admin.png)
2. Enter 'Engineering' as the LDAP Common Name (CN) in the 'LDAP Group cn' field.
3. Enter a default group access level in the 'LDAP Access' field; let's say Developer.
![LDAP group settings filled in](ldap/select_group_cn_engineering.png)
4. Click 'Add synchronization' to add the new LDAP group link.
Now every time a member of the 'Engineering' LDAP group signs in, they automatically become a Developer-level member of the 'example group' GitLab group. Users who are already signed in will see the change in membership after up to one hour.
### Synchronizing with more than one LDAP group (GitLab EE 7.3 and newer)
If you want to add the members of LDAP group to your GitLab group you can add an additional LDAP group link.
If you have two LDAP group links, e.g. 'cn=Engineering' at level 'Developer' and 'cn=QA' at level 'Reporter', and user Jane belongs to both the 'Engineering' and 'QA' LDAP groups, she will get the _highest_ access level of the two, namely 'Developer'.
![Two linked LDAP groups](ldap/two_linked_ldap_groups.png)
### Locking yourself out of your own group
As an LDAP-enabled GitLab user, if you create a group and then set it to synchronize with an LDAP group you do not belong to, you will be removed from the grop as soon as the synchronization takes effect for you.
If you accidentally lock yourself out of your own GitLab group, ask a GitLab administrator to change the LDAP synchronization settings for your group.
### Non-LDAP GitLab users
Your GitLab instance may have users on it for whom LDAP is not enabled.
If this is the case, these users will not be affected by LDAP group synchronization settings: they will be neither added nor removed automatically.
### ActiveDirectory nested group support
If you are using ActiveDirectory, it is possible to create nested LDAP groups: the 'Engineering' LDAP group may contain another LDAP group 'Software', with 'Software' containing LDAP users Alice and Bob.
GitLab will recognize Alice and Bob as members of the 'Engineering' group.
## Define GitLab admin status via LDAP
It is possible to configure GitLab Enterprise Edition (7.1 and newer) so that GitLab admin rights are bestowed on the members of a given LDAP group.
GitLab administrator users who do not have LDAP enabled are not affected by the LDAP admin group feature.
### Enabling the admin group feature
Below we assume that you have an LDAP group with the common name (CN) 'GitLab administrators' containing the users that should be GitLab administrators.
We recommend that you keep a non-LDAP GitLab administrator user around on your GitLab instance in case you accidentally remove the admin status from your own LDAP-enabled GitLab user.
For omnibus-gitlab, add the following to `/etc/gitlab/gitlab.rb` and run `gitlab-ctl reconfigure`.
```ruby
gitlab_rails['ldap_admin_group'] = 'GitLab administrators'
```
For installations from source, add the following setting in the 'ldap' section of gitlab.yml, and run `service gitlab reload` afterwards.
```yaml
admin_group: 'Gitlab administrators'
```
## Synchronising user SSH keys with LDAP
It is possible to configure GitLab Enterprise Edition (7.1 and newer) so that users have their SSH public keys synchronised with an attribute in their LDAP object.
Existing SSH public keys that are manually manged in GitLab are not affected by this feature.
### Enabling the key synchronisation feature
Below we assume that you have LDAP users with an attribute 'sshpublickey' containing the users ssh public key.
For omnibus-gitlab, add the following to `/etc/gitlab/gitlab.rb` and run `gitlab-ctl reconfigure`.
```ruby
gitlab_rails['ldap_sync_ssh_keys'] = 'sshpublickey'
```
For installations from source, add the following setting in the 'ldap' section of gitlab.yml, and run `service gitlab reload` afterwards.
```yaml
sync_ssh_keys: 'sshpublickey'
```
## Using an LDAP filter to limit access to your GitLab server
If you want to limit all GitLab access to a subset of the LDAP users on your LDAP server you can set up an LDAP user filter.
......@@ -138,3 +231,99 @@ Tip: if you want to limit access to the nested members of an Active Directory gr
```
Please note that GitLab does not support the custom filter syntax used by omniauth-ldap.
## Integrate GitLab with more than one LDAP server (Enterprise Edition)
Starting with GitLab Enterprise Edition 7.4 it is possible to give users from more than one LDAP server access to the same GitLab server.
Please use the following steps to enable support for multiple LDAP servers.
### 1. Check your GitLab version
Go to gitlab.example.com/help and verify you are running GitLab Enterprise Edition 7.4.0 or newer.
### 2. Make sure your GitLab server uses the new LDAP syntax
```
# For omnibus packages
sudo gitlab-rails runner 'puts (Gitlab.config.ldap["host"] ? :old_syntax : :new_syntax)'
# For installations from source
cd /home/git/gitlab
bundle exec rails runner -e production 'puts (Gitlab.config.ldap["host"] ? :old_syntax : :new_syntax)'
```
### 3. Migrate existing users and groups
After switching to the new LDAP configuration syntax there will be a mismatch between the LDAP provider linked to your GitLab users and groups and the new LDAP provider defined in GitLab's configuration.
The following command will associate all existing legacy LDAP users and groups on your GitLab server with the first LDAP server listed in `gitlab.rb` (omnibus) or `gitlab.yml`.
```
# For omnibus packages
sudo gitlab-rake gitlab:migrate_ldap_providers
# For installations from source
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:migrate_ldap_providers RAILS_ENV=production
```
### 4. Add new LDAP servers
Now you can add new LDAP servers via `/etc/gitlab/gitlab.rb` (omnibus packages) or `gitlab.yml` (installations from source).
Remember to run `sudo gitlab-ctl reconfigure` or `sudo service gitlab reload` for the new servers to become available.
## Automatic Daily LDAP Sync
GitLab Enterprise Edition will now automatically sync all LDAP members on a daily basis. You can configure the time that it happens.
LDAP group synchronization in GitLab Enterprise Edition works by GitLab periodically updating the group memberships of _active_ GitLab users.
If a GitLab user becomes _inactive_ however, their group memberships in GitLab can start to lag behind the LDAP server group memberships.
Starting with GitLab 7.5 Enterprise Edition, GitLab will also update the LDAP group memberships of inactive users, by doing a daily LDAP check for _all_ GitLab users.
> Example:
John Doe leaves the company and is removed from the LDAP server.
At this point he can no longer log in to GitLab 7.4 EE.
But because he is no longer active on the GitLab EE server (he cannot log in!), his LDAP group memberships in GitLab no longer get updated, and he stays listed as a group member on the GitLab server.
> Now with GitLab 7.5 Enterprise Edition, within 24 hours of John being removed from the LDAP server, his user will also stop being listed as member of any GitLab groups.
## LDAP Synchronization
LDAP membership is checked for a GitLab user:
- when they sign in to the GitLab instance
- on a daily basis
- on any request that they do, once the LDAP cache has expired (default 1 hour, configurable, cache is per user)
If you want a shorter or longer LDAP sync time, you can easily set this with the `sync_time` attribute in your config.
For Omnibus package installations, simply add `"sync_time"` in `/etc/gitlab/gitlab.rb` to your LDAP config.
A typical LDAP configuration for GitLab installed with an Omnibus package might look like this:
```
gitlab_rails['ldap_servers'] = YAML.load <<-EOS
main:
label: 'LDAP'
host: '_your_ldap_server'
port: 636
uid: 'sAMAccountName'
method: 'ssl' # "tls" or "ssl" or "plain"
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
active_directory: true
allow_username_or_email_login: false
base: ''
user_filter: ''
sync_time: 1800
## EE only
group_base: ''
admin_group: ''
sync_ssh_keys: false
EOS
```
Here, `sync_time` is set to `1800` seconds, meaning the LDAP cache will expire every 30 minutes.
For manual GitLab installations, simply uncomment the `sync_time` entry in your `gitlab.yml` and set it to the value you desire.
Please note that changing the LDAP sync time can influence the performance of your GitLab instance.
# GitLab QA
## Login
- Regular account login
- LDAP login
Use the [support document](https://docs.google.com/document/d/1cAHvbdFE6zR5WY-zhn3HsDcACssJE8Cav6WeYq3oCkM/edit#heading=h.2x3u50ukp87w) for the ldap settings.
## Forks
- fork group project
- push changes to fork
- submit merge request to origin project
- accept merge request
## Git
- add, remove ssh key
- git clone, git push over ssh
- git clone, git push over http (with both regular and ldap accounts)
## Project
- create project
- create project using import repo
- transfer project
- rename repo path
- add/remove project member
- remove project
- create git branch with UI
- create git tag with UI
## Web editor
- create, edit, remove file in web UI
## Group
- create group
- create project in group
- add/remove group member
- remove group
## Markdown
- Visit / clone [relative links repository](https://dev.gitlab.org/samples/relative-links/tree/master) and see if the links are linking to the correct documents in the repository
- Check if images are rendered in the md
- Click on a [directory link](https://dev.gitlab.org/samples/relative-links/tree/master/documents) and see if it correctly takes to the tree view
- Click on a [file link](https://dev.gitlab.org/samples/relative-links/blob/master/documents/0.md) and see if it correctly takes to the blob view
- Check if the links in the README when viewed as a [blob](https://dev.gitlab.org/samples/relative-links/blob/master/README.md) are correct
- Select the "markdown" branch and check if all links point to the files within the markdown branch
## Syntax highlighting
- Visit/clone [language highlight repository](https://dev.gitlab.org/samples/languages-highlight)
- Check for obvious errors in highlighting
## Upgrader
- Upgrade from the previous release
- Run the upgrader script in this release (it should not break)
## Rake tasks
- Check if rake gitlab:check is updated and works
- Check if rake gitlab:env:info is updated and works
# Email from GitLab
As a GitLab administrator you can email GitLab users from within GitLab.
In the administrator interface, go to `Users`. Here you will find the button to email users:
![admin users](email1.png)
Here you can simply compose an email.
![compose an email](email2.png)
Which will be sent to all users or users of a chosen group or project.
![recipients](email3.png)
## Note
User can choose to unsubscribe from receiving emails from GitLab by following the unsubscribe link from the email.
Unsubscribing is unauthenticated in order to keep the simplicity of this feature.
On unsubscribe, user will receive an email notifying that unsubscribe happened.
Endpoint that provides unsubscribe option is protected by request being rate-limited.
# From Community Edition 6.0 to Enterprise Edition 6.0
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.0.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-0-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.0)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-0-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From 6.0 to 6.2
## Notice
Security vulnerabilities CVE-2013-4490 and CVE-2013-4489 have been patched in the latest version of GitLab 6.2.
# In 6.1 we remove a lot of deprecated code.
# You should update to 6.0 before installing 6.1 or higher so all the necessary conversions are run.
### Deprecations
#### Global issue numbers
As of 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their url. If you use an old issue number url and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects.
### 0. Backup
It's useful to make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get latest code
```bash
cd /home/git/gitlab
sudo -u git -H git fetch
sudo -u git -H git checkout 6-2-stable # Latest version of 6-2-stable addresses CVE-2013-4489
```
### 3. Install additional packages
```bash
# Add support for lograte for better log file handling
sudo apt-get install logrotate
```
### 4. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
```
### 5. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
```
### 6. Update config files
TIP: to see what changed in gitlab.yml.example in this release use next command:
```
git diff 6-0-stable:config/gitlab.yml.example 6-2-stable:config/gitlab.yml.example
```
* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-2-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/6-2-stable/config/unicorn.rb.example but with your settings.
* Copy rack attack middleware config
```bash
sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
```
* Uncomment `config.middleware.use Rack::Attack` in `/home/git/gitlab/config/application.rb`
* Set up logrotate
```bash
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
```
### 7. Update Init script
```bash
sudo rm /etc/init.d/gitlab
sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/6-2-stable/lib/support/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 8. Start application
sudo service gitlab start
sudo service nginx restart
### 9. Check application status
Check if GitLab and its environment are configured correctly:
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went south? Revert to previous version (6.0)
### 1. Revert the code to the previous version
Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the database migration
(The backup is already migrated to the previous version)
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.1 to Enterprise Edition 6.1
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.1.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-1-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.1)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-1-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.2 to Enterprise Edition 6.2
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.2.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-2-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.2)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-2-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.3 to Enterprise Edition 6.3
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.3.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-3-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.3)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-3-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.4 to Enterprise Edition 6.4
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.4.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-4-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.4)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-4-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.5 to Enterprise Edition 6.5
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.5.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-5-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.5)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-5-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.6 to Enterprise Edition 6.6
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.6.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-6-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.6)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-6-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.7 to Enterprise Edition 6.7
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.7.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-7-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.7)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-7-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.8 to Enterprise Edition 6.8
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.8.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-8-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.8)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-8-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 6.9 to Enterprise Edition 6.9
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 6.9.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 6-9-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 6.9)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 6-9-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
......@@ -125,6 +125,8 @@ sudo -u git -H git checkout v2.4.0
## 7. Install libs, migrations, etc.
```bash
sudo apt-get install libkrb5-dev
cd /home/git/gitlab
# MySQL installations (note: the line below states '--without ... postgres')
......@@ -154,14 +156,14 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
TIP: to see what changed in `gitlab.yml.example` in this release use next command:
```
git diff 6-0-stable:config/gitlab.yml.example 7-6-stable:config/gitlab.yml.example
git diff 6-0-stable:config/gitlab.yml.example 7-6-stable-ee:config/gitlab.yml.example
```
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/subscribers/gitlab-ee/blob/7-6-stable-ee/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/subscribers/gitlab-ee/blob/7-6-stable-ee/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.4.0/config.yml.example but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/lib/support/nginx/gitlab-ssl but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/subscribers/gitlab-ee/blob/7-6-stable-ee/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/subscribers/gitlab-ee/blob/7-6-stable-ee/lib/support/nginx/gitlab-ssl but with your settings.
* Copy rack attack middleware config
```bash
......
# From Community Edition 7.0 to Enterprise Edition 7.0
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 7.0.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 7-0-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 7.0)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 7-0-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 7.1 to Enterprise Edition 7.1
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 7.1.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 7-1-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
Note: Under LDAP settings fill in the `group_base` setting.
* Make `/home/git/gitlab/config/unicorn.rb` same as /home/git/gitlab/config/unicorn.rb.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Update Init script
```bash
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 7.1)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 7-1-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 7.3 to Enterprise Edition 7.3
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 7.3.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 7-3-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Start application
sudo service gitlab start
sudo service nginx restart
### 6. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 7.3)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 7-3-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 7.4 to Enterprise Edition 7.4
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 7.4.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 7-4-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Start application
sudo service gitlab start
sudo service nginx restart
### 6. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 7.4)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 7-4-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 7.5 to Enterprise Edition 7.5
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 7.5.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 7-5-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Start application
sudo service gitlab start
sudo service nginx restart
### 6. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 7.5)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 7-5-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
# From Community Edition 7.6 to Enterprise Edition 7.6
This guide assumes you have a correctly configured and tested installation of GitLab Community Edition 7.6.
If you run into any trouble or if you have any questions please contact us at support@gitlab.com.
### 0. Backup
Make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
sudo service gitlab stop
### 2. Get the EE code
```bash
cd /home/git/gitlab
sudo -u git -H git remote add ee https://gitlab.com/subscribers/gitlab-ee.git
sudo -u git -H git fetch --all
sudo -u git -H git checkout 7-6-stable-ee
```
### 3. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as /home/git/gitlab/config/gitlab.yml.example but with your settings.
### 4. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
### 5. Start application
sudo service gitlab start
sudo service nginx restart
### 6. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went wrong? Revert to previous version (Community Edition 7.6)
### 1. Revert the code to the previous version
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 7-6-stable
```
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
Depending on the installation method and your GitLab version, there are multiple update guides. Choose one that fits your needs.
## CE to EE
- [The CE to EE update guides (subscribers only)](https://gitlab.com/subscribers/gitlab-ee/tree/master/doc/update) the steps are very similar to a version upgrade: stop the server, get the code, update config files for the new functionality, install libs and do migrations, update the init script, start the application and check the application status.
## Omnibus Packages
- [Omnibus update guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md) contains the steps needed to update a GitLab [package](https://about.gitlab.com/downloads/).
......
......@@ -4,6 +4,7 @@
- [Project Features](project_features.md)
- [Authorization for merge requests](authorization_for_merge_requests.md)
- [Groups](groups.md)
- [Share projects with other groups](share_projects_with_other_groups.md)
- [Labels](labels.md)
- [GitLab Flow](gitlab_flow.md)
- [Notifications](notifications.md)
......
......@@ -238,6 +238,16 @@ In a CI strategy you can merge in master at the start of the day to prevent pain
In a synchronization point strategy you only merge in from well defined points in time, for example a tagged release.
This strategy is [advocated by Linus Torvalds](https://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html) because the state of the code at these points is better known.
GitLab Enterprise Edition offers a way to rebase before merging a merge request. You can configure this per project bassis by navigating to the project settings page and selecting `Merge Requests Rebase` checkbox.
![Merge request settings](merge_request_settings.png)
Before accepting a merge request, select `rebase before merge`.
![Merge request widget](merge_request_widget.png)
GitLab will attempt to cleanly rebase before merging branches. If clean rebase is not possible, regular merge will be performed.
If clean rebase is possible and history of the traget branch will be altered with the the merge.
In conclusion, we can say that you should try to prevent merge commits, but not eliminate them.
Your codebase should be clean but your history should represent what actually happened.
Developing software happen in small messy steps and it is OK to have your history reflect this.
......
......@@ -69,3 +69,15 @@ gitlab_rails['gitlab_default_can_create_group'] = false
# For installations from source, uncomment the 'default_can_create_group'
# line in /home/git/gitlab/config/gitlab.yml
```
## Lock project membership to members of the group
In GitLab Enterprise Edition it is possible to lock membership in project to the level of members in group.
This allows group owner to lock down any new project membership to any of the projects within the group allowing tighter control over project membership.
To enable this feature, navigate to group settings page, select `Member lock` and `Save group`.
![Checkbox for membership lock](groups/membership_lock.png)
This will disable the option for all users who previously had permissions to operate project memberships so no new users can be added. Furthermore, any request to add new user to project through API will not be possible.
# Share Projects with other Groups
In GitLab Enterprise Edition you can share projects with other groups.
This makes it possible to add a group of users to a project with a single action.
## Groups as collections of users
In GitLab Community Edition groups are used primarily to [create collections of projects](groups.md).
In GitLab Enterprise Edition you can also take advantage of the fact that groups define collections of _users_, namely the group members.
## Sharing a project with a group of users
The primary mechanism to give a group of users, say 'Engineering', access to a project, say 'Project Acme', in GitLab is to make the 'Engineering' group the owner of 'Project Acme'.
But what if 'Project Acme' already belongs to another group, say 'Open Source'?
This is where the (Enterprise Edition only) group sharing feature can be of use.
To share 'Project Acme' with the 'Engineering' group, go to the project settings page for 'Project Acme' and use the left navigation menu to go to the 'Groups' section.
![The 'Groups' section in the project settings screen (Enterprise Edition only)](groups/share_project_with_groups.png)
Now you can add the 'Engineering' group with the maximum access level of your choice.
After sharing 'Project Acme' with 'Engineering', the project is listed on the group dashboard.
!['Project Acme' is listed as a shared project for 'Engineering'](groups/other_group_sees_shared_project.png)
## Maximum access level
!['Project Acme' is shared with 'Engineering' with a maximum access level of 'Developer'](groups/max_access_level.png)
In the screenshot above, the maximum access level of 'Developer' for members from 'Engineering' means that users with higher access levels in 'Engineering' ('Master' or 'Owner') will only have 'Developer' access to 'Project Acme'.
Feature: Admin Appearance
Scenario: Create new appearance
Given I sign in as an admin
And I visit admin appearance page
When submit form with new appearance
Then I should be redirected to admin appearance page
And I should see newly created appearance
Scenario: Preview appearance
Given application has custom appearance
And I sign in as an admin
When I visit admin appearance page
And I click preview button
Then I should see a customized appearance
Scenario: Custom sign-in page
Given application has custom appearance
When I visit login page
Then I should see a customized appearance
Scenario: Appearance logo
Given application has custom appearance
And I sign in as an admin
And I visit admin appearance page
When I attach a logo
Then I should see a logo
And I remove the logo
Then I should see logo removed
Scenario: Header logos
Given application has custom appearance
And I sign in as an admin
And I visit admin appearance page
When I attach header logos
Then I should see header logos
And I remove the header logos
Then I should see header logos removed
Feature: Admin email
Background:
Given I sign in as an admin
And there are groups with projects
@javascript
Scenario: Create a new email notification
Given I visit admin email page
When I submit form with email notification info
Then I should see a notification email is begin sent
And admin emails are being sent
Scenario: Create a new email notification
Given I visit unsubscribe from admin notification page
When I click unsubscribe
Then I get redirected to the sign in path
And unsubscribed email is sent
......@@ -21,6 +21,11 @@ Feature: Admin Groups
When I select user "John Doe" from user list as "Reporter"
Then I should see "John Doe" in team list in every project as "Reporter"
Scenario: Shared projects
Given group has shared projects
When I visit group page
Then I should see project shared with group
@javascript
Scenario: Remove user from group
Given we have user "John Doe" in group
......
......@@ -55,6 +55,13 @@ Feature: Groups
Then I should not see group "Owned" avatar
And I should not see the "Remove avatar" button
Scenario: Add new LDAP synchronization
Given LDAP enabled
When I visit Group "Owned" LDAP settings page
And I add a new LDAP synchronization
Then I see a new LDAP synchronization listed
And LDAP disabled
# Leave
@javascript
......@@ -141,3 +148,14 @@ Feature: Groups
And I click on one group milestone
Then I should see group milestone with descriptions and expiry date
And I should see group milestone with all issues and MRs assigned to that milestone
@javascript
Scenario: I should see audit events
Given User "Mary Jane" exists
When I visit group "Owned" members page
And I select user "Mary Jane" from list with role "Reporter"
And I change the role to "Developer"
And I click on the "Remove User From Group" button for "Mary Jane"
When I visit group "Owned" settings page
And I go to "Audit Events"
Then I should see the audit event listed
Feature: Groups Management
Background:
Given "Pete Peters" is owner of group "Sourcing"
And "Open" is in group "Sourcing"
And "Mary Jane" has master access for project "Open"
Scenario: Project master can add members before lock
Given I sign in as "Mary Jane"
And I go to "Open" project members page
Then I can control user membership
When Group membership lock is enabled
And I reload "Open" project members page
Then I cannot control user membership from project page
And I logout
Scenario: Group owner lock membership controls
Given I sign in as "Pete Peters"
And I go to group settings page
And I enable membership lock
And I go to project settings
Then I cannot control user membership from project page
And I logout
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
Feature: Project Group Links
Background:
Given I sign in as a user
And I own project "Shop"
And project "Shop" is shared with group "Ops"
And project "Shop" is not shared with group "Market"
And I visit project group links page
Scenario: I should see list of groups
Then I should see project already shared with group "Ops"
Then I should see project is not shared with group "Market"
@javascript
Scenario: I share project with group
When I select group "Market" for share
Then I should see project is shared with group "Market"
......@@ -148,6 +148,11 @@ Feature: Project Merge Requests
Then I should see a comment like "Line is wrong" in the second file
And I should still see a comment like "Line is correct" in the first file
Scenario: I submit new unassigned merge request with template description
Given I click link "New Merge Request"
And I select "fix" as source
Then I should see description field pre-filled
@javascript
Scenario: I unfold diff
Given project "Shop" have "Bug NS-05" open merge request with diffs inside
......
......@@ -25,6 +25,13 @@ Feature: Project
And change project path settings
Then I should see project with new path settings
Scenario: I visit edit project and fill in merge request template
When I visit edit project "Shop" page
Then I should see project settings
And I fill in merge request template
And I save project
Then I should see project with merge request template saved
Scenario: I should see project readme and version
When I visit project "Shop" page
And I should see project "Shop" version
......@@ -42,3 +49,14 @@ Feature: Project
Then I should see project "Forum" README
And I visit project "Shop" page
Then I should see project "Shop" README
@javascript
Scenario: I should see audit events
And gitlab user "Pete"
And "Pete" is "Shop" developer
When I visit project "Shop" settings page
And I go to "Members"
And I change "Pete" access level to master
When I visit project "Shop" settings page
And I go to "Audit Events"
Then I should see the audit event listed
......@@ -61,6 +61,12 @@ Feature: Project Services
And I fill email on push settings
Then I should see email on push service settings saved
Scenario: Activate JIRA service
When I visit project "Shop" services page
And I click jira service link
And I fill jira settings
Then I should see jira service settings saved
Scenario: Activate Atlassian Bamboo CI service
When I visit project "Shop" services page
And I click Atlassian Bamboo CI service link
......
......@@ -35,3 +35,8 @@ Feature: Project Team Management
And I click link "Import team from another project"
And I submit "Website" project for import team
Then I should see "Mike" in team list as "Reporter"
Scenario: See all members of projects shared group
Given I share project with group "OpenSource"
And I visit project "Shop" team page
Then I should see "Opensource" group user listing
class Spinach::Features::AdminAppearance < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
step 'submit form with new appearance' do
fill_in 'appearance_title', with: 'MyCompany'
fill_in 'appearance_description', with: 'dev server'
click_button 'Save'
end
step 'I should be redirected to admin appearance page' do
current_path.should == admin_appearances_path
page.should have_content 'Appearance settings'
end
step 'I should see newly created appearance' do
page.should have_field('appearance_title', with: 'MyCompany')
page.should have_field('appearance_description', with: 'dev server')
page.should have_content 'Last edit'
end
step 'I click preview button' do
click_link "Preview"
end
step 'application has custom appearance' do
create(:appearance)
end
step 'I should see a customized appearance' do
page.should have_content appearance.title
page.should have_content appearance.description
end
step 'I attach a logo' do
attach_file(:appearance_logo, File.join(Rails.root, 'public', 'gitlab_logo.png'))
click_button 'Save'
end
step 'I attach header logos' do
attach_file(:appearance_light_logo, File.join(Rails.root, 'public', 'header_logo_light.png'))
attach_file(:appearance_dark_logo, File.join(Rails.root, 'public', 'header_logo_dark.png'))
click_button 'Save'
end
step 'I should see a logo' do
page.should have_xpath('//img[@src="/uploads/appearance/logo/1/gitlab_logo.png"]')
end
step 'I should see header logos' do
page.should have_xpath('//img[@src="/uploads/appearance/light_logo/1/header_logo_light.png"]')
page.should have_xpath('//img[@src="/uploads/appearance/dark_logo/1/header_logo_dark.png"]')
end
step 'I remove the logo' do
click_link 'Remove logo'
end
step 'I remove the header logos' do
click_link 'Remove header logos'
end
step 'I should see logo removed' do
page.should_not have_xpath('//img[@src="/uploads/appearance/logo/1/gitlab_logo.png"]')
end
step 'I should see header logos removed' do
page.should_not have_xpath('//img[@src="/uploads/appearance/light_logo/1/header_logo_light.png"]')
page.should_not have_xpath('//img[@src="/uploads/appearance/dark_logo/1/header_logo_dark.png"]')
end
def appearance
Appearance.last
end
end
class Spinach::Features::AdminEmail < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedAdmin
step 'I submit form with email notification info' do
ActionMailer::Base.deliveries = []
@email_text = "Your project has been moved."
@selected_group = Group.last
# ensure there are ppl to be emailed
2.times do
@selected_group.add_user(create(:user), Gitlab::Access::DEVELOPER)
end
within('form#new-admin-email') do
fill_in :subject, with: 'my subject'
fill_in :body, with: @email_text
# Note: Unable to use select2 helper because
# the helper uses select2 method "val" to select the group from the dropdown
# and the method "val" requires "initSelection" to be used in the select2 call
select2_container = first("#s2id_recipients")
select2_container.find(".select2-choice").click
find(:xpath, "//body").find("input.select2-input").set(@selected_group.name)
page.execute_script(%|$("input.select2-input:visible").keyup();|)
find(:xpath, "//body").find(".group-name", text: @selected_group.name).click
find('.btn-create').click
end
end
step 'I should see a notification email is begin sent' do
expect(find('.flash-notice')).to have_content 'Email sent'
end
step 'admin emails are being sent' do
expect(ActionMailer::Base.deliveries.count).to eql @selected_group.users.count
mail = ActionMailer::Base.deliveries.last
expect(mail.text_part.body.decoded).to include @email_text
end
step 'I visit unsubscribe from admin notification page' do
@user = create(:user)
urlsafe_email = Base64.urlsafe_encode64(@user.email)
visit unsubscribe_path(urlsafe_email)
end
step 'I click unsubscribe' do
click_button 'Unsubscribe'
end
step 'I get redirected to the sign in path' do
current_path.should == root_path
end
step 'unsubscribed email is sent' do
mail = ActionMailer::Base.deliveries.last
expect(mail.text_part.body.decoded).to include "You have been unsubscribed from receiving GitLab administrator notifications."
end
end
......@@ -57,6 +57,21 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
end
end
step 'group has shared projects' do
share_link = shared_project.project_group_links.new(group_access: Gitlab::Access::MASTER)
share_link.group_id = current_group.id
share_link.save!
end
step 'I visit group page' do
visit admin_group_path(current_group)
end
step 'I should see project shared with group' do
page.should have_content(shared_project.name_with_namespace)
page.should have_content "Projects shared with"
end
step 'we have user "John Doe" in group' do
current_group.add_user(user_john, Gitlab::Access::REPORTER)
end
......@@ -79,6 +94,10 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
@group ||= Group.first
end
def shared_project
@shared_project ||= create(:empty_project)
end
def user_john
@user_john ||= User.find_by(name: "John Doe")
end
......
......@@ -8,7 +8,7 @@ class Spinach::Features::DashboardHelp < Spinach::FeatureSteps
end
step 'I visit the "Rake Tasks" help page' do
visit help_page_path("raketasks", "maintenance")
visit help_page_path("raketasks", "maintenance.md")
end
step 'I should see "Rake Tasks" page markdown rendered' do
......
......@@ -57,6 +57,33 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
projects_with_access.should_not have_content("Mary Jane")
end
step 'I change the role to "Developer"' do
user = User.find_by(name: "Mary Jane")
member = Group.find_by(name: "Owned").members.where(user_id: user.id).first
within "#group_member_#{member.id}" do
find(".btn-tiny.btn.js-toggle-button").click
within "#edit_group_member_#{member.id}" do
select 'Developer', from: 'group_member_access_level'
click_on 'Save'
end
end
end
step 'I go to "Audit Events"' do
click_link 'Audit Events'
end
step 'I should see the audit event listed' do
within ('table#audits') do
page.should have_content 'Add user access as reporter'
page.should have_content 'Change access level from reporter to developer'
page.should have_content 'Remove user access'
page.should have_content('John Doe', count: 3)
page.should have_content('Mary Jane', count: 3)
end
end
step 'project from group "Owned" has issues assigned to me' do
create :issue,
project: project,
......@@ -91,6 +118,17 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
page.should have_content "Tokugawa Shogunate"
end
Then 'I should be redirected to group page' do
current_path.should == group_path(Group.last)
end
And 'I change group name' do
within '#tab-edit' do
fill_in 'group_name', with: 'new-name'
click_button "Save group"
end
end
step 'I change group "Owned" name to "new-name"' do
fill_in 'group_name', with: 'new-name'
fill_in 'group_path', with: 'new-name'
......@@ -273,4 +311,26 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
author: current_user,
milestone: milestone2_project3
end
step 'LDAP enabled' do
Gitlab.config.ldap.stub(:enabled).and_return(true)
end
step 'LDAP disabled' do
Gitlab.config.ldap.stub(:enabled).and_return(false)
end
step 'I add a new LDAP synchronization' do
within('form#new_ldap_group_link') do
find('#ldap_group_link_cn', visible: false).set('my-group-cn')
# fill_in('LDAP Group cn', with: 'my-group-cn', visible: false)
select 'Developer', from: "ldap_group_link_group_access"
click_button 'Add synchronization'
end
end
step 'I see a new LDAP synchronization listed' do
expect(page).not_to have_content('No synchronizations yet')
expect(page).to have_content('As Developer on ldap server')
end
end
class Spinach::Features::GroupsManagement < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedGroup
include SharedUser
include Select2Helper
step '"Open" is in group "Sourcing"' do
@group = Group.find_by(name: "Sourcing")
@project ||= create(:project, name: "Open", namespace: @group)
end
step '"Mary Jane" has master access for project "Open"' do
@user = User.find_by(name: "Mary Jane") || create(:user, name: "Mary Jane")
@project = Project.find_by(name: "Open")
@project.team << [@user, :master]
end
step "Group membership lock is enabled" do
@group = Group.find_by(name: "Sourcing")
@group.update_attributes(membership_lock: true)
end
step 'I go to "Open" project members page' do
click_link 'Sourcing / Open'
click_link 'Settings'
click_link 'Members'
end
step 'I can control user membership' do
page.should have_link 'New project member'
page.should have_link 'Import members'
page.should have_selector '#project_member_access_level', text: 'Master'
end
step 'I reload "Open" project members page' do
click_link 'Members'
end
step 'I go to group settings page' do
click_link 'sidebar-groups-tab'
click_link 'Sourcing'
click_link 'Settings'
end
step 'I enable membership lock' do
check 'group_membership_lock'
click_button 'Save group'
end
step 'I go to project settings' do
@project = Project.find_by(name: "Open")
click_link 'Projects'
link = "/#{@project.path_with_namespace}/team"
find(:xpath, "//a[@href=\"#{link}\"]").click
end
step 'I cannot control user membership from project page' do
page.should_not have_link 'New project member'
page.should_not have_link 'Import members'
page.should have_selector '#project_member_access_level', text: 'Master'
end
end
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
......@@ -256,6 +256,16 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end
end
step 'I select "fix" as source' do
select "fix", from: "merge_request_source_branch"
select "feature", from: "merge_request_target_branch"
click_button "Compare branches"
end
step 'I should see description field pre-filled' do
find_field('merge_request_description').value.should == 'This merge request should contain the following.'
end
step 'I unfold diff' do
first('.js-unfold').click
end
......
......@@ -2,6 +2,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
include Select2Helper
step 'change project settings' do
fill_in 'project_name_edit', with: 'NewName'
......@@ -14,6 +15,8 @@ class Spinach::Features::Project < Spinach::FeatureSteps
step 'I should see project with new settings' do
find_field('project_name').value.should == 'NewName'
find('#project_issues_enabled').should_not be_checked
find('#project_merge_requests_enabled').should be_checked
end
step 'change project path settings' do
......@@ -25,6 +28,20 @@ class Spinach::Features::Project < Spinach::FeatureSteps
project.path.should == "new-path"
end
step 'I fill in merge request template' do
fill_in 'project_merge_requests_template', with: "This merge request should contain the following."
end
step 'I should see project with merge request template saved' do
find_field('project_merge_requests_template').value.should == 'This merge request should contain the following.'
end
step 'I should see project "Shop" README link' do
within '.project-side' do
page.should have_content "README.md"
end
end
step 'I should see project "Shop" version' do
within '.project-side' do
page.should have_content "Version: 6.7.0.pre"
......@@ -53,4 +70,41 @@ class Spinach::Features::Project < Spinach::FeatureSteps
page.should have_link "README.md"
page.should have_content "testme"
end
step 'gitlab user "Pete"' do
create(:user, name: "Pete")
end
step '"Pete" is "Shop" developer' do
user = User.find_by(name: "Pete")
project = Project.find_by(name: "Shop")
project.team << [user, :developer]
end
step 'I visit project "Shop" settings page' do
click_link 'Settings'
end
step 'I go to "Members"' do
click_link 'Members'
end
step 'I change "Pete" access level to master' do
user = User.find_by(name: "Pete")
within "#user_#{user.id}" do
select "Master", from: "project_member_access_level"
end
end
step 'I go to "Audit Events"' do
click_link 'Audit Events'
end
step 'I should see the audit event listed' do
within ('table#audits') do
page.should have_content "Change access level from developer to master"
page.should have_content(project.owner.name)
page.should have_content('Pete')
end
end
end
class Spinach::Features::ProjectGroupLinks < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
include Select2Helper
step 'I should see project already shared with group "Ops"' do
within '.enabled-groups' do
page.should have_content "Ops"
end
end
step 'I should see project is not shared with group "Market"' do
within '.enabled-groups' do
page.should_not have_content "Market"
end
end
step 'I select group "Market" for share' do
group = Group.find_by(path: 'market')
select2(group.id, from: "#link_group_id")
select "Master", from: 'link_group_access'
click_button "Share"
end
step 'I should see project is shared with group "Market"' do
within '.enabled-groups' do
page.should have_content "Market"
end
end
step 'project "Shop" is shared with group "Ops"' do
group = create(:group, name: 'Ops')
share_link = project.project_group_links.new(group_access: Gitlab::Access::MASTER)
share_link.group_id = group.id
share_link.save!
end
step 'project "Shop" is not shared with group "Market"' do
create(:group, name: 'Market', path: 'market')
end
step 'I visit project group links page' do
visit project_group_links_path(project)
end
def project
@project ||= Project.find_by_name "Shop"
end
end
......@@ -151,6 +151,25 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
find_field('Sound').find('option[selected]').value.should == 'bike'
end
step 'I click jira service link' do
click_link 'JIRA'
end
step 'I fill jira settings' do
fill_in 'Project url', with: 'http://jira.example'
fill_in 'Username', with: 'gitlab'
fill_in 'Password', with: 'gitlab'
fill_in 'Api version', with: '2'
click_button 'Save'
end
step 'I should see jira service settings saved' do
find_field('Project url').value.should == 'http://jira.example'
find_field('Username').value.should == 'gitlab'
find_field('Password').value.should_not == 'gitlab'
find_field('Api version').value.should == '2'
end
step 'I click Atlassian Bamboo CI service link' do
click_link 'Atlassian Bamboo CI'
end
......
......@@ -104,4 +104,23 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
click_link('Remove user from team')
end
end
step 'I share project with group "OpenSource"' do
project = Project.find_by(name: 'Shop')
os_group = create(:group, name: 'OpenSource')
os_project = create(:project, group: os_group)
@os_user1 = create(:user)
@os_user2 = create(:user)
os_group.add_owner(@os_user1)
os_group.add_user(@os_user2, Gitlab::Access::DEVELOPER)
share_link = project.project_group_links.new(group_access: Gitlab::Access::MASTER)
share_link.group_id = os_group.id
share_link.save!
end
step 'I should see "Opensource" group user listing' do
page.should have_content("Shared with OpenSource group, members with Master role (2)")
page.should have_content(@os_user1.name)
page.should have_content(@os_user2.name)
end
end
......@@ -8,5 +8,12 @@ module SharedAdmin
step 'system has users' do
2.times { create(:user) }
end
And 'there are groups with projects' do
2.times do
group = create :group
create :project, group: group
end
end
end
......@@ -20,6 +20,10 @@ module SharedAuthentication
login_with(user_exists("Mary Jane"))
end
step 'I sign in as "Pete Peters"' do
login_with(user_exists("Pete Peters"))
end
step 'I should be redirected to sign in page' do
current_path.should == new_user_session_path
end
......
......@@ -21,6 +21,10 @@ module SharedGroup
is_member_of("Mary Jane", "Guest", Gitlab::Access::GUEST)
end
step '"Pete Peters" is owner of group "Sourcing"' do
is_member_of("Pete Peters", "Sourcing", Gitlab::Access::OWNER)
end
step 'I should see group "TestGroup"' do
page.should have_content "TestGroup"
end
......
......@@ -7,6 +7,10 @@ module SharedPaths
visit new_project_path
end
step 'I visit login page' do
visit new_user_session_path
end
# ----------------------------------------
# User
# ----------------------------------------
......@@ -39,6 +43,10 @@ module SharedPaths
visit edit_group_path(Group.find_by(name:"Owned"))
end
step 'I visit group "Owned" LDAP settings page' do
visit group_ldap_group_links_path(Group.find_by(name:"Owned"))
end
step 'I visit group "Guest" page' do
visit group_path(Group.find_by(name:"Guest"))
end
......@@ -163,10 +171,18 @@ module SharedPaths
visit admin_groups_path
end
step 'I visit admin appearance page' do
visit admin_appearances_path
end
step 'I visit admin teams page' do
visit admin_teams_path
end
step 'I visit admin email page' do
visit admin_email_path
end
step 'I visit admin settings page' do
visit admin_application_settings_path
end
......@@ -227,6 +243,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
......
......@@ -10,7 +10,7 @@ module SharedProject
# Create a specific project called "Shop"
step 'I own project "Shop"' do
@project = Project.find_by(name: "Shop")
@project ||= create(:project, name: "Shop", namespace: @user.namespace, snippets_enabled: true)
@project ||= create(:project, name: "Shop", namespace: @user.namespace, snippets_enabled: true, merge_requests_template: "This merge request should contain the following.")
@project.team << [@user, :master]
end
......
......@@ -7,4 +7,21 @@ class Spinach::Features::User < Spinach::FeatureSteps
step 'I should see user "John Doe" page' do
expect(title).to match(/^\s*John Doe/)
end
step 'I visit unsubscribe link' do
email = Base64.urlsafe_encode64("joh@doe.org")
visit "/unsubscribes/#{email}"
end
step 'I should see unsubscribe text and button' do
page.should have_content "Unsubscribe from Admin notifications Yes, I want to unsubscribe joh@doe.org from any further admin emails."
end
step 'I press the unsubscribe button' do
click_button("Unsubscribe")
end
step 'I should be unsubscribed' do
current_path.should == root_path
end
end
......@@ -67,3 +67,10 @@ Feature: User
And I should see project "Enterprise"
And I should not see project "Internal"
And I should not see project "Community"
Scenario: I unsubscribe from admin notifications
Given I sign in as "John Doe"
When I visit unsubscribe link
Then I should see unsubscribe text and button
And I press the unsubscribe button
Then I should be unsubscribed
......@@ -43,6 +43,8 @@ module API
mount ProjectMembers
mount DeployKeys
mount ProjectHooks
mount ProjectGitHook
mount Ldap
mount Services
mount Files
mount Commits
......
......@@ -39,6 +39,11 @@ module API
expose :issues_events, :merge_requests_events, :tag_push_events
end
class ProjectGitHook < Grape::Entity
expose :id, :project_id, :created_at
expose :commit_message_regex, :deny_delete_tag
end
class ForkedFromProject < Grape::Entity
expose :id
expose :name, :name_with_namespace
......@@ -65,7 +70,12 @@ module API
end
class Group < Grape::Entity
expose :id, :name, :path, :owner_id
expose :id, :name, :path, :owner_id, :ldap_cn, :ldap_access
expose :ldap_group_links, if: ->(group, _) { group.ldap_group_links.any? } do |group, _|
group.ldap_group_links.map do |group_link|
group_link.slice(:cn, :group_access)
end
end
end
class GroupDetail < Group
......@@ -204,6 +214,14 @@ module API
end
end
class LdapGroup < Grape::Entity
expose :cn
end
class ProjectGroupLink < Grape::Entity
expose :id, :project_id, :group_id, :group_access
end
class Namespace < Grape::Entity
expose :id, :path, :kind
end
......
......@@ -47,11 +47,19 @@ module API
authenticated_as_admin!
required_attributes! [:name, :path]
attrs = attributes_for_keys [:name, :path]
@group = Group.new(attrs)
group_attrs = attributes_for_keys [:name, :path]
@group = Group.new(group_attrs)
@group.owner = current_user
if @group.save
# NOTE: add backwards compatibility for single ldap link
ldap_attrs = attributes_for_keys [:ldap_cn, :ldap_access]
if ldap_attrs.present?
@group.ldap_group_links.create({
cn: ldap_attrs[:ldap_cn],
group_access: ldap_attrs[:ldap_access]
})
end
present @group, with: Entities::Group
else
render_api_error!("Failed to save group #{@group.errors.messages}", 400)
......
module API
# groups API
class Ldap < Grape::API
before { authenticate! }
resource :ldap do
helpers do
def get_group_list(provider, search)
Gitlab::LDAP::Adapter.new(provider).groups("#{search}*", 20)
end
end
# Get a LDAP groups list. Limit size to 20 of them.
# Filter results by name using search param
#
# Example Request:
# GET /ldap/groups
get 'groups' do
provider = Gitlab::LDAP::Config.servers.first['provider_name']
@groups = Gitlab::LDAP::Adapter.new(provider).groups("#{params[:search]}*", 20)
present @groups, with: Entities::LdapGroup
end
# Get a LDAP groups list by the requested provider. Lited size to 20 of them.
# Filter results by name using search param
#
# Example Request:
# GET /ldap/ldapmain/groups
get ':provider/groups' do
@groups = get_group_list(params[:provider], params[:search])
present @groups, with: Entities::LdapGroup
end
end
end
end
module API
# Projects git hook API
class ProjectGitHook < Grape::API
before { authenticate! }
before { authorize_admin_project }
resource :projects do
# Get project git hook
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# GET /projects/:id/git_hook
get ":id/git_hook" do
@git_hooks = user_project.git_hook
present @git_hooks, with: Entities::ProjectGitHook
end
# Add git hook to project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# POST /projects/:id/git_hook
post ":id/git_hook" do
attrs = attributes_for_keys [
:commit_message_regex,
:deny_delete_tag
]
if user_project.git_hook
error!("Project git hook exists", 422)
else
@git_hook = user_project.create_git_hook(attrs)
present @git_hook, with: Entities::ProjectGitHook
end
end
# Update an existing project git hook
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# PUT /projects/:id/git_hook
put ":id/git_hook" do
@git_hook = user_project.git_hook
attrs = attributes_for_keys [
:commit_message_regex,
:deny_delete_tag
]
if @git_hook && @git_hook.update_attributes(attrs)
present @git_hook, with: Entities::ProjectGitHook
else
not_found!
end
end
# Deletes project git hook. This is an idempotent function.
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# DELETE /projects/:id/git_hook
delete ":id/git_hook" do
@git_hook = user_project.git_hook
if @git_hook
@git_hook.destroy
else
not_found!
end
end
end
end
end
......@@ -53,6 +53,10 @@ module API
authorize! :admin_project, user_project
required_attributes! [:user_id, :access_level]
if user_project.group && user_project.group.membership_lock
not_allowed!
end
# either the user is already a team member or a new one
team_member = user_project.team_member_by_id(params[:user_id])
if team_member.nil?
......
......@@ -245,6 +245,30 @@ module API
user_project.forked_project_link.destroy
end
end
# Share project with group
#
# Parameters:
# id (required) - The ID of a project
# group_id (required) - The ID of a group
# group_access (required) - Level of permissions for sharing
#
# Example Request:
# POST /projects/:id/share
post ":id/share" do
authorize! :admin_project, user_project
required_attributes! [:group_id, :group_access]
link = user_project.project_group_links.new
link.group_id = params[:group_id]
link.group_access = params[:group_access]
if link.save
present link, with: Entities::ProjectGroupLink
else
render_api_error!(link.errors.full_messages.first, 409)
end
end
# search for projects current_user has access to
#
# Parameters:
......
......@@ -9,8 +9,11 @@ module API
# Example Request:
# GET /users
get do
skip_ldap = params[:skip_ldap].present? && params[:skip_ldap] == 'true'
@users = User.all
@users = @users.active if params[:active].present?
@users = @users.where('provider != ? OR provider IS NULL', 'ldap') if skip_ldap
@users = @users.search(params[:search]) if params[:search].present?
@users = paginate @users
......
......@@ -2,6 +2,11 @@ module Gitlab
class Auth
def find(login, password)
user = User.by_login(login)
if Devise.omniauth_providers.include?(:kerberos)
kerberos_user = Gitlab::Kerberos::Authentication.login(login, password)
return kerberos_user if kerberos_user
end
# If no user is found, or it's an LDAP server, try LDAP.
# LDAP users are only authenticated via LDAP
......
......@@ -87,17 +87,80 @@ module Gitlab
:push_code
end
if user.can?(action, project)
build_status_object(true)
else
build_status_object(false, "You don't have permission")
# Stop execution if user has no access to this project
unless user.can?(action, project)
return build_status_object(false, "You don't have permission")
end
# Return build_status_object(true) if all git hook checks passed successfully
# or build_status_object(false) if any hook fails
pass_git_hooks?(user, project, ref, oldrev, newrev)
end
def forced_push?(project, oldrev, newrev)
Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
end
def pass_git_hooks?(user, project, ref, oldrev, newrev)
return build_status_object(true) unless project.git_hook
return build_status_object(true) unless newrev && oldrev
git_hook = project.git_hook
# Prevent tag removal
if git_hook.deny_delete_tag
if project.repository.tag_names.include?(ref) && newrev =~ /0000000/
return build_status_object(false, "You can not delete tag")
end
end
# Check commit messages unless its branch removal
if git_hook.commit_validation? && newrev !~ /00000000/
commits = project.repository.commits_between(oldrev, newrev)
commits.each do |commit|
if git_hook.commit_message_regex.present?
unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex)
return build_status_object(false, "Commit message does not follow the pattern")
end
end
if git_hook.author_email_regex.present?
unless commit.committer_email =~ Regexp.new(git_hook.author_email_regex)
return build_status_object(false, "Commiter's email does not follow the pattern")
end
unless commit.author_email =~ Regexp.new(git_hook.author_email_regex)
return build_status_object(false, "Author's email does not follow the pattern")
end
end
# Check whether author is a GitLab member
if git_hook.member_check
unless User.existing_member?(commit.author_email)
return build_status_object(false, "Author is not a member of team")
end
if commit.author_email != commit.committer_email
unless User.existing_member?(commit.committer_email)
return build_status_object(false, "Commiter is not a member of team")
end
end
end
if git_hook.file_name_regex.present?
commit.diffs.each do |diff|
if (diff.renamed_file || diff.new_file) && diff.new_path =~ Regexp.new(git_hook.file_name_regex)
return build_status_object(false, "File name #{diff.new_path.inspect} does not follow the pattern")
end
end
end
end
end
build_status_object(true)
end
private
def protected_branch_action(project, oldrev, newrev, branch_name)
......
require "krb5_auth"
# This calls helps to authenticate to Kerberos by providing username and password
module Gitlab
module Kerberos
class Authentication
def self.login(login, password)
return unless Devise.omniauth_providers.include?(:kerberos)
return unless login.present? && password.present?
auth = new(login, password)
auth.login
end
def initialize(login, password)
@login = login
@password = password
@krb5 = ::Krb5Auth::Krb5.new
end
def valid?
@krb5.get_init_creds_password(@login, @password)
rescue ::Krb5Auth::Krb5::Exception
false
end
def login
valid? && find_by_login(@login)
end
private
def find_by_login(login)
identity = ::Identity.
where(provider: :kerberos).
where('lower(extern_uid) = ?', login).last
identity && identity.user
end
end
end
end
# LDAP authorization model
#
# * Check if we are allowed access (not blocked)
# * Update authorizations and associations
#
module Gitlab
module LDAP
class Access
attr_reader :adapter, :provider, :user
attr_reader :adapter, :provider, :user, :ldap_user
def self.open(user, &block)
Gitlab::LDAP::Adapter.open(user.ldap_identity.provider) do |adapter|
......@@ -16,6 +17,8 @@ module Gitlab
def self.allowed?(user)
self.open(user) do |access|
if access.allowed?
access.update_permissions
access.update_email
user.last_credential_check_at = Time.now
user.save
true
......@@ -49,6 +52,133 @@ module Gitlab
def ldap_config
Gitlab::LDAP::Config.new(provider)
end
def ldap_user
@ldap_user ||= Gitlab::LDAP::Person.find_by_dn(user.ldap_identity.extern_uid, adapter)
end
def update_permissions
if sync_ssh_keys?
update_ssh_keys
end
# Skip updating group permissions
# if instance does not use group_base setting
return true unless group_base.present?
update_ldap_group_links
if admin_group.present?
update_admin_status
end
end
# Update user ssh keys if they changed in LDAP
def update_ssh_keys
user.keys.ldap.where.not(key: ldap_user.ssh_keys).each do |deleted_key|
Rails.logger.info "#{self.class.name}: removing LDAP SSH key #{deleted_key.key} from #{user.name} (#{user.id})"
unless deleted_key.destroy
Rails.logger.error "#{self.class.name}: failed to remove LDAP SSH key #{key.inspect} from #{user.name} (#{user.id})"
end
end
(ldap_user.ssh_keys - user.keys.ldap.pluck(:key)).each do |key|
Rails.logger.info "#{self.class.name}: adding LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})"
new_key = LDAPKey.new(title: "LDAP - #{ldap_config.sync_ssh_keys}", key: key)
new_key.user = user
unless new_key.save
Rails.logger.error "#{self.class.name}: failed to add LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})\n"\
"error messages: #{new_key.errors.messages}"
end
end
end
# Update user email if it changed in LDAP
def update_email
if ldap_user.try(:email)
ldap_email = ldap_user.email.last.to_s.downcase
if (user.email != ldap_email)
user.update(email: ldap_email)
else
false
end
else
false
end
end
def update_admin_status
admin_group = Gitlab::LDAP::Group.find_by_cn(ldap_config.admin_group, adapter)
if admin_group.has_member?(Gitlab::LDAP::Person.find_by_dn(user.ldap_identity.extern_uid, adapter))
unless user.admin?
user.admin = true
user.save
end
else
if user.admin?
user.admin = false
user.save
end
end
end
# Loop throug all ldap conneted groups, and update the users link with it
def update_ldap_group_links
gitlab_groups_with_ldap_link.each do |group|
active_group_links = group.ldap_group_links.where(cn: cns_with_access)
if active_group_links.any?
group.add_users([user.id], fetch_group_access(group, user, active_group_links))
else
group.users.delete(user)
end
end
end
def ldap_groups
@ldap_groups ||= ::LdapGroupLink.with_provider(provider).distinct(:cn).pluck(:cn).map do |cn|
Gitlab::LDAP::Group.find_by_cn(cn, adapter)
end.compact
end
# returns a collection of cn strings to which the user has access
def cns_with_access
@ldap_groups_with_access ||= ldap_groups.select do |ldap_group|
ldap_group.has_member?(ldap_user)
end.map(&:cn)
end
def sync_ssh_keys?
ldap_config.sync_ssh_keys?
end
def group_base
ldap_config.group_base
end
def admin_group
ldap_config.admin_group
end
private
def gitlab_groups_with_ldap_link
::Group.includes(:ldap_group_links).references(:ldap_group_links).
where.not(ldap_group_links: { id: nil }).
where(ldap_group_links: { provider: provider })
end
# Get the group_access for a give user.
# Always respect the current level, never downgrade it.
def fetch_group_access(group, user, active_group_links)
current_access_level = group.group_members.where(user_id: user).maximum(:access_level)
max_group_access_level = active_group_links.maximum(:group_access)
# TODO: Test if nil value of current_access_level in handled properly
[current_access_level, max_group_access_level].compact.max
end
end
end
end
......@@ -22,6 +22,30 @@ module Gitlab
Gitlab::LDAP::Config.new(provider)
end
# Get LDAP groups from ou=Groups
#
# cn - filter groups by name
#
# Ex.
# groups("dev*") # return all groups start with 'dev'
#
def groups(cn = "*", size = nil)
options = {
base: config.group_base,
filter: Net::LDAP::Filter.eq("cn", cn)
}
options.merge!(size: size) if size
ldap_search(options).map do |entry|
Gitlab::LDAP::Group.new(entry, self)
end
end
def group(*args)
groups(*args).first
end
def users(field, value, limit = nil)
if field.to_sym == :dn
options = {
......
......@@ -4,12 +4,16 @@ module Gitlab
class Config
attr_accessor :provider, :options
class InvalidProvider < StandardError; end
def self.enabled?
Gitlab.config.ldap.enabled
end
def self.servers
Gitlab.config.ldap.servers.values
rescue Settingslogic::MissingSetting
[]
end
def self.providers
......@@ -21,7 +25,7 @@ module Gitlab
end
def self.invalid_provider(provider)
raise "Unknown provider (#{provider}). Available providers: #{providers}"
raise InvalidProvider.new("Unknown provider (#{provider}). Available providers: #{providers}")
end
def initialize(provider)
......@@ -32,6 +36,7 @@ module Gitlab
else
self.class.invalid_provider(provider)
end
@options = config_for(@provider) # Use @provider, not provider
end
......@@ -57,6 +62,10 @@ module Gitlab
options['uid']
end
def label
options['label']
end
def sync_ssh_keys?
sync_ssh_keys.present?
end
......@@ -83,6 +92,7 @@ module Gitlab
end
protected
def base_config
Gitlab.config.ldap
end
......
module Gitlab
module LDAP
class Group
attr_accessor :adapter
def self.find_by_cn(cn, adapter)
adapter.group(cn)
end
def initialize(entry, adapter=nil)
Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" }
@entry = entry
@adapter = adapter
end
def cn
entry.cn.first
end
def name
cn
end
def path
name.parameterize
end
def memberuid?
entry.respond_to? :memberuid
end
def member_uids
entry.memberuid
end
def has_member?(user)
if memberuid?
member_uids.include?(user.uid)
elsif member_dns.include?(user.dn)
true
elsif adapter.config.active_directory
adapter.dn_matches_filter?(user.dn, active_directory_recursive_memberof_filter)
end
end
def member_dns
if entry.respond_to? :member
entry.member
elsif entry.respond_to? :uniquemember
entry.uniquemember
elsif entry.respond_to? :memberof
entry.memberof
else
Rails.logger.warn("Could not find member DNs for LDAP group #{entry.inspect}")
[]
end
end
private
# We use the ActiveDirectory LDAP_MATCHING_RULE_IN_CHAIN matching rule; see
# http://msdn.microsoft.com/en-us/library/aa746475%28VS.85%29.aspx#code-snippet-5
def active_directory_recursive_memberof_filter
Net::LDAP::Filter.ex("memberOf:1.2.840.113556.1.4.1941", entry.dn)
end
def entry
@entry
end
end
end
end
......@@ -46,6 +46,14 @@ module Gitlab
entry.dn
end
def ssh_keys
if config.sync_ssh_keys? && entry.respond_to?(config.sync_ssh_keys)
entry[config.sync_ssh_keys.to_sym]
else
[]
end
end
private
def entry
......
......@@ -23,11 +23,17 @@ module Gitlab
end
def issues_for(project = nil)
issues.map do |entry|
if should_lookup?(project, entry[:project])
entry[:project].issues.where(iid: entry[:id]).first
if project && project.jira_tracker?
issues.uniq.map do |jira_identifier|
JiraIssue.new(jira_identifier[:id])
end
end.reject(&:nil?)
else
issues.map do |entry|
if should_lookup?(project, entry[:project])
entry[:project].issues.where(iid: entry[:id]).first
end
end.reject(&:nil?)
end
end
def merge_requests_for(project = nil)
......
......@@ -2,6 +2,8 @@ module Gitlab
module Satellite
# GitLab server-side merge
class MergeAction < Action
include Gitlab::Popen
attr_accessor :merge_request
def initialize(user, merge_request)
......@@ -27,16 +29,24 @@ module Gitlab
def merge!(merge_commit_message = nil)
in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo)
# If rebase before merge
# Attempt a rebase and return if succesful.
# If unsuccesful, continue with regular merge.
if merge_request.should_rebase
if rebase_in_satellite!(merge_repo)
remove_source_branch(merge_repo)
return true
end
end
if merge_in_satellite!(merge_repo, merge_commit_message)
# push merge back to bare repo
# will raise CommandFailed when push fails
merge_repo.git.push(default_options, :origin, merge_request.target_branch)
# remove source branch
if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch) && !merge_request.for_fork?
# will raise CommandFailed when push fails
merge_repo.git.push(default_options, :origin, ":#{merge_request.source_branch}")
end
remove_source_branch(merge_repo)
# merge, push and branch removal successful
true
end
......@@ -133,6 +143,40 @@ module Gitlab
handle_exception(ex)
end
# Rebases before merging the source_branch into the target_branch in the satellite.
# Before starting the rebase, clears out the satellite.
# Returns false if rebase cannot be done cleanly and resets the satellite.
# Returns true otherwise.
# Eg. of clean rebase
# source_branch: feature
# target_branch: master
#
# git checkout feature
# git pull --rebase origin master
# git push origin feature:master
# git merge feature
# git push remote master
def rebase_in_satellite!(repo)
update_satellite_source_and_target!(repo)
repo.git.checkout(default_options({b: true}), merge_request.source_branch, "source/#{merge_request.source_branch}")
output, status = popen(%W(git pull --rebase origin #{merge_request.target_branch}), repo.working_dir)
if status == 0
Gitlab::AppLogger.info "Rebasing before merge in #{merge_request.source_project.path_with_namespace} MR!#{merge_request.id}: #{output}."
if merge_request.source_branch && merge_request.target_branch
repo.git.push(default_options, "origin", "#{merge_request.source_branch}:#{merge_request.target_branch}")
end
else
repo.git.rebase(default_options, "--abort")
Gitlab::AppLogger.info "Rebasing in in #{merge_request.source_project.path_with_namespace} MR!#{merge_request.id} aborted, rebase manually."
prepare_satellite!(repo)
false
end
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
# Assumes a satellite exists that is a fresh clone of the projects repo, prepares satellite for merges, diffs etc
def update_satellite_source_and_target!(repo)
repo.remote_add('source', merge_request.source_project.repository.path_to_repo)
......@@ -141,6 +185,15 @@ module Gitlab
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
def remove_source_branch(repo)
if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch) && !merge_request.for_fork?
# will raise CommandFailed when push fails
repo.git.push(default_options, :origin, ":#{merge_request.source_branch}")
end
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
end
end
end
......@@ -43,17 +43,17 @@ module Gitlab
end
def latest_version_raw
remote_tags, _ = Gitlab::Popen.popen(%W(git ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
remote_tags, _ = Gitlab::Popen.popen(%W(git ls-remote --tags origin))
git_tags = remote_tags.split("\n").grep(/tags\/v#{current_version.major}/)
git_tags = git_tags.select { |version| version =~ /v\d\.\d\.\d\Z/ }
last_tag = git_tags.last.match(/v\d\.\d\.\d/).to_s
git_tags = git_tags.select { |version| version =~ /v\d\.\d\.\d-ee\Z/ }
last_tag = git_tags.last.match(/v\d\.\d\.\d-ee/).to_s
end
def update_commands
{
"Stash changed files" => %W(git stash),
"Get latest code" => %W(git fetch),
"Switch to new version" => %W(git checkout v#{latest_version}),
"Switch to new version" => %W(git checkout v#{latest_version}-ee),
"Install gems" => %W(bundle),
"Migrate DB" => %W(bundle exec rake db:migrate),
"Recompile assets" => %W(bundle exec rake assets:clean assets:precompile),
......
desc "GITLAB | migrate provider names to multiple ldap setup"
namespace :gitlab do
task migrate_ldap_providers: :environment do
config = Gitlab::LDAP::Config
raise 'No LDAP server hash defined. See config/gitlab.yml.example for an example' unless config.servers.any?
provider = config.servers.first['provider_name']
valid_providers = config.providers
unmigrated_group_links = LdapGroupLink.where('provider IS NULL OR provider NOT IN (?)', config.providers)
puts "found #{unmigrated_group_links.count} unmigrated LDAP links"
puts "setting provider to #{provider}"
unmigrated_group_links.update_all provider: provider
unmigrated_ldap_users = User.where(provider: 'ldap')
puts "found #{unmigrated_ldap_users.count} unmigrated LDAP users"
puts "setting provider to #{provider}"
unmigrated_ldap_users.update_all provider: provider
end
end
require 'spec_helper'
describe UnsubscribesController do
let!(:user) { create :user, email: 'me@example.com' }
describe "show" do
it "responds with success" do
get :show, email: Base64.urlsafe_encode64('me@example.com')
assert_response :success
end
it "behaves the same if email address isn't known in the system" do
get :show, email: Base64.urlsafe_encode64('i@dont_exists.com')
assert_response :success
end
end
describe "create" do
it "unsubscribes the connected user" do
post :create, email: Base64.urlsafe_encode64('me@example.com')
assert user.reload.admin_email_unsubscribed_at
end
# Don't tell if the email does not exists
it "behaves the same if email address isn't known in the system" do
post :create, email: Base64.urlsafe_encode64('i@dont_exists.com')
assert_response :redirect
end
end
end
......@@ -196,6 +196,13 @@ FactoryGirl.define do
project
end
factory :ldap_group_link do
cn 'group1'
group_access Gitlab::Access::GUEST
provider 'ldapmain'
group
end
factory :identity do
provider 'ldapmain'
extern_uid 'my-ldap-id'
......
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :appearance do
title "GitLab Enterprise Edition"
description "Open source software to collaborate on code"
end
end
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :git_hook do
force_push_regex "MyString"
deny_delete_tag false
delete_branch_regex "MyString"
project
commit_message_regex "MyString"
end
end
FactoryGirl.define do
factory :project_group_link do
project
group
end
end
......@@ -3,11 +3,16 @@ require 'spec_helper'
describe ProjectsFinder do
let(:user) { create :user }
let(:group) { create :group }
let(:group2) { create :group }
let(:project1) { create(:empty_project, :public, group: group) }
let(:project2) { create(:empty_project, :internal, group: group) }
let(:project3) { create(:empty_project, :private, group: group) }
let(:project4) { create(:empty_project, :private, group: group) }
let(:project5) { create(:empty_project, :private, group: group2) }
let(:project6) { create(:empty_project, :internal, group: group2) }
let(:project7) { create(:empty_project, :public, group: group2) }
let(:project8) { create(:empty_project, :private, group: group2) }
context 'non authenticated' do
subject { ProjectsFinder.new.execute(nil, group: group) }
......@@ -48,4 +53,18 @@ describe ProjectsFinder do
it { should include(project3) }
it { should include(project4) }
end
context 'authenticated, group member with project shared with group' do
before {
group.add_user(user, Gitlab::Access::DEVELOPER)
project5.project_group_links.create group_access: Gitlab::Access::MASTER, group: group
}
subject { ProjectsFinder.new.execute(user, group: group2) }
it { should include(project5) }
it { should include(project6) }
it { should include(project7) }
it { should_not include(project8) }
end
end
......@@ -336,6 +336,52 @@ describe GitlabMarkdownHelper do
end
end
describe "referencing a Redmine issue" do
let(:actual) { "Reference to Redmine ##{issue.iid}" }
let(:expected) { "http://redmine.example/issues/#{issue.iid}" }
let(:reference) { "##{issue.iid}" }
before do
issue_tracker_config = { "redmine" => { "title" => "Redmine tracker", "issues_url" => "http://redmine.example/issues/:id" } }
Gitlab.config.stub(:issues_tracker).and_return(issue_tracker_config)
@project.stub(:issues_tracker).and_return("redmine")
@project.stub(:issues_tracker_id).and_return("REDMINE")
end
it "should link using a valid id" do
gfm(actual).should match(expected)
end
it "should link with adjacent text" do
# Wrap the reference in parenthesis
gfm(actual.gsub(reference, "(#{reference})")).should match(expected)
# Append some text to the end of the reference
gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected)
end
it "should keep whitespace intact" do
actual = "Referenced #{reference} already."
expected = /Referenced <a.+>[^\s]+<\/a> already/
gfm(actual).should match(expected)
end
it "should not link with an invalid id" do
# Modify the reference string so it's still parsed, but is invalid
invalid_reference = actual.gsub(/(\d+)$/, "r45")
gfm(invalid_reference).should == invalid_reference
end
it "should include a title attribute" do
title = "Issue in Redmine tracker"
gfm(actual).should match(/title="#{title}"/)
end
it "should include standard gfm classes" do
gfm(actual).should match(/class="\s?gfm gfm-issue\s?"/)
end
end
describe "referencing a merge request" do
let(:object) { merge_request }
let(:reference) { "!#{merge_request.iid}" }
......
require "spec_helper"
describe MergeRequestsHelper do
let(:project) { create :project }
let(:merge_request) { MergeRequest.new }
let(:ci_service) { CiService.new }
let(:last_commit) { Commit.new({}) }
before do
merge_request.stub(:source_project) { project }
merge_request.stub(:last_commit) { last_commit }
project.stub(:ci_service) { ci_service }
last_commit.stub(:sha) { '12d65c' }
end
describe :ci_build_details_path do
it 'does not include api credentials in a link' do
ci_service.stub(:build_page) { "http://secretuser:secretpass@jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c" }
expect(ci_build_details_path(merge_request)).to_not match("secret")
end
end
end
\ No newline at end of file
......@@ -8,5 +8,13 @@ describe MergeRequestsHelper do
end
it { should eq('#1, #2, and #3') }
context 'for JIRA issues' do
let(:issues) do
[JiraIssue.new('JIRA-123'), JiraIssue.new('JIRA-456'), JiraIssue.new('FOOBAR-7890')]
end
it { should eq('#JIRA-123, #JIRA-456, and #FOOBAR-7890') }
end
end
end
......@@ -17,4 +17,16 @@ describe OauthHelper do
helper.additional_providers.should == []
end
end
describe "kerberos_enabled?" do
it 'returns true' do
allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :github, :kerberos] }
helper.kerberos_enabled?.should be_true
end
it 'returns false' do
allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :ldapmain] }
helper.kerberos_enabled?.should be_false
end
end
end
\ No newline at end of file
......@@ -35,6 +35,17 @@ describe Gitlab::Auth do
expect( gl_auth.find(username, password) ).to_not eql user
end
context "with kerberos" do
before { Devise.stub(omniauth_providers: [:kerberos]) }
it "finds user" do
Gitlab::Kerberos::Authentication.stub(valid?: true)
Gitlab::Kerberos::Authentication.stub(email: user.email)
expect( gl_auth.find(username, password) ).to eql user
end
end
context "with ldap enabled" do
before { Gitlab::LDAP::Config.stub(enabled?: true) }
......
......@@ -168,4 +168,48 @@ describe Gitlab::GitAccess do
end
end
end
describe "pass_git_hooks?" do
describe "author email check" do
it 'returns true' do
access.pass_git_hooks?(user, project, 'refs/heads/master', '6f6d7e7ed', '570e7b2ab').should be_true
end
it 'returns false' do
project.create_git_hook
project.git_hook.update(commit_message_regex: "@only.com")
access.pass_git_hooks?(user, project, 'refs/heads/master', '6f6d7e7ed', '570e7b2ab').allowed?.should be_false
end
end
describe "member_check" do
before do
project.create_git_hook
project.git_hook.update(member_check: true)
end
it 'returns false for non-member user' do
access.pass_git_hooks?(user, project, 'refs/heads/master', '6f6d7e7ed', '570e7b2ab').allowed?.should be_false
end
it 'returns true if committer is a gitlab member' do
create(:user, email: 'dmitriy.zaporozhets@gmail.com')
access.pass_git_hooks?(user, project, 'refs/heads/master', '6f6d7e7ed', '570e7b2ab').allowed?.should be_true
end
end
describe "file names check" do
it 'returns false when filename is prohibited' do
project.create_git_hook
project.git_hook.update(file_name_regex: "jpg$")
access.pass_git_hooks?(user, project, 'refs/heads/master', '913c66a37', '33f3729a4').allowed?.should be_false
end
it 'returns true if file name is allowed' do
project.create_git_hook
project.git_hook.update(file_name_regex: "exe$")
access.pass_git_hooks?(user, project, 'refs/heads/master', '913c66a37', '33f3729a4').allowed?.should be_true
end
end
end
end
require 'spec_helper'
describe Gitlab::Kerberos::Authentication do
let(:klass) { Gitlab::Kerberos::Authentication }
let(:user) { create(:omniauth_user, provider: :kerberos, extern_uid: 'gitlab') }
let(:login) { 'john' }
let(:password) { 'password' }
describe :login do
before do
Devise.stub(omniauth_providers: [:kerberos])
end
it "finds the user if authentication is successful" do
kerberos_realm = user.email.sub(/.*@/, '')
::Krb5Auth::Krb5.any_instance.stub(get_init_creds_password: true)
::Krb5Auth::Krb5.any_instance.stub(get_default_realm: kerberos_realm)
expect(klass.login('gitlab', password)).to be_true
end
it "returns false if there is no such user in kerberos" do
kerberos_login = "some-login"
kerberos_realm = user.email.sub(/.*@/, '')
::Krb5Auth::Krb5.any_instance.stub(get_init_creds_password: true)
::Krb5Auth::Krb5.any_instance.stub(get_default_realm: kerberos_realm)
expect(klass.login(kerberos_login, password)).to be_false
end
end
end
\ No newline at end of file
......@@ -28,7 +28,7 @@ describe Gitlab::LDAP::Access do
it { should be_true }
end
context 'without ActiveDirectory enabled' do
context 'withoud ActiveDirectory enabled' do
before do
Gitlab::LDAP::Config.stub(enabled?: true)
Gitlab::LDAP::Config.any_instance.stub(active_directory: false)
......@@ -38,4 +38,298 @@ describe Gitlab::LDAP::Access do
end
end
end
end
\ No newline at end of file
describe :update_permissions do
subject { access.update_permissions }
it "syncs ssh keys if enabled by configuration" do
access.stub sync_ssh_keys?: 'sshpublickey'
expect(access).to receive(:update_ssh_keys).once
subject
end
it "does update group permissions with a group base configured" do
access.stub group_base: 'my-group-base'
expect(access).to receive(:update_ldap_group_links)
subject
end
it "does not update group permissions without a group base configured" do
access.stub group_base: ''
expect(access).not_to receive(:update_ldap_group_links)
subject
end
it "does update admin group permissions if admin group is configured" do
access.stub admin_group: 'my-admin-group'
access.stub :update_ldap_group_links
expect(access).to receive(:update_admin_status)
subject
end
end
describe :update_ssh_keys do
let(:ssh_key) { 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj' }
let(:ssh_key_attribute_name) { 'sshpublickey' }
let(:entry) {
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: #{ssh_key}") }
before do
Gitlab::LDAP::Config.any_instance.stub(sync_ssh_keys: ssh_key_attribute_name)
access.stub sync_ssh_keys?: true
end
it "should add a SSH key if it is in LDAP but not in gitlab" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: #{ssh_key}")
Gitlab::LDAP::Adapter.any_instance.stub(:user) { Gitlab::LDAP::Person.new(entry, 'ldapmain') }
expect{ access.update_ssh_keys }.to change(user.keys, :count).from(0).to(1)
end
it "should add a SSH key and give it a proper name" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: #{ssh_key}")
Gitlab::LDAP::Adapter.any_instance.stub(:user) { Gitlab::LDAP::Person.new(entry, 'ldapmain') }
access.update_ssh_keys
expect(user.keys.last.title).to match(/LDAP/)
expect(user.keys.last.title).to match(/#{access.ldap_config.sync_ssh_keys}/)
end
it "should not add a SSH key if it is invalid" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: I am not a valid key")
Gitlab::LDAP::Adapter.any_instance.stub(:user) { Gitlab::LDAP::Person.new(entry, 'ldapmain') }
expect{ access.update_ssh_keys }.to_not change(user.keys, :count)
end
context 'user has at least one LDAPKey' do
before { user.keys.ldap.create key: ssh_key, title: 'to be removed' }
it "should remove a SSH key if it is no longer in LDAP" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}:\n")
Gitlab::LDAP::Adapter.any_instance.stub(:user) { Gitlab::LDAP::Person.new(entry, 'ldapmain') }
expect{ access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0)
end
it "should remove a SSH key if the ldap attribute was removed" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
Gitlab::LDAP::Adapter.any_instance.stub(:user) { Gitlab::LDAP::Person.new(entry, 'ldapmain') }
expect{ access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0)
end
end
end
describe :update_user_email do
let(:entry) { Net::LDAP::Entry.new }
before do
access.stub ldap_user: Gitlab::LDAP::Person.new(entry, user.ldap_identity.provider)
end
it "should not update email if email attribute is not set" do
expect{ access.update_email }.to_not change(user, :unconfirmed_email)
end
it "should not update the email if the user has the same email in GitLab and in LDAP" do
entry['mail'] = [user.email]
expect{ access.update_email }.to_not change(user, :unconfirmed_email)
end
it "should not update the email if the user has the same email GitLab and in LDAP, but with upper case in LDAP" do
entry['mail'] = [user.email.upcase]
expect{ access.update_email }.to_not change(user, :unconfirmed_email)
end
it "should update the email if the user email is different" do
entry['mail'] = ["new_email@example.com"]
expect{ access.update_email }.to change(user, :unconfirmed_email)
end
end
describe :update_admin_status do
before do
access.stub(admin_group: "GLAdmins")
ldap_user_entry = Net::LDAP::Entry.new
Gitlab::LDAP::Adapter.any_instance.stub(:user) { Gitlab::LDAP::Person.new(ldap_user_entry, user.ldap_identity.provider) }
Gitlab::LDAP::Person.any_instance.stub(:uid) { 'admin2' }
end
it "should give admin privileges to an User" do
admin_group = Net::LDAP::Entry.from_single_ldif_string(
%Q{dn: cn=#{access.admin_group},ou=groups,dc=bar,dc=com
cn: #{access.admin_group}
description: GitLab admins
gidnumber: 42
memberuid: admin1
memberuid: admin2
memberuid: admin3
objectclass: top
objectclass: posixGroup
})
Gitlab::LDAP::Adapter.any_instance.stub(:group) { Gitlab::LDAP::Group.new(admin_group) }
expect{ access.update_admin_status }.to change(user, :admin?).to(true)
end
it "should remove admin privileges from an User" do
user.update_attribute(:admin, true)
admin_group = Net::LDAP::Entry.from_single_ldif_string(
%Q{dn: cn=#{access.admin_group},ou=groups,dc=bar,dc=com
cn: #{access.admin_group}
description: GitLab admins
gidnumber: 42
memberuid: admin1
memberuid: admin3
objectclass: top
objectclass: posixGroup
})
Gitlab::LDAP::Adapter.any_instance.stub(:group) { Gitlab::LDAP::Group.new(admin_group) }
expect{ access.update_admin_status }.to change(user, :admin?).to(false)
end
end
describe :update_ldap_group_links do
let(:cns_with_access) { %w(ldap-group1 ldap-group2) }
let(:gitlab_group_1) { create :group }
let(:gitlab_group_2) { create :group }
before do
access.stub(cns_with_access: cns_with_access)
end
context "non existing access for group-1, allowed via ldap-group1 as MASTER" do
before do
gitlab_group_1.ldap_group_links.create({
cn: 'ldap-group1', group_access: Gitlab::Access::MASTER, provider: 'ldapmain' })
end
it "gives the user master access for group 1" do
access.update_ldap_group_links
expect( gitlab_group_1.has_master?(user) ).to be_true
end
end
context "existing access as guest for group-1, allowed via ldap-group1 as DEVELOPER" do
before do
gitlab_group_1.group_members.guests.create(user_id: user.id)
gitlab_group_1.ldap_group_links.create({
cn: 'ldap-group1', group_access: Gitlab::Access::MASTER, provider: 'ldapmain' })
end
it "upgrades the users access to master for group 1" do
expect { access.update_ldap_group_links }.to \
change{ gitlab_group_1.has_master?(user) }.from(false).to(true)
end
end
context "existing access as MASTER for group-1, allowed via ldap-group1 as DEVELOPER" do
before do
gitlab_group_1.group_members.masters.create(user_id: user.id)
gitlab_group_1.ldap_group_links.create({
cn: 'ldap-group1', group_access: Gitlab::Access::DEVELOPER, provider: 'ldapmain' })
end
it "keeps the users master access for group 1" do
expect { access.update_ldap_group_links }.not_to \
change{ gitlab_group_1.has_master?(user) }
end
end
context "existing access as master for group-1, not allowed" do
before do
gitlab_group_1.group_members.masters.create(user_id: user.id)
gitlab_group_1.ldap_group_links.create({
cn: 'ldap-group1', group_access: Gitlab::Access::MASTER, provider: 'ldapmain'})
access.stub(cns_with_access: ['ldap-group2'])
end
it "removes user from gitlab_group_1" do
expect { access.update_ldap_group_links }.to \
change{ gitlab_group_1.members.where(user_id: user).any? }.from(true).to(false)
end
end
end
describe 'ldap_groups' do
let(:ldap_group_1) do
Net::LDAP::Entry.from_single_ldif_string(
%Q{dn: cn=#{access.ldap_config.admin_group},ou=groups,dc=bar,dc=com
cn: #{access.ldap_config.admin_group}
description: GitLab group 1
gidnumber: 42
memberuid: user1
memberuid: user2
objectclass: top
objectclass: posixGroup
})
end
it "returns an interator of LDAP Groups" do
::LdapGroupLink.create({
cn: 'example', group_access: Gitlab::Access::DEVELOPER, group_id: 42, provider: 'ldapmain' })
Gitlab::LDAP::Adapter.any_instance.stub(:group) { Gitlab::LDAP::Group.new(ldap_group_1) }
expect(access.ldap_groups.first).to be_a Gitlab::LDAP::Group
end
it "only returns found ldap groups" do
::LdapGroupLink.create cn: 'example', group_access: Gitlab::Access::DEVELOPER, group_id: 42
Gitlab::LDAP::Group.stub(find_by_cn: nil) # group not found
expect(access.ldap_groups).to be_empty
end
end
describe :cns_with_access do
let(:ldap_group_response_1) do
Net::LDAP::Entry.from_single_ldif_string(
%Q{dn: cn=group1,ou=groups,dc=bar,dc=com
cn: group1
description: GitLab group 1
gidnumber: 21
memberuid: #{ldap_user.uid}
memberuid: user2
objectclass: top
objectclass: posixGroup
})
end
let(:ldap_group_response_2) do
Net::LDAP::Entry.from_single_ldif_string(
%Q{dn: cn=group2,ou=groups,dc=bar,dc=com
cn: group2
description: GitLab group 2
gidnumber: 42
memberuid: user3
memberuid: user4
objectclass: top
objectclass: posixGroup
})
end
let(:ldap_groups) do
[
Gitlab::LDAP::Group.new(ldap_group_response_1),
Gitlab::LDAP::Group.new(ldap_group_response_2)
]
end
let(:ldap_user) { Gitlab::LDAP::Person.new(Net::LDAP::Entry.new, user.ldap_identity.provider) }
before do
access.stub(ldap_user: ldap_user)
ldap_user.stub(:uid) { 'user42' }
end
it "only returns ldap cns to which the user has access" do
access.stub(ldap_groups: ldap_groups)
expect(access.cns_with_access).to eql ['group1']
end
end
end
......@@ -74,6 +74,15 @@ describe Gitlab::ReferenceExtractor do
subject.issues_for(project).should == [@i0, @i1]
end
it 'returns JIRA issues for a JIRA-integrated project' do
project.stub(jira_tracker?: true)
subject.analyze('JIRA-123 and FOOBAR-4567', project)
subject.issues_for(project).should eq(
[JiraIssue.new('JIRA-123'), JiraIssue.new('FOOBAR-4567')]
)
end
it 'accesses valid merge requests' do
@m0 = create(:merge_request, source_project: project, target_project: project, source_branch: 'aaa')
@m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'bbb')
......
......@@ -101,4 +101,36 @@ describe 'Gitlab::Satellite::MergeAction' do
merge_request_with_conflict).can_be_merged?.should be_false }
end
end
describe '#can_be_rebased?' do
context 'on fork' do
before(:each) do
merge_request.stub(:should_rebase).and_return(true)
end
it { Gitlab::Satellite::MergeAction.new(
merge_request_fork.author,
merge_request_fork).merge!.should be_true }
it { Gitlab::Satellite::MergeAction.new(
merge_request_fork_with_conflict.author,
merge_request_fork_with_conflict).merge!.should be_false }
end
context 'between branches' do
before(:each) do
merge_request.stub(:should_rebase).and_return(true)
end
it { Gitlab::Satellite::MergeAction.new(
merge_request.author,
merge_request).merge!.should be_true }
it { Gitlab::Satellite::MergeAction.new(
merge_request_with_conflict.author,
merge_request_with_conflict).merge!.should be_false }
end
end
end
......@@ -17,8 +17,8 @@ describe Gitlab::Upgrader do
describe 'latest_version_raw' do
it 'should be latest version for GitLab 5' do
upgrader.stub(current_version_raw: "5.3.0")
upgrader.latest_version_raw.should == "v5.4.2"
upgrader.stub(current_version_raw: "6.3.0-ee")
upgrader.latest_version_raw.should match(/v6\.\d\.\d-ee/)
end
end
end
......@@ -627,4 +627,30 @@ describe Notify do
should have_body_text /#{diff_path}/
end
end
describe 'admin notification' do
let(:example_site_path) { root_path }
let(:user) { create(:user) }
subject { @email = Notify.send_admin_notification(user.id, 'Admin announcement','Text') }
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
sender.display_name.should eq("GitLab")
sender.address.should eq(gitlab_sender)
end
it 'is sent to recipient' do
should deliver_to user.email
end
it 'has the correct subject' do
should have_subject 'Admin announcement'
end
it 'includes unsubscribe link' do
unsubscribe_link = "http://localhost/unsubscribes/#{Base64.urlsafe_encode64(user.email)}"
should have_body_text(unsubscribe_link)
end
end
end
require 'spec_helper'
describe Appearance do
subject { create(:appearance) }
it { should be_valid }
end
require 'spec_helper'
describe Mentionable do
include Mentionable
describe :references do
let(:project) { create(:project) }
it 'excludes JIRA references' do
project.stub(jira_tracker?: true)
references(project, 'JIRA-123').should be_empty
end
end
end
describe Issue, "Mentionable" do
describe :mentioned_users do
let!(:user) { create(:user, username: 'stranger') }
......
require 'spec_helper'
describe GitHook do
describe "Associations" do
it { should belong_to(:project) }
end
describe "Validation" do
it { should validate_presence_of(:project) }
end
end
require 'spec_helper'
describe JiraIssue do
subject { JiraIssue.new('JIRA-123') }
its(:id) { should eq('JIRA-123') }
its(:iid) { should eq('JIRA-123') }
its(:to_s) { should eq('JIRA-123') }
describe :== do
specify { subject.should eq(JiraIssue.new('JIRA-123')) }
specify { subject.should_not eq(JiraIssue.new('JIRA-124')) }
it 'only compares with JiraIssues' do
subject.should_not eq('JIRA-123')
end
end
end
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
# username :string(255)
# password :string(255)
# api_version :string(255)
require 'spec_helper'
describe JiraService, models: true do
describe "Associations" do
it { should belong_to :project }
it { should have_one :service_hook }
end
describe "Execute" do
let(:user) { create(:user) }
let(:project) { create(:project) }
before do
@jira_service = JiraService.new
@jira_service.stub(
project_id: project.id,
project: project,
service_hook: true,
project_url: 'http://jira.example.com',
username: 'gitlab_jira_username',
password: 'gitlab_jira_password',
api_version: '2'
)
@sample_data = GitPushService.new.sample_data(project, user)
# https://github.com/bblimke/webmock#request-with-basic-authentication
@api_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions'
WebMock.stub_request(:post, @api_url)
end
it "should call JIRA API" do
@jira_service.execute(@sample_data, JiraIssue.new("JIRA-123"))
WebMock.should have_requested(:post, @api_url).with(
body: /Issue solved with/
).once
end
it "calls the api with jira_issue_transition_id" do
@jira_service.jira_issue_transition_id = 'this-is-a-custom-id'
@jira_service.execute(@sample_data, JiraIssue.new("JIRA-123"))
WebMock.should have_requested(:post, @api_url).with(
body: /this-is-a-custom-id/
).once
end
end
end
require 'spec_helper'
describe LdapGroupLink do
let(:klass) { LdapGroupLink }
let(:ldap_group_link) { build :ldap_group_link }
describe "validation" do
describe "cn" do
it "validates uniquiness based on group_id and provider" do
create(:ldap_group_link, cn: 'group1', group_id: 1, provider: 'ldapmain')
group_link = build(:ldap_group_link,
cn: 'group1', group_id: 1, provider: 'ldapmain')
expect(group_link).to_not be_valid
group_link.group_id = 2
expect(group_link).to be_valid
group_link.group_id = 1
group_link.provider = 'ldapalt'
expect(group_link).to be_valid
end
end
describe :provider do
it "shows the set value" do
ldap_group_link.provider = '1235'
expect( ldap_group_link.provider ).to eql '1235'
end
it "defaults to the first ldap server if empty" do
expect( klass.new.provider ).to eql Gitlab::LDAP::Config.providers.first
end
end
end
end
\ No newline at end of file
......@@ -112,6 +112,17 @@ describe MergeRequest do
subject.closes_issues.should include(issue2)
end
context 'for a project with JIRA integration' do
let(:issue0) { JiraIssue.new('JIRA-123') }
let(:issue1) { JiraIssue.new('FOOBAR-4567') }
it 'returns sorted JiraIssues' do
subject.project.stub(default_branch: subject.target_branch)
subject.closes_issues.should eq([issue1, issue0])
end
end
end
it_behaves_like 'an editable mentionable' do
......
require 'spec_helper'
describe ProjectGroupLink do
describe "Associations" do
it { should belong_to(:group) }
it { should belong_to(:project) }
end
describe "Validation" do
let!(:project_group_link) { create(:project_group_link) }
it { should validate_presence_of(:project_id) }
it { should validate_uniqueness_of(:group_id).scoped_to(:project_id).with_message(/already shared/) }
it { should validate_presence_of(:group_id) }
it { should validate_presence_of(:group_access) }
end
end
......@@ -66,5 +66,23 @@ describe ProjectTeam do
it { project.team.member?(guest).should be_true }
end
end
end
describe :max_invited_level do
let(:group) { create(:group) }
let(:project) { create(:empty_project) }
before do
project.project_group_links.create(
group: group,
group_access: Gitlab::Access::DEVELOPER
)
group.add_user(master, Gitlab::Access::MASTER)
group.add_user(reporter, Gitlab::Access::REPORTER)
end
it { project.team.max_invited_level(master.id).should == Gitlab::Access::DEVELOPER }
it { project.team.max_invited_level(reporter.id).should == Gitlab::Access::REPORTER }
it { project.team.max_invited_level(nonmember.id).should be_nil }
end
end
......@@ -469,6 +469,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
......
......@@ -12,6 +12,7 @@ describe API::API, api: true do
before do
group1.add_owner(user1)
group2.add_owner(user2)
group1.ldap_group_links.create cn: 'ldap-group', group_access: Gitlab::Access::MASTER
end
describe "GET /groups" do
......@@ -29,6 +30,12 @@ describe API::API, api: true do
json_response.should be_an Array
json_response.length.should == 1
json_response.first['name'].should == group1.name
json_response.first['ldap_cn'].should == group1.ldap_cn
json_response.first['ldap_access'].should == group1.ldap_access
ldap_group_link = json_response.first['ldap_group_links'].first
ldap_group_link['cn'].should == group1.ldap_cn
ldap_group_link['group_access'].should == group1.ldap_access
end
end
......@@ -104,6 +111,13 @@ describe API::API, api: true do
post api("/groups", admin), { name: 'test' }
response.status.should == 400
end
it "creates an ldap_group_link if ldap_cn and ldap_access are supplied" do
group_attributes = attributes_for(:group, ldap_cn: 'ldap-group', ldap_access: Gitlab::Access::DEVELOPER)
expect {
post api("/groups", admin), group_attributes
}.to change{ LdapGroupLink.count }.by(1)
end
end
end
......
require 'spec_helper'
describe API::API do
include ApiHelpers
let(:user) { create(:user) }
before do
groups = [
OpenStruct.new(cn: 'developers'),
OpenStruct.new(cn: 'students')
]
Gitlab::LDAP::Adapter.any_instance.stub(
groups: groups
)
end
describe "GET /ldap/groups" do
context "when unauthenticated" do
it "should return authentication error" do
get api("/ldap/groups")
response.status.should == 401
end
end
context "when authenticated as user" do
it "should return an array of ldap groups" do
get api("/ldap/groups", user)
response.status.should == 200
json_response.should be_an Array
json_response.length.should == 2
json_response.first['cn'].should == 'developers'
end
end
end
describe "GET /ldap/ldapmain/groups" do
context "when unauthenticated" do
it "should return authentication error" do
get api("/ldap/ldapmain/groups")
response.status.should == 401
end
end
context "when authenticated as user" do
it "should return an array of ldap groups" do
get api("/ldap/ldapmain/groups", user)
response.status.should == 200
json_response.should be_an Array
json_response.length.should == 2
json_response.first['cn'].should == 'developers'
end
end
end
end
require 'spec_helper'
describe API::API, 'ProjectGitHook', api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user3) { create(:user) }
let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
before do
project.team << [user, :master]
project.team << [user3, :developer]
end
describe "GET /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
context "authorized user" do
it "should return project git hook" do
get api("/projects/#{project.id}/git_hook", user)
response.status.should eq(200)
json_response.should be_an Hash
json_response['project_id'].should eq(project.id)
end
end
context "unauthorized user" do
it "should not access project git hooks" do
get api("/projects/#{project.id}/git_hook", user3)
response.status.should eq(403)
end
end
end
describe "POST /projects/:id/git_hook" do
context "authorized user" do
it "should add git hook to project" do
post api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: true
response.status.should eq(201)
json_response.should be_an Hash
json_response['project_id'].should eq(project.id)
json_response['deny_delete_tag'].should eq(true)
end
end
context "unauthorized user" do
it "should not add git hook to project" do
post api("/projects/#{project.id}/git_hook", user3),
deny_delete_tag: true
response.status.should eq(403)
end
end
end
describe "POST /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
context "with existing git hook" do
it "should not add git hook to project" do
post api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: true
response.status.should eq(422)
end
end
end
describe "PUT /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
it "should update an existing project git hook" do
put api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*'
response.status.should eq(200)
json_response['deny_delete_tag'].should eq(false)
json_response['commit_message_regex'].should eq('Fixes \d+\..*')
end
end
describe "PUT /projects/:id/git_hook" do
it "should error on non existing project git hook" do
put api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*'
response.status.should eq(404)
end
it "should not update git hook for unauthorized user" do
post api("/projects/#{project.id}/git_hook", user3),
deny_delete_tag: true
response.status.should eq(403)
end
end
describe "DELETE /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
context "authorized user" do
it "should delete git hook from project" do
delete api("/projects/#{project.id}/git_hook", user)
response.status.should eq(200)
json_response.should be_an Hash
end
end
context "unauthorized user" do
it "should return a 403 error" do
delete api("/projects/#{project.id}/git_hook", user3)
response.status.should eq(403)
end
end
end
describe "DELETE /projects/:id/git_hook" do
context "for non existing git hook" do
it "should delete git hook from project" do
delete api("/projects/#{project.id}/git_hook", user)
response.status.should eq(404)
json_response.should be_an Hash
json_response['message'].should eq("404 Not Found")
end
it "should return a 403 error if not authorized" do
delete api("/projects/#{project.id}/git_hook", user3)
response.status.should eq(403)
end
end
end
end
......@@ -90,6 +90,18 @@ describe API::API, api: true do
post api("/projects/#{project.id}/members", user), user_id: user2.id, access_level: 1234
response.status.should == 422
end
context 'project in a group' do
before do
project2 = create(:project, group: create(:group, membership_lock: true))
project2.group.add_owner(user)
post api("/projects/#{project2.id}/members", user), user_id: user2.id, access_level: ProjectMember::MASTER
end
it 'should return a 405 method not allowed error when group membership lock is enabled' do
response.status.should == 405
end
end
end
describe "PUT /projects/:id/members/:user_id" do
......
......@@ -610,6 +610,37 @@ describe API::API, api: true do
end
end
describe "POST /projects/:id/share" do
let(:group) { create(:group) }
it "should share project with group" do
expect {
post api("/projects/#{project.id}/share", user), group_id: group.id,
group_access: Gitlab::Access::DEVELOPER
}.to change { ProjectGroupLink.count }.by(1)
response.status.should == 201
json_response['group_id'].should == group.id
json_response['group_access'].should == Gitlab::Access::DEVELOPER
end
it "should return a 400 error when group id is not given" do
post api("/projects/#{project.id}/share", user), group_access: Gitlab::Access::DEVELOPER
response.status.should == 400
end
it "should return a 400 error when access level is not given" do
post api("/projects/#{project.id}/share", user), group_id: group.id
response.status.should == 400
end
it "should return a 409 error when wrong params passed" do
post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234
response.status.should == 409
json_response['message'].should == 'Group access is not included in the list'
end
end
describe "GET /projects/search/:query" do
let!(:query) { 'query'}
let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) }
......
......@@ -119,3 +119,12 @@ describe Admin::DashboardController, "routing" do
end
end
describe Admin::EmailsController, "routing" do
it "to #show" do
get("/admin/email").should route_to('admin/emails#show')
end
it "to #create" do
post("/admin/email").should route_to('admin/emails#create')
end
end
require 'spec_helper'
describe LdapGroupResetService do
# TODO: refactor to multi-ldap setup
let(:group) { create(:group) }
let(:user) { create(:user) }
let(:ldap_user) { create(:omniauth_user, extern_uid: 'john', provider: 'ldap', last_credential_check_at: Time.now) }
let(:ldap_user_2) { create(:omniauth_user, extern_uid: 'mike', provider: 'ldap', last_credential_check_at: Time.now) }
before do
group.add_owner(user)
group.add_owner(ldap_user)
group.add_user(ldap_user_2, Gitlab::Access::REPORTER)
group.ldap_group_links.create cn: 'developers', group_access: Gitlab::Access::DEVELOPER
end
describe '#execute' do
context 'initiated by ldap user' do
before { LdapGroupResetService.new.execute(group, ldap_user) }
it { member_access(ldap_user).should == Gitlab::Access::OWNER }
it { member_access(ldap_user_2).should == Gitlab::Access::GUEST }
it { member_access(user).should == Gitlab::Access::OWNER }
it { expect(ldap_user.reload.last_credential_check_at).to be_nil }
it { expect(ldap_user_2.reload.last_credential_check_at).to be_nil }
end
context 'initiated by regular user' do
before { LdapGroupResetService.new.execute(group, user) }
it { member_access(ldap_user).should == Gitlab::Access::GUEST }
it { member_access(ldap_user_2).should == Gitlab::Access::GUEST }
it { member_access(user).should == Gitlab::Access::OWNER }
it { expect(ldap_user.reload.last_credential_check_at).to be_nil }
it { expect(ldap_user_2.reload.last_credential_check_at).to be_nil }
end
end
def member_access(user)
group.members.find_by(user_id: user).access_level
end
end
require 'spec_helper'
describe AdminEmailsWorker do
context "recipients" do
let(:recipient_id) { "group-#{group.id}" }
let(:group) { create :group }
before do
2.times do
group.add_user(create(:user), Gitlab::Access::DEVELOPER)
end
unsubscribed_user = create(:user, admin_email_unsubscribed_at: 5.days.ago)
group.add_user(unsubscribed_user, Gitlab::Access::DEVELOPER)
ActionMailer::Base.deliveries = []
end
it "sends email to subscribed users" do
AdminEmailsWorker.new.perform(recipient_id, 'subject', 'body')
expect(ActionMailer::Base.deliveries.count).to eql 2
end
end
end
\ No newline at end of file
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