Commit f2190750 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge remote-tracking branch 'ee-com/master' into js-reduce-ce-ee-conflicts

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parents 87c18617 300898f0
...@@ -7,5 +7,8 @@ export default () => { ...@@ -7,5 +7,8 @@ export default () => {
Cookies.set(el.name, el.value, { Cookies.set(el.name, el.value, {
expires: 365 * 10, expires: 365 * 10,
}); });
document.body.scrollTop = 0;
window.location.reload();
}); });
}; };
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, prefer-arrow-callback, consistent-return, object-shorthand, no-unused-vars, one-var, one-var-declaration-per-line, no-else-return, comma-dangle, max-len */ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, prefer-arrow-callback, consistent-return, object-shorthand, no-unused-vars, one-var, one-var-declaration-per-line, no-else-return, comma-dangle, max-len */
/* global Mousetrap */ /* global Mousetrap */
/* global findFileURL */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import findAndFollowLink from './shortcuts_dashboard_navigation'; import findAndFollowLink from './shortcuts_dashboard_navigation';
...@@ -20,6 +19,7 @@ import findAndFollowLink from './shortcuts_dashboard_navigation'; ...@@ -20,6 +19,7 @@ import findAndFollowLink from './shortcuts_dashboard_navigation';
const $globalDropdownMenu = $('.global-dropdown-menu'); const $globalDropdownMenu = $('.global-dropdown-menu');
const $globalDropdownToggle = $('.global-dropdown-toggle'); const $globalDropdownToggle = $('.global-dropdown-toggle');
const findFileURL = document.body.dataset.findFile;
$('.global-dropdown').on('hide.bs.dropdown', () => { $('.global-dropdown').on('hide.bs.dropdown', () => {
$globalDropdownMenu.removeClass('shortcuts'); $globalDropdownMenu.removeClass('shortcuts');
......
...@@ -187,11 +187,12 @@ ...@@ -187,11 +187,12 @@
@include set-invisible; @include set-invisible;
display: block; display: block;
position: absolute; position: absolute;
width: 100%; width: auto;
top: 100%; top: 100%;
left: 0; left: 0;
z-index: 9; z-index: 9;
min-width: 240px; min-width: 240px;
max-width: 500px;
margin-top: 2px; margin-top: 2px;
margin-bottom: 0; margin-bottom: 0;
font-size: 14px; font-size: 14px;
......
...@@ -244,6 +244,10 @@ ...@@ -244,6 +244,10 @@
} }
} }
.block-last {
padding: 16px 0;
}
.trigger-build-variable { .trigger-build-variable {
color: $code-color; color: $code-color;
} }
......
...@@ -114,6 +114,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -114,6 +114,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:html_emails_enabled, :html_emails_enabled,
:koding_enabled, :koding_enabled,
:koding_url, :koding_url,
:password_authentication_enabled,
:plantuml_enabled, :plantuml_enabled,
:plantuml_url, :plantuml_url,
:max_artifacts_size, :max_artifacts_size,
...@@ -136,7 +137,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -136,7 +137,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:require_two_factor_authentication, :require_two_factor_authentication,
:session_expire_delay, :session_expire_delay,
:sign_in_text, :sign_in_text,
:signin_enabled,
:signup_enabled, :signup_enabled,
:sentry_dsn, :sentry_dsn,
:sentry_enabled, :sentry_enabled,
......
...@@ -174,7 +174,7 @@ class ApplicationController < ActionController::Base ...@@ -174,7 +174,7 @@ class ApplicationController < ActionController::Base
end end
def check_password_expiration def check_password_expiration
if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && current_user.allow_password_authentication?
return redirect_to new_profile_password_path return redirect_to new_profile_password_path
end end
end end
......
class PasswordsController < Devise::PasswordsController class PasswordsController < Devise::PasswordsController
include Gitlab::CurrentSettings
before_action :resource_from_email, only: [:create] before_action :resource_from_email, only: [:create]
before_action :prevent_ldap_reset, only: [:create] before_action :check_password_authentication_available, only: [:create]
before_action :throttle_reset, only: [:create] before_action :throttle_reset, only: [:create]
def edit def edit
...@@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController ...@@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController
def update def update
super do |resource| super do |resource|
if resource.valid? && resource.require_password? if resource.valid? && resource.require_password_creation?
resource.update_attribute(:password_automatically_set, false) resource.update_attribute(:password_automatically_set, false)
end end
end end
...@@ -38,11 +40,11 @@ class PasswordsController < Devise::PasswordsController ...@@ -38,11 +40,11 @@ class PasswordsController < Devise::PasswordsController
self.resource = resource_class.find_by_email(email) self.resource = resource_class.find_by_email(email)
end end
def prevent_ldap_reset def check_password_authentication_available
return unless resource && resource.ldap_user? return if current_application_settings.password_authentication_enabled? && (resource.nil? || resource.allow_password_authentication?)
redirect_to after_sending_reset_password_instructions_path_for(resource_name), redirect_to after_sending_reset_password_instructions_path_for(resource_name),
alert: "Cannot reset password for LDAP user." alert: "Password authentication is unavailable."
end end
def throttle_reset def throttle_reset
......
...@@ -77,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController ...@@ -77,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
end end
def authorize_change_password! def authorize_change_password!
return render_404 if @user.ldap_user? render_404 unless @user.allow_password_authentication?
end end
def user_params def user_params
......
...@@ -230,7 +230,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -230,7 +230,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue def issue
return @issue if defined?(@issue) return @issue if defined?(@issue)
# The Sortable default scope causes performance issues when used with find_by # The Sortable default scope causes performance issues when used with find_by
@noteable = @issue ||= @project.issues.find_by!(iid: params[:id]) @noteable = @issue ||= @project.issues.where(iid: params[:id]).reorder(nil).take!
return render_404 unless can?(current_user, :read_issue, @issue) return render_404 unless can?(current_user, :read_issue, @issue)
......
...@@ -109,7 +109,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap ...@@ -109,7 +109,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
@target_project = @merge_request.target_project @target_project = @merge_request.target_project
@source_project = @merge_request.source_project @source_project = @merge_request.source_project
@commits = @merge_request.compare_commits.reverse @commits = @merge_request.commits
@commit = @merge_request.diff_head_commit @commit = @merge_request.diff_head_commit
@note_counts = Note.where(commit_id: @commits.map(&:id)) @note_counts = Note.where(commit_id: @commits.map(&:id))
......
...@@ -69,8 +69,7 @@ class Projects::TriggersController < Projects::ApplicationController ...@@ -69,8 +69,7 @@ class Projects::TriggersController < Projects::ApplicationController
def trigger_params def trigger_params
params.require(:trigger).permit( params.require(:trigger).permit(
:description, :description
trigger_schedule_attributes: [:id, :active, :cron, :cron_timezone, :ref]
) )
end end
end end
...@@ -59,7 +59,7 @@ class SessionsController < Devise::SessionsController ...@@ -59,7 +59,7 @@ class SessionsController < Devise::SessionsController
user = User.admins.last user = User.admins.last
return unless user && user.require_password? return unless user && user.require_password_creation?
Users::UpdateService.new(user).execute do |user| Users::UpdateService.new(user).execute do |user|
@token = user.generate_reset_token @token = user.generate_reset_token
......
module ApplicationSettingsHelper module ApplicationSettingsHelper
delegate :gravatar_enabled?, delegate :gravatar_enabled?,
:signup_enabled?, :signup_enabled?,
:signin_enabled?, :password_authentication_enabled?,
:akismet_enabled?, :akismet_enabled?,
:koding_enabled?, :koding_enabled?,
to: :current_application_settings to: :current_application_settings
......
...@@ -50,12 +50,12 @@ module ButtonHelper ...@@ -50,12 +50,12 @@ module ButtonHelper
def http_clone_button(project, placement = 'right', append_link: true) def http_clone_button(project, placement = 'right', append_link: true)
klass = 'http-selector' klass = 'http-selector'
klass << ' has-tooltip' if current_user.try(:require_password?) || current_user.try(:require_personal_access_token?) klass << ' has-tooltip' if current_user.try(:require_password_creation?) || current_user.try(:require_personal_access_token_creation_for_git_auth?)
protocol = gitlab_config.protocol.upcase protocol = gitlab_config.protocol.upcase
tooltip_title = tooltip_title =
if current_user.try(:require_password?) if current_user.try(:require_password_creation?)
_("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol } _("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol }
else else
_("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol } _("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol }
......
...@@ -214,11 +214,11 @@ module ProjectsHelper ...@@ -214,11 +214,11 @@ module ProjectsHelper
def show_no_password_message? def show_no_password_message?
cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && cookies[:hide_no_password_message].blank? && !current_user.hide_no_password &&
( current_user.require_password? || current_user.require_personal_access_token? ) ( current_user.require_password_creation? || current_user.require_personal_access_token_creation_for_git_auth? )
end end
def link_to_set_password def link_to_set_password
if current_user.require_password? if current_user.require_password_creation?
link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path
else else
link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path
...@@ -551,4 +551,12 @@ module ProjectsHelper ...@@ -551,4 +551,12 @@ module ProjectsHelper
current_application_settings.restricted_visibility_levels || [] current_application_settings.restricted_visibility_levels || []
end end
def find_file_path
return unless @project && !@project.empty_repo?
ref = @ref || @project.repository.root_ref
project_find_file_path(@project, ref)
end
end end
...@@ -250,6 +250,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -250,6 +250,7 @@ class ApplicationSetting < ActiveRecord::Base
koding_url: nil, koding_url: nil,
max_artifacts_size: Settings.artifacts['max_size'], max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'], max_attachment_size: Settings.gitlab['max_attachment_size'],
password_authentication_enabled: Settings.gitlab['password_authentication_enabled'],
performance_bar_allowed_group_id: nil, performance_bar_allowed_group_id: nil,
plantuml_enabled: false, plantuml_enabled: false,
plantuml_url: nil, plantuml_url: nil,
...@@ -264,7 +265,6 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -264,7 +265,6 @@ class ApplicationSetting < ActiveRecord::Base
shared_runners_text: nil, shared_runners_text: nil,
sidekiq_throttling_enabled: false, sidekiq_throttling_enabled: false,
sign_in_text: nil, sign_in_text: nil,
signin_enabled: Settings.gitlab['signin_enabled'],
signup_enabled: Settings.gitlab['signup_enabled'], signup_enabled: Settings.gitlab['signup_enabled'],
terminal_max_session_time: 0, terminal_max_session_time: 0,
two_factor_grace_period: 48, two_factor_grace_period: 48,
......
...@@ -5,25 +5,6 @@ ...@@ -5,25 +5,6 @@
module Sortable module Sortable
extend ActiveSupport::Concern extend ActiveSupport::Concern
module DropDefaultScopeOnFinders
# Override these methods to drop the `ORDER BY id DESC` default scope.
# See http://dba.stackexchange.com/a/110919 for why we do this.
%i[find find_by find_by!].each do |meth|
define_method meth do |*args, &block|
return super(*args, &block) if block
unordered_relation = unscope(:order)
# We cannot simply call `meth` on `unscope(:order)`, since that is also
# an instance of the same relation class this module is included into,
# which means we'd get infinite recursion.
# We explicitly use the original implementation to prevent this.
original_impl = method(__method__).super_method.unbind
original_impl.bind(unordered_relation).call(*args)
end
end
end
included do included do
# By default all models should be ordered # By default all models should be ordered
# by created_at field starting from newest # by created_at field starting from newest
...@@ -37,10 +18,6 @@ module Sortable ...@@ -37,10 +18,6 @@ module Sortable
scope :order_updated_asc, -> { reorder(updated_at: :asc) } scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) } scope :order_name_asc, -> { reorder(name: :asc) }
scope :order_name_desc, -> { reorder(name: :desc) } scope :order_name_desc, -> { reorder(name: :desc) }
# All queries (relations) on this model are instances of this `relation_klass`.
relation_klass = relation_delegate_class(ActiveRecord::Relation)
relation_klass.prepend DropDefaultScopeOnFinders
end end
module ClassMethods module ClassMethods
......
...@@ -35,9 +35,6 @@ class MergeRequest < ActiveRecord::Base ...@@ -35,9 +35,6 @@ class MergeRequest < ActiveRecord::Base
after_create :ensure_merge_request_diff, unless: :importing? after_create :ensure_merge_request_diff, unless: :importing?
after_update :reload_diff_if_branch_changed after_update :reload_diff_if_branch_changed
delegate :commits, :real_size, :commit_shas, :commits_count,
to: :merge_request_diff, prefix: nil
# When this attribute is true some MR validation is ignored # When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests # It allows us to close or modify broken merge requests
attr_accessor :allow_broken attr_accessor :allow_broken
...@@ -228,6 +225,36 @@ class MergeRequest < ActiveRecord::Base ...@@ -228,6 +225,36 @@ class MergeRequest < ActiveRecord::Base
"#{project.to_reference(from, full: full)}#{reference}" "#{project.to_reference(from, full: full)}#{reference}"
end end
def commits
if persisted?
merge_request_diff.commits
elsif compare_commits
compare_commits.reverse
else
[]
end
end
def commits_count
if persisted?
merge_request_diff.commits_count
elsif compare_commits
compare_commits.size
else
0
end
end
def commit_shas
if persisted?
merge_request_diff.commit_shas
elsif compare_commits
compare_commits.reverse.map(&:sha)
else
[]
end
end
def first_commit def first_commit
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end end
...@@ -250,9 +277,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -250,9 +277,7 @@ class MergeRequest < ActiveRecord::Base
def diff_size def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform # Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here. # highlighting, which we don't need here.
return real_size if merge_request_diff merge_request_diff&.real_size || diffs.real_size
diffs.real_size
end end
def diff_base_commit def diff_base_commit
......
...@@ -844,7 +844,7 @@ class Project < ActiveRecord::Base ...@@ -844,7 +844,7 @@ class Project < ActiveRecord::Base
end end
def ci_service def ci_service
@ci_service ||= ci_services.find_by(active: true) @ci_service ||= ci_services.reorder(nil).find_by(active: true)
end end
def deployment_services def deployment_services
...@@ -852,7 +852,7 @@ class Project < ActiveRecord::Base ...@@ -852,7 +852,7 @@ class Project < ActiveRecord::Base
end end
def deployment_service def deployment_service
@deployment_service ||= deployment_services.find_by(active: true) @deployment_service ||= deployment_services.reorder(nil).find_by(active: true)
end end
def monitoring_services def monitoring_services
...@@ -860,7 +860,7 @@ class Project < ActiveRecord::Base ...@@ -860,7 +860,7 @@ class Project < ActiveRecord::Base
end end
def monitoring_service def monitoring_service
@monitoring_service ||= monitoring_services.find_by(active: true) @monitoring_service ||= monitoring_services.reorder(nil).find_by(active: true)
end end
def jira_tracker? def jira_tracker?
......
...@@ -130,6 +130,7 @@ class Repository ...@@ -130,6 +130,7 @@ class Repository
commits commits
end end
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/384
def find_commits_by_message(query, ref = nil, path = nil, limit = 1000, offset = 0) def find_commits_by_message(query, ref = nil, path = nil, limit = 1000, offset = 0)
unless exists? && has_visible_content? && query.present? unless exists? && has_visible_content? && query.present?
return [] return []
...@@ -617,6 +618,7 @@ class Repository ...@@ -617,6 +618,7 @@ class Repository
commit(sha) commit(sha)
end end
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/383
def last_commit_id_for_path(sha, path) def last_commit_id_for_path(sha, path)
key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}"
......
...@@ -599,16 +599,20 @@ class User < ActiveRecord::Base ...@@ -599,16 +599,20 @@ class User < ActiveRecord::Base
keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh') keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh')
end end
def require_password? def require_password_creation?
password_automatically_set? && !ldap_user? && current_application_settings.signin_enabled? password_automatically_set? && allow_password_authentication?
end end
def require_personal_access_token? def require_personal_access_token_creation_for_git_auth?
return false if current_application_settings.signin_enabled? || ldap_user? return false if allow_password_authentication? || ldap_user?
PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none? PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none?
end end
def allow_password_authentication?
!ldap_user? && current_application_settings.password_authentication_enabled?
end
def can_change_username? def can_change_username?
gitlab_config.username_changing_enabled gitlab_config.username_changing_enabled
end end
......
...@@ -129,6 +129,7 @@ class GitOperationService ...@@ -129,6 +129,7 @@ class GitOperationService
end end
end end
# Gitaly note: JV: wait with migrating #update_ref until we know how to migrate its call sites.
def update_ref(ref, newrev, oldrev) def update_ref(ref, newrev, oldrev)
# We use 'git update-ref' because libgit2/rugged currently does not # We use 'git update-ref' because libgit2/rugged currently does not
# offer 'compare and swap' ref updates. Without compare-and-swap we can # offer 'compare and swap' ref updates. Without compare-and-swap we can
......
...@@ -165,9 +165,9 @@ ...@@ -165,9 +165,9 @@
.form-group .form-group
.col-sm-offset-2.col-sm-10 .col-sm-offset-2.col-sm-10
.checkbox .checkbox
= f.label :signin_enabled do = f.label :password_authentication_enabled do
= f.check_box :signin_enabled = f.check_box :password_authentication_enabled
Sign-in enabled Password authentication enabled
- if omniauth_enabled? && button_based_providers.any? - if omniauth_enabled? && button_based_providers.any?
.form-group .form-group
= f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'control-label col-sm-2' = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'control-label col-sm-2'
......
...@@ -6,15 +6,15 @@ ...@@ -6,15 +6,15 @@
- else - else
= render 'devise/shared/tabs_normal' = render 'devise/shared/tabs_normal'
.tab-content .tab-content
- if signin_enabled? || ldap_enabled? || crowd_enabled? - if password_authentication_enabled? || ldap_enabled? || crowd_enabled?
= render 'devise/shared/signin_box' = render 'devise/shared/signin_box'
-# Signup only makes sense if you can also sign-in -# Signup only makes sense if you can also sign-in
- if signin_enabled? && signup_enabled? - if password_authentication_enabled? && signup_enabled?
= render 'devise/shared/signup_box' = render 'devise/shared/signup_box'
-# Show a message if none of the mechanisms above are enabled -# Show a message if none of the mechanisms above are enabled
- if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) - if !password_authentication_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div %div
No authentication methods configured. No authentication methods configured.
......
...@@ -13,12 +13,12 @@ ...@@ -13,12 +13,12 @@
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) } .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) }
.login-body .login-body
= render 'devise/sessions/new_ldap', server: server = render 'devise/sessions/new_ldap', server: server
- if signin_enabled? - if password_authentication_enabled?
.login-box.tab-pane{ id: 'ldap-standard', role: 'tabpanel' } .login-box.tab-pane{ id: 'ldap-standard', role: 'tabpanel' }
.login-body .login-body
= render 'devise/sessions/new_base' = render 'devise/sessions/new_base'
- elsif signin_enabled? - elsif password_authentication_enabled?
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' } .login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body .login-body
= render 'devise/sessions/new_base' = render 'devise/sessions/new_base'
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
- @ldap_servers.each_with_index do |server, i| - @ldap_servers.each_with_index do |server, i|
%li{ class: active_when(i.zero? && !crowd_enabled?) } %li{ class: active_when(i.zero? && !crowd_enabled?) }
= link_to server['label'], "##{server['provider_name']}", 'data-toggle' => 'tab' = link_to server['label'], "##{server['provider_name']}", 'data-toggle' => 'tab'
- if signin_enabled? - if password_authentication_enabled?
%li %li
= link_to 'Standard', '#ldap-standard', 'data-toggle' => 'tab' = link_to 'Standard', '#ldap-standard', 'data-toggle' => 'tab'
- if signin_enabled? && signup_enabled? - if password_authentication_enabled? && signup_enabled?
%li %li
= link_to 'Register', '#register-pane', 'data-toggle' => 'tab' = link_to 'Register', '#register-pane', 'data-toggle' => 'tab'
%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' } %ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' }
%li.active{ role: 'presentation' } %li.active{ role: 'presentation' }
%a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in
- if signin_enabled? && signup_enabled? - if password_authentication_enabled? && signup_enabled?
%li{ role: 'presentation' } %li{ role: 'presentation' }
%a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register
...@@ -3,6 +3,6 @@ ...@@ -3,6 +3,6 @@
= icon('bullhorn') = icon('bullhorn')
= license_message = license_message
- BroadcastMessage.current.each do |message| - BroadcastMessage.current&.each do |message|
= broadcast_message(message) = broadcast_message(message)
!!! 5 !!! 5
%html{ lang: I18n.locale, class: "#{page_class}" } %html{ lang: I18n.locale, class: "#{page_class}" }
= render "layouts/head" = render "layouts/head"
%body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } } %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } }
= render "layouts/init_auto_complete" if @gfm_form = render "layouts/init_auto_complete" if @gfm_form
- if show_new_nav? - if show_new_nav?
= render "layouts/header/new" = render "layouts/header/new"
......
...@@ -103,8 +103,3 @@ ...@@ -103,8 +103,3 @@
= yield :header_content = yield :header_content
= render 'shared/outdated_browser' = render 'shared/outdated_browser'
- if @project && !@project.empty_repo?
- if ref = @ref || @project.repository.root_ref
:javascript
var findFileURL = "#{project_find_file_path(@project, ref)}";
...@@ -84,8 +84,3 @@ ...@@ -84,8 +84,3 @@
= icon('times', class: 'js-navbar-toggle-left', style: 'display: none;') = icon('times', class: 'js-navbar-toggle-left', style: 'display: none;')
= render 'shared/outdated_browser' = render 'shared/outdated_browser'
- if @project && !@project.empty_repo?
- if ref = @ref || @project.repository.root_ref
:javascript
var findFileURL = "#{project_find_file_path(@project, ref)}";
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
= link_to profile_emails_path, title: 'Emails' do = link_to profile_emails_path, title: 'Emails' do
%span %span
Emails Emails
- unless current_user.ldap_user? - if current_user.allow_password_authentication?
= nav_link(controller: :passwords) do = nav_link(controller: :passwords) do
= link_to edit_profile_password_path, title: 'Password' do = link_to edit_profile_password_path, title: 'Password' do
%span %span
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#js-details-block-vue #js-details-block-vue
- if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?) - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
.block{ class: ("block-first" if !@build.coverage) } .block
.title .title
Job artifacts Job artifacts
- if @build.artifacts_expired? - if @build.artifacts_expired?
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
Browse Browse
- if @build.trigger_request - if @build.trigger_request
.build-widget .build-widget.block
%h4.title %h4.title
Trigger Trigger
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
.js-build-variable.trigger-build-variable= key .js-build-variable.trigger-build-variable= key
.js-build-value.trigger-build-value= value .js-build-value.trigger-build-value= value
.block %div{ class: (@build.pipeline.stages_count > 1 ? "block" : "block-last") }
%p %p
Commit Commit
= link_to @build.pipeline.short_sha, project_commit_path(@project, @build.pipeline.sha), class: 'commit-sha link-commit' = link_to @build.pipeline.short_sha, project_commit_path(@project, @build.pipeline.sha), class: 'commit-sha link-commit'
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
- if @build.pipeline.stages_count > 1 - if @build.pipeline.stages_count > 1
.dropdown.build-dropdown .dropdown.build-dropdown
.title %div
%span{ class: "ci-status-icon-#{@build.pipeline.status}" } %span{ class: "ci-status-icon-#{@build.pipeline.status}" }
= ci_icon_for_status(@build.pipeline.status) = ci_icon_for_status(@build.pipeline.status)
Pipeline Pipeline
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
%p %p
Metrics are automatically configured and monitored Metrics are automatically configured and monitored
based on a library of metrics from popular exporters. based on a library of metrics from popular exporters.
= link_to 'More information', '#' = link_to 'More information', help_page_path('user/project/integrations/prometheus')
.col-lg-9 .col-lg-9
.panel.panel-default.js-panel-monitored-metrics{ data: { "active-metrics" => "#{project_prometheus_active_metrics_path(@project, :json)}" } } .panel.panel-default.js-panel-monitored-metrics{ data: { "active-metrics" => "#{project_prometheus_active_metrics_path(@project, :json)}" } }
...@@ -41,5 +41,5 @@ ...@@ -41,5 +41,5 @@
%code %code
$CI_ENVIRONMENT_SLUG $CI_ENVIRONMENT_SLUG
to exporter&rsquo;s queries. to exporter&rsquo;s queries.
= link_to 'More information', '#' = link_to 'More information', help_page_path('user/project/integrations/prometheus', anchor: 'metrics-and-labels')
%ul.list-unstyled.metrics-list.js-missing-var-metrics-list %ul.list-unstyled.metrics-list.js-missing-var-metrics-list
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
.tree-controls .tree-controls
= render 'projects/find_file_link' = render 'projects/find_file_link'
= lock_file_link(html_options: { class: 'btn btn-grouped path-lock' }) = lock_file_link(html_options: { class: 'btn path-lock' })
= link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn btn-grouped' = link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn'
= render 'projects/buttons/download', project: @project, ref: @ref = render 'projects/buttons/download', project: @project, ref: @ref
...@@ -39,22 +39,3 @@ ...@@ -39,22 +39,3 @@
- else - else
.settings-message.text-center .settings-message.text-center
This user has no active #{type} Tokens. This user has no active #{type} Tokens.
%hr
%h5 Inactive #{type} Tokens (#{inactive_tokens.length})
- if inactive_tokens.present?
.table-responsive
%table.table.inactive-tokens
%thead
%tr
%th Name
%th Created
%tbody
- inactive_tokens.each do |token|
%tr
%td= token.name
%td= token.created_at.to_date.to_s(:medium)
- else
.settings-message.text-center
This user has no inactive #{type} Tokens.
---
title: Remove Inactive Personal Access Tokens list from Access Tokens page
merge_request: 12866
author:
---
title: Supplement Portuguese Brazil translation of Project Page & Repository Page
merge_request: 12156
author: Huang Tao
---
title: Fix vertical space in job details sidebar
merge_request:
author:
---
title: Increase width of dropdown menus automatically
merge_request: 12809
author: Thomas Wucher
---
title: Improve performance of lookups of issues, merge requests etc by dropping unnecessary ORDER BY clause
merge_request:
author:
---
title: Fixes needed when GitLab sign-in is not enabled
merge_request: 12491
author: Robin Bobbitt
...@@ -257,7 +257,7 @@ rescue ArgumentError # no user configured ...@@ -257,7 +257,7 @@ rescue ArgumentError # no user configured
end end
Settings.gitlab['time_zone'] ||= nil Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['password_authentication_enabled'] ||= true if Settings.gitlab['password_authentication_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]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing))(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing))(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil?
......
...@@ -196,6 +196,10 @@ if Gitlab::Metrics.enabled? ...@@ -196,6 +196,10 @@ if Gitlab::Metrics.enabled?
loc && loc[0].start_with?(models) && method.source =~ regex loc && loc[0].start_with?(models) && method.source =~ regex
end end
end end
# Ability is in app/models, is not an ActiveRecord model, but should still
# be instrumented.
Gitlab::Metrics::Instrumentation.instrument_methods(Ability)
end end
Gitlab::Metrics::Instrumentation.configure do |config| Gitlab::Metrics::Instrumentation.configure do |config|
......
class RenameApplicationSettingsSigninEnabledToPasswordAuthenticationEnabled < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
rename_column_concurrently :application_settings, :signin_enabled, :password_authentication_enabled
end
def down
cleanup_concurrent_column_rename :application_settings, :password_authentication_enabled, :signin_enabled
end
end
class CleanupApplicationSettingsSigninEnabledRename < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
cleanup_concurrent_column_rename :application_settings, :signin_enabled, :password_authentication_enabled
end
def down
rename_column_concurrently :application_settings, :password_authentication_enabled, :signin_enabled
end
end
...@@ -42,7 +42,6 @@ ActiveRecord::Schema.define(version: 20170707184244) do ...@@ -42,7 +42,6 @@ ActiveRecord::Schema.define(version: 20170707184244) do
create_table "application_settings", force: :cascade do |t| create_table "application_settings", force: :cascade do |t|
t.integer "default_projects_limit" t.integer "default_projects_limit"
t.boolean "signup_enabled" t.boolean "signup_enabled"
t.boolean "signin_enabled"
t.boolean "gravatar_enabled" t.boolean "gravatar_enabled"
t.text "sign_in_text" t.text "sign_in_text"
t.datetime "created_at" t.datetime "created_at"
...@@ -149,6 +148,7 @@ ActiveRecord::Schema.define(version: 20170707184244) do ...@@ -149,6 +148,7 @@ ActiveRecord::Schema.define(version: 20170707184244) do
t.string "slack_app_secret" t.string "slack_app_secret"
t.string "slack_app_verification_token" t.string "slack_app_verification_token"
t.integer "performance_bar_allowed_group_id" t.integer "performance_bar_allowed_group_id"
t.boolean "password_authentication_enabled"
end end
create_table "approvals", force: :cascade do |t| create_table "approvals", force: :cascade do |t|
......
...@@ -85,6 +85,7 @@ Manage files and branches from the UI (user interface): ...@@ -85,6 +85,7 @@ Manage files and branches from the UI (user interface):
- [Discussions](user/discussions/index.md) Threads, comments, and resolvable discussions in issues, commits, and merge requests. - [Discussions](user/discussions/index.md) Threads, comments, and resolvable discussions in issues, commits, and merge requests.
- [Issues](user/project/issues/index.md) - [Issues](user/project/issues/index.md)
- [Issue Board](user/project/issue_board.md) - [Issue Board](user/project/issue_board.md)
- **(EES/EEP)** [Related Issues](user/project/issues/related_issues.md): create a relationship between issues
- [Issues and merge requests templates](user/project/description_templates.md): Create templates for submitting new issues and merge requests. - [Issues and merge requests templates](user/project/description_templates.md): Create templates for submitting new issues and merge requests.
- [Labels](user/project/labels.md): Categorize your issues or merge requests based on descriptive titles. - [Labels](user/project/labels.md): Categorize your issues or merge requests based on descriptive titles.
- [Merge Requests](user/project/merge_requests/index.md) - [Merge Requests](user/project/merge_requests/index.md)
......
# IP whitelist
> Introduced in GitLab 9.4.
GitLab provides some [monitoring endpoints] that provide health check information
when probed.
To control access to those endpoints via IP whitelisting, you can add single
hosts or use IP ranges:
**For Omnibus installations**
1. Open `/etc/gitlab/gitlab.rb` and add or uncomment the following:
```ruby
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1']
```
1. Save the file and [reconfigure] GitLab for the changes to take effect.
---
**For installations from source**
1. Edit `config/gitlab.yml`:
```yaml
monitoring:
# by default only local IPs are allowed to access monitoring resources
ip_whitelist:
- 127.0.0.0/8
- 192.168.0.1
```
1. Save the file and [restart] GitLab for the changes to take effect.
[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
[restart]: ../restart_gitlab.md#installations-from-source
[monitoring endpoints]: ../../user/admin_area/monitoring/health_check.md
# GitLab Prometheus metrics # GitLab Prometheus metrics
>**Note:** >**Note:**
Available since [Omnibus GitLab 9.3][29118]. Currently experimental. For installations from source Available since [Omnibus GitLab 9.3][29118]. Currently experimental. For
you'll have to configure it yourself. installations from source you'll have to configure it yourself.
GitLab monitors its own internal service metrics, and makes them available at the `/-/metrics` endpoint. Unlike other [Prometheus] exporters, this endpoint requires authentication as it is available on the same URL and port as user traffic.
To enable the GitLab Prometheus metrics: To enable the GitLab Prometheus metrics:
...@@ -15,9 +13,14 @@ To enable the GitLab Prometheus metrics: ...@@ -15,9 +13,14 @@ To enable the GitLab Prometheus metrics:
## Collecting the metrics ## Collecting the metrics
Since the metrics endpoint is available on the same host and port as other traffic, it requires authentication. The token and URL to access is displayed on the [Health Check][health-check] page. GitLab monitors its own internal service metrics, and makes them available at the
`/-/metrics` endpoint. Unlike other [Prometheus] exporters, in order to access
it, the client IP needs to be [included in a whitelist][whitelist].
Currently the embedded Prometheus server is not automatically configured to collect metrics from this endpoint. We recommend setting up another Prometheus server, because the embedded server configuration is overwritten one every reconfigure of GitLab. In the future this will not be required. Currently the embedded Prometheus server is not automatically configured to
collect metrics from this endpoint. We recommend setting up another Prometheus
server, because the embedded server configuration is overwritten once every
[reconfigure of GitLab][reconfigure]. In the future this will not be required.
## Metrics available ## Metrics available
...@@ -44,4 +47,5 @@ In this experimental phase, only a few metrics are available: ...@@ -44,4 +47,5 @@ In this experimental phase, only a few metrics are available:
[29118]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29118 [29118]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29118
[Prometheus]: https://prometheus.io [Prometheus]: https://prometheus.io
[restart]: ../../restart_gitlab.md#omnibus-gitlab-restart [restart]: ../../restart_gitlab.md#omnibus-gitlab-restart
[health-check]: ../../../user/admin_area/monitoring/health_check.md [whitelist]: ../ip_whitelist.md
[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
...@@ -25,7 +25,7 @@ Example response: ...@@ -25,7 +25,7 @@ Example response:
"id" : 1, "id" : 1,
"default_branch_protection" : 2, "default_branch_protection" : 2,
"restricted_visibility_levels" : [], "restricted_visibility_levels" : [],
"signin_enabled" : true, "password_authentication_enabled" : true,
"after_sign_out_path" : null, "after_sign_out_path" : null,
"max_attachment_size" : 10, "max_attachment_size" : 10,
"user_oauth_applications" : true, "user_oauth_applications" : true,
...@@ -62,7 +62,7 @@ PUT /application/settings ...@@ -62,7 +62,7 @@ PUT /application/settings
| --------- | ---- | :------: | ----------- | | --------- | ---- | :------: | ----------- |
| `default_projects_limit` | integer | no | Project limit per user. Default is `100000` | | `default_projects_limit` | integer | no | Project limit per user. Default is `100000` |
| `signup_enabled` | boolean | no | Enable registration. Default is `true`. | | `signup_enabled` | boolean | no | Enable registration. Default is `true`. |
| `signin_enabled` | boolean | no | Enable login via a GitLab account. Default is `true`. | | `password_authentication_enabled` | boolean | no | Enable authentication via a GitLab account password. Default is `true`. |
| `gravatar_enabled` | boolean | no | Enable Gravatar | | `gravatar_enabled` | boolean | no | Enable Gravatar |
| `sign_in_text` | string | no | Text on login page | | `sign_in_text` | string | no | Text on login page |
| `home_page_url` | string | no | Redirect to this URL when not logged in | | `home_page_url` | string | no | Redirect to this URL when not logged in |
...@@ -110,7 +110,7 @@ Example response: ...@@ -110,7 +110,7 @@ Example response:
"id": 1, "id": 1,
"default_projects_limit": 100000, "default_projects_limit": 100000,
"signup_enabled": true, "signup_enabled": true,
"signin_enabled": true, "password_authentication_enabled": true,
"gravatar_enabled": true, "gravatar_enabled": true,
"sign_in_text": "", "sign_in_text": "",
"created_at": "2015-06-12T15:51:55.432Z", "created_at": "2015-06-12T15:51:55.432Z",
......
# Multi-Project Pipeline Graphs # Multi-project pipeline graphs
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/2121) in > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/2121) in
[GitLab Enterprise Edition Premium 9.3](https://about.gitlab.com/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs). [GitLab Enterprise Edition Premium 9.3](https://about.gitlab.com/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs).
When you set up [GitLab CI/CD](README.md) across multiple projects, you can visualize
the entire pipeline, including all multi-project stages.
## Overview ## Overview
GitLab CI/CD is a powerful continuous integration tool built-in GitLab. GitLab CI/CD is a powerful continuous integration tool built-in GitLab.
...@@ -10,12 +13,14 @@ GitLab CI works not only per project, but also across projects. When you ...@@ -10,12 +13,14 @@ GitLab CI works not only per project, but also across projects. When you
configure GitLab CI for your project, you can visualize the stages configure GitLab CI for your project, you can visualize the stages
of your [jobs](pipelines.md#jobs) on a chart called [pipeline graph](pipelines.md#pipeline-graphs). of your [jobs](pipelines.md#jobs) on a chart called [pipeline graph](pipelines.md#pipeline-graphs).
When you set up [GitLab CI/CD](README.md) across multiple projects, you can visualize
the entire pipeline, including all multi-project stages.
![Multi-project pipeline graph](img/multi_project_pipeline_graph.png) ![Multi-project pipeline graph](img/multi_project_pipeline_graph.png)
Multi-Project Pipeline Graphs are useful for larger projects, especially those For areas where the pipeline mini-graph is present, when hovering or clicking
(mobile) they will expand and be shown next to each other.
![Multi-project mini graph](img/multi_pipeline_mini_graph.gif)
Multi-project pipeline graphs are useful for larger projects, especially those
adopting a [microservices architecture](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/), adopting a [microservices architecture](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/),
that often have a set of interdependent components which form the complete product. that often have a set of interdependent components which form the complete product.
...@@ -24,7 +29,7 @@ that often have a set of interdependent components which form the complete produ ...@@ -24,7 +29,7 @@ that often have a set of interdependent components which form the complete produ
Let's assume you deploy your web app from different projects in GitLab: Let's assume you deploy your web app from different projects in GitLab:
- One for the free version, which has its own pipeline that builds and tests your app - One for the free version, which has its own pipeline that builds and tests your app
- One for the paid version adds-ons, which also pass through builds and tests - One for the paid version add-ons, which also pass through builds and tests
- One for the documentation, which also builds, tests, and deploys with an SSG - One for the documentation, which also builds, tests, and deploys with an SSG
With Multi-Project Pipeline Graphs, you can visualize the entire pipeline in a With Multi-Project Pipeline Graphs, you can visualize the entire pipeline in a
......
...@@ -186,9 +186,9 @@ by name. The order of severity is: ...@@ -186,9 +186,9 @@ by name. The order of severity is:
![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png) ![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png)
### Multi-Project Pipelines Graphs ### Multi-project pipelines graphs
With [Multi-Project Pipeline Graphs](multi_project_pipeline_graphs.md), With [multi-project pipeline graphs](multi_project_pipeline_graphs.md),
you can visualize cross-project pipelines. you can visualize cross-project pipelines.
It is available only in [GitLab Enterprise Edition Premium][eep]. It is available only in [GitLab Enterprise Edition Premium][eep].
......
# InputSetter # InputSetter
`InputSetter` is a plugin that allows for udating DOM out of the scope of droplab when a list item is clicked. `InputSetter` is a plugin that allows for updating DOM out of the scope of droplab when a list item is clicked.
## Usage ## Usage
......
...@@ -12,6 +12,56 @@ The `setup` task is a alias for `gitlab:setup`. ...@@ -12,6 +12,56 @@ The `setup` task is a alias for `gitlab:setup`.
This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database. This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database.
Note: `db:setup` calls `db:seed` but this does nothing. Note: `db:setup` calls `db:seed` but this does nothing.
### Automation
If you're very sure that you want to **wipe the current database** and refill
seeds, you could:
``` shell
echo 'yes' | bundle exec rake setup
```
To save you from answering `yes` manually.
### Discard stdout
Since the script would print a lot of information, it could be slowing down
your terminal, and it would generate more than 20G logs if you just redirect
it to a file. If we don't care about the output, we could just redirect it to
`/dev/null`:
``` shell
echo 'yes' | bundle exec rake setup > /dev/null
```
Note that since you can't see the questions from stdout, you might just want
to `echo 'yes'` to keep it running. It would still print the errors on stderr
so no worries about missing errors.
### Notes for MySQL
Since the seeds would contain various UTF-8 characters, such as emojis or so,
we'll need to make sure that we're using `utf8mb4` for all the encoding
settings and `utf8mb4_unicode_ci` for collation. Please check
[MySQL utf8mb4 support](../install/database_mysql.md#mysql-utf8mb4-support)
Make sure that `config/database.yml` has `encoding: utf8mb4`, too.
Next, we'll need to update the schema to make the indices fit:
``` shell
sed -i 's/limit: 255/limit: 191/g' db/schema.rb
```
Then run the setup script:
``` shell
bundle exec rake setup
```
To make sure that indices still fit. You could find great details in:
[How to support full Unicode in MySQL databases](https://mathiasbynens.be/notes/mysql-utf8mb4)
## Run tests ## Run tests
In order to run the test you can use the following commands: In order to run the test you can use the following commands:
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior) be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
section. section.
- [Access token](#access-token) has been deprecated in GitLab 9.4 - [Access token](#access-token) has been deprecated in GitLab 9.4
in favor of [IP Whitelist](#ip-whitelist) in favor of [IP whitelist](#ip-whitelist)
GitLab provides liveness and readiness probes to indicate service health and GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the reachability to required services. These probes report on the status of the
...@@ -14,109 +14,101 @@ database connection, Redis connection, and access to the filesystem. These ...@@ -14,109 +14,101 @@ database connection, Redis connection, and access to the filesystem. These
endpoints [can be provided to schedulers like Kubernetes][kubernetes] to hold endpoints [can be provided to schedulers like Kubernetes][kubernetes] to hold
traffic until the system is ready or restart the container as needed. traffic until the system is ready or restart the container as needed.
## IP Whitelist ## IP whitelist
To access monitoring resources the client IP needs to be included in the whitelist. To access monitoring resources, the client IP needs to be included in a whitelist.
To add or remove hosts or IP ranges from the list you can edit `gitlab.rb` or `gitlab.yml`.
Example whitelist configuration: [Read how to add IPs to a whitelist for the monitoring endpoints.][admin].
```yaml
monitoring:
ip_whitelist:
- 127.0.0.0/8 # by default only local IPs are allowed to access monitoring resources
```
## Access Token (Deprecated) ## Using the endpoint
An access token needs to be provided while accessing the probe endpoints. The current With default whitelist settings, the probes can be accessed from localhost:
accepted token can be found under the **Admin area ➔ Monitoring ➔ Health check**
(`admin/health_check`) page of your GitLab instance.
![access token](img/health_check_token.png) - `http://localhost/-/readiness`
- `http://localhost/-/liveness`
The access token can be passed as a URL parameter: which will then provide a report of system health in JSON format.
Readiness example output:
``` ```
https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN {
"queues_check" : {
"status" : "ok"
},
"redis_check" : {
"status" : "ok"
},
"shared_state_check" : {
"status" : "ok"
},
"fs_shards_check" : {
"labels" : {
"shard" : "default"
},
"status" : "ok"
},
"db_check" : {
"status" : "ok"
},
"cache_check" : {
"status" : "ok"
}
}
``` ```
which will then provide a report of system health in JSON format: Liveness example output:
``` ```
{ {
"db_check": { "fs_shards_check" : {
"status": "ok" "status" : "ok"
}, },
"redis_check": { "cache_check" : {
"status": "ok" "status" : "ok"
}, },
"fs_shards_check": { "db_check" : {
"status": "ok", "status" : "ok"
"labels": { },
"shard": "default" "redis_check" : {
} "status" : "ok"
} },
"queues_check" : {
"status" : "ok"
},
"shared_state_check" : {
"status" : "ok"
}
} }
``` ```
## Using the Endpoint
With default whitelist settings, the probes can be accessed from localhost:
- `http://localhost/-/readiness`
- `http://localhost/-/liveness`
## Status ## Status
On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint
will return a valid successful HTTP status code, and a `success` message. will return a valid successful HTTP status code, and a `success` message.
## Old behavior ## Access token (Deprecated)
>**Notes:** >**Note:**
- Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1. Access token has been deprecated in GitLab 9.4
- The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and will in favor of [IP whitelist](#ip-whitelist)
be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
section.
GitLab provides a health check endpoint for uptime monitoring on the `health_check` web
endpoint. The health check reports on the overall system status based on the status of
the database connection, the state of the database migrations, and the ability to write
and access the cache. This endpoint can be provided to uptime monitoring services like
[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health].
Once you have the [access token](#access-token) or your client IP is [whitelisted](#ip-whitelist),
health information can be retrieved as plain text, JSON, or XML using the `health_check` endpoint:
- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN`
- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN`
- `https://gitlab.example.com/health_check.xml?token=ACCESS_TOKEN`
You can also ask for the status of specific services:
- `https://gitlab.example.com/health_check/cache.json?token=ACCESS_TOKEN`
- `https://gitlab.example.com/health_check/database.json?token=ACCESS_TOKEN`
- `https://gitlab.example.com/health_check/migrations.json?token=ACCESS_TOKEN`
For example, the JSON output of the following health check: An access token needs to be provided while accessing the probe endpoints. The current
accepted token can be found under the **Admin area ➔ Monitoring ➔ Health check**
(`admin/health_check`) page of your GitLab instance.
```bash ![access token](img/health_check_token.png)
curl --header "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json
```
would be like: The access token can be passed as a URL parameter:
``` ```
{"healthy":true,"message":"success"} https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN
``` ```
On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint
will return a valid successful HTTP status code, and a `success` message. Ideally your
uptime monitoring should look for the success message.
[ce-10416]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10416 [ce-10416]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10416
[ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888 [ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888
[pingdom]: https://www.pingdom.com [pingdom]: https://www.pingdom.com
[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html [nagios-health]: https://nagios-plugins.org/doc/man/check_http.html
[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring [newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring
[kubernetes]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ [kubernetes]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
[admin]: ../../../administration/monitoring/ip_whitelist.md
...@@ -23,21 +23,33 @@ deployments right inside the [Deploy Board], without the need to leave GitLab. ...@@ -23,21 +23,33 @@ deployments right inside the [Deploy Board], without the need to leave GitLab.
## Use cases ## Use cases
Canary deployments can be used you want to ship features to only a portion of Canary deployments can be used when you want to ship features to only a portion of
your pods fleet and watch their behavior as a percentage of your user base your pods fleet and watch their behavior as a percentage of your user base
visits the temporarily deployed feature. If all works well, you can deploy the visits the temporarily deployed feature. If all works well, you can deploy the
feature to production knowing that it won't cause any problems. feature to production knowing that it won't cause any problems.
Canary deployments are also especially useful for backend refactors, performance
improvements, or other changes where the user interface doesn't change, but you
want to make sure the performance stays the same, or improves. Developers need
to be careful when using canaries with user-facing changes, because by default,
requests from the same user will be randomly distributed between canary and
non-canary pods, which could result in confusion or even errors. If needed, you
may want to consider [setting `service.spec.sessionAffinity` to `ClientIP` in
your Kubernetes service definitions][kube-net], but that is beyond the scope of
this document.
## Enabling Canary Deployments ## Enabling Canary Deployments
Canary deployments require that you properly configure Deploy Boards: Canary deployments require that you properly configure Deploy Boards:
1. Follow the steps to [enable Deploy Boards](deploy_boards.md#enabling-deploy-boards). 1. Follow the steps to [enable Deploy Boards](deploy_boards.md#enabling-deploy-boards).
1. To track canary deployments you need to label your Kubernetes deployments and 1. To track canary deployments you need to label your Kubernetes deployments and
pods with `track: canary`. To get started quickly, you can use the [Autodeploy] pods with `track: canary`. To get started quickly, you can use the [Auto Deploy]
template for canary deployments that GitLab provides. template for canary deployments that GitLab provides.
Depending on the deploy, the label should be either `stable` or `canary`. Depending on the deploy, the label should be either `stable` or `canary`.
Usually, `stable` and blank or missing label means the same thing, and `canary`
or any other track means canary/temporary.
This allows GitLab to discover whether deployment is stable or canary (temporary). This allows GitLab to discover whether deployment is stable or canary (temporary).
Once all of the above are set up and the pipeline has run at least once, Once all of the above are set up and the pipeline has run at least once,
...@@ -56,3 +68,4 @@ can easily notice them. ...@@ -56,3 +68,4 @@ can easily notice them.
[kube-canary]: https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments [kube-canary]: https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments
[deploy board]: deploy_boards.md [deploy board]: deploy_boards.md
[cd-blog]: https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/ [cd-blog]: https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/
[kube-net]: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
# Slack application (only available on GitLab.com) # GitLab Slack application
Since GitLab 9.4 you can install GitLab.com Slack application to get [slash commands](https://docs.gitlab.com/ce/integration/slash_commands.html) working. >**Notes:**
The only difference is that all the commands should be prefixed with `/gitlab` keyword: - Introduced in [GitLab Enterprise Edition] 9.4.
- Currently only configurable for GitLab.com, it will not work for on-premises
installations. You can configure the [Slack slash commands](slack_slash_commands.md)
service instead. We're working with Slack on making this configurable for all
GitLab installations.
Slack provides a native application which you can enable via your project's
integrations on GitLab.com.
## Configuration
Keep in mind that you need to have the appropriate permissions for your Slack
team in order to be able to install a new application, read more in Slack's
docs on [Adding an app to your team][slack-docs].
To enable GitLab's service for your Slack team:
1. Go to your project's **Settings > Integration > Slack application** (only
visible on GitLab.com)
1. Click the "Add to Slack" button
That's all! You can now start using the Slack slash commands.
## Usage
After confirming the installation, you, and everyone else in your Slack team,
can use all the [slash commands].
When you perform your first slash command you will be asked to authorize your
Slack user on GitLab.com.
The only difference with the [manually configurable Slack slash commands][slack-manual]
is that all the commands should be prefixed with the `/gitlab` keyword.
We are working on making this configurable in the future.
For example, to show the issue number `1001` under the `gitlab-org/gitlab-ce`
project, you would do:
``` ```
# Show the issue #1001
/gitlab gitlab-org/gitlab-ce issue show 1001 /gitlab gitlab-org/gitlab-ce issue show 1001
``` ```
To install GitLab application to your Slack team you need to go to [slack-docs]: https://get.slack.help/hc/en-us/articles/202035138-Adding-apps-to-your-team
`Project Settings > Integration > Slack application` page and press "Add to Slack" button. [slash commands]: ../../../integration/slash_commands.md
Keep in mind that you have to have appropriate permissions for that team to be able to [slack-manual]: slack_slash_commands.md
install a new application, see details in [Add an app to your team](https://get.slack.help/hc/en-us/articles/202035138-Adding-apps-to-your-team).
After confirming installation you, and everyone else in your Slack team, can use all the commands.
When you perform your first slash command you will be asked to authorize your Slack user
inside GitLab.com.
...@@ -46,6 +46,7 @@ Click on the service links to see further configuration instructions and details ...@@ -46,6 +46,7 @@ Click on the service links to see further configuration instructions and details
| Pipelines emails | Email the pipeline status to a list of recipients | | Pipelines emails | Email the pipeline status to a list of recipients |
| [Slack Notifications](slack.md) | Send GitLab events (e.g. issue created) to Slack as notifications | | [Slack Notifications](slack.md) | Send GitLab events (e.g. issue created) to Slack as notifications |
| [Slack slash commands](slack_slash_commands.md) | Use slash commands in Slack to control GitLab | | [Slack slash commands](slack_slash_commands.md) | Use slash commands in Slack to control GitLab |
| [GitLab Slack application](gitlab_slack_application.md) | Use Slack's official application
| PivotalTracker | Project Management Software (Source Commits Endpoint) | | PivotalTracker | Project Management Software (Source Commits Endpoint) |
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps | | [Prometheus](prometheus.md) | Monitor the performance of your deployed apps |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | | Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
......
...@@ -132,6 +132,14 @@ Issues can be [exported as CSV](csv_export.md) from GitLab and are sent to your ...@@ -132,6 +132,14 @@ Issues can be [exported as CSV](csv_export.md) from GitLab and are sent to your
_Exporting issues to CSV is available only in [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/)._ _Exporting issues to CSV is available only in [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/)._
## Related Issues (EES/SSP)
Related Issues are a bi-directional relationship between any two issues
and appear in a block below the issue description. Issues can be across groups
and projects.
Read more about [Related Issues](related_issues.md).
### Issue's API ### Issue's API
Read through the [API documentation](../../../api/issues.md). Read through the [API documentation](../../../api/issues.md).
...@@ -12,9 +12,9 @@ Is it simple as the name implies: a _request_ to _merge_ one branch into another ...@@ -12,9 +12,9 @@ Is it simple as the name implies: a _request_ to _merge_ one branch into another
With GitLab merge requests, you can: With GitLab merge requests, you can:
- Compare the changes between two [branches](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell#_git_branching) - Compare the changes between two [branches](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell#_git_branching)
- Discuss and review the proposed modifications inline - [Review and discuss](../../discussions/index.md#discussions) the proposed modifications inline
- Live preview the changes when [Review Apps](../../../ci/review_apps/index.md) is configured for your project - Live preview the changes when [Review Apps](../../../ci/review_apps/index.md) is configured for your project
- Build, test, and deploy your code is a per-branch basis with built-in [GitLab CI/CD](../../../ci/README.md) - Build, test, and deploy your code in a per-branch basis with built-in [GitLab CI/CD](../../../ci/README.md)
- Prevent the merge request from being merged before it's ready with [WIP MRs](#work-in-progress-merge-requests) - Prevent the merge request from being merged before it's ready with [WIP MRs](#work-in-progress-merge-requests)
- View the deployment process through [Pipeline Graphs](../../../ci/pipelines.md#pipeline-graphs) - View the deployment process through [Pipeline Graphs](../../../ci/pipelines.md#pipeline-graphs)
- [Automatically close the issue(s)](../../project/issues/closing_issues.md#via-merge-request) that originated the implementation proposed in the merge request - [Automatically close the issue(s)](../../project/issues/closing_issues.md#via-merge-request) that originated the implementation proposed in the merge request
...@@ -24,14 +24,14 @@ With GitLab merge requests, you can: ...@@ -24,14 +24,14 @@ With GitLab merge requests, you can:
- Add a time estimation and the time spent with that merge request with [Time Tracking](../../../workflow/time_tracking.html#time-tracking) - Add a time estimation and the time spent with that merge request with [Time Tracking](../../../workflow/time_tracking.html#time-tracking)
- [Resolve merge conflicts from the UI](#resolve-conflicts) - [Resolve merge conflicts from the UI](#resolve-conflicts)
With [GitLab Enterprise Edition][ee], you can also: With **[GitLab Enterprise Edition][ee]**, you can also:
- View the deployment process across projects with [Multi-Project Pipeline Graphs](../../../ci/multi_project_pipeline_graphs.md) (available only in GitLab Enterprise Edition Premium) - View the deployment process across projects with [Multi-Project Pipeline Graphs](../../../ci/multi_project_pipeline_graphs.md) (available only in GitLab Enterprise Edition Premium)
- Request [approvals](#merge-request-approvals) from your managers (available in GitLab Enterprise Edition Starter) - Request [approvals](#merge-request-approvals) from your managers (available in GitLab Enterprise Edition Starter)
- Enable [fast-forward merge requests](#fast-forward-merge-requests) (available in GitLab Enterprise Edition Starter) - Enable [fast-forward merge requests](#fast-forward-merge-requests) (available in GitLab Enterprise Edition Starter)
- [Squash and merge](#squash-and-merge) for a cleaner commit history (available in GitLab Enterprise Edition Starter) - [Squash and merge](#squash-and-merge) for a cleaner commit history (available in GitLab Enterprise Edition Starter)
- Enable [semi-linear history merge requests](#semi-linear-history-merge-requests) as another security layer to guarantee the pipeline is passing in the target branch (available in GitLab Enterprise Edition Starter) - Enable [semi-linear history merge requests](#semi-linear-history-merge-requests) as another security layer to guarantee the pipeline is passing in the target branch (available in GitLab Enterprise Edition Starter)
- Analise the impact of your changes with [Code Quality reports](#code-quality-reports) (available only in GitLab Enterprise Edition Starter) - Analyze the impact of your changes with [Code Quality reports](#code-quality-reports) (available in GitLab Enterprise Edition Starter)
## Use cases ## Use cases
...@@ -41,8 +41,8 @@ A. Consider you are a software developer working in a team: ...@@ -41,8 +41,8 @@ A. Consider you are a software developer working in a team:
1. You gather feedback from your team 1. You gather feedback from your team
1. You work on the implementation optimizing code with [Code Quality reports](#code-quality-reports) 1. You work on the implementation optimizing code with [Code Quality reports](#code-quality-reports)
1. You build and test your changes with GitLab CI/CD 1. You build and test your changes with GitLab CI/CD
1. You request the approval from your manager 1. You request the [approval](#merge-request-approvals) from your manager
1. Your manager pushes a commit with his final review and set the merge request to [merge when pipeline succeeds](#merge-when-pipeline-succeeds) 1. Your manager pushes a commit with his final review, [approves the merge request](#merge-request-approvals), and set it to [merge when pipeline succeeds](#merge-when-pipeline-succeeds)
1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#manual-actions) for GitLab CI/CD 1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#manual-actions) for GitLab CI/CD
1. Your implementations were successfully shipped to your customer 1. Your implementations were successfully shipped to your customer
...@@ -52,7 +52,7 @@ B. Consider you're a web developer writing a webpage for your company's website: ...@@ -52,7 +52,7 @@ B. Consider you're a web developer writing a webpage for your company's website:
1. You gather feedback from your reviewers 1. You gather feedback from your reviewers
1. Your changes are previewed with [Review Apps](../../../ci/review_apps/index.md) 1. Your changes are previewed with [Review Apps](../../../ci/review_apps/index.md)
1. You request your web designers for their implementation 1. You request your web designers for their implementation
1. You request the approval from your manager 1. You request the [approval](#merge-request-approvals) from your manager
1. Once approved, your merge request is [squashed and merged](#squash-and-merge), and [deployed to staging with GitLab Pages](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) 1. Once approved, your merge request is [squashed and merged](#squash-and-merge), and [deployed to staging with GitLab Pages](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
1. Your production team [cherry picks](#cherry-pick-changes) the merge commit into production 1. Your production team [cherry picks](#cherry-pick-changes) the merge commit into production
......
...@@ -41,7 +41,7 @@ server up and running for your GitLab instance. ...@@ -41,7 +41,7 @@ server up and running for your GitLab instance.
Before we begin, let's understand a few concepts first. Before we begin, let's understand a few concepts first.
### Static sites ## Static sites
GitLab Pages only supports static websites, meaning, GitLab Pages only supports static websites, meaning,
your output files must be HTML, CSS, and JavaScript only. your output files must be HTML, CSS, and JavaScript only.
...@@ -51,14 +51,14 @@ CSS, and JS, or use a [Static Site Generator (SSG)](https://www.staticgen.com/) ...@@ -51,14 +51,14 @@ CSS, and JS, or use a [Static Site Generator (SSG)](https://www.staticgen.com/)
to simplify your code and build the static site for you, to simplify your code and build the static site for you,
which is highly recommendable and much faster than hardcoding. which is highly recommendable and much faster than hardcoding.
#### Further Reading ### Further reading
- Read through this technical overview on [Static versus Dynamic Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) - Read through this technical overview on [Static versus Dynamic Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/)
- Understand [how modern Static Site Generators work](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) and what you can add to your static site - Understand [how modern Static Site Generators work](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) and what you can add to your static site
- You can use [any SSG with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) - You can use [any SSG with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
- Fork an [example project](https://gitlab.com/pages) to build your website based upon - Fork an [example project](https://gitlab.com/pages) to build your website based upon
### GitLab Pages domain ## GitLab Pages domain
If you set up a GitLab Pages project on GitLab.com, If you set up a GitLab Pages project on GitLab.com,
it will automatically be accessible under a it will automatically be accessible under a
...@@ -73,9 +73,9 @@ Pages wildcard domain. This guide is valid for any GitLab instance, ...@@ -73,9 +73,9 @@ Pages wildcard domain. This guide is valid for any GitLab instance,
you just need to replace Pages wildcard domain on GitLab.com you just need to replace Pages wildcard domain on GitLab.com
(`*.gitlab.io`) with your own. (`*.gitlab.io`) with your own.
#### Practical examples ### Practical examples
**Project Websites:** #### Project Websites
- You created a project called `blog` under your username `john`, - You created a project called `blog` under your username `john`,
therefore your project URL is `https://gitlab.com/john/blog/`. therefore your project URL is `https://gitlab.com/john/blog/`.
...@@ -87,7 +87,7 @@ URL is `https://gitlab.com/websites/blog/`. Once you enable ...@@ -87,7 +87,7 @@ URL is `https://gitlab.com/websites/blog/`. Once you enable
GitLab Pages for this project, the site will live under GitLab Pages for this project, the site will live under
`https://websites.gitlab.io/blog/`. `https://websites.gitlab.io/blog/`.
**User and Group Websites:** #### User and Group Websites
- Under your username, `john`, you created a project called - Under your username, `john`, you created a project called
`john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`. `john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`.
...@@ -97,6 +97,10 @@ will be published under `https://john.gitlab.io`. ...@@ -97,6 +97,10 @@ will be published under `https://john.gitlab.io`.
`websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`. Once you enable GitLab Pages for your project, `websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`. Once you enable GitLab Pages for your project,
your website will be published under `https://websites.gitlab.io`. your website will be published under `https://websites.gitlab.io`.
>**Note:**
GitLab Pages [does **not** support subgroups](../../group/subgroups/index.md#limitations).
You can only create the highest level group website.
**General example:** **General example:**
- On GitLab.com, a project site will always be available under - On GitLab.com, a project site will always be available under
......
...@@ -398,6 +398,9 @@ don't redirect HTTP to HTTPS. ...@@ -398,6 +398,9 @@ don't redirect HTTP to HTTPS.
[rfc]: https://tools.ietf.org/html/rfc2818#section-3.1 "HTTP Over TLS RFC" [rfc]: https://tools.ietf.org/html/rfc2818#section-3.1 "HTTP Over TLS RFC"
GitLab Pages [does **not** support subgroups](../../group/subgroups/index.md#limitations).
You can only create the highest level group website.
## Redirects in GitLab Pages ## Redirects in GitLab Pages
Since you cannot use any custom server configuration files, like `.htaccess` or Since you cannot use any custom server configuration files, like `.htaccess` or
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
- [Description templates](../user/project/description_templates.md) - [Description templates](../user/project/description_templates.md)
- [Feature branch workflow](workflow.md) - [Feature branch workflow](workflow.md)
- [GitLab Flow](gitlab_flow.md) - [GitLab Flow](gitlab_flow.md)
- [Groups](groups.md) - [Groups](../user/group/index.md)
- Issues - The GitLab Issue Tracker is an advanced and complete tool for - Issues - The GitLab Issue Tracker is an advanced and complete tool for
tracking the evolution of a new idea or the process of solving a problem. tracking the evolution of a new idea or the process of solving a problem.
- (EE) [Exporting Issues](../user/project/issues/csv_export.md) Export issues as a CSV, emailed as an attachment. - (EE) [Exporting Issues](../user/project/issues/csv_export.md) Export issues as a CSV, emailed as an attachment.
......
...@@ -5,7 +5,7 @@ to a project with a single action. ...@@ -5,7 +5,7 @@ to a project with a single action.
## Groups as collections of users ## Groups as collections of users
Groups are used primarily to [create collections of projects](groups.md), but you can also Groups are used primarily to [create collections of projects](../user/group/index.md), but you can also
take advantage of the fact that groups define collections of _users_, namely the group take advantage of the fact that groups define collections of _users_, namely the group
members. members.
......
...@@ -695,7 +695,8 @@ module API ...@@ -695,7 +695,8 @@ module API
expose :id expose :id
expose :default_projects_limit expose :default_projects_limit
expose :signup_enabled expose :signup_enabled
expose :signin_enabled expose :password_authentication_enabled
expose :password_authentication_enabled, as: :signin_enabled
expose :gravatar_enabled expose :gravatar_enabled
expose :sign_in_text expose :sign_in_text
expose :after_sign_up_text expose :after_sign_up_text
......
...@@ -113,7 +113,7 @@ module API ...@@ -113,7 +113,7 @@ module API
end end
get "/broadcast_message" do get "/broadcast_message" do
if message = BroadcastMessage.current.last if message = BroadcastMessage.current&.last
present message, with: Entities::BroadcastMessage present message, with: Entities::BroadcastMessage
else else
{} {}
......
...@@ -65,6 +65,7 @@ module API ...@@ -65,6 +65,7 @@ module API
:shared_runners_enabled, :shared_runners_enabled,
:sidekiq_throttling_enabled, :sidekiq_throttling_enabled,
:sign_in_text, :sign_in_text,
:password_authentication_enabled,
:signin_enabled, :signin_enabled,
:signup_enabled, :signup_enabled,
:terminal_max_session_time, :terminal_max_session_time,
...@@ -95,7 +96,9 @@ module API ...@@ -95,7 +96,9 @@ module API
requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com' requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
end end
optional :after_sign_up_text, type: String, desc: 'Text shown after sign up' optional :after_sign_up_text, type: String, desc: 'Text shown after sign up'
optional :signin_enabled, type: Boolean, desc: 'Flag indicating if sign in is enabled' optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
mutually_exclusive :password_authentication_enabled, :signin_enabled
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication' optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication'
given require_two_factor_authentication: ->(val) { val } do given require_two_factor_authentication: ->(val) { val } do
requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication' requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication'
...@@ -216,6 +219,10 @@ module API ...@@ -216,6 +219,10 @@ module API
put "application/settings" do put "application/settings" do
attrs = declared_params(include_missing: false) attrs = declared_params(include_missing: false)
if attrs.has_key?(:signin_enabled)
attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled)
end
if current_settings.update_attributes(attrs) if current_settings.update_attributes(attrs)
present current_settings, with: Entities::ApplicationSetting present current_settings, with: Entities::ApplicationSetting
else else
......
...@@ -46,39 +46,6 @@ module API ...@@ -46,39 +46,6 @@ module API
expose :awardable_id, :awardable_type expose :awardable_id, :awardable_type
end end
class ApplicationSetting < Grape::Entity
expose :id
expose :default_projects_limit
expose :signup_enabled
expose :signin_enabled
expose :gravatar_enabled
expose :sign_in_text
expose :after_sign_up_text
expose :created_at
expose :updated_at
expose :home_page_url
expose :default_branch_protection
expose :restricted_visibility_levels
expose :max_attachment_size
expose :session_expire_delay
expose :default_project_visibility
expose :default_snippet_visibility
expose :default_group_visibility
expose :domain_whitelist
expose :domain_blacklist_enabled
expose :domain_blacklist
expose :user_oauth_applications
expose :after_sign_out_path
expose :container_registry_token_expire_delay
expose :repository_storage
expose :repository_storages
expose :koding_enabled
expose :koding_url
expose :plantuml_enabled
expose :plantuml_url
expose :terminal_max_session_time
end
class Project < Grape::Entity class Project < Grape::Entity
expose :id, :description, :default_branch, :tag_list expose :id, :description, :default_branch, :tag_list
expose :public?, as: :public expose :public?, as: :public
...@@ -209,7 +176,8 @@ module API ...@@ -209,7 +176,8 @@ module API
expose :id expose :id
expose :default_projects_limit expose :default_projects_limit
expose :signup_enabled expose :signup_enabled
expose :signin_enabled expose :password_authentication_enabled
expose :password_authentication_enabled, as: :signin_enabled
expose :gravatar_enabled expose :gravatar_enabled
expose :sign_in_text expose :sign_in_text
expose :after_sign_up_text expose :after_sign_up_text
......
...@@ -44,7 +44,9 @@ module API ...@@ -44,7 +44,9 @@ module API
requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com' requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
end end
optional :after_sign_up_text, type: String, desc: 'Text shown after sign up' optional :after_sign_up_text, type: String, desc: 'Text shown after sign up'
optional :signin_enabled, type: Boolean, desc: 'Flag indicating if sign in is enabled' optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
mutually_exclusive :password_authentication_enabled, :signin_enabled
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication' optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication'
given require_two_factor_authentication: ->(val) { val } do given require_two_factor_authentication: ->(val) { val } do
requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication' requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication'
...@@ -127,7 +129,7 @@ module API ...@@ -127,7 +129,7 @@ module API
:max_attachment_size, :session_expire_delay, :disabled_oauth_sign_in_sources, :max_attachment_size, :session_expire_delay, :disabled_oauth_sign_in_sources,
:user_oauth_applications, :user_default_external, :signup_enabled, :user_oauth_applications, :user_default_external, :signup_enabled,
:send_user_confirmation_email, :domain_whitelist, :domain_blacklist_enabled, :send_user_confirmation_email, :domain_whitelist, :domain_blacklist_enabled,
:after_sign_up_text, :signin_enabled, :require_two_factor_authentication, :after_sign_up_text, :password_authentication_enabled, :signin_enabled, :require_two_factor_authentication,
:home_page_url, :after_sign_out_path, :sign_in_text, :help_page_text, :home_page_url, :after_sign_out_path, :sign_in_text, :help_page_text,
:shared_runners_enabled, :max_artifacts_size, :max_pages_size, :container_registry_token_expire_delay, :shared_runners_enabled, :max_artifacts_size, :max_pages_size, :container_registry_token_expire_delay,
:metrics_enabled, :sidekiq_throttling_enabled, :recaptcha_enabled, :metrics_enabled, :sidekiq_throttling_enabled, :recaptcha_enabled,
...@@ -139,7 +141,13 @@ module API ...@@ -139,7 +141,13 @@ module API
:repository_storage, :repository_storages, :repository_size_limit :repository_storage, :repository_storages, :repository_size_limit
end end
put "application/settings" do put "application/settings" do
if current_settings.update_attributes(declared_params(include_missing: false)) attrs = declared_params(include_missing: false)
if attrs.has_key?(:signin_enabled)
attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled)
end
if current_settings.update_attributes(attrs)
present current_settings, with: Entities::ApplicationSetting present current_settings, with: Entities::ApplicationSetting
else else
render_validation_error!(current_settings) render_validation_error!(current_settings)
......
...@@ -39,7 +39,7 @@ module Gitlab ...@@ -39,7 +39,7 @@ module Gitlab
rate_limit!(ip, success: result.success?, login: login) rate_limit!(ip, success: result.success?, login: login)
Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor)
return result if result.success? || current_application_settings.signin_enabled? || Gitlab::LDAP::Config.enabled? return result if result.success? || current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled?
# If sign-in is disabled and LDAP is not configured, recommend a # If sign-in is disabled and LDAP is not configured, recommend a
# personal access token on failed auth attempts # personal access token on failed auth attempts
...@@ -50,6 +50,10 @@ module Gitlab ...@@ -50,6 +50,10 @@ module Gitlab
# Avoid resource intensive login checks if password is not provided # Avoid resource intensive login checks if password is not provided
return unless password.present? return unless password.present?
# Nothing to do here if internal auth is disabled and LDAP is
# not configured
return unless current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled?
Gitlab::Auth::UniqueIpsLimiter.limit_user! do Gitlab::Auth::UniqueIpsLimiter.limit_user! do
user = User.by_login(login) user = User.by_login(login)
......
...@@ -38,7 +38,7 @@ module Gitlab ...@@ -38,7 +38,7 @@ module Gitlab
repo = options.delete(:repo) repo = options.delete(:repo)
raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log) raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log)
repo.log(options).map { |c| decorate(c) } repo.log(options)
end end
# Get single commit # Get single commit
......
...@@ -331,85 +331,10 @@ module Gitlab ...@@ -331,85 +331,10 @@ module Gitlab
# ) # )
# #
def log(options) def log(options)
default_options = { raw_log(options).map { |c| Commit.decorate(c) }
limit: 10,
offset: 0,
path: nil,
follow: false,
skip_merges: false,
disable_walk: false,
after: nil,
before: nil
}
options = default_options.merge(options)
options[:limit] ||= 0
options[:offset] ||= 0
actual_ref = options[:ref] || root_ref
begin
sha = sha_from_ref(actual_ref)
rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
# Return an empty array if the ref wasn't found
return []
end
if log_using_shell?(options)
log_by_shell(sha, options)
else
log_by_walk(sha, options)
end
end
def log_using_shell?(options)
options[:path].present? ||
options[:disable_walk] ||
options[:skip_merges] ||
options[:after] ||
options[:before]
end
def log_by_walk(sha, options)
walk_options = {
show: sha,
sort: Rugged::SORT_NONE,
limit: options[:limit],
offset: options[:offset]
}
Rugged::Walker.walk(rugged, walk_options).to_a
end
def log_by_shell(sha, options)
limit = options[:limit].to_i
offset = options[:offset].to_i
use_follow_flag = options[:follow] && options[:path].present?
# We will perform the offset in Ruby because --follow doesn't play well with --skip.
# See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
offset_in_ruby = use_follow_flag && options[:offset].present?
limit += offset if offset_in_ruby
cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} log]
cmd << "--max-count=#{limit}"
cmd << '--format=%H'
cmd << "--skip=#{offset}" unless offset_in_ruby
cmd << '--follow' if use_follow_flag
cmd << '--no-merges' if options[:skip_merges]
cmd << "--after=#{options[:after].iso8601}" if options[:after]
cmd << "--before=#{options[:before].iso8601}" if options[:before]
cmd << sha
# :path can be a string or an array of strings
if options[:path].present?
cmd << '--'
cmd += Array(options[:path])
end
raw_output = IO.popen(cmd) { |io| io.read }
lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
end end
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/382
def count_commits(options) def count_commits(options)
cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list] cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list]
cmd << "--after=#{options[:after].iso8601}" if options[:after] cmd << "--after=#{options[:after].iso8601}" if options[:after]
...@@ -454,7 +379,7 @@ module Gitlab ...@@ -454,7 +379,7 @@ module Gitlab
# Counts the amount of commits between `from` and `to`. # Counts the amount of commits between `from` and `to`.
def count_commits_between(from, to) def count_commits_between(from, to)
commits_between(from, to).size Commit.between(self, from, to).size
end end
# Returns the SHA of the most recent common ancestor of +from+ and +to+ # Returns the SHA of the most recent common ancestor of +from+ and +to+
...@@ -912,6 +837,89 @@ module Gitlab ...@@ -912,6 +837,89 @@ module Gitlab
private private
def raw_log(options)
default_options = {
limit: 10,
offset: 0,
path: nil,
follow: false,
skip_merges: false,
disable_walk: false,
after: nil,
before: nil
}
options = default_options.merge(options)
options[:limit] ||= 0
options[:offset] ||= 0
actual_ref = options[:ref] || root_ref
begin
sha = sha_from_ref(actual_ref)
rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
# Return an empty array if the ref wasn't found
return []
end
if log_using_shell?(options)
log_by_shell(sha, options)
else
log_by_walk(sha, options)
end
end
def log_using_shell?(options)
options[:path].present? ||
options[:disable_walk] ||
options[:skip_merges] ||
options[:after] ||
options[:before]
end
def log_by_walk(sha, options)
walk_options = {
show: sha,
sort: Rugged::SORT_NONE,
limit: options[:limit],
offset: options[:offset]
}
Rugged::Walker.walk(rugged, walk_options).to_a
end
# Gitaly note: JV: although #log_by_shell shells out to Git I think the
# complexity is such that we should migrate it as Ruby before trying to
# do it in Go.
def log_by_shell(sha, options)
limit = options[:limit].to_i
offset = options[:offset].to_i
use_follow_flag = options[:follow] && options[:path].present?
# We will perform the offset in Ruby because --follow doesn't play well with --skip.
# See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
offset_in_ruby = use_follow_flag && options[:offset].present?
limit += offset if offset_in_ruby
cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} log]
cmd << "--max-count=#{limit}"
cmd << '--format=%H'
cmd << "--skip=#{offset}" unless offset_in_ruby
cmd << '--follow' if use_follow_flag
cmd << '--no-merges' if options[:skip_merges]
cmd << "--after=#{options[:after].iso8601}" if options[:after]
cmd << "--before=#{options[:before].iso8601}" if options[:before]
cmd << sha
# :path can be a string or an array of strings
if options[:path].present?
cmd << '--'
cmd += Array(options[:path])
end
raw_output = IO.popen(cmd) { |io| io.read }
lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
end
# We are trying to deprecate this method because it does a lot of work # We are trying to deprecate this method because it does a lot of work
# but it seems to be used only to look up submodule URL's. # but it seems to be used only to look up submodule URL's.
# https://gitlab.com/gitlab-org/gitaly/issues/329 # https://gitlab.com/gitlab-org/gitaly/issues/329
......
# Gitaly note: JV: does not need to be migrated, works without a repo.
module Gitlab module Gitlab
module GitRefValidator module GitRefValidator
extend self extend self
......
# Gitaly note: JV: two sets of straightforward RPC's. 1 Hard RPC: fork_repository.
# SSH key operations are not part of Gitaly so will never be migrated.
require 'securerandom' require 'securerandom'
module Gitlab module Gitlab
...@@ -68,6 +71,7 @@ module Gitlab ...@@ -68,6 +71,7 @@ module Gitlab
# Ex. # Ex.
# add_repository("/path/to/storage", "gitlab/gitlab-ci") # add_repository("/path/to/storage", "gitlab/gitlab-ci")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def add_repository(storage, name) def add_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path, gitlab_shell_fast_execute([gitlab_shell_projects_path,
'add-project', storage, "#{name}.git"]) 'add-project', storage, "#{name}.git"])
...@@ -81,6 +85,7 @@ module Gitlab ...@@ -81,6 +85,7 @@ module Gitlab
# Ex. # Ex.
# import_repository("/path/to/storage", "gitlab/gitlab-ci", "https://github.com/randx/six.git") # import_repository("/path/to/storage", "gitlab/gitlab-ci", "https://github.com/randx/six.git")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def import_repository(storage, name, url) def import_repository(storage, name, url)
# Timeout should be less than 900 ideally, to prevent the memory killer # Timeout should be less than 900 ideally, to prevent the memory killer
# to silently kill the process without knowing we are timing out here. # to silently kill the process without knowing we are timing out here.
...@@ -127,6 +132,7 @@ module Gitlab ...@@ -127,6 +132,7 @@ module Gitlab
# Ex. # Ex.
# fetch_remote("gitlab/gitlab-ci", "upstream") # fetch_remote("gitlab/gitlab-ci", "upstream")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def fetch_remote(storage, name, remote, forced: false, no_tags: false) def fetch_remote(storage, name, remote, forced: false, no_tags: false)
args = [gitlab_shell_projects_path, 'fetch-remote', storage, "#{name}.git", remote, "#{Gitlab.config.gitlab_shell.git_timeout}"] args = [gitlab_shell_projects_path, 'fetch-remote', storage, "#{name}.git", remote, "#{Gitlab.config.gitlab_shell.git_timeout}"]
args << '--force' if forced args << '--force' if forced
...@@ -143,6 +149,7 @@ module Gitlab ...@@ -143,6 +149,7 @@ module Gitlab
# Ex. # Ex.
# mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new") # mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def mv_repository(storage, path, new_path) def mv_repository(storage, path, new_path)
gitlab_shell_fast_execute([gitlab_shell_projects_path, 'mv-project', gitlab_shell_fast_execute([gitlab_shell_projects_path, 'mv-project',
storage, "#{path}.git", "#{new_path}.git"]) storage, "#{path}.git", "#{new_path}.git"])
...@@ -171,6 +178,7 @@ module Gitlab ...@@ -171,6 +178,7 @@ module Gitlab
# Ex. # Ex.
# fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "randx") # fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "randx")
# #
# Gitaly note: JV: not easy to migrate because this involves two Gitaly servers, not one.
def fork_repository(forked_from_storage, path, forked_to_storage, fork_namespace) def fork_repository(forked_from_storage, path, forked_to_storage, fork_namespace)
gitlab_shell_fast_execute([gitlab_shell_projects_path, 'fork-project', gitlab_shell_fast_execute([gitlab_shell_projects_path, 'fork-project',
forked_from_storage, "#{path}.git", forked_to_storage, forked_from_storage, "#{path}.git", forked_to_storage,
...@@ -185,6 +193,7 @@ module Gitlab ...@@ -185,6 +193,7 @@ module Gitlab
# Ex. # Ex.
# remove_repository("/path/to/storage", "gitlab/gitlab-ci") # remove_repository("/path/to/storage", "gitlab/gitlab-ci")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def remove_repository(storage, name) def remove_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path, gitlab_shell_fast_execute([gitlab_shell_projects_path,
'rm-project', storage, "#{name}.git"]) 'rm-project', storage, "#{name}.git"])
...@@ -294,6 +303,7 @@ module Gitlab ...@@ -294,6 +303,7 @@ module Gitlab
# Ex. # Ex.
# add_namespace("/path/to/storage", "gitlab") # add_namespace("/path/to/storage", "gitlab")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def add_namespace(storage, name) def add_namespace(storage, name)
path = full_path(storage, name) path = full_path(storage, name)
FileUtils.mkdir_p(path, mode: 0770) unless exists?(storage, name) FileUtils.mkdir_p(path, mode: 0770) unless exists?(storage, name)
...@@ -307,6 +317,7 @@ module Gitlab ...@@ -307,6 +317,7 @@ module Gitlab
# Ex. # Ex.
# rm_namespace("/path/to/storage", "gitlab") # rm_namespace("/path/to/storage", "gitlab")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def rm_namespace(storage, name) def rm_namespace(storage, name)
FileUtils.rm_r(full_path(storage, name), force: true) FileUtils.rm_r(full_path(storage, name), force: true)
end end
...@@ -316,6 +327,7 @@ module Gitlab ...@@ -316,6 +327,7 @@ module Gitlab
# Ex. # Ex.
# mv_namespace("/path/to/storage", "gitlab", "gitlabhq") # mv_namespace("/path/to/storage", "gitlab", "gitlabhq")
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def mv_namespace(storage, old_name, new_name) def mv_namespace(storage, old_name, new_name)
return false if exists?(storage, new_name) || !exists?(storage, old_name) return false if exists?(storage, new_name) || !exists?(storage, old_name)
...@@ -341,6 +353,7 @@ module Gitlab ...@@ -341,6 +353,7 @@ module Gitlab
# exists?(storage, 'gitlab') # exists?(storage, 'gitlab')
# exists?(storage, 'gitlab/cookies.git') # exists?(storage, 'gitlab/cookies.git')
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def exists?(storage, dir_name) def exists?(storage, dir_name)
File.exist?(full_path(storage, dir_name)) File.exist?(full_path(storage, dir_name))
end end
......
This diff is collapsed.
...@@ -30,6 +30,15 @@ describe ApplicationController do ...@@ -30,6 +30,15 @@ describe ApplicationController do
expect(controller).not_to receive(:redirect_to) expect(controller).not_to receive(:redirect_to)
controller.send(:check_password_expiration) controller.send(:check_password_expiration)
end end
it 'does not redirect if the user is over their password expiry but sign-in is disabled' do
stub_application_setting(password_authentication_enabled: false)
user.password_expires_at = Time.new(2002)
allow(controller).to receive(:current_user).and_return(user)
expect(controller).not_to receive(:redirect_to)
controller.send(:check_password_expiration)
end
end end
describe "#authenticate_user_from_token!" do describe "#authenticate_user_from_token!" do
......
require 'spec_helper'
describe PasswordsController do
describe '#check_password_authentication_available' do
before do
@request.env["devise.mapping"] = Devise.mappings[:user]
end
context 'when password authentication is disabled' do
it 'prevents a password reset' do
stub_application_setting(password_authentication_enabled: false)
post :create
expect(flash[:alert]).to eq 'Password authentication is unavailable.'
end
end
context 'when reset email belongs to an ldap user' do
let(:user) { create(:omniauth_user, provider: 'ldapmain', email: 'ldapuser@gitlab.com') }
it 'prevents a password reset' do
post :create, user: { email: user.email }
expect(flash[:alert]).to eq 'Password authentication is unavailable.'
end
end
end
end
...@@ -2,13 +2,6 @@ FactoryGirl.define do ...@@ -2,13 +2,6 @@ FactoryGirl.define do
factory :ci_trigger_without_token, class: Ci::Trigger do factory :ci_trigger_without_token, class: Ci::Trigger do
factory :ci_trigger do factory :ci_trigger do
sequence(:token) { |n| "token#{n}" } sequence(:token) { |n| "token#{n}" }
factory :ci_trigger_for_trigger_schedule do
token { SecureRandom.hex(15) }
owner factory: :user
project factory: :project
ref 'master'
end
end end
end end
end end
...@@ -8,8 +8,8 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do ...@@ -8,8 +8,8 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do
find(".table.active-tokens") find(".table.active-tokens")
end end
def inactive_impersonation_tokens def no_personal_access_tokens_message
find(".table.inactive-tokens") find(".settings-message")
end end
before do before do
...@@ -60,15 +60,17 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do ...@@ -60,15 +60,17 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do
click_on "Revoke" click_on "Revoke"
expect(inactive_impersonation_tokens).to have_text(impersonation_token.name) expect(page).to have_selector(".settings-message")
expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.")
end end
it "moves expired tokens to the 'inactive' section" do it "removes expired tokens from 'active' section" do
impersonation_token.update(expires_at: 5.days.ago) impersonation_token.update(expires_at: 5.days.ago)
visit admin_user_impersonation_tokens_path(user_id: user.username) visit admin_user_impersonation_tokens_path(user_id: user.username)
expect(inactive_impersonation_tokens).to have_text(impersonation_token.name) expect(page).to have_selector(".settings-message")
expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.")
end end
end end
end end
...@@ -4,6 +4,11 @@ feature 'Merge request conflict resolution', js: true, feature: true do ...@@ -4,6 +4,11 @@ feature 'Merge request conflict resolution', js: true, feature: true do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
before do
# In order to have the diffs collapsed, we need to disable the increase feature
stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
end
def create_merge_request(source_branch) def create_merge_request(source_branch)
create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr| create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr|
mr.mark_as_unmergeable mr.mark_as_unmergeable
......
require 'spec_helper' require 'spec_helper'
describe 'Profile > Password', feature: true do describe 'Profile > Password', feature: true do
let(:user) { create(:user, password_automatically_set: true) } context 'Password authentication enabled' do
let(:user) { create(:user, password_automatically_set: true) }
before do before do
sign_in(user) sign_in(user)
visit edit_profile_password_path visit edit_profile_password_path
end end
def fill_passwords(password, confirmation) def fill_passwords(password, confirmation)
fill_in 'New password', with: password fill_in 'New password', with: password
fill_in 'Password confirmation', with: confirmation fill_in 'Password confirmation', with: confirmation
click_button 'Save password' click_button 'Save password'
end end
context 'User with password automatically set' do
describe 'User puts different passwords in the field and in the confirmation' do
it 'shows an error message' do
fill_passwords('mypassword', 'mypassword2')
context 'User with password automatically set' do page.within('.alert-danger') do
describe 'User puts different passwords in the field and in the confirmation' do expect(page).to have_content("Password confirmation doesn't match Password")
it 'shows an error message' do end
fill_passwords('mypassword', 'mypassword2') end
it 'does not contain the current password field after an error' do
fill_passwords('mypassword', 'mypassword2')
page.within('.alert-danger') do expect(page).to have_no_field('user[current_password]')
expect(page).to have_content("Password confirmation doesn't match Password")
end end
end end
it 'does not contain the current password field after an error' do describe 'User puts the same passwords in the field and in the confirmation' do
fill_passwords('mypassword', 'mypassword2') it 'shows a success message' do
fill_passwords('mypassword', 'mypassword')
expect(page).to have_no_field('user[current_password]') page.within('.flash-notice') do
expect(page).to have_content('Password was successfully updated. Please login with it')
end
end
end end
end end
end
describe 'User puts the same passwords in the field and in the confirmation' do context 'Password authentication unavailable' do
it 'shows a success message' do before do
fill_passwords('mypassword', 'mypassword') gitlab_sign_in(user)
end
page.within('.flash-notice') do context 'Regular user' do
expect(page).to have_content('Password was successfully updated. Please login with it') let(:user) { create(:user) }
end
it 'renders 404 when sign-in is disabled' do
stub_application_setting(password_authentication_enabled: false)
visit edit_profile_password_path
expect(page).to have_http_status(404)
end
end
context 'LDAP user' do
let(:user) { create(:omniauth_user, provider: 'ldapmain') }
it 'renders 404' do
visit edit_profile_password_path
expect(page).to have_http_status(404)
end end
end end
end end
......
...@@ -7,8 +7,8 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do ...@@ -7,8 +7,8 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do
find(".table.active-tokens") find(".table.active-tokens")
end end
def inactive_personal_access_tokens def no_personal_access_tokens_message
find(".table.inactive-tokens") find(".settings-message")
end end
def created_personal_access_token def created_personal_access_token
...@@ -80,14 +80,16 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do ...@@ -80,14 +80,16 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do
visit profile_personal_access_tokens_path visit profile_personal_access_tokens_path
click_on "Revoke" click_on "Revoke"
expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) expect(page).to have_selector(".settings-message")
expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.")
end end
it "moves expired tokens to the 'inactive' section" do it "removes expired tokens from 'active' section" do
personal_access_token.update(expires_at: 5.days.ago) personal_access_token.update(expires_at: 5.days.ago)
visit profile_personal_access_tokens_path visit profile_personal_access_tokens_path
expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) expect(page).to have_selector(".settings-message")
expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.")
end end
context "when revocation fails" do context "when revocation fails" do
......
...@@ -110,6 +110,10 @@ feature 'Diff file viewer', :js, feature: true do ...@@ -110,6 +110,10 @@ feature 'Diff file viewer', :js, feature: true do
context 'binary file that appears to be text in the first 1024 bytes' do context 'binary file that appears to be text in the first 1024 bytes' do
before do before do
# The file we're visiting is smaller than 10 KB and we want it collapsed
# so we need to disable the size increase feature.
stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
visit_commit('7b1cf4336b528e0f3d1d140ee50cafdbc703597c') visit_commit('7b1cf4336b528e0f3d1d140ee50cafdbc703597c')
end end
......
...@@ -30,7 +30,7 @@ feature 'No Password Alert' do ...@@ -30,7 +30,7 @@ feature 'No Password Alert' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') } let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') }
before do before do
stub_application_setting(signin_enabled?: false) stub_application_setting(password_authentication_enabled?: false)
stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config]) stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config])
end end
......
...@@ -35,7 +35,7 @@ describe ButtonHelper do ...@@ -35,7 +35,7 @@ describe ButtonHelper do
context 'with internal auth disabled' do context 'with internal auth disabled' do
before do before do
stub_application_setting(signin_enabled?: false) stub_application_setting(password_authentication_enabled?: false)
end end
context 'when user has no personal access tokens' do context 'when user has no personal access tokens' do
......
...@@ -160,7 +160,7 @@ describe ProjectsHelper do ...@@ -160,7 +160,7 @@ describe ProjectsHelper do
context 'user requires a personal access token' do context 'user requires a personal access token' do
it 'returns true' do it 'returns true' do
stub_application_setting(signin_enabled?: false) stub_application_setting(password_authentication_enabled?: false)
expect(helper.show_no_password_message?).to be_truthy expect(helper.show_no_password_message?).to be_truthy
end end
...@@ -184,7 +184,7 @@ describe ProjectsHelper do ...@@ -184,7 +184,7 @@ describe ProjectsHelper do
let(:user) { create(:user) } let(:user) { create(:user) }
it 'returns link to create a personal access token' do it 'returns link to create a personal access token' do
stub_application_setting(signin_enabled?: false) stub_application_setting(password_authentication_enabled?: false)
expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>} expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>}
end end
......
...@@ -206,7 +206,7 @@ describe Gitlab::Auth, lib: true do ...@@ -206,7 +206,7 @@ describe Gitlab::Auth, lib: true do
end end
it 'throws an error suggesting user create a PAT when internal auth is disabled' do it 'throws an error suggesting user create a PAT when internal auth is disabled' do
allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false }
expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError) expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError)
end end
...@@ -279,6 +279,16 @@ describe Gitlab::Auth, lib: true do ...@@ -279,6 +279,16 @@ describe Gitlab::Auth, lib: true do
gl_auth.find_with_user_password('ldap_user', 'password') gl_auth.find_with_user_password('ldap_user', 'password')
end end
end end
context "with sign-in disabled" do
before do
stub_application_setting(password_authentication_enabled: false)
end
it "does not find user by valid login/password" do
expect(gl_auth.find_with_user_password(username, password)).to be_nil
end
end
end end
private private
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::FakeApplicationSettings do describe Gitlab::FakeApplicationSettings do
let(:defaults) { { signin_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } } let(:defaults) { { password_authentication_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } }
subject { described_class.new(defaults) } subject { described_class.new(defaults) }
it 'wraps OpenStruct variables properly' do it 'wraps OpenStruct variables properly' do
expect(subject.signin_enabled).to be_falsey expect(subject.password_authentication_enabled).to be_falsey
expect(subject.signup_enabled).to be_truthy expect(subject.signup_enabled).to be_truthy
expect(subject.foobar).to eq('asdf') expect(subject.foobar).to eq('asdf')
end end
it 'defines predicate methods' do it 'defines predicate methods' do
expect(subject.signin_enabled?).to be_falsey expect(subject.password_authentication_enabled?).to be_falsey
expect(subject.signup_enabled?).to be_truthy expect(subject.signup_enabled?).to be_truthy
end end
it 'predicate method changes when value is updated' do it 'predicate method changes when value is updated' do
subject.signin_enabled = true subject.password_authentication_enabled = true
expect(subject.signin_enabled?).to be_truthy expect(subject.password_authentication_enabled?).to be_truthy
end end
it 'does not define a predicate method' do it 'does not define a predicate method' do
......
...@@ -34,7 +34,7 @@ EOT ...@@ -34,7 +34,7 @@ EOT
describe 'size limit feature toggles' do describe 'size limit feature toggles' do
context 'when the feature gitlab_git_diff_size_limit_increase is enabled' do context 'when the feature gitlab_git_diff_size_limit_increase is enabled' do
before do before do
Feature.enable('gitlab_git_diff_size_limit_increase') stub_feature_flags(gitlab_git_diff_size_limit_increase: true)
end end
it 'returns 200 KB for size_limit' do it 'returns 200 KB for size_limit' do
...@@ -48,7 +48,7 @@ EOT ...@@ -48,7 +48,7 @@ EOT
context 'when the feature gitlab_git_diff_size_limit_increase is disabled' do context 'when the feature gitlab_git_diff_size_limit_increase is disabled' do
before do before do
Feature.disable('gitlab_git_diff_size_limit_increase') stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
end end
it 'returns 100 KB for size_limit' do it 'returns 100 KB for size_limit' do
......
...@@ -705,9 +705,9 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -705,9 +705,9 @@ describe Gitlab::Git::Repository, seed_helper: true do
# Add new commits so that there's a renamed file in the commit history # Add new commits so that there's a renamed file in the commit history
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
commit_with_old_name = new_commit_edit_old_file(repo) commit_with_old_name = Gitlab::Git::Commit.decorate(new_commit_edit_old_file(repo))
rename_commit = new_commit_move_file(repo) rename_commit = Gitlab::Git::Commit.decorate(new_commit_move_file(repo))
commit_with_new_name = new_commit_edit_new_file(repo) commit_with_new_name = Gitlab::Git::Commit.decorate(new_commit_edit_new_file(repo))
end end
after(:context) do after(:context) do
...@@ -880,8 +880,8 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -880,8 +880,8 @@ describe Gitlab::Git::Repository, seed_helper: true do
context "compare results between log_by_walk and log_by_shell" do context "compare results between log_by_walk and log_by_shell" do
let(:options) { { ref: "master" } } let(:options) { { ref: "master" } }
let(:commits_by_walk) { repository.log(options).map(&:oid) } let(:commits_by_walk) { repository.log(options).map(&:id) }
let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:oid) } let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:id) }
it { expect(commits_by_walk).to eq(commits_by_shell) } it { expect(commits_by_walk).to eq(commits_by_shell) }
...@@ -924,7 +924,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -924,7 +924,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(commits.size).to be > 0 expect(commits.size).to be > 0
expect(commits).to satisfy do |commits| expect(commits).to satisfy do |commits|
commits.all? { |commit| commit.time >= options[:after] } commits.all? { |commit| commit.committed_date >= options[:after] }
end end
end end
end end
...@@ -937,7 +937,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -937,7 +937,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(commits.size).to be > 0 expect(commits.size).to be > 0
expect(commits).to satisfy do |commits| expect(commits).to satisfy do |commits|
commits.all? { |commit| commit.time <= options[:before] } commits.all? { |commit| commit.committed_date <= options[:before] }
end end
end end
end end
...@@ -946,7 +946,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -946,7 +946,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } } let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } }
def commit_files(commit) def commit_files(commit)
commit.diff(commit.parent_ids.first).deltas.flat_map do |delta| commit.diff_from_parent.deltas.flat_map do |delta|
[delta.old_file[:path], delta.new_file[:path]].uniq.compact [delta.old_file[:path], delta.new_file[:path]].uniq.compact
end end
end end
......
require 'spec_helper'
describe Sortable do
let(:relation) { Issue.all }
describe '#where' do
it 'orders by id, descending' do
order_node = relation.where(iid: 1).order_values.first
expect(order_node).to be_a(Arel::Nodes::Descending)
expect(order_node.expr.name).to eq(:id)
end
end
describe '#find_by' do
it 'does not order' do
expect(relation).to receive(:unscope).with(:order).and_call_original
relation.find_by(iid: 1)
end
end
end
...@@ -23,38 +23,29 @@ describe GitlabIssueTrackerService, models: true do ...@@ -23,38 +23,29 @@ describe GitlabIssueTrackerService, models: true do
describe 'project and issue urls' do describe 'project and issue urls' do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:service) { project.create_gitlab_issue_tracker_service(active: true) }
context 'with absolute urls' do context 'with absolute urls' do
before do before do
GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root" allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root")
@service = project.create_gitlab_issue_tracker_service(active: true)
end
after do
@service.destroy!
end end
it 'gives the correct path' do it 'gives the correct path' do
expect(@service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues") expect(service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues")
expect(@service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new") expect(service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new")
expect(@service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432") expect(service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432")
end end
end end
context 'with relative urls' do context 'with relative urls' do
before do before do
GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root" allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root")
@service = project.create_gitlab_issue_tracker_service(active: true)
end
after do
@service.destroy!
end end
it 'gives the correct path' do it 'gives the correct path' do
expect(@service.project_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues") expect(service.project_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues")
expect(@service.new_issue_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new") expect(service.new_issue_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new")
expect(@service.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432") expect(service.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432")
end end
end end
end end
......
...@@ -2054,4 +2054,26 @@ describe User, models: true do ...@@ -2054,4 +2054,26 @@ describe User, models: true do
user.invalidate_merge_request_cache_counts user.invalidate_merge_request_cache_counts
end end
end end
describe '#allow_password_authentication?' do
context 'regular user' do
let(:user) { build(:user) }
it 'returns true when sign-in is enabled' do
expect(user.allow_password_authentication?).to be_truthy
end
it 'returns false when sign-in is disabled' do
stub_application_setting(password_authentication_enabled: false)
expect(user.allow_password_authentication?).to be_falsey
end
end
it 'returns false for ldap user' do
user = create(:omniauth_user, provider: 'ldapmain')
expect(user.allow_password_authentication?).to be_falsey
end
end
end end
...@@ -35,6 +35,17 @@ describe API::Internal do ...@@ -35,6 +35,17 @@ describe API::Internal do
expect(json_response).to be_empty expect(json_response).to be_empty
end end
end end
context 'nil broadcast message' do
it 'returns nothing' do
allow(BroadcastMessage).to receive(:current).and_return(nil)
get api('/internal/broadcast_message'), secret_token: secret_token
expect(response).to have_http_status(200)
expect(json_response).to be_empty
end
end
end end
describe 'GET /internal/broadcast_messages' do describe 'GET /internal/broadcast_messages' do
......
...@@ -13,6 +13,7 @@ describe API::Settings, 'Settings' do ...@@ -13,6 +13,7 @@ describe API::Settings, 'Settings' do
expect(json_response['default_projects_limit']).to eq(42) expect(json_response['default_projects_limit']).to eq(42)
expect(json_response['signin_enabled']).to be_truthy expect(json_response['signin_enabled']).to be_truthy
expect(json_response['repository_storages']).to eq(['default']) expect(json_response['repository_storages']).to eq(['default'])
expect(json_response['password_authentication_enabled']).to be_truthy
expect(json_response['koding_enabled']).to be_falsey expect(json_response['koding_enabled']).to be_falsey
expect(json_response['koding_url']).to be_nil expect(json_response['koding_url']).to be_nil
expect(json_response['plantuml_enabled']).to be_falsey expect(json_response['plantuml_enabled']).to be_falsey
...@@ -33,8 +34,8 @@ describe API::Settings, 'Settings' do ...@@ -33,8 +34,8 @@ describe API::Settings, 'Settings' do
it "updates application settings" do it "updates application settings" do
put api("/application/settings", admin), put api("/application/settings", admin),
default_projects_limit: 3, default_projects_limit: 3,
signin_enabled: false,
repository_storages: ['custom'], repository_storages: ['custom'],
password_authentication_enabled: false,
koding_enabled: true, koding_enabled: true,
koding_url: 'http://koding.example.com', koding_url: 'http://koding.example.com',
plantuml_enabled: true, plantuml_enabled: true,
...@@ -48,6 +49,7 @@ describe API::Settings, 'Settings' do ...@@ -48,6 +49,7 @@ describe API::Settings, 'Settings' do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['default_projects_limit']).to eq(3) expect(json_response['default_projects_limit']).to eq(3)
expect(json_response['signin_enabled']).to be_falsey expect(json_response['signin_enabled']).to be_falsey
expect(json_response['password_authentication_enabled']).to be_falsey
expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['repository_storages']).to eq(['custom'])
expect(json_response['koding_enabled']).to be_truthy expect(json_response['koding_enabled']).to be_truthy
expect(json_response['koding_url']).to eq('http://koding.example.com') expect(json_response['koding_url']).to eq('http://koding.example.com')
......
...@@ -11,7 +11,7 @@ describe API::V3::Settings, 'Settings' do ...@@ -11,7 +11,7 @@ describe API::V3::Settings, 'Settings' do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response).to be_an Hash expect(json_response).to be_an Hash
expect(json_response['default_projects_limit']).to eq(42) expect(json_response['default_projects_limit']).to eq(42)
expect(json_response['signin_enabled']).to be_truthy expect(json_response['password_authentication_enabled']).to be_truthy
expect(json_response['repository_storage']).to eq('default') expect(json_response['repository_storage']).to eq('default')
expect(json_response['koding_enabled']).to be_falsey expect(json_response['koding_enabled']).to be_falsey
expect(json_response['koding_url']).to be_nil expect(json_response['koding_url']).to be_nil
...@@ -29,12 +29,12 @@ describe API::V3::Settings, 'Settings' do ...@@ -29,12 +29,12 @@ describe API::V3::Settings, 'Settings' do
it "updates application settings" do it "updates application settings" do
put v3_api("/application/settings", admin), put v3_api("/application/settings", admin),
default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com', default_projects_limit: 3, password_authentication_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com',
plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com' plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com'
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['default_projects_limit']).to eq(3) expect(json_response['default_projects_limit']).to eq(3)
expect(json_response['signin_enabled']).to be_falsey expect(json_response['password_authentication_enabled']).to be_falsey
expect(json_response['repository_storage']).to eq('custom') expect(json_response['repository_storage']).to eq('custom')
expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['repository_storages']).to eq(['custom'])
expect(json_response['koding_enabled']).to be_truthy expect(json_response['koding_enabled']).to be_truthy
......
...@@ -463,7 +463,7 @@ describe 'Git HTTP requests', lib: true do ...@@ -463,7 +463,7 @@ describe 'Git HTTP requests', lib: true do
context 'when internal auth is disabled' do context 'when internal auth is disabled' do
before do before do
allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false }
end end
it 'rejects pulls with personal access token error message' do it 'rejects pulls with personal access token error message' do
......
...@@ -101,7 +101,7 @@ describe JwtController do ...@@ -101,7 +101,7 @@ describe JwtController do
context 'when internal auth is disabled' do context 'when internal auth is disabled' do
it 'rejects the authorization attempt with personal access token message' do it 'rejects the authorization attempt with personal access token message' do
allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false }
get '/jwt/auth', parameters, headers get '/jwt/auth', parameters, headers
expect(response).to have_http_status(401) expect(response).to have_http_status(401)
......
This diff is collapsed.
This diff is collapsed.
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