Commit 300898f0 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ce-to-ee-2017-07-14' into 'master'

CE Upstream - Friday (2017-07-14)

See merge request !2435
parents ca559ae6 807e4ad3
......@@ -7,5 +7,8 @@ export default () => {
Cookies.set(el.name, el.value, {
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 */
/* global Mousetrap */
/* global findFileURL */
import Cookies from 'js-cookie';
import findAndFollowLink from './shortcuts_dashboard_navigation';
......@@ -20,6 +19,7 @@ import findAndFollowLink from './shortcuts_dashboard_navigation';
const $globalDropdownMenu = $('.global-dropdown-menu');
const $globalDropdownToggle = $('.global-dropdown-toggle');
const findFileURL = document.body.dataset.findFile;
$('.global-dropdown').on('hide.bs.dropdown', () => {
$globalDropdownMenu.removeClass('shortcuts');
......
......@@ -187,11 +187,12 @@
@include set-invisible;
display: block;
position: absolute;
width: 100%;
width: auto;
top: 100%;
left: 0;
z-index: 9;
min-width: 240px;
max-width: 500px;
margin-top: 2px;
margin-bottom: 0;
font-size: 14px;
......
......@@ -244,6 +244,10 @@
}
}
.block-last {
padding: 16px 0;
}
.trigger-build-variable {
color: $code-color;
}
......
......@@ -114,6 +114,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:html_emails_enabled,
:koding_enabled,
:koding_url,
:password_authentication_enabled,
:plantuml_enabled,
:plantuml_url,
:max_artifacts_size,
......@@ -136,7 +137,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:require_two_factor_authentication,
:session_expire_delay,
:sign_in_text,
:signin_enabled,
:signup_enabled,
:sentry_dsn,
:sentry_enabled,
......
......@@ -174,7 +174,7 @@ class ApplicationController < ActionController::Base
end
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
end
end
......
class PasswordsController < Devise::PasswordsController
include Gitlab::CurrentSettings
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]
def edit
......@@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController
def update
super do |resource|
if resource.valid? && resource.require_password?
if resource.valid? && resource.require_password_creation?
resource.update_attribute(:password_automatically_set, false)
end
end
......@@ -38,11 +40,11 @@ class PasswordsController < Devise::PasswordsController
self.resource = resource_class.find_by_email(email)
end
def prevent_ldap_reset
return unless resource && resource.ldap_user?
def check_password_authentication_available
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),
alert: "Cannot reset password for LDAP user."
alert: "Password authentication is unavailable."
end
def throttle_reset
......
......@@ -77,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
end
def authorize_change_password!
return render_404 if @user.ldap_user?
render_404 unless @user.allow_password_authentication?
end
def user_params
......
......@@ -230,7 +230,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue
return @issue if defined?(@issue)
# 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)
......
......@@ -109,7 +109,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
@target_project = @merge_request.target_project
@source_project = @merge_request.source_project
@commits = @merge_request.compare_commits.reverse
@commits = @merge_request.commits
@commit = @merge_request.diff_head_commit
@note_counts = Note.where(commit_id: @commits.map(&:id))
......
......@@ -69,8 +69,7 @@ class Projects::TriggersController < Projects::ApplicationController
def trigger_params
params.require(:trigger).permit(
:description,
trigger_schedule_attributes: [:id, :active, :cron, :cron_timezone, :ref]
:description
)
end
end
......@@ -59,7 +59,7 @@ class SessionsController < Devise::SessionsController
user = User.admins.last
return unless user && user.require_password?
return unless user && user.require_password_creation?
Users::UpdateService.new(user).execute do |user|
@token = user.generate_reset_token
......
module ApplicationSettingsHelper
delegate :gravatar_enabled?,
:signup_enabled?,
:signin_enabled?,
:password_authentication_enabled?,
:akismet_enabled?,
:koding_enabled?,
to: :current_application_settings
......
......@@ -50,12 +50,12 @@ module ButtonHelper
def http_clone_button(project, placement = 'right', append_link: true)
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
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 }
else
_("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol }
......
......@@ -214,11 +214,11 @@ module ProjectsHelper
def show_no_password_message?
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
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
else
link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path
......@@ -551,4 +551,12 @@ module ProjectsHelper
current_application_settings.restricted_visibility_levels || []
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
......@@ -250,6 +250,7 @@ class ApplicationSetting < ActiveRecord::Base
koding_url: nil,
max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
password_authentication_enabled: Settings.gitlab['password_authentication_enabled'],
performance_bar_allowed_group_id: nil,
plantuml_enabled: false,
plantuml_url: nil,
......@@ -264,7 +265,6 @@ class ApplicationSetting < ActiveRecord::Base
shared_runners_text: nil,
sidekiq_throttling_enabled: false,
sign_in_text: nil,
signin_enabled: Settings.gitlab['signin_enabled'],
signup_enabled: Settings.gitlab['signup_enabled'],
terminal_max_session_time: 0,
two_factor_grace_period: 48,
......
......@@ -5,25 +5,6 @@
module Sortable
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
# By default all models should be ordered
# by created_at field starting from newest
......@@ -37,10 +18,6 @@ module Sortable
scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) }
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
module ClassMethods
......
......@@ -35,9 +35,6 @@ class MergeRequest < ActiveRecord::Base
after_create :ensure_merge_request_diff, unless: :importing?
after_update :reload_diff_if_branch_changed
delegate :commits, :real_size, :commit_shas, :commits_count,
to: :merge_request_diff, prefix: nil
delegate :codeclimate_artifact, to: :head_pipeline, prefix: :head, allow_nil: true
delegate :codeclimate_artifact, to: :base_pipeline, prefix: :base, allow_nil: true
......@@ -231,6 +228,36 @@ class MergeRequest < ActiveRecord::Base
"#{project.to_reference(from, full: full)}#{reference}"
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
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
......@@ -253,9 +280,7 @@ class MergeRequest < ActiveRecord::Base
def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here.
return real_size if merge_request_diff
diffs.real_size
merge_request_diff&.real_size || diffs.real_size
end
def diff_base_commit
......
......@@ -844,7 +844,7 @@ class Project < ActiveRecord::Base
end
def ci_service
@ci_service ||= ci_services.find_by(active: true)
@ci_service ||= ci_services.reorder(nil).find_by(active: true)
end
def deployment_services
......@@ -852,7 +852,7 @@ class Project < ActiveRecord::Base
end
def deployment_service
@deployment_service ||= deployment_services.find_by(active: true)
@deployment_service ||= deployment_services.reorder(nil).find_by(active: true)
end
def monitoring_services
......@@ -860,7 +860,7 @@ class Project < ActiveRecord::Base
end
def monitoring_service
@monitoring_service ||= monitoring_services.find_by(active: true)
@monitoring_service ||= monitoring_services.reorder(nil).find_by(active: true)
end
def jira_tracker?
......
......@@ -130,6 +130,7 @@ class Repository
commits
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)
unless exists? && has_visible_content? && query.present?
return []
......@@ -617,6 +618,7 @@ class Repository
commit(sha)
end
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/383
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)}"
......
......@@ -599,16 +599,20 @@ class User < ActiveRecord::Base
keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh')
end
def require_password?
password_automatically_set? && !ldap_user? && current_application_settings.signin_enabled?
def require_password_creation?
password_automatically_set? && allow_password_authentication?
end
def require_personal_access_token?
return false if current_application_settings.signin_enabled? || ldap_user?
def require_personal_access_token_creation_for_git_auth?
return false if allow_password_authentication? || ldap_user?
PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none?
end
def allow_password_authentication?
!ldap_user? && current_application_settings.password_authentication_enabled?
end
def can_change_username?
gitlab_config.username_changing_enabled
end
......
......@@ -129,6 +129,7 @@ class GitOperationService
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)
# We use 'git update-ref' because libgit2/rugged currently does not
# offer 'compare and swap' ref updates. Without compare-and-swap we can
......
......@@ -165,9 +165,9 @@
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :signin_enabled do
= f.check_box :signin_enabled
Sign-in enabled
= f.label :password_authentication_enabled do
= f.check_box :password_authentication_enabled
Password authentication enabled
- if omniauth_enabled? && button_based_providers.any?
.form-group
= f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'control-label col-sm-2'
......
......@@ -6,15 +6,15 @@
- else
= render 'devise/shared/tabs_normal'
.tab-content
- if signin_enabled? || ldap_enabled? || crowd_enabled?
- if password_authentication_enabled? || ldap_enabled? || crowd_enabled?
= render 'devise/shared/signin_box'
-# 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'
-# 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
No authentication methods configured.
......
......@@ -13,12 +13,12 @@
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) }
.login-body
= render 'devise/sessions/new_ldap', server: server
- if signin_enabled?
- if password_authentication_enabled?
.login-box.tab-pane{ id: 'ldap-standard', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
- elsif signin_enabled?
- elsif password_authentication_enabled?
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
......@@ -8,9 +8,9 @@
- @ldap_servers.each_with_index do |server, i|
%li{ class: active_when(i.zero? && !crowd_enabled?) }
= link_to server['label'], "##{server['provider_name']}", 'data-toggle' => 'tab'
- if signin_enabled?
- if password_authentication_enabled?
%li
= link_to 'Standard', '#ldap-standard', 'data-toggle' => 'tab'
- if signin_enabled? && signup_enabled?
- if password_authentication_enabled? && signup_enabled?
%li
= link_to 'Register', '#register-pane', 'data-toggle' => 'tab'
%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' }
%li.active{ role: 'presentation' }
%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' }
%a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register
......@@ -3,6 +3,6 @@
= icon('bullhorn')
= license_message
- BroadcastMessage.current.each do |message|
- BroadcastMessage.current&.each do |message|
= broadcast_message(message)
!!! 5
%html{ lang: I18n.locale, class: "#{page_class}" }
= 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
- if show_new_nav?
= render "layouts/header/new"
......
......@@ -103,8 +103,3 @@
= yield :header_content
= 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 @@
= icon('times', class: 'js-navbar-toggle-left', style: 'display: none;')
= 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 @@
= link_to profile_emails_path, title: 'Emails' do
%span
Emails
- unless current_user.ldap_user?
- if current_user.allow_password_authentication?
= nav_link(controller: :passwords) do
= link_to edit_profile_password_path, title: 'Password' do
%span
......
......@@ -11,7 +11,7 @@
#js-details-block-vue
- if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
.block{ class: ("block-first" if !@build.coverage) }
.block
.title
Job artifacts
- if @build.artifacts_expired?
......@@ -37,7 +37,7 @@
Browse
- if @build.trigger_request
.build-widget
.build-widget.block
%h4.title
Trigger
......@@ -55,7 +55,7 @@
.js-build-variable.trigger-build-variable= key
.js-build-value.trigger-build-value= value
.block
%div{ class: (@build.pipeline.stages_count > 1 ? "block" : "block-last") }
%p
Commit
= link_to @build.pipeline.short_sha, project_commit_path(@project, @build.pipeline.sha), class: 'commit-sha link-commit'
......@@ -69,7 +69,7 @@
- if @build.pipeline.stages_count > 1
.dropdown.build-dropdown
.title
%div
%span{ class: "ci-status-icon-#{@build.pipeline.status}" }
= ci_icon_for_status(@build.pipeline.status)
Pipeline
......
......@@ -8,7 +8,7 @@
%p
Metrics are automatically configured and monitored
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
.panel.panel-default.js-panel-monitored-metrics{ data: { "active-metrics" => "#{project_prometheus_active_metrics_path(@project, :json)}" } }
......@@ -41,5 +41,5 @@
%code
$CI_ENVIRONMENT_SLUG
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
......@@ -39,22 +39,3 @@
- else
.settings-message.text-center
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
end
Settings.gitlab['time_zone'] ||= 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['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?
......
......@@ -196,6 +196,10 @@ if Gitlab::Metrics.enabled?
loc && loc[0].start_with?(models) && method.source =~ regex
end
end
# Ability is in app/models, is not an ActiveRecord model, but should still
# be instrumented.
Gitlab::Metrics::Instrumentation.instrument_methods(Ability)
end
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
create_table "application_settings", force: :cascade do |t|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
t.boolean "signin_enabled"
t.boolean "gravatar_enabled"
t.text "sign_in_text"
t.datetime "created_at"
......@@ -149,6 +148,7 @@ ActiveRecord::Schema.define(version: 20170707184244) do
t.string "slack_app_secret"
t.string "slack_app_verification_token"
t.integer "performance_bar_allowed_group_id"
t.boolean "password_authentication_enabled"
end
create_table "approvals", force: :cascade do |t|
......
......@@ -25,7 +25,7 @@ Example response:
"id" : 1,
"default_branch_protection" : 2,
"restricted_visibility_levels" : [],
"signin_enabled" : true,
"password_authentication_enabled" : true,
"after_sign_out_path" : null,
"max_attachment_size" : 10,
"user_oauth_applications" : true,
......@@ -62,7 +62,7 @@ PUT /application/settings
| --------- | ---- | :------: | ----------- |
| `default_projects_limit` | integer | no | Project limit per user. Default is `100000` |
| `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 |
| `sign_in_text` | string | no | Text on login page |
| `home_page_url` | string | no | Redirect to this URL when not logged in |
......@@ -110,7 +110,7 @@ Example response:
"id": 1,
"default_projects_limit": 100000,
"signup_enabled": true,
"signin_enabled": true,
"password_authentication_enabled": true,
"gravatar_enabled": true,
"sign_in_text": "",
"created_at": "2015-06-12T15:51:55.432Z",
......
# 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
......
......@@ -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.
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
In order to run the test you can use the following commands:
......
......@@ -695,7 +695,8 @@ module API
expose :id
expose :default_projects_limit
expose :signup_enabled
expose :signin_enabled
expose :password_authentication_enabled
expose :password_authentication_enabled, as: :signin_enabled
expose :gravatar_enabled
expose :sign_in_text
expose :after_sign_up_text
......
......@@ -113,7 +113,7 @@ module API
end
get "/broadcast_message" do
if message = BroadcastMessage.current.last
if message = BroadcastMessage.current&.last
present message, with: Entities::BroadcastMessage
else
{}
......
......@@ -65,6 +65,7 @@ module API
:shared_runners_enabled,
:sidekiq_throttling_enabled,
:sign_in_text,
:password_authentication_enabled,
:signin_enabled,
:signup_enabled,
:terminal_max_session_time,
......@@ -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'
end
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'
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'
......@@ -216,6 +219,10 @@ module API
put "application/settings" do
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
else
......
......@@ -46,39 +46,6 @@ module API
expose :awardable_id, :awardable_type
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
expose :id, :description, :default_branch, :tag_list
expose :public?, as: :public
......@@ -209,7 +176,8 @@ module API
expose :id
expose :default_projects_limit
expose :signup_enabled
expose :signin_enabled
expose :password_authentication_enabled
expose :password_authentication_enabled, as: :signin_enabled
expose :gravatar_enabled
expose :sign_in_text
expose :after_sign_up_text
......
......@@ -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'
end
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'
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'
......@@ -127,7 +129,7 @@ module API
:max_attachment_size, :session_expire_delay, :disabled_oauth_sign_in_sources,
:user_oauth_applications, :user_default_external, :signup_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,
:shared_runners_enabled, :max_artifacts_size, :max_pages_size, :container_registry_token_expire_delay,
:metrics_enabled, :sidekiq_throttling_enabled, :recaptcha_enabled,
......@@ -139,7 +141,13 @@ module API
:repository_storage, :repository_storages, :repository_size_limit
end
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
else
render_validation_error!(current_settings)
......
......@@ -39,7 +39,7 @@ module Gitlab
rate_limit!(ip, success: result.success?, login: login)
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
# personal access token on failed auth attempts
......@@ -50,6 +50,10 @@ module Gitlab
# Avoid resource intensive login checks if password is not provided
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
user = User.by_login(login)
......
......@@ -38,7 +38,7 @@ module Gitlab
repo = options.delete(:repo)
raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log)
repo.log(options).map { |c| decorate(c) }
repo.log(options)
end
# Get single commit
......
......@@ -331,85 +331,10 @@ module Gitlab
# )
#
def 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
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) }
raw_log(options).map { |c| Commit.decorate(c) }
end
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/382
def count_commits(options)
cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list]
cmd << "--after=#{options[:after].iso8601}" if options[:after]
......@@ -454,7 +379,7 @@ module Gitlab
# Counts the amount of commits between `from` and `to`.
def count_commits_between(from, to)
commits_between(from, to).size
Commit.between(self, from, to).size
end
# Returns the SHA of the most recent common ancestor of +from+ and +to+
......@@ -912,6 +837,89 @@ module Gitlab
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
# but it seems to be used only to look up submodule URL's.
# https://gitlab.com/gitlab-org/gitaly/issues/329
......
# Gitaly note: JV: does not need to be migrated, works without a repo.
module Gitlab
module GitRefValidator
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'
module Gitlab
......@@ -68,6 +71,7 @@ module Gitlab
# Ex.
# add_repository("/path/to/storage", "gitlab/gitlab-ci")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def add_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path,
'add-project', storage, "#{name}.git"])
......@@ -81,6 +85,7 @@ module Gitlab
# Ex.
# 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)
# Timeout should be less than 900 ideally, to prevent the memory killer
# to silently kill the process without knowing we are timing out here.
......@@ -127,6 +132,7 @@ module Gitlab
# Ex.
# 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)
args = [gitlab_shell_projects_path, 'fetch-remote', storage, "#{name}.git", remote, "#{Gitlab.config.gitlab_shell.git_timeout}"]
args << '--force' if forced
......@@ -143,6 +149,7 @@ module Gitlab
# Ex.
# 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)
gitlab_shell_fast_execute([gitlab_shell_projects_path, 'mv-project',
storage, "#{path}.git", "#{new_path}.git"])
......@@ -171,6 +178,7 @@ module Gitlab
# Ex.
# 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)
gitlab_shell_fast_execute([gitlab_shell_projects_path, 'fork-project',
forked_from_storage, "#{path}.git", forked_to_storage,
......@@ -185,6 +193,7 @@ module Gitlab
# Ex.
# remove_repository("/path/to/storage", "gitlab/gitlab-ci")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def remove_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path,
'rm-project', storage, "#{name}.git"])
......@@ -294,6 +303,7 @@ module Gitlab
# Ex.
# add_namespace("/path/to/storage", "gitlab")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def add_namespace(storage, name)
path = full_path(storage, name)
FileUtils.mkdir_p(path, mode: 0770) unless exists?(storage, name)
......@@ -307,6 +317,7 @@ module Gitlab
# Ex.
# rm_namespace("/path/to/storage", "gitlab")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def rm_namespace(storage, name)
FileUtils.rm_r(full_path(storage, name), force: true)
end
......@@ -316,6 +327,7 @@ module Gitlab
# Ex.
# 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)
return false if exists?(storage, new_name) || !exists?(storage, old_name)
......@@ -341,6 +353,7 @@ module Gitlab
# exists?(storage, 'gitlab')
# exists?(storage, 'gitlab/cookies.git')
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def exists?(storage, dir_name)
File.exist?(full_path(storage, dir_name))
end
......
This diff is collapsed.
......@@ -30,6 +30,15 @@ describe ApplicationController do
expect(controller).not_to receive(:redirect_to)
controller.send(:check_password_expiration)
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
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
factory :ci_trigger_without_token, class: Ci::Trigger do
factory :ci_trigger do
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
......@@ -8,8 +8,8 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do
find(".table.active-tokens")
end
def inactive_impersonation_tokens
find(".table.inactive-tokens")
def no_personal_access_tokens_message
find(".settings-message")
end
before do
......@@ -60,15 +60,17 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do
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
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)
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
......@@ -4,6 +4,11 @@ feature 'Merge request conflict resolution', js: true, feature: true do
let(:user) { create(:user) }
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)
create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr|
mr.mark_as_unmergeable
......
require 'spec_helper'
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
sign_in(user)
visit edit_profile_password_path
end
before do
sign_in(user)
visit edit_profile_password_path
end
def fill_passwords(password, confirmation)
fill_in 'New password', with: password
fill_in 'Password confirmation', with: confirmation
def fill_passwords(password, confirmation)
fill_in 'New password', with: password
fill_in 'Password confirmation', with: confirmation
click_button 'Save password'
end
click_button 'Save password'
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
describe 'User puts different passwords in the field and in the confirmation' do
it 'shows an error message' do
fill_passwords('mypassword', 'mypassword2')
page.within('.alert-danger') do
expect(page).to have_content("Password confirmation doesn't match Password")
end
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_content("Password confirmation doesn't match Password")
expect(page).to have_no_field('user[current_password]')
end
end
it 'does not contain the current password field after an error' do
fill_passwords('mypassword', 'mypassword2')
describe 'User puts the same passwords in the field and in the confirmation' do
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
describe 'User puts the same passwords in the field and in the confirmation' do
it 'shows a success message' do
fill_passwords('mypassword', 'mypassword')
context 'Password authentication unavailable' do
before do
gitlab_sign_in(user)
end
page.within('.flash-notice') do
expect(page).to have_content('Password was successfully updated. Please login with it')
end
context 'Regular user' do
let(:user) { create(:user) }
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
......
......@@ -7,8 +7,8 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do
find(".table.active-tokens")
end
def inactive_personal_access_tokens
find(".table.inactive-tokens")
def no_personal_access_tokens_message
find(".settings-message")
end
def created_personal_access_token
......@@ -80,14 +80,16 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do
visit profile_personal_access_tokens_path
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
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)
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
context "when revocation fails" 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
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')
end
......
......@@ -30,7 +30,7 @@ feature 'No Password Alert' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') }
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])
end
......
......@@ -35,7 +35,7 @@ describe ButtonHelper do
context 'with internal auth disabled' do
before do
stub_application_setting(signin_enabled?: false)
stub_application_setting(password_authentication_enabled?: false)
end
context 'when user has no personal access tokens' do
......
......@@ -160,7 +160,7 @@ describe ProjectsHelper do
context 'user requires a personal access token' 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
end
......@@ -184,7 +184,7 @@ describe ProjectsHelper do
let(:user) { create(:user) }
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>}
end
......
......@@ -206,7 +206,7 @@ describe Gitlab::Auth, lib: true do
end
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)
end
......@@ -279,6 +279,16 @@ describe Gitlab::Auth, lib: true do
gl_auth.find_with_user_password('ldap_user', 'password')
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
private
......
require 'spec_helper'
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) }
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.foobar).to eq('asdf')
end
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
end
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
it 'does not define a predicate method' do
......
......@@ -34,7 +34,7 @@ EOT
describe 'size limit feature toggles' do
context 'when the feature gitlab_git_diff_size_limit_increase is enabled' do
before do
Feature.enable('gitlab_git_diff_size_limit_increase')
stub_feature_flags(gitlab_git_diff_size_limit_increase: true)
end
it 'returns 200 KB for size_limit' do
......@@ -48,7 +48,7 @@ EOT
context 'when the feature gitlab_git_diff_size_limit_increase is disabled' do
before do
Feature.disable('gitlab_git_diff_size_limit_increase')
stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
end
it 'returns 100 KB for size_limit' 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
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
commit_with_old_name = new_commit_edit_old_file(repo)
rename_commit = new_commit_move_file(repo)
commit_with_new_name = new_commit_edit_new_file(repo)
commit_with_old_name = Gitlab::Git::Commit.decorate(new_commit_edit_old_file(repo))
rename_commit = Gitlab::Git::Commit.decorate(new_commit_move_file(repo))
commit_with_new_name = Gitlab::Git::Commit.decorate(new_commit_edit_new_file(repo))
end
after(:context) 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
let(:options) { { ref: "master" } }
let(:commits_by_walk) { repository.log(options).map(&:oid) }
let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:oid) }
let(:commits_by_walk) { repository.log(options).map(&:id) }
let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:id) }
it { expect(commits_by_walk).to eq(commits_by_shell) }
......@@ -924,7 +924,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(commits.size).to be > 0
expect(commits).to satisfy do |commits|
commits.all? { |commit| commit.time >= options[:after] }
commits.all? { |commit| commit.committed_date >= options[:after] }
end
end
end
......@@ -937,7 +937,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(commits.size).to be > 0
expect(commits).to satisfy do |commits|
commits.all? { |commit| commit.time <= options[:before] }
commits.all? { |commit| commit.committed_date <= options[:before] }
end
end
end
......@@ -946,7 +946,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } }
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
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
describe 'project and issue urls' do
let(:project) { create(:empty_project) }
let(:service) { project.create_gitlab_issue_tracker_service(active: true) }
context 'with absolute urls' do
before do
GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root"
@service = project.create_gitlab_issue_tracker_service(active: true)
end
after do
@service.destroy!
allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root")
end
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.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.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.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432")
end
end
context 'with relative urls' do
before do
GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root"
@service = project.create_gitlab_issue_tracker_service(active: true)
end
after do
@service.destroy!
allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root")
end
it 'gives the correct path' do
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.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432")
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.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432")
end
end
end
......
......@@ -2055,6 +2055,28 @@ describe User, models: true do
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
describe '#forget_me!' do
subject { create(:user, remember_created_at: Time.now) }
......
......@@ -35,6 +35,17 @@ describe API::Internal do
expect(json_response).to be_empty
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
describe 'GET /internal/broadcast_messages' do
......
......@@ -13,6 +13,7 @@ describe API::Settings, 'Settings' do
expect(json_response['default_projects_limit']).to eq(42)
expect(json_response['signin_enabled']).to be_truthy
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_url']).to be_nil
expect(json_response['plantuml_enabled']).to be_falsey
......@@ -33,8 +34,8 @@ describe API::Settings, 'Settings' do
it "updates application settings" do
put api("/application/settings", admin),
default_projects_limit: 3,
signin_enabled: false,
repository_storages: ['custom'],
password_authentication_enabled: false,
koding_enabled: true,
koding_url: 'http://koding.example.com',
plantuml_enabled: true,
......@@ -48,6 +49,7 @@ describe API::Settings, 'Settings' do
expect(response).to have_http_status(200)
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_storages']).to eq(['custom'])
expect(json_response['koding_enabled']).to be_truthy
expect(json_response['koding_url']).to eq('http://koding.example.com')
......
......@@ -11,7 +11,7 @@ describe API::V3::Settings, 'Settings' do
expect(response).to have_http_status(200)
expect(json_response).to be_an Hash
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['koding_enabled']).to be_falsey
expect(json_response['koding_url']).to be_nil
......@@ -29,12 +29,12 @@ describe API::V3::Settings, 'Settings' do
it "updates application settings" do
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'
expect(response).to have_http_status(200)
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_storages']).to eq(['custom'])
expect(json_response['koding_enabled']).to be_truthy
......
......@@ -463,7 +463,7 @@ describe 'Git HTTP requests', lib: true do
context 'when internal auth is disabled' 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
it 'rejects pulls with personal access token error message' do
......
......@@ -101,7 +101,7 @@ describe JwtController do
context 'when internal auth is disabled' 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
expect(response).to have_http_status(401)
......
......@@ -59,6 +59,7 @@ RSpec.configure do |config|
config.include ApiHelpers, :api
config.include Gitlab::Routing, type: :routing
config.include MigrationsHelpers, :migration
config.include StubFeatureFlags
config.include EE::LicenseHelpers
config.include Rails.application.routes.url_helpers, type: :routing
......@@ -86,6 +87,8 @@ RSpec.configure do |config|
config.before(:example) do
# Skip pre-receive hook check so we can use the web editor and merge.
allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
# Enable all features by default for testing
allow(Feature).to receive(:enabled?) { true }
end
config.before(:example, :request_store) do
......
module StubFeatureFlags
def stub_feature_flags(features)
features.each do |feature_name, enabled|
allow(Feature).to receive(:enabled?).with(feature_name) { enabled }
allow(Feature).to receive(:enabled?).with(feature_name.to_s) { enabled }
end
end
end
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