Commit 31040b5b authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 185f428f
......@@ -203,6 +203,13 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fixes style-lint errors and warnings for EE builds.scss file.
## 12.2.8
### Fixed (1 change)
- Geo: LFS not being synced. !17633
## 12.2.7
### Security (1 change)
......@@ -471,6 +478,13 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fix alignment of activity dropdown in epic tabs; add counter to discussion tab.
## 12.1.14
### Fixed (1 change)
- Geo: LFS not being synced. !17633
## 12.1.12
### Security (4 changes)
......
......@@ -307,6 +307,13 @@ entry.
- Updates tooltip of 'detached' label/state.
## 12.2.8
### Security (1 change)
- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
## 12.2.7
### Security (1 change)
......@@ -649,6 +656,13 @@ entry.
- Update Packer.gitlab-ci.yml to use latest image. (Kelly Hair)
## 12.1.14
### Security (1 change)
- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
## 12.1.12
### Security (12 changes)
......
......@@ -561,3 +561,6 @@ export const getDateInPast = (date, daysInPast) => {
dateClone.setTime(dateClone.getTime() - daysInPast * 24 * 60 * 60 * 1000),
).toISOString();
};
export const beginOfDayTime = 'T00:00:00Z';
export const endOfDayTime = 'T23:59:59Z';
import LengthValidator from '~/pages/sessions/new/length_validator';
import UsernameValidator from '~/pages/sessions/new/username_validator';
import NoEmojiValidator from '~/emoji/no_emoji_validator';
document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new
new LengthValidator(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
});
.signup-page {
.page-wrap {
background-color: $gray-light;
}
.gitlab-logo {
width: 80px;
height: 80px;
}
.signup-box-container {
max-width: 900px;
&.navless-container {
// overriding .devise-layout-html.navless-container to support the sticky footer
// without having a header on size xs
@include media-breakpoint-down(xs) {
padding: 65px $gl-padding; // height of footer
padding-top: $gl-padding;
}
}
}
.signup-heading h2 {
font-weight: $gl-font-weight-bold;
@include media-breakpoint-down(md) {
font-size: $gl-font-size-large;
}
}
.signup-box {
background-color: $white-light;
box-shadow: 0 0 0 1px $border-color;
border-radius: $border-radius;
}
.form-control {
&:active,
&:focus {
background-color: $white-light;
}
}
.devise-errors {
h2 {
font-size: $gl-font-size;
color: $red-700;
}
}
}
......@@ -215,6 +215,12 @@
body {
// offset height of fixed header + 1 to avoid scroll
height: calc(100% - 51px);
// offset without the header
&.navless {
height: calc(100% - 11px);
}
margin: 0;
padding: 0;
......
......@@ -5,23 +5,21 @@ class HealthController < ActionController::Base
include RequiresWhitelistedMonitoringClient
def readiness
results = checks.flat_map(&:readiness)
success = results.all?(&:success)
# disable static error pages at the gitlab-workhorse level, we want to see this error response even in production
headers["X-GitLab-Custom-Error"] = 1 unless success
response = results.map { |result| [result.name, result.payload] }.to_h
render json: response, status: success ? :ok : :service_unavailable
render_probe(::Gitlab::HealthChecks::Probes::Readiness)
end
def liveness
render json: { status: 'ok' }, status: :ok
render_probe(::Gitlab::HealthChecks::Probes::Liveness)
end
private
def checks
::Gitlab::HealthChecks::CHECKS
def render_probe(probe_class)
result = probe_class.new.execute
# disable static error pages at the gitlab-workhorse level, we want to see this error response even in production
headers["X-GitLab-Custom-Error"] = 1 unless result.success?
render json: result.json, status: result.http_status
end
end
......@@ -6,13 +6,19 @@ class RegistrationsController < Devise::RegistrationsController
include RecaptchaExperimentHelper
include InvisibleCaptcha
layout :choose_layout
prepend_before_action :check_captcha, only: :create
before_action :whitelist_query_limiting, only: [:destroy]
before_action :ensure_terms_accepted,
if: -> { action_name == 'create' && Gitlab::CurrentSettings.current_application_settings.enforce_terms? }
def new
redirect_to(new_user_session_path)
if helpers.use_experimental_separate_sign_up_flow?
@resource = build_resource
else
redirect_to new_user_session_path(anchor: 'register-pane')
end
end
def create
......@@ -144,6 +150,16 @@ class RegistrationsController < Devise::RegistrationsController
def stored_location_or_dashboard(user)
stored_location_for(user) || dashboard_projects_path
end
# Part of an experiment to build a new sign up flow. Will be resolved
# with https://gitlab.com/gitlab-org/growth/engineering/issues/64
def choose_layout
if helpers.use_experimental_separate_sign_up_flow?
'devise_experimental_separate_sign_up_flow'
else
'devise'
end
end
end
RegistrationsController.prepend_if_ee('EE::RegistrationsController')
......@@ -4,4 +4,8 @@ module SessionsHelper
def unconfirmed_email?
flash[:alert] == t(:unconfirmed, scope: [:devise, :failure])
end
def use_experimental_separate_sign_up_flow?
::Gitlab.dev_env_or_com? && Feature.enabled?(:experimental_separate_sign_up_flow)
end
end
# frozen_string_literal: true
# Add methods used by the groups API
module GroupAPICompatibility
extend ActiveSupport::Concern
def project_creation_level_str
::Gitlab::Access.project_creation_string_options.key(project_creation_level)
end
def project_creation_level_str=(value)
write_attribute(:project_creation_level, ::Gitlab::Access.project_creation_string_options.fetch(value))
end
def subgroup_creation_level_str
::Gitlab::Access.subgroup_creation_string_options.key(subgroup_creation_level)
end
def subgroup_creation_level_str=(value)
write_attribute(:subgroup_creation_level, ::Gitlab::Access.subgroup_creation_string_options.fetch(value))
end
end
......@@ -14,6 +14,7 @@ class Group < Namespace
include TokenAuthenticatable
include WithUploads
include Gitlab::Utils::StrongMemoize
include GroupAPICompatibility
ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
......
......@@ -256,7 +256,7 @@ class Namespace < ApplicationRecord
end
def has_parent?
parent.present?
parent_id.present? || parent.present?
end
def root_ancestor
......
......@@ -5,7 +5,7 @@ module DataFields
class_methods do
# Provide convenient accessor methods for data fields.
# TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
def data_field(*args)
args.each do |arg|
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
......
......@@ -4,7 +4,7 @@ class IssueTrackerService < Service
validate :one_issue_tracker, if: :activated?, on: :manual_change
# TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# https://gitlab.com/gitlab-org/gitlab/issues/29404
data_field :project_url, :issues_url, :new_issue_url
default_value_for :category, 'issue_tracker'
......@@ -25,7 +25,7 @@ class IssueTrackerService < Service
end
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
def title
if title_attribute = read_attribute(:title)
title_attribute
......@@ -36,7 +36,7 @@ class IssueTrackerService < Service
end
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
def description
if description_attribute = read_attribute(:description)
description_attribute
......@@ -49,7 +49,7 @@ class IssueTrackerService < Service
def handle_properties
# this has been moved from initialize_properties and should be improved
# as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
return unless properties
@legacy_properties_data = properties.dup
......
......@@ -19,7 +19,7 @@ class JiraService < IssueTrackerService
# for more information check: https://gitlab.com/gitlab-org/gitlab-foss/issues/49936.
# TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# https://gitlab.com/gitlab-org/gitlab/issues/29404
data_field :username, :password, :url, :api_url, :jira_issue_transition_id
before_update :reset_password
......
......@@ -7,7 +7,7 @@
in running SQL queries. These settings require a
= link_to 'restart', help_page_path('administration/restart_gitlab')
to take effect.
= link_to icon('question-circle'), help_page_path('administration/monitoring/performance/introduction')
= link_to icon('question-circle'), help_page_path('administration/monitoring/performance/index')
.form-group
.form-check
= f.check_box :metrics_enabled, class: 'form-check-input'
......
- page_title "Sign up"
= render 'devise/shared/signup_box'
- if use_experimental_separate_sign_up_flow?
= render 'devise/shared/experimental_separate_sign_up_flow_box'
- else
= render 'devise/shared/signup_box'
= render 'devise/shared/sign_in_link'
......@@ -4,6 +4,7 @@
- if form_based_providers.any?
= render 'devise/shared/tabs_ldap'
- else
- unless use_experimental_separate_sign_up_flow?
= render 'devise/shared/tabs_normal'
.tab-content
- if password_authentication_enabled_for_web? || ldap_enabled? || crowd_enabled?
......
- max_name_length = 128
- max_username_length = 255
.signup-box.p-3.mb-2
.signup-body
= form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
.devise-errors.mt-0
= render "devise/shared/error_messages", resource: resource
= invisible_captcha
.name.form-group
= f.label :name, _('Full name'), class: 'label-bold'
= f.text_field :name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_name_length, :max_length_message => s_("SignUp|Name is too long (maximum is %{max_length} characters).") % { max_length: max_name_length }, :qa_selector => 'new_user_name_field' }, required: true, title: _("This field is required.")
.username.form-group
= f.label :username, class: 'label-bold'
= f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
%p.validation-error.gl-field-error-ignore.field-validation.mt-1.hide.cred= _('Username is already taken.')
%p.validation-success.gl-field-error-ignore.field-validation.mt-1.hide.cgreen= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.field-validation.mt-1.hide= _('Checking username availability...')
.form-group
= f.label :email, class: 'label-bold'
= f.email_field :email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.")
.form-group.append-bottom-20#password-strength
= f.label :password, class: 'label-bold'
= f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length }
%p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length }
- if Gitlab::CurrentSettings.current_application_settings.enforce_terms?
.form-group
= check_box_tag :terms_opt_in, '1', false, required: true, data: { qa_selector: 'new_user_accept_terms_checkbox' }
= label_tag :terms_opt_in do
- terms_link = link_to s_("I accept the|Terms of Service and Privacy Policy"), terms_path, target: "_blank"
- accept_terms_label = _("I accept the %{terms_link}") % { terms_link: terms_link }
= accept_terms_label.html_safe
= render_if_exists 'devise/shared/email_opted_in', f: f
.submit-container.mt-3
= f.submit _("Register"), class: "btn-register btn btn-block btn-success mb-0 p-2", data: { qa_selector: 'new_user_register_button' }
%p
%p.text-center
%span.light
Already have login and password?
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
......@@ -22,3 +22,8 @@
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
- if use_experimental_separate_sign_up_flow?
%p.light.mt-2
= _("Don't have an account yet?")
= link_to _("Register now"), new_registration_path(:user)
- page_description brand_title unless page_description
-# Needs a redirect on the client side since it's using an anchor to distuingish
-# between sign in and registration. We need to inline the JS to not render
-# anything from this page beforehand.
-# Part of an experiment to build a new sign up flow. Will be removed again with
-# https://gitlab.com/gitlab-org/growth/engineering/issues/64
- if use_experimental_separate_sign_up_flow? && current_path?("sessions#new")
= javascript_tag nonce: true do
:plain
if (window.location.hash === '#register-pane') {
window.location.replace("/users/sign_up")
}
- site_name = "GitLab"
%head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" }
......
!!! 5
%html.devise-layout-html.navless{ class: system_message_class }
= render "layouts/head"
%body.ui-indigo.signup-page.application.navless{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } }
= header_message
= render "layouts/init_client_detection_flags"
.page-wrap
.container.signup-box-container.navless-container.mt-0
= render "layouts/broadcast"
.content
= render "layouts/flash"
.row.mb-3
.col-sm-8.offset-sm-2.col-md-6.offset-md-3.new-session-forms-container
= render_if_exists 'layouts/devise_help_text'
.text-center.signup-heading.mt-3.mb-3
= image_tag(image_url('logo.svg'), class: 'gitlab-logo', alt: 'GitLab Logo')
%h2= _('Register for GitLab.com')
= yield
%hr.footer-fixed
.footer-container
.container
.footer-links
= link_to _("Help"), help_path
= link_to _("About GitLab"), "https://about.gitlab.com/"
= footer_message
---
title: Experimental separate sign up flow
merge_request: 16482
author:
type: other
---
title: Export liveness and readiness probes
merge_request:
author:
type: changed
---
title: Fix moved help URL for monitoring performance
merge_request:
author:
type: fixed
---
title: 'API: Add missing group parameters'
merge_request: 17220
author: Mathieu Parent
type: added
---
title: Limit search for IID to a type to avoid leaking records with the same IID that
the user does not have access to
merge_request:
author:
type: security
......@@ -31,6 +31,13 @@ GET /groups
"path": "foo-bar",
"description": "An interesting group",
"visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "owner",
"emails_disabled": null,
"lfs_enabled": true,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
......@@ -57,6 +64,13 @@ GET /groups?statistics=true
"path": "foo-bar",
"description": "An interesting group",
"visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "owner",
"emails_disabled": null,
"lfs_enabled": true,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
......@@ -119,6 +133,13 @@ GET /groups/:id/subgroups
"path": "foo-bar",
"description": "An interesting group",
"visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "owner",
"emails_disabled": null,
"lfs_enabled": true,
"avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg",
"web_url": "http://gitlab.example.com/groups/foo-bar",
......@@ -434,6 +455,13 @@ Parameters:
| `path` | string | yes | The path of the group. |
| `description` | string | no | The group's description. |
| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `subgroup_creation_level` | integer | no | Allowed to create subgroups. Can be `owner` (Owners), or `maintainer` (Maintainers). |
| `emails_disabled` | boolean | no | Disable email notifications |
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
| `parent_id` | integer | no | The parent group ID for creating nested group. |
......@@ -472,6 +500,13 @@ PUT /groups/:id
| `membership_lock` | boolean | no | **(STARTER)** Prevent adding new members to project membership within this group. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `subgroup_creation_level` | integer | no | Allowed to create subgroups. Can be `owner` (Owners), or `maintainer` (Maintainers). |
| `emails_disabled` | boolean | no | Disable email notifications |
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
......
......@@ -378,6 +378,13 @@ module API
class Group < BasicGroupDetails
expose :path, :description, :visibility
expose :share_with_group_lock
expose :require_two_factor_authentication
expose :two_factor_grace_period
expose :project_creation_level_str, as: :project_creation_level
expose :auto_devops_enabled
expose :subgroup_creation_level_str, as: :subgroup_creation_level
expose :emails_disabled
expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url do |group, options|
group.avatar_url(only_path: false)
......
......@@ -11,9 +11,15 @@ module API
optional :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the group'
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users in this group to setup Two-factor authentication'
optional :two_factor_grace_period, type: Integer, desc: 'Time before Two-factor authentication is enforced'
optional :project_creation_level, type: String, values: ::Gitlab::Access.project_creation_string_values, desc: 'Determine if developers can create projects in the group', as: :project_creation_level_str
optional :auto_devops_enabled, type: Boolean, desc: 'Default to Auto DevOps pipeline for all projects within this group'
optional :subgroup_creation_level, type: String, values: ::Gitlab::Access.subgroup_creation_string_values, desc: 'Allowed to create subgroups', as: :subgroup_creation_level_str
optional :emails_disabled, type: Boolean, desc: 'Disable email notifications'
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
end
params :optional_params_ee do
......
......@@ -103,10 +103,22 @@ module Gitlab
}
end
def project_creation_string_options
{
'noone' => NO_ONE_PROJECT_ACCESS,
'maintainer' => MAINTAINER_PROJECT_ACCESS,
'developer' => DEVELOPER_MAINTAINER_PROJECT_ACCESS
}
end
def project_creation_values
project_creation_options.values
end
def project_creation_string_values
project_creation_string_options.keys
end
def project_creation_level_name(name)
project_creation_options.key(name)
end
......@@ -117,6 +129,21 @@ module Gitlab
s_('SubgroupCreationlevel|Maintainers') => MAINTAINER_SUBGROUP_ACCESS
}
end
def subgroup_creation_string_options
{
'owner' => OWNER_SUBGROUP_ACCESS,
'maintainer' => MAINTAINER_SUBGROUP_ACCESS
}
end
def subgroup_creation_values
subgroup_creation_options.values
end
def subgroup_creation_string_values
subgroup_creation_string_options.keys
end
end
def human_access
......
# frozen_string_literal: true
module Gitlab
module HealthChecks
module Probes
class Liveness
def execute
Probes::Status.new(200, status: 'ok')
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module HealthChecks
module Probes
class Readiness
attr_reader :checks
# This accepts an array of Proc
# that returns `::Gitlab::HealthChecks::Result`
def initialize(*additional_checks)
@checks = ::Gitlab::HealthChecks::CHECKS.map { |check| check.method(:readiness) }
@checks += additional_checks
end
def execute
readiness = probe_readiness
success = all_succeeded?(readiness)
Probes::Status.new(
success ? 200 : 503,
status(success).merge(payload(readiness))
)
end
private
def all_succeeded?(readiness)
readiness.all? do |name, probes|
probes.any?(&:success)
end
end
def status(success)
{ status: success ? 'ok' : 'failed' }
end
def payload(readiness)
readiness.transform_values do |probes|
probes.map(&:payload)
end
end
def probe_readiness
checks
.flat_map(&:call)
.compact
.group_by(&:name)
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module HealthChecks
module Probes
Status = Struct.new(:http_status, :json) do
# We accept 2xx
def success?
http_status / 100 == 2
end
end
end
end
end
......@@ -31,7 +31,15 @@ module Gitlab
@server = ::WEBrick::HTTPServer.new(
Port: settings.port, BindAddress: settings.address,
Logger: logger, AccessLog: access_log)
server.mount "/", Rack::Handler::WEBrick, rack_app
server.mount_proc '/readiness' do |req, res|
render_probe(
::Gitlab::HealthChecks::Probes::Readiness.new, req, res)
end
server.mount_proc '/liveness' do |req, res|
render_probe(
::Gitlab::HealthChecks::Probes::Liveness.new, req, res)
end
server.mount '/', Rack::Handler::WEBrick, rack_app
server.start
end
......@@ -51,6 +59,14 @@ module Gitlab
run -> (env) { [404, {}, ['']] }
end
end
def render_probe(probe, req, res)
result = probe.execute
res.status = result.http_status
res.content_type = 'application/json; charset=utf-8'
res.body = result.json.to_json
end
end
end
end
......
......@@ -5472,6 +5472,9 @@ msgstr ""
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
msgid "Don't have an account yet?"
msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
......@@ -13081,6 +13084,12 @@ msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
msgid "Register for GitLab.com"
msgstr ""
msgid "Register now"
msgstr ""
msgid "Register with two-factor app"
msgstr ""
......
......@@ -259,6 +259,7 @@ module QA
module Milestone
autoload :New, 'qa/page/project/milestone/new'
autoload :Index, 'qa/page/project/milestone/index'
autoload :Show, 'qa/page/project/milestone/show'
end
module Operations
......@@ -449,6 +450,7 @@ module QA
autoload :Logging, 'qa/support/page/logging'
end
autoload :Api, 'qa/support/api'
autoload :Dates, 'qa/support/dates'
autoload :Waiter, 'qa/support/waiter'
autoload :Retrier, 'qa/support/retrier'
end
......
......@@ -17,5 +17,3 @@ module QA
end
end
end
QA::Page::Project::Milestone::Index.prepend_if_ee('QA::EE::Page::Project::Milestone::Index')
# frozen_string_literal: true
module QA
module Page
module Project
module Milestone
class Show < Page::Base
end
end
end
end
end
QA::Page::Project::Milestone::Show.prepend_if_ee('QA::EE::Page::Project::Milestone::Show')
# frozen_string_literal: true
module QA
module Support
module Dates
def current_date_yyyy_mm_dd
current_date.strftime("%Y/%m/%d")
end
def next_month_yyyy_mm_dd
current_date.next_month.strftime("%Y/%m/%d")
end
private
def current_date
DateTime.now
end
end
end
end
......@@ -24,11 +24,12 @@ describe HealthController do
it 'responds with readiness checks data' do
subject
expect(json_response['db_check']['status']).to eq('ok')
expect(json_response['cache_check']['status']).to eq('ok')
expect(json_response['queues_check']['status']).to eq('ok')
expect(json_response['shared_state_check']['status']).to eq('ok')
expect(json_response['gitaly_check']['status']).to eq('ok')
expect(json_response['db_check']).to contain_exactly({ 'status' => 'ok' })
expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
expect(json_response['queues_check']).to contain_exactly({ 'status' => 'ok' })
expect(json_response['shared_state_check']).to contain_exactly({ 'status' => 'ok' })
expect(json_response['gitaly_check']).to contain_exactly(
{ 'status' => 'ok', 'labels' => { 'shard' => 'default' } })
end
it 'responds with readiness checks data when a failure happens' do
......@@ -37,9 +38,9 @@ describe HealthController do
subject
expect(json_response['redis_check']['status']).to eq('failed')
expect(json_response['redis_check']['message']).to eq('check error')
expect(json_response['cache_check']['status']).to eq('ok')
expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
expect(json_response['redis_check']).to contain_exactly(
{ 'status' => 'failed', 'message' => 'check error' })
expect(response.status).to eq(503)
expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
......@@ -90,7 +91,7 @@ describe HealthController do
it 'responds with liveness checks data' do
subject
expect(json_response['status']).to eq('ok')
expect(json_response).to eq('status' => 'ok')
end
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
describe 'Signup' do
shared_examples 'Signup' do
include TermsHelper
before do
......@@ -13,8 +13,7 @@ describe 'Signup' do
describe 'username validation', :js do
before do
visit root_path
click_link 'Register'
visit new_user_registration_path
end
it 'does not show an error border if the username is available' do
......@@ -130,8 +129,7 @@ describe 'Signup' do
describe 'user\'s full name validation', :js do
before do
visit root_path
click_link 'Register'
visit new_user_registration_path
end
it 'does not show an error border if the user\'s fullname length is not longer than 128 characters' do
......@@ -177,12 +175,16 @@ describe 'Signup' do
end
it 'creates the user account and sends a confirmation email' do
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
expect { click_button 'Register' }.to change { User.count }.by(1)
......@@ -198,12 +200,16 @@ describe 'Signup' do
end
it 'creates the user account and sends a confirmation email' do
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
expect { click_button 'Register' }.to change { User.count }.by(1)
......@@ -216,12 +222,16 @@ describe 'Signup' do
context "when sigining up with different cased emails" do
it "creates the user successfully" do
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email.capitalize
end
fill_in 'new_user_password', with: new_user.password
click_button "Register"
......@@ -236,12 +246,16 @@ describe 'Signup' do
end
it 'creates the user account and goes to dashboard' do
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
click_button "Register"
......@@ -255,7 +269,7 @@ describe 'Signup' do
it "displays the errors" do
existing_user = create(:user)
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
......@@ -264,15 +278,21 @@ describe 'Signup' do
click_button "Register"
expect(current_path).to eq user_registration_path
if Feature.enabled?(:experimental_separate_sign_up_flow)
expect(page).to have_content("error prohibited this user from being saved")
expect(page).to have_content("Email has already been taken")
else
expect(page).to have_content("errors prohibited this user from being saved")
expect(page).to have_content("Email has already been taken")
expect(page).to have_content("Email confirmation doesn't match")
end
end
it 'does not redisplay the password' do
existing_user = create(:user)
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
......@@ -291,12 +311,16 @@ describe 'Signup' do
end
it 'requires the user to check the checkbox' do
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
click_button 'Register'
......@@ -306,12 +330,16 @@ describe 'Signup' do
end
it 'asks the user to accept terms before going to the dashboard' do
visit root_path
visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
check :terms_opt_in
......@@ -321,3 +349,20 @@ describe 'Signup' do
end
end
end
describe 'With original flow' do
it_behaves_like 'Signup' do
before do
stub_feature_flags(experimental_separate_sign_up_flow: false)
end
end
end
describe 'With experimental flow on GitLab.com' do
it_behaves_like 'Signup' do
before do
expect(Gitlab).to receive(:com?).and_return(true).at_least(:once)
stub_feature_flags(experimental_separate_sign_up_flow: true)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::HealthChecks::Probes::Liveness do
let(:liveness) { described_class.new }
describe '#call' do
subject { liveness.execute }
it 'responds with liveness checks data' do
expect(subject.http_status).to eq(200)
expect(subject.json[:status]).to eq('ok')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::HealthChecks::Probes::Readiness do
let(:readiness) { described_class.new }
describe '#call' do
subject { readiness.execute }
it 'responds with readiness checks data' do
expect(subject.http_status).to eq(200)
expect(subject.json[:status]).to eq('ok')
expect(subject.json['db_check']).to contain_exactly(status: 'ok')
expect(subject.json['cache_check']).to contain_exactly(status: 'ok')
expect(subject.json['queues_check']).to contain_exactly(status: 'ok')
expect(subject.json['shared_state_check']).to contain_exactly(status: 'ok')
expect(subject.json['gitaly_check']).to contain_exactly(
status: 'ok', labels: { shard: 'default' })
end
context 'when Redis fails' do
before do
allow(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_return(
Gitlab::HealthChecks::Result.new('redis_check', false, "check error"))
end
it 'responds with failure' do
expect(subject.http_status).to eq(503)
expect(subject.json[:status]).to eq('failed')
expect(subject.json['cache_check']).to contain_exactly(status: 'ok')
expect(subject.json['redis_check']).to contain_exactly(
status: 'failed', message: 'check error')
end
end
end
end
......@@ -4,35 +4,42 @@ require 'spec_helper'
describe Gitlab::Metrics::Exporter::BaseExporter do
let(:exporter) { described_class.new }
let(:server) { double('server') }
let(:socket) { double('socket') }
let(:log_filename) { File.join(Rails.root, 'log', 'sidekiq_exporter.log') }
let(:settings) { double('settings') }
before do
allow(::WEBrick::HTTPServer).to receive(:new).and_return(server)
allow(server).to receive(:mount)
allow(server).to receive(:start)
allow(server).to receive(:shutdown)
allow(server).to receive(:listeners) { [socket] }
allow(socket).to receive(:close)
allow_any_instance_of(described_class).to receive(:log_filename).and_return(log_filename)
allow_any_instance_of(described_class).to receive(:settings).and_return(settings)
end
describe 'when exporter is enabled' do
before do
allow(::WEBrick::HTTPServer).to receive(:new).with(
Port: anything,
BindAddress: anything,
Logger: anything,
AccessLog: anything
).and_wrap_original do |m, *args|
m.call(DoNotListen: true, Logger: args.first[:Logger])
end
allow_any_instance_of(::WEBrick::HTTPServer).to receive(:start)
allow(settings).to receive(:enabled).and_return(true)
allow(settings).to receive(:port).and_return(3707)
allow(settings).to receive(:port).and_return(8082)
allow(settings).to receive(:address).and_return('localhost')
end
after do
exporter.stop
end
describe 'when exporter is stopped' do
describe '#start' do
it 'starts the exporter' do
expect { exporter.start.join }.to change { exporter.thread? }.from(false).to(true)
expect_any_instance_of(::WEBrick::HTTPServer).to receive(:start)
expect(server).to have_received(:start)
expect { exporter.start.join }.to change { exporter.thread? }.from(false).to(true)
end
describe 'with custom settings' do
......@@ -45,23 +52,25 @@ describe Gitlab::Metrics::Exporter::BaseExporter do
end
it 'starts server with port and address from settings' do
exporter.start.join
expect(::WEBrick::HTTPServer).to have_received(:new).with(
expect(::WEBrick::HTTPServer).to receive(:new).with(
Port: port,
BindAddress: address,
Logger: anything,
AccessLog: anything
)
).and_wrap_original do |m, *args|
m.call(DoNotListen: true, Logger: args.first[:Logger])
end
exporter.start.join
end
end
end
describe '#stop' do
it "doesn't shutdown stopped server" do
expect { exporter.stop }.not_to change { exporter.thread? }
expect_any_instance_of(::WEBrick::HTTPServer).not_to receive(:shutdown)
expect(server).not_to have_received(:shutdown)
expect { exporter.stop }.not_to change { exporter.thread? }
end
end
end
......@@ -73,19 +82,65 @@ describe Gitlab::Metrics::Exporter::BaseExporter do
describe '#start' do
it "doesn't start running server" do
expect { exporter.start.join }.not_to change { exporter.thread? }
expect_any_instance_of(::WEBrick::HTTPServer).not_to receive(:start)
expect(server).to have_received(:start).once
expect { exporter.start.join }.not_to change { exporter.thread? }
end
end
describe '#stop' do
it 'shutdowns server' do
expect_any_instance_of(::WEBrick::HTTPServer).to receive(:shutdown)
expect { exporter.stop }.to change { exporter.thread? }.from(true).to(false)
end
end
end
end
describe 'request handling' do
using RSpec::Parameterized::TableSyntax
expect(socket).to have_received(:close)
expect(server).to have_received(:shutdown)
where(:method_class, :path, :http_status) do
Net::HTTP::Get | '/metrics' | 200
Net::HTTP::Get | '/liveness' | 200
Net::HTTP::Get | '/readiness' | 200
Net::HTTP::Get | '/' | 404
end
before do
allow(settings).to receive(:enabled).and_return(true)
allow(settings).to receive(:port).and_return(0)
allow(settings).to receive(:address).and_return('127.0.0.1')
# We want to wrap original method
# and run handling of requests
# in separate thread
allow_any_instance_of(::WEBrick::HTTPServer)
.to receive(:start).and_wrap_original do |m, *args|
Thread.new do
m.call(*args)
rescue IOError
# is raised as we close listeners
end
end
exporter.start.join
end
after do
exporter.stop
end
with_them do
let(:config) { exporter.server.config }
let(:request) { method_class.new(path) }
it 'responds with proper http_status' do
http = Net::HTTP.new(config[:BindAddress], config[:Port])
response = http.request(request)
expect(response.code).to eq(http_status.to_s)
end
end
end
......@@ -97,18 +152,18 @@ describe Gitlab::Metrics::Exporter::BaseExporter do
describe '#start' do
it "doesn't start" do
expect_any_instance_of(::WEBrick::HTTPServer).not_to receive(:start)
expect(exporter.start).to be_nil
expect { exporter.start }.not_to change { exporter.thread? }
expect(server).not_to have_received(:start)
end
end
describe '#stop' do
it "doesn't shutdown" do
expect { exporter.stop }.not_to change { exporter.thread? }
expect_any_instance_of(::WEBrick::HTTPServer).not_to receive(:shutdown)
expect(server).not_to have_received(:shutdown)
expect { exporter.stop }.not_to change { exporter.thread? }
end
end
end
......
......@@ -880,22 +880,6 @@ describe Group do
end
end
describe '#has_parent?' do
context 'when the group has a parent' do
it 'is truthy' do
group = create(:group, :nested)
expect(group.has_parent?).to be_truthy
end
end
context 'when the group has no parent' do
it 'is falsy' do
group = create(:group, parent: nil)
expect(group.has_parent?).to be_falsy
end
end
end
context 'with uploads' do
it_behaves_like 'model with uploads', true do
let(:model_object) { create(:group, :with_avatar) }
......
......@@ -933,4 +933,25 @@ describe Namespace do
end
end
end
describe '#has_parent?' do
it 'returns true when the group has a parent' do
group = create(:group, :nested)
expect(group.has_parent?).to be_truthy
end
it 'returns true when the group has an unsaved parent' do
parent = build(:group)
group = build(:group, parent: parent)
expect(group.has_parent?).to be_truthy
end
it 'returns false when the group has no parent' do
group = create(:group, parent: nil)
expect(group.has_parent?).to be_falsy
end
end
end
......@@ -41,7 +41,7 @@ describe BugzillaService do
{ project_url: url, issues_url: url, new_issue_url: url }
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { access_params.merge(title: title, description: description) }
let(:service) do
......
......@@ -55,7 +55,7 @@ describe CustomIssueTrackerService do
{ project_url: url, issues_url: url, new_issue_url: url }
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { access_params.merge(title: title, description: description) }
let(:service) do
......
......@@ -58,7 +58,7 @@ describe GitlabIssueTrackerService do
{ project_url: url, issues_url: url, new_issue_url: url }
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { access_params.merge(title: title, description: description) }
let(:service) do
......
......@@ -278,7 +278,7 @@ describe JiraService do
end
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { data_params.merge(title: title, description: description) }
let!(:service) do
......
......@@ -57,7 +57,7 @@ describe RedmineService do
{ project_url: url, issues_url: url, new_issue_url: url }
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { access_params.merge(title: title, description: description) }
let(:service) do
......
......@@ -45,7 +45,7 @@ describe YoutrackService do
{ project_url: url, issues_url: url, new_issue_url: url }
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { access_params.merge(title: title, description: description) }
let(:service) do
......
......@@ -121,7 +121,7 @@ describe Service do
end
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-foss/issues/63084
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { data_params.merge(title: title, description: description) }
let!(:template) do
......
require 'spec_helper'
describe API::Groups do
include GroupAPIHelpers
include UploadHelpers
let(:user1) { create(:user, can_create_group: false) }
......@@ -350,6 +351,13 @@ describe API::Groups do
expect(json_response['description']).to eq(group1.description)
expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level))
expect(json_response['avatar_url']).to eq(group1.avatar_url(only_path: false))
expect(json_response['share_with_group_lock']).to eq(group1.share_with_group_lock)
expect(json_response['require_two_factor_authentication']).to eq(group1.require_two_factor_authentication)
expect(json_response['two_factor_grace_period']).to eq(group1.two_factor_grace_period)
expect(json_response['auto_devops_enabled']).to eq(group1.auto_devops_enabled)
expect(json_response['emails_disabled']).to eq(group1.emails_disabled)
expect(json_response['project_creation_level']).to eq('maintainer')
expect(json_response['subgroup_creation_level']).to eq('maintainer')
expect(json_response['web_url']).to eq(group1.web_url)
expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled)
expect(json_response['full_name']).to eq(group1.full_name)
......@@ -485,11 +493,30 @@ describe API::Groups do
context 'when authenticated as the group owner' do
it 'updates the group' do
put api("/groups/#{group1.id}", user1), params: { name: new_group_name, request_access_enabled: true }
put api("/groups/#{group1.id}", user1), params: {
name: new_group_name,
request_access_enabled: true,
project_creation_level: "noone",
subgroup_creation_level: "maintainer"
}
expect(response).to have_gitlab_http_status(200)
expect(json_response['name']).to eq(new_group_name)
expect(json_response['description']).to eq('')
expect(json_response['visibility']).to eq('public')
expect(json_response['share_with_group_lock']).to eq(false)
expect(json_response['require_two_factor_authentication']).to eq(false)
expect(json_response['two_factor_grace_period']).to eq(48)
expect(json_response['auto_devops_enabled']).to eq(nil)
expect(json_response['emails_disabled']).to eq(nil)
expect(json_response['project_creation_level']).to eq("noone")
expect(json_response['subgroup_creation_level']).to eq("maintainer")
expect(json_response['request_access_enabled']).to eq(true)
expect(json_response['parent_id']).to eq(nil)
expect(json_response['projects']).to be_an Array
expect(json_response['projects'].length).to eq(2)
expect(json_response['shared_projects']).to be_an Array
expect(json_response['shared_projects'].length).to eq(0)
end
it 'returns 404 for a non existing group' do
......@@ -864,7 +891,9 @@ describe API::Groups do
describe "POST /groups" do
context "when authenticated as user without group permissions" do
it "does not create group" do
post api("/groups", user1), params: attributes_for(:group)
group = attributes_for_group_api
post api("/groups", user1), params: group
expect(response).to have_gitlab_http_status(403)
end
......@@ -896,7 +925,7 @@ describe API::Groups do
context "when authenticated as user with group permissions" do
it "creates group" do
group = attributes_for(:group, { request_access_enabled: false })
group = attributes_for_group_api request_access_enabled: false
post api("/groups", user3), params: group
......@@ -911,7 +940,7 @@ describe API::Groups do
it "creates a nested group" do
parent = create(:group)
parent.add_owner(user3)
group = attributes_for(:group, { parent_id: parent.id })
group = attributes_for_group_api parent_id: parent.id
post api("/groups", user3), params: group
......
......@@ -634,10 +634,47 @@ describe API::Users do
end
describe "GET /users/sign_up" do
context 'when experimental_separate_sign_up_flow is active' do
before do
stub_feature_flags(experimental_separate_sign_up_flow: true)
end
context 'on gitlab.com' do
before do
allow(::Gitlab).to receive(:com?).and_return(true)
end
it "shows sign up page" do
get "/users/sign_up"
expect(response).to have_gitlab_http_status(200)
expect(response).to render_template(:new)
end
end
context 'not on gitlab.com' do
before do
allow(::Gitlab).to receive(:com?).and_return(false)
end
it "redirects to sign in page" do
get "/users/sign_up"
expect(response).to have_gitlab_http_status(302)
expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane'))
end
end
end
context 'when experimental_separate_sign_up_flow is not active' do
before do
allow(::Gitlab).to receive(:com?).and_return(true)
stub_feature_flags(experimental_separate_sign_up_flow: false)
end
it "redirects to sign in page" do
get "/users/sign_up"
expect(response).to have_gitlab_http_status(302)
expect(response).to redirect_to(new_user_session_path)
expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane'))
end
end
end
......
# frozen_string_literal: true
module GroupAPIHelpers
extend self
def attributes_for_group_api(params = {})
# project_creation_level and subgroup_creation_level are Integers in the model
# but are strings in the API
attributes_for(:group, params).except(:project_creation_level, :subgroup_creation_level)
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