Commit dd559674 authored by Valery Sizov's avatar Valery Sizov

Merge branch '7-4-stable-ee' into ce_stable

Conflicts:
	VERSION
	lib/gitlab/ldap/adapter.rb
parents 9712fbcd aae4e3f8
...@@ -210,6 +210,9 @@ v 6.9.0 ...@@ -210,6 +210,9 @@ v 6.9.0
- Labels for merge requests (Drew Blessing) - Labels for merge requests (Drew Blessing)
- Threaded emails by setting a Message-ID (Philip Blatter) - 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 v 6.8.0
- Ability to at mention users that are participating in issue and merge req. discussion - 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) - 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.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
...@@ -38,6 +38,7 @@ gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' ...@@ -38,6 +38,7 @@ gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
# LDAP Auth # LDAP Auth
gem 'gitlab_omniauth-ldap', '1.1.0', require: "omniauth-ldap" gem 'gitlab_omniauth-ldap', '1.1.0', require: "omniauth-ldap"
gem 'net-ldap'
# Git Wiki # Git Wiki
gem 'gollum-lib', '~> 3.0.0' gem 'gollum-lib', '~> 3.0.0'
......
...@@ -650,6 +650,7 @@ DEPENDENCIES ...@@ -650,6 +650,7 @@ DEPENDENCIES
minitest (~> 5.3.0) minitest (~> 5.3.0)
mousetrap-rails mousetrap-rails
mysql2 mysql2
net-ldap
newrelic_rpm newrelic_rpm
nprogress-rails nprogress-rails
omniauth (~> 1.1.3) omniauth (~> 1.1.3)
......
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 Copyright (c) 2013-2014 GitLab B.V.
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:
The above copyright notice and this permission notice shall be included in This software and associated documentation files (the "Software") can only be
all copies or substantial portions of the Software. 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 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
......
# ![logo](https://about.gitlab.com/images/gitlab_logo.png) GitLab # ![logo](https://about.gitlab.com/images/gitlab_logo.png) GitLab
For upgrading from GitLab CE to GitLab EE there is [upgrade guide](doc/update/7.4-ce-to-ee.md)
## Open source software to collaborate on code ## Open source software to collaborate on code
![Animated screenshots](https://about.gitlab.com/images/animated/compiled.gif) ![Animated screenshots](https://about.gitlab.com/images/animated/compiled.gif)
...@@ -13,7 +15,7 @@ ...@@ -13,7 +15,7 @@
## Canonical source ## 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 ## Code status
...@@ -124,7 +126,7 @@ And surf to [localhost:3000](http://localhost:3000/) and login with `root` / `5i ...@@ -124,7 +126,7 @@ And surf to [localhost:3000](http://localhost:3000/) and login with `root` / `5i
## Documentation ## 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 ## Getting help
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
users_path: "/api/:version/users.json" users_path: "/api/:version/users.json"
user_path: "/api/:version/users/:id.json" user_path: "/api/:version/users/:id.json"
notes_path: "/api/:version/projects/:id/notes.json" notes_path: "/api/:version/projects/:id/notes.json"
ldap_groups_path: "/api/:version/ldap/:provider/groups.json"
namespaces_path: "/api/:version/namespaces.json" namespaces_path: "/api/:version/namespaces.json"
project_users_path: "/api/:version/projects/:id/users.json" project_users_path: "/api/:version/projects/:id/users.json"
...@@ -37,7 +38,7 @@ ...@@ -37,7 +38,7 @@
# Return users list. Filtered by query # Return users list. Filtered by query
# Only active users retrieved # Only active users retrieved
users: (query, callback) -> users: (query, skip_ldap, callback) ->
url = Api.buildUrl(Api.users_path) url = Api.buildUrl(Api.users_path)
$.ajax( $.ajax(
...@@ -47,6 +48,7 @@ ...@@ -47,6 +48,7 @@
search: query search: query
per_page: 20 per_page: 20
active: true active: true
skip_ldap: skip_ldap
dataType: "json" dataType: "json"
).done (users) -> ).done (users) ->
callback(users) callback(users)
...@@ -85,3 +87,19 @@ ...@@ -85,3 +87,19 @@
buildUrl: (url) -> buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root? url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version) 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)
# 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/
$ ->
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
...@@ -24,6 +24,14 @@ class Project ...@@ -24,6 +24,14 @@ class Project
else else
$('#project_issues_tracker_id').removeAttr('disabled') $('#project_issues_tracker_id').removeAttr('disabled')
$('#project_merge_requests_enabled').change ->
if ($(this).is(':checked') == true)
$('#project_merge_requests_template').removeAttr('disabled')
else
$('#project_merge_requests_template').attr('disabled', 'disabled')
$('#project_merge_requests_template').change()
@Project = Project @Project = Project
......
...@@ -15,12 +15,14 @@ $ -> ...@@ -15,12 +15,14 @@ $ ->
user.name user.name
$('.ajax-users-select').each (i, select) -> $('.ajax-users-select').each (i, select) ->
skip_ldap = $(select).hasClass('skip_ldap')
$(select).select2 $(select).select2
placeholder: "Search for a user" placeholder: "Search for a user"
multiple: $(select).hasClass('multiselect') multiple: $(select).hasClass('multiselect')
minimumInputLength: 0 minimumInputLength: 0
query: (query) -> query: (query) ->
Api.users query.term, (users) -> Api.users query.term, skip_ldap, (users) ->
data = { results: users } data = { results: users }
query.callback(data) query.callback(data)
......
...@@ -291,6 +291,15 @@ img.emoji { ...@@ -291,6 +291,15 @@ img.emoji {
margin-bottom: 10px; margin-bottom: 10px;
} }
.group-name {
font-size: 14px;
line-height: 24px;
}
.available-groups form {
margin: 5px 0;
}
table { table {
td.permission-x { td.permission-x {
background: #D9EDF7 !important; background: #D9EDF7 !important;
......
.appearance-logo-preview {
max-width: 400px;
margin-bottom: 20px;
}
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
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, :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
class Groups::LdapGroupLinksController < ApplicationController
before_action :group
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
...@@ -39,6 +39,8 @@ class GroupsController < ApplicationController ...@@ -39,6 +39,8 @@ class GroupsController < ApplicationController
@events = @events.limit(20).offset(params[:offset] || 0) @events = @events.limit(20).offset(params[:offset] || 0)
@last_push = current_user.recent_push if current_user @last_push = current_user.recent_push if current_user
@shared_projects = @group.shared_projects
respond_to do |format| respond_to do |format|
format.html format.html
format.json { pager_json("events/_events", @events.count) } format.json { pager_json("events/_events", @events.count) }
......
...@@ -5,8 +5,12 @@ class HelpController < ApplicationController ...@@ -5,8 +5,12 @@ class HelpController < ApplicationController
def show def show
@category = params[:category] @category = params[:category]
@file = params[:file] @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' render 'show'
else else
not_found! not_found!
......
...@@ -26,7 +26,7 @@ class Profiles::KeysController < ApplicationController ...@@ -26,7 +26,7 @@ class Profiles::KeysController < ApplicationController
def destroy def destroy
@key = current_user.keys.find(params[:id]) @key = current_user.keys.find(params[:id])
@key.destroy @key.destroy unless @key.is_a? LDAPKey
respond_to do |format| respond_to do |format|
format.html { redirect_to profile_keys_url } 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)
end
end
class Projects::GroupLinksController < Projects::ApplicationController
layout 'project_settings'
before_filter :authorize_admin_project!
def index
@group_links = project.project_group_links.all
@available_groups = Group.all
@available_groups -= project.invited_groups
@available_groups -= [project.group]
end
def create
link = project.project_group_links.new
link.group_id = params[:group_id]
link.group_access = params[: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
...@@ -40,7 +40,7 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -40,7 +40,7 @@ class Projects::ServicesController < Projects::ApplicationController
def service_params def service_params
params.require(:service).permit( params.require(:service).permit(
:title, :token, :type, :active, :api_key, :subdomain, :title, :token, :type, :active, :api_key, :subdomain,
:room, :recipients, :project_url, :webhook, :room, :recipients, :project_url, :webhook, :username, :password, :api_version,
:user_key, :device, :priority, :sound :user_key, :device, :priority, :sound
) )
end end
......
...@@ -7,6 +7,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -7,6 +7,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
def index def index
@group = @project.group @group = @project.group
@project_members = @project.project_members.order('access_level DESC') @project_members = @project.project_members.order('access_level DESC')
@project_group_links = @project.project_group_links
end end
def new def new
......
...@@ -206,7 +206,7 @@ class ProjectsController < ApplicationController ...@@ -206,7 +206,7 @@ class ProjectsController < ApplicationController
params.require(:project).permit( params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list, :name, :path, :description, :issues_tracker, :tag_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :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
) )
end end
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 ...@@ -37,12 +37,24 @@ class ProjectsFinder
) )
else else
# User has no access to group or group projects # User has no access to group or group projects
# or has access through shared project
# #
# Return only: # Return only:
# public projects # public projects
# internal projects # internal projects
# # shared projects
group.projects.public_and_internal_only 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
end end
else else
......
module AdminEmailHelper
def admin_email_grouped_recipient_options
options_for_select([['All GitLab users', 'all']]) +
grouped_options_for_select(
'Groups' => Group.pluck(:name, :id).map{ |name, id| [name, "group-#{id}"] },
'Projects' => grouped_project_list
)
end
protected
def grouped_project_list
Group.includes(:projects).flat_map do |group|
group.human_name
group.projects.map do |project|
["#{group.human_name} / #{project.name}", "project-#{project.id}"]
end
end
end
end
\ No newline at end of file
module AppearancesHelper module AppearancesHelper
def brand_item
nil
end
def brand_title def brand_title
'GitLab Community Edition' if brand_item
brand_item.title
else
'GitLab Enterprise Edition'
end
end end
def brand_image def brand_image
nil if brand_item.logo?
image_tag brand_item.logo
else
nil
end
end end
def brand_text def brand_text
nil markdown(brand_item.description)
end
def brand_item
@appearance ||= Appearance.first
end end
end end
...@@ -6,7 +6,7 @@ module GroupsHelper ...@@ -6,7 +6,7 @@ module GroupsHelper
def leave_group_message(group) def leave_group_message(group)
"Are you sure you want to leave \"#{group}\" group?" "Are you sure you want to leave \"#{group}\" group?"
end end
def should_user_see_group_roles?(user, group) def should_user_see_group_roles?(user, group)
if user if user
user.is_admin? || group.members.exists?(user_id: user.id) user.is_admin? || group.members.exists?(user_id: user.id)
......
...@@ -30,8 +30,15 @@ module MergeRequestsHelper ...@@ -30,8 +30,15 @@ module MergeRequestsHelper
classes classes
end end
def ci_build_details_path(merge_request) def ci_build_details_path merge_request
merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha) 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 end
def merge_path_description(merge_request, separator) def merge_path_description(merge_request, separator)
......
...@@ -2,6 +2,7 @@ module SelectsHelper ...@@ -2,6 +2,7 @@ module SelectsHelper
def users_select_tag(id, opts = {}) def users_select_tag(id, opts = {})
css_class = "ajax-users-select " css_class = "ajax-users-select "
css_class << "multiselect " if opts[:multiple] css_class << "multiselect " if opts[:multiple]
css_class << "skip_ldap " if opts[:skip_ldap]
css_class << (opts[:class] || '') css_class << (opts[:class] || '')
value = opts[:selected] || '' value = opts[:selected] || ''
...@@ -17,4 +18,12 @@ module SelectsHelper ...@@ -17,4 +18,12 @@ module SelectsHelper
project_id = opts[:project_id] || @project.id project_id = opts[:project_id] || @project.id
hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder, 'data-project-id' => project_id) hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder, 'data-project-id' => project_id)
end end
def ldap_server_select_options
options_from_collection_for_select(
Gitlab::LDAP::Config.servers,
'provider_name',
'label'
)
end
end end
...@@ -75,8 +75,8 @@ module TabHelper ...@@ -75,8 +75,8 @@ module TabHelper
def project_tab_class def project_tab_class
return "active" if current_page?(controller: "/projects", action: :edit, id: @project) return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
if ['services', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name if ['services', 'git_hooks', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name
"active" "active"
end end
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 class Notify < ActionMailer::Base
include ActionDispatch::Routing::PolymorphicRoutes include ActionDispatch::Routing::PolymorphicRoutes
include Emails::AdminNotification
include Emails::Issues include Emails::Issues
include Emails::MergeRequests include Emails::MergeRequests
include Emails::Notes include Emails::Notes
......
class Appearance < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
validates :logo, file_size: { maximum: 1000.kilobytes.to_i }
mount_uploader :logo, AttachmentUploader
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
end
...@@ -19,6 +19,9 @@ require 'file_size_validator' ...@@ -19,6 +19,9 @@ require 'file_size_validator'
class Group < Namespace class Group < Namespace
has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember'
has_many :users, through: :group_members 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? } validate :avatar_type, if: ->(user) { user.avatar_changed? }
validates :avatar, file_size: { maximum: 100.kilobytes.to_i } validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
...@@ -70,10 +73,27 @@ class Group < Namespace ...@@ -70,10 +73,27 @@ class Group < Namespace
end end
end end
def human_ldap_access
Gitlab::Access.options_with_owner.key ldap_access
end
def public_profile? def public_profile?
projects.public_only.any? projects.public_only.any?
end 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 class << self
def search(query) def search(query)
where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%") 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 ...@@ -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 :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' } validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
scope :ldap, -> { where(type: 'LDAPKey') }
delegate :name, :email, to: :user, prefix: true delegate :name, :email, to: :user, prefix: true
after_create :add_to_shell 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)
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,8 @@ class GroupMember < Member ...@@ -26,6 +26,8 @@ class GroupMember < Member
scope :with_group, ->(group) { where(source_id: group.id) } scope :with_group, ->(group) { where(source_id: group.id) }
scope :with_user, ->(user) { where(user_id: user.id) } scope :with_user, ->(user) { where(user_id: user.id) }
scope :with_ldap_dn, -> { references(:user).includes(:user).
where(users: { provider: 'ldap' }) }
after_create :notify_create after_create :notify_create
after_update :notify_update after_update :notify_update
......
...@@ -51,6 +51,7 @@ class Project < ActiveRecord::Base ...@@ -51,6 +51,7 @@ class Project < ActiveRecord::Base
belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id" belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id"
belongs_to :namespace 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' has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
# Project services # Project services
...@@ -64,8 +65,11 @@ class Project < ActiveRecord::Base ...@@ -64,8 +65,11 @@ class Project < ActiveRecord::Base
has_one :assembla_service, dependent: :destroy has_one :assembla_service, dependent: :destroy
has_one :gemnasium_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy
has_one :slack_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 :buildbox_service, dependent: :destroy
has_one :pushover_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_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link has_one :forked_from_project, through: :forked_project_link
# Merge Requests for target project should be removed with it # Merge Requests for target project should be removed with it
...@@ -88,6 +92,9 @@ class Project < ActiveRecord::Base ...@@ -88,6 +92,9 @@ class Project < ActiveRecord::Base
has_many :users_star_projects, dependent: :destroy has_many :users_star_projects, dependent: :destroy
has_many :starrers, through: :users_star_projects, source: :user 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 :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true delegate :members, to: :team, prefix: true
...@@ -313,7 +320,7 @@ class Project < ActiveRecord::Base ...@@ -313,7 +320,7 @@ class Project < ActiveRecord::Base
end end
def available_services_names def available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack pushover buildbox) %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack jira jenkins pushover buildbox)
end end
def gitlab_ci? def gitlab_ci?
...@@ -328,6 +335,14 @@ class Project < ActiveRecord::Base ...@@ -328,6 +335,14 @@ class Project < ActiveRecord::Base
@ci_service ||= ci_services.select(&:activated?).first @ci_service ||= ci_services.select(&:activated?).first
end end
def jira_tracker?
self.issues_tracker == "jira"
end
def redmine_tracker?
self.issues_tracker == "redmine"
end
# For compatibility with old code # For compatibility with old code
def code def code
path path
...@@ -620,4 +635,12 @@ class Project < ActiveRecord::Base ...@@ -620,4 +635,12 @@ class Project < ActiveRecord::Base
def origin_merge_requests def origin_merge_requests
merge_requests.where(source_project_id: self.id) merge_requests.where(source_project_id: self.id)
end end
def group_ldap_synced?
if group
group.ldap_synced?
else
false
end
end
end end
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
status = Nokogiri.parse(response).xpath('//img[@class="build-caption-status-icon"]').first.attributes['alt'].value
if status.include?('Success')
'success'
elsif status.include?('Failed') || status.include?('Aborted')
'failed'
elsif status.include?('In progress')
'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
...@@ -145,14 +145,63 @@ class ProjectTeam ...@@ -145,14 +145,63 @@ class ProjectTeam
access << group.group_members.find_by(user_id: user_id).try(:access_field) access << group.group_members.find_by(user_id: user_id).try(:access_field)
end end
if project.invited_groups.any?
access << max_invited_level(user_id)
end
access.compact.max access.compact.max
end 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 private
def fetch_members(level = nil) def fetch_members(level = nil)
project_members = project.project_members project_members = project.project_members
group_members = group ? group.group_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 if level
project_members = project_members.send(level) project_members = project_members.send(level)
...@@ -160,6 +209,7 @@ class ProjectTeam ...@@ -160,6 +209,7 @@ class ProjectTeam
end end
user_ids = project_members.pluck(:user_id) 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_ids += group_members.pluck(:user_id) if group
User.where(id: user_ids) User.where(id: user_ids)
......
...@@ -178,6 +178,7 @@ class User < ActiveRecord::Base ...@@ -178,6 +178,7 @@ class User < ActiveRecord::Base
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } 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 :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 :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, -> { where('provider LIKE ?', 'ldap%') } scope :ldap, -> { where('provider LIKE ?', 'ldap%') }
scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active }
...@@ -293,7 +294,8 @@ class User < ActiveRecord::Base ...@@ -293,7 +294,8 @@ class User < ActiveRecord::Base
@authorized_projects ||= begin @authorized_projects ||= begin
project_ids = personal_projects.pluck(:id) project_ids = personal_projects.pluck(:id)
project_ids += groups_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') Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC')
end end
end end
...@@ -428,7 +430,7 @@ class User < ActiveRecord::Base ...@@ -428,7 +430,7 @@ class User < ActiveRecord::Base
if !Gitlab.config.ldap.enabled if !Gitlab.config.ldap.enabled
false false
elsif ldap_user? 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 else
false false
end end
...@@ -529,6 +531,10 @@ class User < ActiveRecord::Base ...@@ -529,6 +531,10 @@ class User < ActiveRecord::Base
SystemHooksService.new SystemHooksService.new
end end
def admin_unsubscribe!
update_column :admin_email_unsubscribed_at, Time.now
end
def starred?(project) def starred?(project)
starred_projects.exists?(project) starred_projects.exists?(project)
end end
......
...@@ -13,5 +13,9 @@ module Files ...@@ -13,5 +13,9 @@ module Files
def repository def repository
project.repository project.repository
end end
def git_hook
project.git_hook
end
end end
end end
...@@ -17,6 +17,10 @@ module Files ...@@ -17,6 +17,10 @@ module Files
return error("You can only create files if you are on top of a branch") return error("You can only create files if you are on top of a branch")
end 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_name = File.basename(path)
file_path = path file_path = path
......
...@@ -17,6 +17,10 @@ module Files ...@@ -17,6 +17,10 @@ module Files
return error("You can only create files if you are on top of a branch") return error("You can only create files if you are on top of a branch")
end 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) blob = repository.blob_at_branch(ref, path)
unless blob unless blob
......
...@@ -17,6 +17,10 @@ module Files ...@@ -17,6 +17,10 @@ module Files
return error("You can only create files if you are on top of a branch") return error("You can only create files if you are on top of a branch")
end 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) blob = repository.blob_at_branch(ref, path)
unless blob unless blob
......
...@@ -87,7 +87,11 @@ class GitPushService ...@@ -87,7 +87,11 @@ class GitPushService
if !issues_to_close.empty? && is_default_branch if !issues_to_close.empty? && is_default_branch
issues_to_close.each do |issue| 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
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 ...@@ -19,6 +19,9 @@ module MergeRequests
# Generate suggested MR title based on source branch name # Generate suggested MR title based on source branch name
merge_request.title = merge_request.source_branch.titleize.humanize 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( compare_result = CompareService.new.execute(
current_user, current_user,
merge_request.source_project, 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
.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
.form-actions
= f.submit 'Save', class: 'btn btn-save'
= link_to 'Preview', 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 look of sign-in and sign-up pages here
%hr
= 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
= select_tag :recipients, admin_email_grouped_recipient_options, class: :select2, required: true
.form-actions
= submit_tag 'Send message', class: 'btn btn-create'
...@@ -51,7 +51,12 @@ ...@@ -51,7 +51,12 @@
%li Renaming group path will rename directory for all related projects %li Renaming group path will rename directory for all related projects
%li It will change web url for access group and group projects. %li It will change web url for access group and group projects.
%li It will change the git path to repositories under this group. %li It will change the git path to repositories under this group.
.form-actions .form-actions
= f.submit 'Save changes', class: "btn btn-primary" = f.submit 'Save changes', class: "btn btn-primary"
= link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel" = 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 @@ ...@@ -31,6 +31,17 @@
%strong %strong
= @group.created_at.stamp("March 1, 1999") = @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.panel-default
.panel-heading .panel-heading
%h3.panel-title %h3.panel-title
...@@ -49,6 +60,22 @@ ...@@ -49,6 +60,22 @@
.panel-footer .panel-footer
= paginate @projects, param_name: 'projects_page', theme: 'gitlab' = 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 .col-md-6
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
...@@ -60,7 +87,7 @@ ...@@ -60,7 +87,7 @@
= form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do = form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
%div %div
= users_select_tag(:user_ids, multiple: true) = users_select_tag(:user_ids, { multiple: true, skip_ldap: @group.ldap_synced? })
%div.prepend-top-10 %div.prepend-top-10
= select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2"
%hr %hr
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
.panel-heading .panel-heading
Users (#{@users.total_count}) Users (#{@users.total_count})
.panel-head-actions .panel-head-actions
= link_to 'Send email to users', admin_email_path, class: 'btn btn-info'
.dropdown.inline .dropdown.inline
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort: %span.light sort:
......
= form_for @users_group, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f| = form_for @users_group, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
.form-group .form-group
= f.label :user_ids, "People", class: 'control-label' = 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 .form-group
= f.label :access_level, "Group Access", class: 'control-label' = f.label :access_level, "Group Access", class: 'control-label'
......
...@@ -7,4 +7,8 @@ ...@@ -7,4 +7,8 @@
= link_to projects_group_path(@group) do = link_to projects_group_path(@group) do
%i.fa.fa-folder %i.fa.fa-folder
Projects Projects
= nav_link(controller: :ldap_group_links) do
= link_to group_ldap_group_links_path(@group) do
%i.icon-exchange
LDAP Groups
- 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
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
= f.label :description, "Details", class: 'control-label' = f.label :description, "Details", class: 'control-label'
.col-sm-10 .col-sm-10
= f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4
.form-group .form-group
.col-sm-2 .col-sm-2
.col-sm-10 .col-sm-10
...@@ -52,5 +51,4 @@ ...@@ -52,5 +51,4 @@
Removing group will cause all child projects and resources to be removed. Removing group will cause all child projects and resources to be removed.
%br %br
%strong Removed group can not be restored! %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" = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove"
.row
.col-md-2= render 'groups/settings_nav'
.col-md-10
%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 @@ ...@@ -17,6 +17,10 @@
- if current_user && current_user.can?(:manage_group, @group) - if current_user && current_user.can?(:manage_group, @group)
.pull-right .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 = link_to '#', class: 'btn btn-new js-toggle-button' do
Add members Add members
%i.fa.fa-chevron-down %i.fa.fa-chevron-down
...@@ -24,6 +28,19 @@ ...@@ -24,6 +28,19 @@
.js-toggle-content.hide.new-group-member-holder .js-toggle-content.hide.new-group-member-holder
= render "new_group_member" = 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.panel-default.prepend-top-20
.panel-heading .panel-heading
%strong #{@group.name} %strong #{@group.name}
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
%p %p
= escaped_autolink(@group.description) = escaped_autolink(@group.description)
= render "projects", projects: @projects = render "projects", projects: @projects
%br
= render "shared_projects", projects: @shared_projects
- if current_user - if current_user
.prepend-top-20 .prepend-top-20
= link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
......
%div %div
%h1 %h1
GitLab GitLab
%span.light Enterprise Edition
%span= Gitlab::VERSION %span= Gitlab::VERSION
%small= Gitlab::REVISION %small= Gitlab::REVISION
%p.slead %p.slead
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
-# https://github.com/gitlabhq/gitlabhq/pull/5958#issuecomment-45397555 -# https://github.com/gitlabhq/gitlabhq/pull/5958#issuecomment-45397555
- if controller_name == 'projects' && action_name == 'show' - if controller_name == 'projects' && action_name == 'show'
%meta{name: "go-import", content: "#{@project.web_url_without_protocol} git #{@project.web_url}.git"} %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
= "#{title} | " if defined?(title) = "#{title} | " if defined?(title)
......
...@@ -16,4 +16,5 @@ ...@@ -16,4 +16,5 @@
= link_to "Hooks", admin_hooks_path = link_to "Hooks", admin_hooks_path
= nav_link(controller: :background_jobs) do = nav_link(controller: :background_jobs) do
= link_to "Background Jobs", admin_background_jobs_path = link_to "Background Jobs", admin_background_jobs_path
= nav_link(controller: :appearances) do
= link_to "Appearance", admin_appearances_path
%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
= ldap_group_link.cn
%small.light== as #{ldap_group_link.human_access} on #{ldap_group_link.provider_label}
.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')
.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.
...@@ -6,4 +6,5 @@ ...@@ -6,4 +6,5 @@
%span.cgray %span.cgray
added #{time_ago_with_tooltip(key.created_at)} added #{time_ago_with_tooltip(key.created_at)}
= link_to 'Remove', profile_key_path(key), 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', profile_key_path(key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
.panel-heading .panel-heading
SSH Keys (#{@keys.count}) SSH Keys (#{@keys.count})
%ul.well-list#keys-table %ul.well-list#keys-table
= render @keys = render partial: "key", collection: @keys
- if @keys.blank? - if @keys.blank?
%li %li
.nothing-here-block There are no SSH keys with access to your account. .nothing-here-block There are no SSH keys with access to your account.
......
...@@ -19,4 +19,5 @@ ...@@ -19,4 +19,5 @@
= @key.key = @key.key
.pull-right .pull-right
= link_to 'Remove', profile_key_path(@key), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key" - unless @key.is_a? LDAPKey
= link_to 'Remove', profile_key_path(@key), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
= link_to project_team_index_path(@project), class: "team-tab tab" do = link_to project_team_index_path(@project), class: "team-tab tab" do
%i.fa.fa-users %i.fa.fa-users
Members Members
= nav_link(controller: :group_links) do
= link_to project_group_links_path(@project) do
%i.icon-share
Groups
= nav_link(controller: :deploy_keys) do = nav_link(controller: :deploy_keys) do
= link_to project_deploy_keys_path(@project) do = link_to project_deploy_keys_path(@project) do
%i.fa.fa-key %i.fa.fa-key
...@@ -15,6 +19,10 @@ ...@@ -15,6 +19,10 @@
= link_to project_hooks_path(@project) do = link_to project_hooks_path(@project) do
%i.fa.fa-link %i.fa.fa-link
Web Hooks Web Hooks
= nav_link(controller: :git_hooks) do
= link_to project_git_hooks_path(@project) do
%i.icon-upload
Git Hooks
= nav_link(controller: :services) do = nav_link(controller: :services) do
= link_to project_services_path(@project) do = link_to project_services_path(@project) do
%i.fa.fa-cogs %i.fa.fa-cogs
......
...@@ -66,6 +66,13 @@ ...@@ -66,6 +66,13 @@
= f.check_box :merge_requests_enabled = f.check_box :merge_requests_enabled
%span.descr Submit changes to be merged upstream. %span.descr Submit changes to be merged upstream.
.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 .form-group
= f.label :wiki_enabled, "Wiki", class: 'control-label' = f.label :wiki_enabled, "Wiki", class: 'control-label'
.col-sm-10 .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
.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 :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-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
- if @available_groups.present?
.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 :group_id, 'Group', class: 'control-label'
.col-sm-10
= select_tag :group_id, options_from_collection_for_select(@available_groups, :id, :name), class: 'select2'
.form-group
= label_tag :group_access, 'Max access level', class: 'control-label'
.col-sm-10
= select_tag :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,10 @@ ...@@ -21,6 +21,10 @@
.bs-callout .bs-callout
= @service.help = @service.help
- if @service.help.present?
.bs-callout
= @service.help
.form-group .form-group
= f.label :active, "Active", class: "control-label" = f.label :active, "Active", class: "control-label"
.col-sm-10 .col-sm-10
...@@ -43,6 +47,8 @@ ...@@ -43,6 +47,8 @@
= f.text_area name, rows: 5, class: "form-control", placeholder: placeholder = f.text_area name, rows: 5, class: "form-control", placeholder: placeholder
- elsif type == 'checkbox' - elsif type == 'checkbox'
= f.check_box name = f.check_box name
- elsif type == 'password'
= f.password_field name, class: "form-control"
- elsif type == 'select' - elsif type == 'select'
= f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
.form-group .form-group
= f.label :user_ids, "People", class: 'control-label' = f.label :user_ids, "People", class: 'control-label'
.col-sm-10 .col-sm-10
= users_select_tag(:user_ids, multiple: true) = users_select_tag(:user_ids, { multiple: true, skip_ldap: @project.group_ldap_synced? })
%p 2. Set access level for them %p 2. Set access level for them
.form-group .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)}
...@@ -14,3 +14,5 @@ ...@@ -14,3 +14,5 @@
= render "team", members: @project_members = render "team", members: @project_members
- if @group - if @group
= render "group_members" = 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
\ No newline at end of file
...@@ -70,7 +70,7 @@ production: &base ...@@ -70,7 +70,7 @@ production: &base
# This happens when the commit is pushed or merged into the default branch of a project. # 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. # 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 # 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 project features settings
default_projects_features: default_projects_features:
...@@ -183,6 +183,33 @@ production: &base ...@@ -183,6 +183,33 @@ production: &base
# #
user_filter: '' 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 # 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 # 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. # so that GitLab can remember which LDAP server a user belongs to.
...@@ -191,7 +218,6 @@ production: &base ...@@ -191,7 +218,6 @@ production: &base
# host: # host:
# .... # ....
## OmniAuth settings ## OmniAuth settings
omniauth: omniauth:
# Allow login via Twitter, Google, etc. using OmniAuth providers # Allow login via Twitter, Google, etc. using OmniAuth providers
......
...@@ -52,15 +52,17 @@ class Settings < Settingslogic ...@@ -52,15 +52,17 @@ class Settings < Settingslogic
end end
end end
# Default settings # Default settings
Settings['ldap'] ||= Settingslogic.new({}) Settings['ldap'] ||= Settingslogic.new({})
Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil? Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
Settings.ldap['sync_time'] = 3600 if Settings.ldap['sync_time'].nil?
# backwards compatibility, we only have one host # backwards compatibility, we only have one host
if Settings.ldap['enabled'] || Rails.env.test? if Settings.ldap['enabled'] || Rails.env.test?
if Settings.ldap['host'].present? if Settings.ldap['host'].present?
server = Settings.ldap.except('sync_time') server = Settings.ldap.except('sync_time')
server = Settingslogic.new(server)
server['label'] = 'LDAP'
server['provider_name'] = 'ldap' server['provider_name'] = 'ldap'
Settings.ldap['servers'] = { Settings.ldap['servers'] = {
'ldap' => server 'ldap' => server
...@@ -68,11 +70,14 @@ if Settings.ldap['enabled'] || Rails.env.test? ...@@ -68,11 +70,14 @@ if Settings.ldap['enabled'] || Rails.env.test?
end end
Settings.ldap['servers'].each do |key, server| Settings.ldap['servers'].each do |key, server|
server = Settingslogic.new(server)
server['label'] ||= 'LDAP' server['label'] ||= 'LDAP'
server['allow_username_or_email_login'] = false if server['allow_username_or_email_login'].nil? 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['active_directory'] = true if server['active_directory'].nil?
server['provider_name'] ||= "ldap#{key}".downcase server['provider_name'] ||= "ldap#{key}".downcase
server['sync_time'] = 3600 if server['sync_time'].nil?
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name']) server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
Settings.ldap['servers'][key] = server
end end
end end
...@@ -107,7 +112,7 @@ Settings.gitlab['signup_enabled'] ||= false ...@@ -107,7 +112,7 @@ Settings.gitlab['signup_enabled'] ||= false
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? 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['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['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['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10 Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil? Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil?
......
if Gitlab::LDAP::Config.enabled? if Gitlab::LDAP::Config.enabled?
module OmniAuth::Strategies module OmniAuth::Strategies
server = Gitlab.config.ldap.servers.values.first Gitlab::LDAP::Config.servers.each do |server|
klass = server['provider_class'] # do not redeclare LDAP
const_set(klass, Class.new(LDAP)) unless klass == 'LDAP' next if server['provider_name'] == 'ldap'
const_set(server['provider_class'], Class.new(LDAP))
end
end end
OmniauthCallbacksController.class_eval do OmniauthCallbacksController.class_eval do
server = Gitlab.config.ldap.servers.values.first Gitlab::LDAP::Config.servers.each do |server|
alias_method server['provider_name'], :ldap alias_method server['provider_name'], :ldap
end
end end
end end
\ No newline at end of file
...@@ -205,7 +205,7 @@ Devise.setup do |config| ...@@ -205,7 +205,7 @@ Devise.setup do |config|
# end # end
if Gitlab::LDAP::Config.enabled? 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'] if server['allow_username_or_email_login']
email_stripping_proc = ->(name) {name.gsub(/@.*$/,'')} email_stripping_proc = ->(name) {name.gsub(/@.*$/,'')}
else else
......
...@@ -34,6 +34,7 @@ Gitlab::Application.routes.draw do ...@@ -34,6 +34,7 @@ Gitlab::Application.routes.draw do
get 'help' => 'help#index' get 'help' => 'help#index'
get 'help/:category/:file' => 'help#show', as: :help_page get 'help/:category/:file' => 'help#show', as: :help_page
get 'help/:category/*file' => 'help#show'
get 'help/shortcuts' get 'help/shortcuts'
# #
...@@ -96,6 +97,7 @@ Gitlab::Application.routes.draw do ...@@ -96,6 +97,7 @@ Gitlab::Application.routes.draw do
resources :broadcast_messages, only: [:index, :create, :destroy] resources :broadcast_messages, only: [:index, :create, :destroy]
resource :logs, only: [:show] resource :logs, only: [:show]
resource :background_jobs, controller: 'background_jobs', 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 resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do
member do member do
...@@ -103,6 +105,13 @@ Gitlab::Application.routes.draw do ...@@ -103,6 +105,13 @@ Gitlab::Application.routes.draw do
end end
end end
resource :appearances, path: 'appearance' do
member do
get :preview
delete :logo
end
end
root to: "dashboard#index" root to: "dashboard#index"
end end
...@@ -162,12 +171,23 @@ Gitlab::Application.routes.draw do ...@@ -162,12 +171,23 @@ Gitlab::Application.routes.draw do
end end
scope module: :groups do 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] resources :group_members, only: [:create, :update, :destroy]
resource :avatar, only: [:destroy] resource :avatar, only: [:destroy]
resources :milestones resources :milestones
end end
end end
get 'unsubscribes/:email', to: 'unsubscribes#show', as: :unsubscribe
post 'unsubscribes/:email', to: 'unsubscribes#create'
resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create] resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords, sessions: :sessions, confirmations: :confirmations } devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords, sessions: :sessions, confirmations: :confirmations }
...@@ -287,6 +307,8 @@ Gitlab::Application.routes.draw do ...@@ -287,6 +307,8 @@ Gitlab::Application.routes.draw do
end end
end end
resources :git_hooks, constraints: {id: /\d+/}
resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
member do member do
get :test get :test
...@@ -324,6 +346,8 @@ Gitlab::Application.routes.draw do ...@@ -324,6 +346,8 @@ Gitlab::Application.routes.draw do
end end
end end
resources :group_links, only: [:index, :create, :destroy], constraints: {id: /\d+/}
resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do
member do member do
delete :delete_attachment delete :delete_attachment
......
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
Group.where.not(ldap_cn: nil).each do |group|
# Make sure we use the database column, not the model methods
ldap_cn = group.read_attribute(:ldap_cn)
ldap_access = group.read_attribute(:ldap_access)
group.ldap_group_links.where(cn: ldap_cn).first_or_create do |ldap_group_link|
ldap_group_link.group_access = ldap_access
end
end
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
...@@ -11,11 +11,20 @@ ...@@ -11,11 +11,20 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141007100818) do ActiveRecord::Schema.define(version: 20141010132608) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
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"
end
create_table "broadcast_messages", force: true do |t| create_table "broadcast_messages", force: true do |t|
t.text "message", null: false t.text "message", null: false
t.datetime "starts_at" t.datetime "starts_at"
...@@ -74,6 +83,16 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -74,6 +83,16 @@ ActiveRecord::Schema.define(version: 20141007100818) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree 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"
end
create_table "issues", force: true do |t| create_table "issues", force: true do |t|
t.string "title" t.string "title"
t.integer "assignee_id" t.integer "assignee_id"
...@@ -130,6 +149,15 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -130,6 +149,15 @@ ActiveRecord::Schema.define(version: 20141007100818) do
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree 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| create_table "members", force: true do |t|
t.integer "access_level", null: false t.integer "access_level", null: false
t.integer "source_id", null: false t.integer "source_id", null: false
...@@ -209,6 +237,8 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -209,6 +237,8 @@ ActiveRecord::Schema.define(version: 20141007100818) do
t.string "type" t.string "type"
t.string "description", default: "", null: false t.string "description", default: "", null: false
t.string "avatar" t.string "avatar"
t.string "ldap_cn"
t.integer "ldap_access"
end end
add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree
...@@ -240,6 +270,14 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -240,6 +270,14 @@ ActiveRecord::Schema.define(version: 20141007100818) do
add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree
add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", 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| create_table "projects", force: true do |t|
t.string "name" t.string "name"
t.string "path" t.string "path"
...@@ -247,21 +285,22 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -247,21 +285,22 @@ ActiveRecord::Schema.define(version: 20141007100818) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.integer "creator_id" t.integer "creator_id"
t.boolean "issues_enabled", default: true, null: false t.boolean "issues_enabled", default: true, null: false
t.boolean "wall_enabled", default: true, null: false t.boolean "wall_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false t.boolean "wiki_enabled", default: true, null: false
t.integer "namespace_id" 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.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.datetime "last_activity_at"
t.string "import_url" t.string "import_url"
t.integer "visibility_level", default: 0, null: false t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false t.boolean "archived", default: false, null: false
t.string "import_status" t.string "import_status"
t.float "repository_size", default: 0.0 t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false t.integer "star_count", default: 0, null: false
t.text "merge_requests_template"
end end
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
...@@ -327,12 +366,12 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -327,12 +366,12 @@ ActiveRecord::Schema.define(version: 20141007100818) do
end end
create_table "users", force: true do |t| create_table "users", force: true do |t|
t.string "email", default: "", null: false t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false t.string "encrypted_password", default: "", null: false
t.string "reset_password_token" t.string "reset_password_token"
t.datetime "reset_password_sent_at" t.datetime "reset_password_sent_at"
t.datetime "remember_created_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 "current_sign_in_at"
t.datetime "last_sign_in_at" t.datetime "last_sign_in_at"
t.string "current_sign_in_ip" t.string "current_sign_in_ip"
...@@ -340,24 +379,24 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -340,24 +379,24 @@ ActiveRecord::Schema.define(version: 20141007100818) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "name" t.string "name"
t.boolean "admin", default: false, null: false t.boolean "admin", default: false, null: false
t.integer "projects_limit", default: 10 t.integer "projects_limit", default: 10
t.string "skype", default: "", null: false t.string "skype", default: "", null: false
t.string "linkedin", default: "", null: false t.string "linkedin", default: "", null: false
t.string "twitter", default: "", null: false t.string "twitter", default: "", null: false
t.string "authentication_token" t.string "authentication_token"
t.integer "theme_id", default: 1, null: false t.integer "theme_id", default: 1, null: false
t.string "bio" t.string "bio"
t.integer "failed_attempts", default: 0 t.integer "failed_attempts", default: 0
t.datetime "locked_at" t.datetime "locked_at"
t.string "extern_uid" t.string "extern_uid"
t.string "provider" t.string "provider"
t.string "username" t.string "username"
t.boolean "can_create_group", default: true, null: false t.boolean "can_create_group", default: true, null: false
t.boolean "can_create_team", default: true, null: false t.boolean "can_create_team", default: true, null: false
t.string "state" t.string "state"
t.integer "color_scheme_id", default: 1, null: false t.integer "color_scheme_id", default: 1, null: false
t.integer "notification_level", default: 1, null: false t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at" t.datetime "password_expires_at"
t.integer "created_by_id" t.integer "created_by_id"
t.string "avatar" t.string "avatar"
...@@ -365,9 +404,10 @@ ActiveRecord::Schema.define(version: 20141007100818) do ...@@ -365,9 +404,10 @@ ActiveRecord::Schema.define(version: 20141007100818) do
t.datetime "confirmed_at" t.datetime "confirmed_at"
t.datetime "confirmation_sent_at" t.datetime "confirmation_sent_at"
t.string "unconfirmed_email" t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at" t.datetime "last_credential_check_at"
t.datetime "admin_email_unsubscribed_at"
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
- [System hooks](system_hooks/system_hooks.md) Let GitLab notify you when certain management tasks need to be carried out. - [System hooks](system_hooks/system_hooks.md) Let GitLab notify you when certain management tasks need to be carried out.
- [Security](security/README.md) Learn what you can do to further secure your GitLab instance. - [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. - [Update](update/README.md) Update guides to upgrade your installation.
- [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. - [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. - [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
- [Libravatar](customization/libravatar.md) Use Libravatar for user avatars. - [Libravatar](customization/libravatar.md) Use Libravatar for user avatars.
......
# 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
...@@ -165,9 +165,11 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ...@@ -165,9 +165,11 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
### Clone the Source ### Clone the Source
# Clone GitLab repository # Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-4-stable gitlab
sudo -u git -H git clone https://gitlab.com/subscribers/gitlab-ee.git -b 7-4-stable-ee gitlab
**Note:** You can change `7-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `7-4-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It ### 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.
[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.
## GitLab 7.3 Enterprise Edition
- 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.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.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.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.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
## Previous versions
### Ubuntu 14.04 64-bit
- 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.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.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.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.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,13 +4,13 @@ GitLab integrates with multiple third-party services to allow external issue tra ...@@ -4,13 +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. 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 - [LDAP](ldap.md) Set up sign in via LDAP
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth. - [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 - [Slack](slack.md) Integrate with the Slack chat service
Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html).
## Project services ## Project services
Integration with services such as Campfire, Flowdock, Gemnasium, HipChat, PivotalTracker and Slack are available in the from of a Project Service. Integration with services such as Campfire, Flowdock, Gemnasium, HipChat, PivotalTracker and Slack are available in the from of a Project Service.
......
...@@ -9,5 +9,3 @@ GitLab has a great issue tracker but you can also use an external issue tracker ...@@ -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) ![jira screenshot](jira-integration-points.png)
You can configure the integration in the gitlab.yml configuration file. 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)
# GitLab LDAP integration # GitLab LDAP integration
GitLab can be configured to allow your users to sign with their LDAP credentials to integrate with e.g. Active Directory. 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. 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.
...@@ -18,6 +19,98 @@ GitLab recognizes the following LDAP attributes as email addresses: `mail`, `ema ...@@ -18,6 +19,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`. 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 ## 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. 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.
...@@ -42,3 +135,43 @@ Tip: if you want to limit access to the nested members of an Active Directory gr ...@@ -42,3 +135,43 @@ 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. 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.
# 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
```
# 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
```
Depending on the installation method and your GitLab version, there are multiple update guides. Choose one that fits your needs. 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 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/). - [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/).
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
- [Project Features](project_features.md) - [Project Features](project_features.md)
- [Authorization for merge requests](authorization_for_merge_requests.md) - [Authorization for merge requests](authorization_for_merge_requests.md)
- [Groups](groups.md) - [Groups](groups.md)
- [Share projects with other groups](share_projects_with_other_groups.md)
- [Labels](labels.md) - [Labels](labels.md)
- [GitLab Flow](gitlab_flow.md) - [GitLab Flow](gitlab_flow.md)
- [Notifications](notifications.md) - [Notifications](notifications.md)
......
# 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
@admin
Feature: Admin email
Background:
Given I sign in as an admin
And there are groups with projects
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 ...@@ -21,6 +21,11 @@ Feature: Admin Groups
When I select user "John Doe" from user list as "Reporter" 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" 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 @javascript
Scenario: Remove user from group Scenario: Remove user from group
Given we have user "John Doe" in group Given we have user "John Doe" in group
......
...@@ -55,6 +55,11 @@ Feature: Groups ...@@ -55,6 +55,11 @@ Feature: Groups
Then I should not see group "Owned" avatar Then I should not see group "Owned" avatar
And I should not see the "Remove avatar" button And I should not see the "Remove avatar" button
Scenario: Add new LDAP synchronization
When I visit Group "Owned" LDAP settings page
And I add a new LDAP synchronization
Then I see a new LDAP synchronization listed
# Leave # Leave
@javascript @javascript
......
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"
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 ...@@ -148,6 +148,11 @@ Feature: Project Merge Requests
Then I should see a comment like "Line is wrong" in the second file 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 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 @javascript
Scenario: I unfold diff Scenario: I unfold diff
Given project "Shop" have "Bug NS-05" open merge request with diffs inside Given project "Shop" have "Bug NS-05" open merge request with diffs inside
......
...@@ -25,6 +25,13 @@ Feature: Project ...@@ -25,6 +25,13 @@ Feature: Project
And change project path settings And change project path settings
Then I should see project with new 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 Scenario: I should see project readme and version
When I visit project "Shop" page When I visit project "Shop" page
And I should see project "Shop" version And I should see project "Shop" version
......
...@@ -54,3 +54,9 @@ Feature: Project Services ...@@ -54,3 +54,9 @@ Feature: Project Services
And I click email on push service link And I click email on push service link
And I fill email on push settings And I fill email on push settings
Then I should see email on push service settings saved 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
...@@ -35,3 +35,8 @@ Feature: Project Team Management ...@@ -35,3 +35,8 @@ Feature: Project Team Management
And I click link "Import team from another project" And I click link "Import team from another project"
And I submit "Website" project for import team And I submit "Website" project for import team
Then I should see "Mike" in team list as "Reporter" 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 should see a logo' do
page.should have_xpath('//img[@src="/uploads/appearance/logo/1/gitlab_logo.png"]')
end
step 'I remove the logo' do
click_link 'Remove logo'
end
step 'I should see logo removed' do
page.should_not have_xpath('//img[@src="/uploads/appearance/logo/1/gitlab_logo.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
select @selected_group.name, from: :recipients
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 ...@@ -57,6 +57,21 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
end end
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 step 'we have user "John Doe" in group' do
current_group.add_user(user_john, Gitlab::Access::REPORTER) current_group.add_user(user_john, Gitlab::Access::REPORTER)
end end
...@@ -79,6 +94,10 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps ...@@ -79,6 +94,10 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
@group ||= Group.first @group ||= Group.first
end end
def shared_project
@shared_project ||= create(:empty_project)
end
def user_john def user_john
@user_john ||= User.find_by(name: "John Doe") @user_john ||= User.find_by(name: "John Doe")
end end
......
...@@ -8,7 +8,7 @@ class Spinach::Features::DashboardHelp < Spinach::FeatureSteps ...@@ -8,7 +8,7 @@ class Spinach::Features::DashboardHelp < Spinach::FeatureSteps
end end
step 'I visit the "Rake Tasks" help page' do step 'I visit the "Rake Tasks" help page' do
visit help_page_path("raketasks", "maintenance") visit help_page_path("raketasks", "maintenance.md")
end end
step 'I should see "Rake Tasks" page markdown rendered' do step 'I should see "Rake Tasks" page markdown rendered' do
......
...@@ -92,6 +92,17 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -92,6 +92,17 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
page.should have_content "Currently you are only seeing events from the" page.should have_content "Currently you are only seeing events from the"
end 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 step 'I change group "Owned" name to "new-name"' do
fill_in 'group_name', with: 'new-name' fill_in 'group_name', with: 'new-name'
click_button "Save group" click_button "Save group"
...@@ -274,4 +285,18 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -274,4 +285,18 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
author: current_user, author: current_user,
milestone: milestone2_project3 milestone: milestone2_project3
end 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('my-group-cn as Developer')
end
end end
...@@ -255,6 +255,16 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -255,6 +255,16 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end end
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 step 'I unfold diff' do
first('.js-unfold').click first('.js-unfold').click
end end
......
...@@ -14,6 +14,8 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -14,6 +14,8 @@ class Spinach::Features::Project < Spinach::FeatureSteps
step 'I should see project with new settings' do step 'I should see project with new settings' do
find_field('project_name').value.should == 'NewName' find_field('project_name').value.should == 'NewName'
find('#project_issues_enabled').should_not be_checked
find('#project_merge_requests_enabled').should be_checked
end end
step 'change project path settings' do step 'change project path settings' do
...@@ -25,6 +27,20 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -25,6 +27,20 @@ class Spinach::Features::Project < Spinach::FeatureSteps
project.path.should == "new-path" project.path.should == "new-path"
end 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 step 'I should see project "Shop" version' do
within '.project-side' do within '.project-side' do
page.should have_content "Version: 6.7.0.pre" page.should have_content "Version: 6.7.0.pre"
......
class Spinach::Features::ProjectGroupLinks < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
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
select "Master", from: 'group_access'
select "Market", from: 'group_id'
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')
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
...@@ -137,4 +137,23 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps ...@@ -137,4 +137,23 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
find_field('Priority').find('option[selected]').value.should == '1' find_field('Priority').find('option[selected]').value.should == '1'
find_field('Sound').find('option[selected]').value.should == 'bike' find_field('Sound').find('option[selected]').value.should == 'bike'
end 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
end end
...@@ -104,4 +104,23 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps ...@@ -104,4 +104,23 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
click_link('Remove user from team') click_link('Remove user from team')
end end
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 end
...@@ -8,5 +8,12 @@ module SharedAdmin ...@@ -8,5 +8,12 @@ module SharedAdmin
step 'system has users' do step 'system has users' do
2.times { create(:user) } 2.times { create(:user) }
end end
And 'there are groups with projects' do
2.times do
group = create :group
create :project, group: group
end
end
end end
...@@ -6,6 +6,10 @@ module SharedPaths ...@@ -6,6 +6,10 @@ module SharedPaths
visit new_project_path visit new_project_path
end end
step 'I visit login page' do
visit new_user_session_path
end
# ---------------------------------------- # ----------------------------------------
# User # User
# ---------------------------------------- # ----------------------------------------
...@@ -38,6 +42,10 @@ module SharedPaths ...@@ -38,6 +42,10 @@ module SharedPaths
visit edit_group_path(Group.find_by(name:"Owned")) visit edit_group_path(Group.find_by(name:"Owned"))
end 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 step 'I visit group "Guest" page' do
visit group_path(Group.find_by(name:"Guest")) visit group_path(Group.find_by(name:"Guest"))
end end
...@@ -158,10 +166,17 @@ module SharedPaths ...@@ -158,10 +166,17 @@ module SharedPaths
visit admin_groups_path visit admin_groups_path
end end
step 'I visit admin appearance page' do
visit admin_appearances_path
end
step 'I visit admin teams page' do step 'I visit admin teams page' do
visit admin_teams_path visit admin_teams_path
end end
step 'I visit admin email page' do
visit admin_email_path
end
# ---------------------------------------- # ----------------------------------------
# Generic Project # Generic Project
# ---------------------------------------- # ----------------------------------------
......
...@@ -10,7 +10,7 @@ module SharedProject ...@@ -10,7 +10,7 @@ module SharedProject
# Create a specific project called "Shop" # Create a specific project called "Shop"
step 'I own project "Shop"' do step 'I own project "Shop"' do
@project = Project.find_by(name: "Shop") @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] @project.team << [@user, :master]
end end
......
...@@ -7,4 +7,21 @@ class Spinach::Features::User < Spinach::FeatureSteps ...@@ -7,4 +7,21 @@ class Spinach::Features::User < Spinach::FeatureSteps
step 'I should see user "John Doe" page' do step 'I should see user "John Doe" page' do
expect(title).to match(/^\s*John Doe/) expect(title).to match(/^\s*John Doe/)
end 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 end
...@@ -67,3 +67,10 @@ Feature: User ...@@ -67,3 +67,10 @@ Feature: User
And I should see project "Enterprise" And I should see project "Enterprise"
And I should not see project "Internal" And I should not see project "Internal"
And I should not see project "Community" 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
...@@ -41,6 +41,7 @@ module API ...@@ -41,6 +41,7 @@ module API
mount ProjectMembers mount ProjectMembers
mount DeployKeys mount DeployKeys
mount ProjectHooks mount ProjectHooks
mount Ldap
mount Services mount Services
mount Files mount Files
mount Commits mount Commits
......
...@@ -60,7 +60,12 @@ module API ...@@ -60,7 +60,12 @@ module API
end end
class Group < Grape::Entity 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 end
class GroupDetail < Group class GroupDetail < Group
...@@ -166,6 +171,14 @@ module API ...@@ -166,6 +171,14 @@ module API
expose :created_at expose :created_at
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 class Namespace < Grape::Entity
expose :id, :path, :kind expose :id, :path, :kind
end end
......
...@@ -44,11 +44,19 @@ module API ...@@ -44,11 +44,19 @@ module API
authenticated_as_admin! authenticated_as_admin!
required_attributes! [:name, :path] required_attributes! [:name, :path]
attrs = attributes_for_keys [:name, :path] group_attrs = attributes_for_keys [:name, :path]
@group = Group.new(attrs) @group = Group.new(group_attrs)
@group.owner = current_user @group.owner = current_user
if @group.save 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 present @group, with: Entities::Group
else else
not_found! not_found!
......
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
...@@ -215,6 +215,30 @@ module API ...@@ -215,6 +215,30 @@ module API
user_project.forked_project_link.destroy user_project.forked_project_link.destroy
end end
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 # search for projects current_user has access to
# #
# Parameters: # Parameters:
......
...@@ -9,8 +9,11 @@ module API ...@@ -9,8 +9,11 @@ module API
# Example Request: # Example Request:
# GET /users # GET /users
get do get do
skip_ldap = params[:skip_ldap].present? && params[:skip_ldap] == 'true'
@users = User.all @users = User.all
@users = @users.active if params[:active].present? @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 = @users.search(params[:search]) if params[:search].present?
@users = paginate @users @users = paginate @users
......
...@@ -79,7 +79,8 @@ module Gitlab ...@@ -79,7 +79,8 @@ module Gitlab
:push_code :push_code
end end
user.can?(action, project) user.can?(action, project) &&
pass_git_hooks?(user, project, ref, oldrev, newrev)
end end
def forced_push?(project, oldrev, newrev) def forced_push?(project, oldrev, newrev)
...@@ -93,6 +94,33 @@ module Gitlab ...@@ -93,6 +94,33 @@ module Gitlab
end end
end end
def pass_git_hooks?(user, project, ref, oldrev, newrev)
return true unless project.git_hook
return 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 false
end
end
# Check commit messages unless its branch removal
if git_hook.commit_message_regex.present? && newrev !~ /00000000/
commits = project.repository.commits_between(oldrev, newrev)
commits.each do |commit|
unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex)
return false
end
end
end
true
end
private private
def user_allowed?(user) def user_allowed?(user)
......
# LDAP authorization model # LDAP authorization model
# #
# * Check if we are allowed access (not blocked) # * Check if we are allowed access (not blocked)
# * Update authorizations and associations
# #
module Gitlab module Gitlab
module LDAP module LDAP
class Access class Access
attr_reader :adapter, :provider, :user attr_reader :adapter, :provider, :user, :ldap_user
def self.open(user, &block) def self.open(user, &block)
Gitlab::LDAP::Adapter.open(user.provider) do |adapter| Gitlab::LDAP::Adapter.open(user.provider) do |adapter|
...@@ -16,6 +17,8 @@ module Gitlab ...@@ -16,6 +17,8 @@ module Gitlab
def self.allowed?(user) def self.allowed?(user)
self.open(user) do |access| self.open(user) do |access|
if access.allowed? if access.allowed?
access.update_permissions
access.update_email
user.last_credential_check_at = Time.now user.last_credential_check_at = Time.now
user.save user.save
true true
...@@ -49,6 +52,133 @@ module Gitlab ...@@ -49,6 +52,133 @@ module Gitlab
def ldap_config def ldap_config
Gitlab::LDAP::Config.new(provider) Gitlab::LDAP::Config.new(provider)
end end
def ldap_user
@ldap_user ||= Gitlab::LDAP::Person.find_by_dn(user.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.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 end
end end
...@@ -22,6 +22,33 @@ module Gitlab ...@@ -22,6 +22,33 @@ module Gitlab
Gitlab::LDAP::Config.new(provider) Gitlab::LDAP::Config.new(provider)
end end
<<<<<<< HEAD
=======
# 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
>>>>>>> 7-4-stable-ee
def users(field, value, limit = nil) def users(field, value, limit = nil)
if field.to_sym == :dn if field.to_sym == :dn
options = { options = {
......
...@@ -57,6 +57,10 @@ module Gitlab ...@@ -57,6 +57,10 @@ module Gitlab
options['uid'] options['uid']
end end
def label
options['label']
end
def sync_ssh_keys? def sync_ssh_keys?
sync_ssh_keys.present? sync_ssh_keys.present?
end end
......
module Gitlab
module LDAP
class Group
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 Gitlab.config.ldap.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 ...@@ -46,6 +46,14 @@ module Gitlab
entry.dn entry.dn
end 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 private
def entry def entry
......
...@@ -23,11 +23,17 @@ module Gitlab ...@@ -23,11 +23,17 @@ module Gitlab
end end
def issues_for(project = nil) def issues_for(project = nil)
issues.map do |entry| if project && project.jira_tracker?
if should_lookup?(project, entry[:project]) issues.uniq.map do |jira_identifier|
entry[:project].issues.where(iid: entry[:id]).first JiraIssue.new(jira_identifier[:id])
end 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 end
def merge_requests_for(project = nil) def merge_requests_for(project = nil)
......
...@@ -43,17 +43,17 @@ module Gitlab ...@@ -43,17 +43,17 @@ module Gitlab
end end
def latest_version_raw 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 = remote_tags.split("\n").grep(/tags\/v#{current_version.major}/)
git_tags = git_tags.select { |version| version =~ /v\d\.\d\.\d\Z/ } git_tags = git_tags.select { |version| version =~ /v\d\.\d\.\d-ee\Z/ }
last_tag = git_tags.last.match(/v\d\.\d\.\d/).to_s last_tag = git_tags.last.match(/v\d\.\d\.\d-ee/).to_s
end end
def update_commands def update_commands
{ {
"Stash changed files" => %W(git stash), "Stash changed files" => %W(git stash),
"Get latest code" => %W(git fetch), "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), "Install gems" => %W(bundle),
"Migrate DB" => %W(bundle exec rake db:migrate), "Migrate DB" => %W(bundle exec rake db:migrate),
"Recompile assets" => %W(bundle exec rake assets:clean assets:precompile), "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
...@@ -182,4 +182,11 @@ FactoryGirl.define do ...@@ -182,4 +182,11 @@ FactoryGirl.define do
deploy_key deploy_key
project project
end end
factory :ldap_group_link do
cn 'group1'
group_access Gitlab::Access::GUEST
provider 'ldapmain'
group
end
end end
# 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' ...@@ -3,11 +3,16 @@ require 'spec_helper'
describe ProjectsFinder do describe ProjectsFinder do
let(:user) { create :user } let(:user) { create :user }
let(:group) { create :group } let(:group) { create :group }
let(:group2) { create :group }
let(:project1) { create(:empty_project, :public, group: group) } let(:project1) { create(:empty_project, :public, group: group) }
let(:project2) { create(:empty_project, :internal, group: group) } let(:project2) { create(:empty_project, :internal, group: group) }
let(:project3) { create(:empty_project, :private, group: group) } let(:project3) { create(:empty_project, :private, group: group) }
let(:project4) { 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 context 'non authenticated' do
subject { ProjectsFinder.new.execute(nil, group: group) } subject { ProjectsFinder.new.execute(nil, group: group) }
...@@ -48,4 +53,18 @@ describe ProjectsFinder do ...@@ -48,4 +53,18 @@ describe ProjectsFinder do
it { should include(project3) } it { should include(project3) }
it { should include(project4) } it { should include(project4) }
end 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 end
...@@ -336,6 +336,52 @@ describe GitlabMarkdownHelper do ...@@ -336,6 +336,52 @@ describe GitlabMarkdownHelper do
end end
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 describe "referencing a merge request" do
let(:object) { merge_request } let(:object) { merge_request }
let(:reference) { "!#{merge_request.iid}" } 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 ...@@ -8,5 +8,13 @@ describe MergeRequestsHelper do
end end
it { should eq('#1, #2, and #3') } 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
end end
...@@ -28,7 +28,7 @@ describe Gitlab::LDAP::Access do ...@@ -28,7 +28,7 @@ describe Gitlab::LDAP::Access do
it { should be_true } it { should be_true }
end end
context 'without ActiveDirectory enabled' do context 'withoud ActiveDirectory enabled' do
before do before do
Gitlab::LDAP::Config.stub(enabled?: true) Gitlab::LDAP::Config.stub(enabled?: true)
Gitlab::LDAP::Config.any_instance.stub(active_directory: false) Gitlab::LDAP::Config.any_instance.stub(active_directory: false)
...@@ -38,4 +38,298 @@ describe Gitlab::LDAP::Access do ...@@ -38,4 +38,298 @@ describe Gitlab::LDAP::Access do
end end
end 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.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.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=#{Gitlab.config.ldap['admin_group']},ou=groups,dc=bar,dc=com
cn: #{Gitlab.config.ldap['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.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 ...@@ -74,6 +74,15 @@ describe Gitlab::ReferenceExtractor do
subject.issues_for(project).should == [@i0, @i1] subject.issues_for(project).should == [@i0, @i1]
end 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 it 'accesses valid merge requests' do
@m0 = create(:merge_request, source_project: project, target_project: project, source_branch: 'aaa') @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') @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'bbb')
......
...@@ -17,8 +17,8 @@ describe Gitlab::Upgrader do ...@@ -17,8 +17,8 @@ describe Gitlab::Upgrader do
describe 'latest_version_raw' do describe 'latest_version_raw' do
it 'should be latest version for GitLab 5' do it 'should be latest version for GitLab 5' do
upgrader.stub(current_version_raw: "5.3.0") upgrader.stub(current_version_raw: "6.3.0-ee")
upgrader.latest_version_raw.should == "v5.4.2" upgrader.latest_version_raw.should match(/v6\.\d\.\d-ee/)
end end
end end
end end
...@@ -627,4 +627,30 @@ describe Notify do ...@@ -627,4 +627,30 @@ describe Notify do
should have_body_text /#{diff_path}/ should have_body_text /#{diff_path}/
end end
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 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
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 ...@@ -112,6 +112,17 @@ describe MergeRequest do
subject.closes_issues.should include(issue2) subject.closes_issues.should include(issue2)
end 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 end
it_behaves_like 'an editable mentionable' do 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 ...@@ -66,5 +66,23 @@ describe ProjectTeam do
it { project.team.member?(guest).should be_true } it { project.team.member?(guest).should be_true }
end end
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
...@@ -12,6 +12,7 @@ describe API::API, api: true do ...@@ -12,6 +12,7 @@ describe API::API, api: true do
before do before do
group1.add_owner(user1) group1.add_owner(user1)
group2.add_owner(user2) group2.add_owner(user2)
group1.ldap_group_links.create cn: 'ldap-group', group_access: Gitlab::Access::MASTER
end end
describe "GET /groups" do describe "GET /groups" do
...@@ -29,6 +30,12 @@ describe API::API, api: true do ...@@ -29,6 +30,12 @@ describe API::API, api: true do
json_response.should be_an Array json_response.should be_an Array
json_response.length.should == 1 json_response.length.should == 1
json_response.first['name'].should == group1.name 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
end end
...@@ -103,6 +110,13 @@ describe API::API, api: true do ...@@ -103,6 +110,13 @@ describe API::API, api: true do
post api("/groups", admin), { name: 'test' } post api("/groups", admin), { name: 'test' }
response.status.should == 400 response.status.should == 400
end 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
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
...@@ -589,6 +589,37 @@ describe API::API, api: true do ...@@ -589,6 +589,37 @@ describe API::API, api: true do
end end
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 describe "GET /projects/search/:query" do
let!(:query) { 'query'} let!(:query) { 'query'}
let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) } let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) }
......
...@@ -119,3 +119,12 @@ describe Admin::DashboardController, "routing" do ...@@ -119,3 +119,12 @@ describe Admin::DashboardController, "routing" do
end end
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(:user, extern_uid: 'john', provider: 'ldap', last_credential_check_at: Time.now) }
let(:ldap_user_2) { create(: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