diff --git a/CHANGELOG.md b/CHANGELOG.md index edae647f1f4..c9d7a0a6131 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 14.2.2 (2021-08-31) + +### Security (9 changes) + +- [Prevent non-admins from configuring Jira connect app](gitlab-org/security/gitlab@1bc56361c9daa90accea65836d5a424168a2c544) ([merge request](gitlab-org/security/gitlab!1697)) +- [Only create jira connect NS subscriptions for admins](gitlab-org/security/gitlab@c160da2cb32a5774fef149155cfd397981bf9173) ([merge request](gitlab-org/security/gitlab!1698)) +- [Update apollo_upload_server dependency](gitlab-org/security/gitlab@5ef659b8c9a5a7338830171c62943d3b8bb16410) ([merge request](gitlab-org/security/gitlab!1699)) +- [Ensure shared group members lose project access after group deletion](gitlab-org/security/gitlab@c94e934234a90f82e7fe291ed0f1d6a763b9a977) ([merge request](gitlab-org/security/gitlab!1683)) +- [Update Import/Export to use public email when mapping users](gitlab-org/security/gitlab@13fb902c55c2dfe7ec2bf35f58a9cb3d93905d9a) ([merge request](gitlab-org/security/gitlab!1669)) **GitLab Enterprise Edition** +- [Require sign in for .keys endpoint on non-public instances](gitlab-org/security/gitlab@0979dd458e8fa0d4f5e184ef0b9ea042d79f6c14) ([merge request](gitlab-org/security/gitlab!1676)) +- [Inherit user external status while creating project bots](gitlab-org/security/gitlab@93062909ffc093cb8f718a3ea3f2976292a9b9af) ([merge request](gitlab-org/security/gitlab!1675)) +- [Escape issue reference and title for Jira issues](gitlab-org/security/gitlab@d25ef8599ec03ee80ef1bff7067b2269836400cf) ([merge request](gitlab-org/security/gitlab!1673)) **GitLab Enterprise Edition** +- [Fix stored XSS vulnerability in Datadog settings form](gitlab-org/security/gitlab@23b98dac7864992898992a153950247ac6ccb933) ([merge request](gitlab-org/security/gitlab!1670)) + ## 14.2.1 (2021-08-23) ### Fixed (1 change) @@ -563,6 +577,19 @@ entry. - [Add helpful text to URL group validation and limit text](gitlab-org/gitlab@59a5a6266cb0d5434596170ffa36e4e74b8d2c2c) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65369)) **GitLab Enterprise Edition** - [Refactor external storage admin area configuration UI and docs](gitlab-org/gitlab@497ba4fc8f4ec1d234c9f5f1ec5c69712b8c7cb3) ([merge request](gitlab-org/gitlab!66219)) +## 14.1.4 (2021-08-31) + +### Security (8 changes) + +- [Update apollo_upload_server dependency](gitlab-org/security/gitlab@34e7e3b7590fd76d0f618091551651e8065edfd2) ([merge request](gitlab-org/security/gitlab!1700)) +- [Ensure shared group members lose project access after group deletion](gitlab-org/security/gitlab@4a7b8203776b719c06186c1b189a8cf21572fcd4) ([merge request](gitlab-org/security/gitlab!1684)) +- [Fix stored XSS vulnerability in Datadog settings form](gitlab-org/security/gitlab@0906814af604e7fcab54a96bccadcba11207387d) ([merge request](gitlab-org/security/gitlab!1671)) +- [Inherit user external status while creating project bots](gitlab-org/security/gitlab@d5a26c4145d917b5b49e207e03669d2b7e4ee617) ([merge request](gitlab-org/security/gitlab!1665)) +- [Escape issue reference and title for Jira issues](gitlab-org/security/gitlab@4153444b76421ddf3a7fd21f1fc0500700a4e263) ([merge request](gitlab-org/security/gitlab!1662)) **GitLab Enterprise Edition** +- [Require sign in for .keys endpoint on non-public instances](gitlab-org/security/gitlab@b090b3f6dee6d21d93595c5e46e6c5c7fc30f1fb) ([merge request](gitlab-org/security/gitlab!1658)) +- [Only create jira connect NS subscriptions for admins](gitlab-org/security/gitlab@3f2040c0e2c90f3fcafdbf0f86bd2591bd458dff) ([merge request](gitlab-org/security/gitlab!1648)) +- [Prevent non-admins from configuring Jira connect app](gitlab-org/security/gitlab@fa864c0a2eaf450033f4c594cea07d9f24144cd6) ([merge request](gitlab-org/security/gitlab!1644)) + ## 14.1.3 (2021-08-17) ### Fixed (2 changes) @@ -1181,6 +1208,20 @@ entry. - [Remove diffs gradual load feature flag](gitlab-org/gitlab@027d7c4327b5b6205a84281239027273517bf81b) ([merge request](gitlab-org/gitlab!55478)) - [Remove partial index for Hashed Storage migration](gitlab-org/gitlab@3ed017a1023d7b0941a7606b69e6caee8d22f15c) ([merge request](gitlab-org/gitlab!62920)) +## 14.0.9 (2021-08-31) + +### Security (9 changes) + +- [Update apollo_upload_server dependency](gitlab-org/security/gitlab@ced741d93fa664f0c152f524949258bf969b7667) ([merge request](gitlab-org/security/gitlab!1701)) +- [Ensure shared group members lose project access after group deletion](gitlab-org/security/gitlab@3a41f4e29c01188aaaf01ab5e3deec2a9eeed18e) ([merge request](gitlab-org/security/gitlab!1685)) +- [Fix stored XSS vulnerability in Datadog settings form](gitlab-org/security/gitlab@269e5bf96b5e97c3b8e6f6b8b3f593d958de2ecb) ([merge request](gitlab-org/security/gitlab!1672)) +- [Inherit user external status while creating project bots](gitlab-org/security/gitlab@5bae4e53bd4c363270b2fc2e308b81d2a2a388a6) ([merge request](gitlab-org/security/gitlab!1666)) +- [Escape issue reference and title for Jira issues](gitlab-org/security/gitlab@0397f2b393d563559c49c39c0ba1d192d08a10d7) ([merge request](gitlab-org/security/gitlab!1663)) **GitLab Enterprise Edition** +- [Require sign in for .keys endpoint on non-public instances](gitlab-org/security/gitlab@13a7f6001f663b3745159fa37b518ba4a43355bd) ([merge request](gitlab-org/security/gitlab!1659)) +- [Update Import/Export to use public email when mapping users](gitlab-org/security/gitlab@f3d1b800af55986cef83aeaf4df1312e3070f0c5) ([merge request](gitlab-org/security/gitlab!1654)) **GitLab Enterprise Edition** +- [Only create jira connect NS subscriptions for admins](gitlab-org/security/gitlab@34bdcd45f24eaa051702834fb6c3568e45721004) ([merge request](gitlab-org/security/gitlab!1647)) +- [Prevent non-admins from configuring Jira connect app](gitlab-org/security/gitlab@4af692246224b1cd1e2fe3c6d0ac2613c0f8fe39) ([merge request](gitlab-org/security/gitlab!1643)) + ## 14.0.8 (2021-08-25) ### Fixed (1 change) diff --git a/Gemfile b/Gemfile index b969f1dfa1d..7bd0b16474c 100644 --- a/Gemfile +++ b/Gemfile @@ -101,7 +101,7 @@ gem 'graphql', '~> 1.11.8' # TODO: remove app/views/graphiql/rails/editors/show.html.erb when https://github.com/rmosolgo/graphiql-rails/pull/71 is released: # https://gitlab.com/gitlab-org/gitlab/issues/31747 gem 'graphiql-rails', '~> 1.4.10' -gem 'apollo_upload_server', '~> 2.0.2' +gem 'apollo_upload_server', '~> 2.1.0' gem 'graphql-docs', '~> 1.6.0', group: [:development, :test] gem 'graphlient', '~> 0.4.0' # Used by BulkImport feature (group::import) diff --git a/Gemfile.lock b/Gemfile.lock index f9adeeca757..408e0a08c11 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -80,9 +80,9 @@ GEM aes_key_wrap (1.1.0) akismet (3.0.0) android_key_attestation (0.3.0) - apollo_upload_server (2.0.2) + apollo_upload_server (2.1.0) + actionpack (>= 4.2) graphql (>= 1.8) - rails (>= 4.2) asana (0.10.3) faraday (~> 1.0) faraday_middleware (~> 1.0) @@ -1391,7 +1391,7 @@ DEPENDENCIES acts-as-taggable-on (~> 7.0) addressable (~> 2.8) akismet (~> 3.0) - apollo_upload_server (~> 2.0.2) + apollo_upload_server (~> 2.1.0) asana (~> 0.10.3) asciidoctor (~> 2.0.10) asciidoctor-include-ext (~> 0.3.1) diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue index 0b70e74b8ff..2dfdaa0ea28 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue @@ -39,7 +39,7 @@ export default { return this.value.map((i) => i.type); }, tokens() { - const tokens = [ + return [ { type: this.$options.userType, icon: 'user', @@ -77,20 +77,15 @@ export default { token: PipelineStatusToken, operators: OPERATOR_IS_ONLY, }, - ]; - - if (gon.features.pipelineSourceFilter) { - tokens.push({ + { type: this.$options.sourceType, icon: 'trigger-source', title: s__('Pipeline|Source'), unique: true, token: PipelineSourceToken, operators: OPERATOR_IS_ONLY, - }); - } - - return tokens; + }, + ]; }, parsedParams() { return map(this.params, (val, key) => ({ diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb index a0f387631dd..74fac6ff9bb 100644 --- a/app/controllers/jira_connect/app_descriptor_controller.rb +++ b/app/controllers/jira_connect/app_descriptor_controller.rb @@ -47,7 +47,13 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController postInstallPage: { key: 'gitlab-configuration', name: { value: 'GitLab Configuration' }, - url: relative_to_base_path(jira_connect_subscriptions_path) + url: relative_to_base_path(jira_connect_subscriptions_path), + conditions: [ + { + condition: 'user_is_admin', + invert: false + } + ] } } diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb index a6529ecb4ce..352e78d6255 100644 --- a/app/controllers/jira_connect/application_controller.rb +++ b/app/controllers/jira_connect/application_controller.rb @@ -38,12 +38,30 @@ class JiraConnect::ApplicationController < ApplicationController end def installation_from_jwt - return unless auth_token - strong_memoize(:installation_from_jwt) do + next unless claims['iss'] + + JiraConnectInstallation.find_by_client_key(claims['iss']) + end + end + + def claims + strong_memoize(:claims) do + next {} unless auth_token + # Decode without verification to get `client_key` in `iss` payload, _ = Atlassian::Jwt.decode(auth_token, nil, false) - JiraConnectInstallation.find_by_client_key(payload['iss']) + payload + end + end + + def jira_user + strong_memoize(:jira_user) do + next unless installation_from_jwt + next unless claims['sub'] + + # This only works for Jira Cloud installations. + installation_from_jwt.client.user_info(claims['sub']) end end diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb index a9c4dbf2b17..903ad395e44 100644 --- a/app/controllers/jira_connect/subscriptions_controller.rb +++ b/app/controllers/jira_connect/subscriptions_controller.rb @@ -44,7 +44,9 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController def destroy subscription = current_jira_installation.subscriptions.find(params[:id]) - if subscription.destroy + if !jira_user&.site_admin? + render json: { error: 'forbidden' }, status: :forbidden + elsif subscription.destroy render json: { success: true } else render json: { error: subscription.errors.full_messages.join(', ') }, status: :unprocessable_entity @@ -54,7 +56,7 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController private def create_service - JiraConnectSubscriptions::CreateService.new(current_jira_installation, current_user, namespace_path: params['namespace_path']) + JiraConnectSubscriptions::CreateService.new(current_jira_installation, current_user, namespace_path: params['namespace_path'], jira_user: jira_user) end def allow_rendering_in_iframe diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 33d7eb4a09e..9ad342f3936 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -14,10 +14,6 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :ensure_pipeline, only: [:show, :downloadable_artifacts] - before_action do - push_frontend_feature_flag(:pipeline_source_filter, project, type: :development, default_enabled: :yaml) - end - # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596 before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? } @@ -297,10 +293,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def index_params - permitted_params = [:scope, :username, :ref, :status] - permitted_params << :source if Feature.enabled?(:pipeline_source_filter, project, default_enabled: :yaml) - - params.permit(*permitted_params) + params.permit(:scope, :username, :ref, :status, :source) end def enable_code_quality_walkthrough_experiment diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a089f600bd8..26f56307862 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -20,7 +20,7 @@ class UsersController < ApplicationController skip_before_action :authenticate_user! prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } - before_action :user, except: [:exists, :ssh_keys] + before_action :user, except: [:exists] before_action :authorize_read_user_profile!, only: [:calendar, :calendar_activities, :groups, :projects, :contributed, :starred, :snippets, :followers, :following] @@ -44,12 +44,7 @@ class UsersController < ApplicationController # Get all keys of a user(params[:username]) in a text format # Helpful for sysadmins to put in respective servers - # - # Uses `UserFinder` rather than `find_routable!` because this endpoint should - # be publicly available regardless of instance visibility settings. def ssh_keys - user = UserFinder.new(params[:username]).find_by_username - render plain: user.all_ssh_keys.join("\n") end diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb index a79840216da..37168ae9e5b 100644 --- a/app/finders/ci/pipelines_finder.rb +++ b/app/finders/ci/pipelines_finder.rb @@ -29,8 +29,7 @@ module Ci items = by_username(items) items = by_yaml_errors(items) items = by_updated_at(items) - - items = by_source(items) if Feature.enabled?(:pipeline_source_filter, project, default_enabled: :yaml) + items = by_source(items) sort_items(items) end diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb index f15566a551a..904508867d3 100644 --- a/app/helpers/integrations_helper.rb +++ b/app/helpers/integrations_helper.rb @@ -137,7 +137,7 @@ module IntegrationsHelper def jira_issue_breadcrumb_link(issue_reference) link_to '', { class: 'gl-display-flex gl-align-items-center gl-white-space-nowrap' } do icon = image_tag image_path('illustrations/logos/jira.svg'), width: 15, height: 15, class: 'gl-mr-2' - [icon, issue_reference].join.html_safe + [icon, html_escape(issue_reference)].join.html_safe end end diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb index 79f5a63bcb6..feb1bf5438c 100644 --- a/app/models/design_management/design.rb +++ b/app/models/design_management/design.rb @@ -169,7 +169,7 @@ module DesignManagement @link_reference_pattern ||= begin path_segment = %r{issues/#{Gitlab::Regex.issue}/designs} ext = Regexp.new(Regexp.union(SAFE_IMAGE_EXT + DANGEROUS_IMAGE_EXT).source, Regexp::IGNORECASE) - valid_char = %r{[^/\s]} # any char that is not a forward slash or whitespace + valid_char = %r{[[:word:]\.\-\+]} filename_pattern = %r{ (? #{valid_char}+ \. #{ext}) }x diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb index 5516e6bc2c0..6422f6bddab 100644 --- a/app/models/integrations/datadog.rb +++ b/app/models/integrations/datadog.rb @@ -8,7 +8,6 @@ module Integrations DEFAULT_DOMAIN = 'datadoghq.com' URL_TEMPLATE = 'https://webhooks-http-intake.logs.%{datadog_domain}/api/v2/webhook' - URL_TEMPLATE_API_KEYS = 'https://app.%{datadog_domain}/account/settings#api' URL_API_KEYS_DOCS = "https://docs.#{DEFAULT_DOMAIN}/account_management/api-app-keys/" SUPPORTED_EVENTS = %w[ @@ -90,7 +89,7 @@ module Integrations help: ERB::Util.html_escape( s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.') ) % { - linkOpen: ''.html_safe % api_keys_url, + linkOpen: %Q{}.html_safe, linkClose: ''.html_safe }, required: true @@ -132,12 +131,6 @@ module Integrations url.to_s end - def api_keys_url - return URL_API_KEYS_DOCS unless datadog_site.presence - - sprintf(URL_TEMPLATE_API_KEYS, datadog_domain: datadog_domain) - end - def execute(data) object_kind = data[:object_kind] object_kind = 'job' if object_kind == 'build' diff --git a/app/models/jira_connect_installation.rb b/app/models/jira_connect_installation.rb index 759d44fb29e..e34543534f3 100644 --- a/app/models/jira_connect_installation.rb +++ b/app/models/jira_connect_installation.rb @@ -20,4 +20,8 @@ class JiraConnectInstallation < ApplicationRecord id: JiraConnectSubscription.for_project(project) }) } + + def client + Atlassian::JiraConnect::Client.new(base_url, shared_secret) + end end diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb index 08c4e0231e7..5ffa746e109 100644 --- a/app/services/groups/destroy_service.rb +++ b/app/services/groups/destroy_service.rb @@ -29,14 +29,7 @@ module Groups group.chat_team&.remove_mattermost_team(current_user) - # If any other groups are shared with the group that is being destroyed, - # we should specifically trigger update of all project authorizations - # for users that are the direct members of this group. - # If not, the project authorization records of these users to projects within the shared groups - # will never be removed, causing inconsistencies with access permissions. - if any_other_groups_are_shared_with_this_group? - user_ids_for_project_authorizations_refresh = group.users_ids_of_direct_members - end + user_ids_for_project_authorizations_refresh = obtain_user_ids_for_project_authorizations_refresh group.destroy @@ -52,9 +45,33 @@ module Groups private - def any_other_groups_are_shared_with_this_group? + def any_groups_shared_with_this_group? group.shared_group_links.any? end + + def any_projects_shared_with_this_group? + group.project_group_links.any? + end + + # Destroying a group automatically destroys all project authorizations directly + # associated with the group and descendents. However, project authorizations + # for projects and groups this group is shared with are not. Without a manual + # refresh, the project authorization records of these users to shared projects + # and projects within the shared groups will never be removed, causing + # inconsistencies with access permissions. + # + # This method retrieves the user IDs that need to be refreshed. If only + # groups are shared with this group, only direct members need to be refreshed. + # If projects are also shared with the group, direct members *and* shared + # members of other groups need to be refreshed. + # `Group#user_ids_for_project_authorizations` returns both direct and shared + # members' user IDs. + def obtain_user_ids_for_project_authorizations_refresh + return unless any_projects_shared_with_this_group? || any_groups_shared_with_this_group? + return group.user_ids_for_project_authorizations if any_projects_shared_with_this_group? + + group.users_ids_of_direct_members + end end end diff --git a/app/services/jira_connect_subscriptions/create_service.rb b/app/services/jira_connect_subscriptions/create_service.rb index 38e5fe7e690..2f31a3c8d4e 100644 --- a/app/services/jira_connect_subscriptions/create_service.rb +++ b/app/services/jira_connect_subscriptions/create_service.rb @@ -5,8 +5,11 @@ module JiraConnectSubscriptions include Gitlab::Utils::StrongMemoize MERGE_REQUEST_SYNC_BATCH_SIZE = 20 MERGE_REQUEST_SYNC_BATCH_DELAY = 1.minute.freeze + NOT_SITE_ADMIN = 'The Jira user is not a site administrator.' def execute + return error(NOT_SITE_ADMIN, 403) unless can_administer_jira? + unless namespace && can?(current_user, :create_jira_connect_subscription, namespace) return error('Invalid namespace. Please make sure you have sufficient permissions', 401) end @@ -16,6 +19,10 @@ module JiraConnectSubscriptions private + def can_administer_jira? + @params[:jira_user]&.site_admin? + end + def create_subscription subscription = JiraConnectSubscription.new(installation: jira_connect_installation, namespace: namespace) diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb index 34aa414de8f..e0371e5d80f 100644 --- a/app/services/resource_access_tokens/create_service.rb +++ b/app/services/resource_access_tokens/create_service.rb @@ -16,6 +16,8 @@ module ResourceAccessTokens return error(user.errors.full_messages.to_sentence) unless user.persisted? + user.update!(external: true) if current_user.external? + access_level = params[:access_level] || Gitlab::Access::MAINTAINER member = create_membership(resource, user, access_level) diff --git a/config/feature_flags/development/pipeline_source_filter.yml b/config/feature_flags/development/pipeline_source_filter.yml deleted file mode 100644 index be24f6936e4..00000000000 --- a/config/feature_flags/development/pipeline_source_filter.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: pipeline_source_filter -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67846 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338347 -milestone: '14.2' -type: development -group: group::pipeline execution -default_enabled: false diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index f7b1c2f7567..a5e3b8b24e7 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -1146,14 +1146,22 @@ production: &base # # Use multipart uploads when file size reaches 100MB, see # # http://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html # multipart_chunk_size: 104857600 - # # Turns on AWS Server-Side Encryption with Amazon S3-Managed Keys for backups, this is optional - # # encryption: 'AES256' - # # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional - # # This should be set to the 256-bit encryption key for Amazon S3 to use to encrypt or decrypt your data. - # # 'encryption' must also be set in order for this to have any effect. - # # encryption_key: '' - # # Specifies Amazon S3 storage class to use for backups, this is optional + # # Specifies Amazon S3 storage class to use for backups (optional) # # storage_class: 'STANDARD' + # # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional + # # 'encryption' must be set in order for this to have any effect. + # # 'encryption_key' should be set to the 256-bit encryption key for Amazon S3 to use to encrypt or decrypt your data. + # # encryption: 'AES256' + # # encryption_key: '' + # # + # # Turns on AWS Server-Side Encryption with Amazon S3-Managed keys (optional) + # # https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html + # # For SSE-S3, set 'server_side_encryption' to 'AES256'. + # # For SS3-KMS, set 'server_side_encryption' to 'aws:kms'. Set + # # 'server_side_encryption_kms_key_id' to the ARN of customer master key. + # # storage_options: + # # server_side_encryption: 'aws:kms' + # # server_side_encryption_kms_key_id: 'arn:aws:kms:YOUR-KEY-ID-HERE' ## Pseudonymizer exporter pseudonymizer: diff --git a/config/initializers/apollo_upload_server.rb b/config/initializers/apollo_upload_server.rb new file mode 100644 index 00000000000..295cb5d8ce8 --- /dev/null +++ b/config/initializers/apollo_upload_server.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require 'apollo_upload_server' + +ApolloUploadServer::Middleware.strict_mode = true diff --git a/db/post_migrate/20210811122206_update_external_project_bots.rb b/db/post_migrate/20210811122206_update_external_project_bots.rb new file mode 100644 index 00000000000..dc2e3d316b0 --- /dev/null +++ b/db/post_migrate/20210811122206_update_external_project_bots.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class UpdateExternalProjectBots < ActiveRecord::Migration[6.1] + include Gitlab::Database::MigrationHelpers + + class User < ActiveRecord::Base + self.table_name = 'users' + end + + disable_ddl_transaction! + + TMP_INDEX_NAME = 'tmp_idx_update_external_project_bots' + + def up + add_concurrent_index('users', 'id', name: TMP_INDEX_NAME, where: 'external = true') + + ids = ActiveRecord::Base.connection + .execute("SELECT u.id FROM users u JOIN users u2 on u2.id = u.created_by_id WHERE u.user_type = 6 AND u2.external = true") + .map { |result| result['id'] } + + ids.each_slice(10) do |group| + UpdateExternalProjectBots::User.where(id: group).update_all(external: true) + end + + remove_concurrent_index_by_name('users', TMP_INDEX_NAME) + end + + def down + remove_concurrent_index_by_name('users', TMP_INDEX_NAME) if index_exists_by_name?('users', TMP_INDEX_NAME) + + # This migration is irreversible + end +end diff --git a/db/schema_migrations/20210811122206 b/db/schema_migrations/20210811122206 new file mode 100644 index 00000000000..3bb2799461a --- /dev/null +++ b/db/schema_migrations/20210811122206 @@ -0,0 +1 @@ +f6f5e081672fb42adde980fa12f696f5d8fd11921ee52c1472b3d745bb11a5ff \ No newline at end of file diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index ad7336bba8f..8348dd2ae43 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -32,6 +32,7 @@ GET /projects/:id/pipelines | `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user | | `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` | | `status` | string | no | The status of pipelines, one of: `created`, `waiting_for_resource`, `preparing`, `pending`, `running`, `success`, `failed`, `canceled`, `skipped`, `manual`, `scheduled` | +| `source` | string | no | In [GitLab 14.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/325439), how the pipeline was triggered, one of: `push`, `web`, `trigger`, `schedule`, `api`, `external`, `pipeline`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, `ondemand_dast_scan`, or `ondemand_dast_validation`. | | `ref` | string | no | The ref of pipelines | | `sha` | string | no | The SHA of pipelines | | `yaml_errors`| boolean | no | Returns pipelines with invalid configurations | @@ -55,6 +56,7 @@ Example of response "iid": 12, "project_id": 1, "status": "pending", + "soure": "push", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", @@ -66,6 +68,7 @@ Example of response "iid": 13, "project_id": 1, "status": "pending", + "soure": "web", "ref": "new-pipeline", "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a", "web_url": "https://example.com/foo/bar/pipelines/48", diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index f52e82e6840..631b39de0db 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -122,6 +122,7 @@ you can filter the pipeline list by: - Branch name - Status ([GitLab 13.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/217617)) - Tag ([GitLab 13.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/217617)) +- Source ([GitLab 14.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/338347)) [Starting in GitLab 14.2](https://gitlab.com/gitlab-org/gitlab/-/issues/26621), you can change the pipeline column to display the pipeline ID or the pipeline IID. diff --git a/doc/development/import_export.md b/doc/development/import_export.md index bc1927fffde..2a29df380de 100644 --- a/doc/development/import_export.md +++ b/doc/development/import_export.md @@ -259,7 +259,7 @@ Only include the following attributes for the models specified: included_attributes: user: - :id - - :email + - :public_email # ... ``` diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md index 8bc08bf89d3..33725c289eb 100644 --- a/doc/integration/jira/connect-app.md +++ b/doc/integration/jira/connect-app.md @@ -6,6 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w # GitLab.com for Jira Cloud app **(FREE)** +NOTE: +Only Jira users with administrator level access are able to install or configure +the GitLab app for Jira Cloud. + ## GitLab.com for Jira Cloud app **(FREE SAAS)** You can integrate GitLab.com and Jira Cloud using the @@ -39,7 +43,8 @@ For a walkthrough of the integration with GitLab.com for Jira Cloud app, watch ![Sign in to GitLab.com in GitLab.com for Jira Cloud app](img/jira_dev_panel_setup_com_3_v13_9.png) 1. Select **Add namespace** to open the list of available namespaces. -1. Identify the namespace you want to link, and select **Link**. +1. Identify the namespace you want to link, and select **Link**. Only Jira site + administrators are permitted to add or remove namespaces for an installation. ![Link namespace in GitLab.com for Jira Cloud app](img/jira_dev_panel_setup_com_4_v13_9.png) diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md index 82dcd4a1a13..de92dbf240b 100644 --- a/doc/user/project/settings/import_export.md +++ b/doc/user/project/settings/import_export.md @@ -44,7 +44,7 @@ Note the following: - Group members are exported as project members, as long as the user has a maintainer or administrator role in the group where the exported project lives. - Project members with the [Owner role](../../permissions.md) are imported as Maintainers. -- Imported users can be mapped by their primary email on self-managed instances, if an administrative user (not an owner) does the import. +- Imported users can be mapped by their public email on self-managed instances, if an administrative user (not an owner) does the import. Additionally, the user must be an existing member of the namespace, or the user can be added as a member of the project for contributions to be mapped. Otherwise, a supplementary comment is left to mention that the original author and diff --git a/lib/api/entities/ci/pipeline_basic.rb b/lib/api/entities/ci/pipeline_basic.rb index 8086062dc9b..4d56176bdb3 100644 --- a/lib/api/entities/ci/pipeline_basic.rb +++ b/lib/api/entities/ci/pipeline_basic.rb @@ -4,11 +4,9 @@ module API module Entities module Ci class PipelineBasic < Grape::Entity - expose :id, :project_id, :sha, :ref, :status + expose :id, :project_id, :sha, :ref, :status, :source expose :created_at, :updated_at - expose :source, if: ->(pipeline, options) { ::Feature.enabled?(:pipeline_source_filter, options[:project], default_enabled: :yaml) } - expose :web_url do |pipeline, _options| Gitlab::Routing.url_helpers.project_pipeline_url(pipeline.project, pipeline) end diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb index 3e2e6f1b9ba..dc37465744b 100644 --- a/lib/atlassian/jira_connect/client.rb +++ b/lib/atlassian/jira_connect/client.rb @@ -30,8 +30,21 @@ module Atlassian responses.compact end + def user_info(account_id) + r = get('/rest/api/3/user', { accountId: account_id, expand: 'groups' }) + + JiraUser.new(r.parsed_response) if r.code == 200 + end + private + def get(path, query_params) + uri = URI.join(@base_uri, path) + uri.query = URI.encode_www_form(query_params) + + self.class.get(uri, headers: headers(uri, 'GET')) + end + def store_ff_info(project:, feature_flags:, **opts) items = feature_flags.map { |flag| ::Atlassian::JiraConnect::Serializers::FeatureFlagEntity.represent(flag, opts) } items.reject! { |item| item.issue_keys.empty? } @@ -99,10 +112,11 @@ module Atlassian self.class.post(uri, headers: headers(uri), body: metadata.merge(payload).to_json) end - def headers(uri) + def headers(uri, http_method = 'POST') { - 'Authorization' => "JWT #{jwt_token('POST', uri)}", - 'Content-Type' => 'application/json' + 'Authorization' => "JWT #{jwt_token(http_method, uri)}", + 'Content-Type' => 'application/json', + 'Accept' => 'application/json' } end diff --git a/lib/atlassian/jira_connect/jira_user.rb b/lib/atlassian/jira_connect/jira_user.rb new file mode 100644 index 00000000000..57ceb8fdf13 --- /dev/null +++ b/lib/atlassian/jira_connect/jira_user.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Atlassian + module JiraConnect + class JiraUser + def initialize(data) + @data = data + end + + def site_admin? + groups = @data.dig('groups', 'items') + return false unless groups + + groups.any? { |g| g['name'] == 'site-admins' } + end + end + end +end diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 52810b0fb35..6c5350082e8 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -47,10 +47,12 @@ module Backup return end - directory = connect_to_remote_directory(Gitlab.config.backup.upload) + directory = connect_to_remote_directory + upload = directory.files.create(create_attributes) - if directory.files.create(create_attributes) + if upload progress.puts "done".color(:green) + upload else puts "uploading backup to #{remote_directory} failed".color(:red) raise Backup::Error, 'Backup failed' @@ -206,11 +208,16 @@ module Backup @backup_file_list.map {|item| item.gsub("#{FILE_NAME_SUFFIX}", "")} end - def connect_to_remote_directory(options) - config = ObjectStorage::Config.new(options) - config.load_provider + def object_storage_config + @object_storage_config ||= begin + config = ObjectStorage::Config.new(Gitlab.config.backup.upload) + config.load_provider + config + end + end - connection = ::Fog::Storage.new(config.credentials) + def connect_to_remote_directory + connection = ::Fog::Storage.new(object_storage_config.credentials) # We only attempt to create the directory for local backups. For AWS # and other cloud providers, we cannot guarantee the user will have @@ -280,10 +287,8 @@ module Backup key: remote_target, body: File.open(File.join(backup_path, tar_file)), multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size, - encryption: Gitlab.config.backup.upload.encryption, - encryption_key: Gitlab.config.backup.upload.encryption_key, storage_class: Gitlab.config.backup.upload.storage_class - } + }.merge(encryption_attributes) # Google bucket-only policies prevent setting an ACL. In any case, by default, # all objects are set to the default ACL, which is project-private: @@ -293,6 +298,19 @@ module Backup attrs end + def encryption_attributes + return object_storage_config.fog_attributes if object_storage_config.aws_server_side_encryption_enabled? + + # Use customer-managed keys. Also, this preserves + # backward-compatibility for existing usages of `SSE-S3` that + # don't set `backup.upload.storage_options.server_side_encryption` + # to `'AES256'`. + { + encryption_key: Gitlab.config.backup.upload.encryption_key, + encryption: Gitlab.config.backup.upload.encryption + } + end + def google_provider? Gitlab.config.backup.upload.connection&.provider&.downcase == 'google' end diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml index 4786c7a52cc..630f918a78b 100644 --- a/lib/gitlab/import_export/group/import_export.yml +++ b/lib/gitlab/import_export/group/import_export.yml @@ -20,7 +20,7 @@ tree: included_attributes: user: - :id - - :email + - :public_email - :username author: - :name diff --git a/lib/gitlab/import_export/group/legacy_import_export.yml b/lib/gitlab/import_export/group/legacy_import_export.yml index 0a6234f9f02..082d2346f3d 100644 --- a/lib/gitlab/import_export/group/legacy_import_export.yml +++ b/lib/gitlab/import_export/group/legacy_import_export.yml @@ -20,7 +20,7 @@ tree: included_attributes: user: - :id - - :email + - :public_email - :username author: - :name diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index ff972cf9352..ce886cb8738 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -19,7 +19,8 @@ module Gitlab @exported_members.inject(missing_keys_tracking_hash) do |hash, member| if member['user'] old_user_id = member['user']['id'] - existing_user = User.find_by(find_user_query(member)) + old_user_email = member.dig('user', 'public_email') || member.dig('user', 'email') + existing_user = User.find_by(find_user_query(old_user_email)) if old_user_email hash[old_user_id] = existing_user.id if existing_user && add_team_member(member, existing_user) else add_team_member(member) @@ -94,8 +95,8 @@ module Gitlab relation_class: relation_class) end - def find_user_query(member) - user_arel[:email].eq(member['user']['email']) + def find_user_query(email) + user_arel[:email].eq(email) end def user_arel diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index adf41897af6..56877970ce3 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -115,7 +115,7 @@ tree: included_attributes: user: - :id - - :email + - :public_email - :username author: - :name diff --git a/lib/gitlab/markdown_cache.rb b/lib/gitlab/markdown_cache.rb index db39904ea23..d6371732624 100644 --- a/lib/gitlab/markdown_cache.rb +++ b/lib/gitlab/markdown_cache.rb @@ -11,7 +11,7 @@ module Gitlab # this if the change to the renderer output is a new feature or a # minor bug fix. # See: https://gitlab.com/gitlab-org/gitlab/-/issues/330313 - CACHE_COMMONMARK_VERSION = 28 + CACHE_COMMONMARK_VERSION = 29 CACHE_COMMONMARK_VERSION_START = 10 BaseError = Class.new(StandardError) diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb index 30b3fe3d893..49be3ffc839 100644 --- a/lib/gitlab/middleware/multipart.rb +++ b/lib/gitlab/middleware/multipart.rb @@ -176,7 +176,7 @@ module Gitlab ::Gitlab::Middleware::Multipart::Handler.new(env, message).with_open_files do @app.call(env) end - rescue UploadedFile::InvalidPathError => e + rescue UploadedFile::InvalidPathError, ApolloUploadServer::GraphQLDataBuilder::OutOfBounds => e [400, { 'Content-Type' => 'text/plain' }, [e.message]] end end diff --git a/lib/object_storage/config.rb b/lib/object_storage/config.rb index f933d4e4866..82d9fc07043 100644 --- a/lib/object_storage/config.rb +++ b/lib/object_storage/config.rb @@ -84,13 +84,16 @@ module ObjectStorage def fog_attributes @fog_attributes ||= begin - return {} unless enabled? && aws? - return {} unless server_side_encryption.present? + return {} unless aws_server_side_encryption_enabled? aws_server_side_encryption_headers.compact end end + def aws_server_side_encryption_enabled? + aws? && server_side_encryption.present? + end + private # This returns a Hash of HTTP encryption headers to send along to S3. diff --git a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb index 98f4db13a1d..25c11d92b4e 100644 --- a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb +++ b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb @@ -54,7 +54,10 @@ RSpec.describe JiraConnect::AppDescriptorController do postInstallPage: { key: 'gitlab-configuration', name: { value: 'GitLab Configuration' }, - url: '/subscriptions' + url: '/subscriptions', + conditions: contain_exactly( + a_hash_including(condition: 'user_is_admin', invert: false) + ) }, jiraDevelopmentTool: { actions: { diff --git a/spec/controllers/jira_connect/subscriptions_controller_spec.rb b/spec/controllers/jira_connect/subscriptions_controller_spec.rb index e32915d55a1..f548c1f399d 100644 --- a/spec/controllers/jira_connect/subscriptions_controller_spec.rb +++ b/spec/controllers/jira_connect/subscriptions_controller_spec.rb @@ -102,11 +102,17 @@ RSpec.describe JiraConnect::SubscriptionsController do end context 'with valid JWT' do - let(:jwt) { Atlassian::Jwt.encode({ iss: installation.client_key }, installation.shared_secret) } + let(:claims) { { iss: installation.client_key, sub: 1234 } } + let(:jwt) { Atlassian::Jwt.encode(claims, installation.shared_secret) } + let(:jira_user) { { 'groups' => { 'items' => [{ 'name' => jira_group_name }] } } } + let(:jira_group_name) { 'site-admins' } context 'signed in to GitLab' do before do sign_in(user) + WebMock + .stub_request(:get, "#{installation.base_url}/rest/api/3/user?accountId=1234&expand=groups") + .to_return(body: jira_user.to_json, status: 200, headers: { 'Content-Type' => 'application/json' }) end context 'dev panel integration is available' do @@ -120,6 +126,16 @@ RSpec.describe JiraConnect::SubscriptionsController do expect(response).to have_gitlab_http_status(:ok) end end + + context 'when the Jira user is not a site-admin' do + let(:jira_group_name) { 'some-other-group' } + + it 'returns forbidden' do + subject + + expect(response).to have_gitlab_http_status(:forbidden) + end + end end context 'not signed in to GitLab' do @@ -134,8 +150,14 @@ RSpec.describe JiraConnect::SubscriptionsController do describe '#destroy' do let(:subscription) { create(:jira_connect_subscription, installation: installation) } + let(:jira_user) { { 'groups' => { 'items' => [{ 'name' => jira_group_name }] } } } + let(:jira_group_name) { 'site-admins' } before do + WebMock + .stub_request(:get, "#{installation.base_url}/rest/api/3/user?accountId=1234&expand=groups") + .to_return(body: jira_user.to_json, status: 200, headers: { 'Content-Type' => 'application/json' }) + delete :destroy, params: { jwt: jwt, id: subscription.id } end @@ -148,12 +170,23 @@ RSpec.describe JiraConnect::SubscriptionsController do end context 'with valid JWT' do - let(:jwt) { Atlassian::Jwt.encode({ iss: installation.client_key }, installation.shared_secret) } + let(:claims) { { iss: installation.client_key, sub: 1234 } } + let(:jwt) { Atlassian::Jwt.encode(claims, installation.shared_secret) } it 'deletes the subscription' do expect { subscription.reload }.to raise_error ActiveRecord::RecordNotFound expect(response).to have_gitlab_http_status(:ok) end + + context 'when the Jira user is not a site admin' do + let(:jira_group_name) { 'some-other-group' } + + it 'does not delete the subscription' do + expect(response).to have_gitlab_http_status(:forbidden) + + expect { subscription.reload }.not_to raise_error + end + end end end end diff --git a/spec/features/file_uploads/graphql_add_design_spec.rb b/spec/features/file_uploads/graphql_add_design_spec.rb index f805ea86b4c..17fbf5f6838 100644 --- a/spec/features/file_uploads/graphql_add_design_spec.rb +++ b/spec/features/file_uploads/graphql_add_design_spec.rb @@ -19,8 +19,18 @@ RSpec.describe 'Upload a design through graphQL', :js do let_it_be(:user) { create(:user, :admin) } let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let_it_be(:design) { create(:design) } - let_it_be(:operations) { { "operationName": "uploadDesign", "variables": { "files": [], "projectPath": design.project.full_path, "iid": design.issue.iid }, "query": query }.to_json } let_it_be(:map) { { "1": ["variables.files.0"] }.to_json } + let_it_be(:operations) do + { + "operationName": "uploadDesign", + "variables": { + "files": [nil], + "projectPath": design.project.full_path, + "iid": design.issue.iid + }, + "query": query + }.to_json + end let(:url) { capybara_url("/api/graphql?private_token=#{personal_access_token.token}") } let(:file) { fixture_file_upload('spec/fixtures/dk.png') } diff --git a/spec/finders/ci/pipelines_finder_spec.rb b/spec/finders/ci/pipelines_finder_spec.rb index c7bd52576e8..6e2338ac10e 100644 --- a/spec/finders/ci/pipelines_finder_spec.rb +++ b/spec/finders/ci/pipelines_finder_spec.rb @@ -258,20 +258,8 @@ RSpec.describe Ci::PipelinesFinder do let!(:push_pipeline) { create(:ci_pipeline, project: project, source: 'push') } let!(:api_pipeline) { create(:ci_pipeline, project: project, source: 'api') } - context 'when `pipeline_source_filter` feature flag is disabled' do - before do - stub_feature_flags(pipeline_source_filter: false) - end - - it 'returns all the pipelines' do - is_expected.to contain_exactly(web_pipeline, push_pipeline, api_pipeline) - end - end - - context 'when `pipeline_source_filter` feature flag is enabled' do - it 'returns only the matched pipeline' do - is_expected.to eq([web_pipeline]) - end + it 'returns only the matched pipeline' do + is_expected.to eq([web_pipeline]) end end diff --git a/spec/fixtures/group.json b/spec/fixtures/group.json index 86de34e2f3b..a7c699e2b32 100644 --- a/spec/fixtures/group.json +++ b/spec/fixtures/group.json @@ -1 +1 @@ -{"name":"H5bp","path":"h5bp","owner_id":null,"created_at":"2020-01-09 12:08:57 UTC","updated_at":"2020-01-09 12:08:57 UTC","description":"A voluptate non sequi temporibus quam at.","avatar":{"url":null},"membership_lock":false,"share_with_group_lock":false,"visibility_level":20,"request_access_enabled":true,"ldap_sync_status":"ready","ldap_sync_error":null,"ldap_sync_last_update_at":null,"ldap_sync_last_successful_update_at":null,"ldap_sync_last_sync_at":null,"lfs_enabled":null,"parent_id":null,"repository_size_limit":null,"require_two_factor_authentication":false,"two_factor_grace_period":48,"plan_id":null,"project_creation_level":2,"file_template_project_id":null,"saml_discovery_token":"JZGRJbe3","custom_project_templates_group_id":null,"auto_devops_enabled":null,"last_ci_minutes_notification_at":null,"last_ci_minutes_usage_notification_level":null,"subgroup_creation_level":1,"emails_disabled":null,"max_pages_size":null,"max_artifacts_size":null,"mentions_disabled":null,"milestones":[],"badges":[],"labels":[{"id":69,"title":"Amfunc","color":"#2658d0","project_id":null,"created_at":"2020-01-09T12:08:57.693Z","updated_at":"2020-01-09T12:08:57.693Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":68,"title":"Aquacell","color":"#f658e0","project_id":null,"created_at":"2020-01-09T12:08:57.688Z","updated_at":"2020-01-09T12:08:57.688Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#333333"},{"id":62,"title":"Bryns","color":"#16f0b9","project_id":null,"created_at":"2020-01-09T12:08:57.672Z","updated_at":"2020-01-09T12:08:57.672Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":61,"title":"Pephfunc","color":"#556319","project_id":null,"created_at":"2020-01-09T12:08:57.669Z","updated_at":"2020-01-09T12:08:57.669Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":67,"title":"Sinesync","color":"#4c44e8","project_id":null,"created_at":"2020-01-09T12:08:57.685Z","updated_at":"2020-01-09T12:08:57.685Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":65,"title":"Traphwood","color":"#71b900","project_id":null,"created_at":"2020-01-09T12:08:57.679Z","updated_at":"2020-01-09T12:08:57.679Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":66,"title":"Tricell","color":"#179ad3","project_id":null,"created_at":"2020-01-09T12:08:57.683Z","updated_at":"2020-01-09T12:08:57.683Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":63,"title":"Trienceforge","color":"#cb1e0e","project_id":null,"created_at":"2020-01-09T12:08:57.674Z","updated_at":"2020-01-09T12:08:57.674Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":64,"title":"Trinix","color":"#66ca41","project_id":null,"created_at":"2020-01-09T12:08:57.677Z","updated_at":"2020-01-09T12:08:57.677Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"}],"boards":[],"members":[{"id":8,"access_level":10,"source_id":28,"source_type":"Namespace","user_id":13,"notification_level":3,"created_at":"2020-01-09T12:08:57.884Z","updated_at":"2020-01-09T12:08:57.884Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":13,"email":"lorraine@leannon.info","username":"elina.lakin"}},{"id":7,"access_level":30,"source_id":28,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2020-01-09T12:08:57.129Z","updated_at":"2020-01-09T12:08:57.898Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"email":"admin@example.com","username":"root"}},{"id":9,"access_level":20,"source_id":28,"source_type":"Namespace","user_id":8,"notification_level":3,"created_at":"2020-01-09T12:08:57.901Z","updated_at":"2020-01-09T12:08:57.901Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":8,"email":"euna_schroeder@bernier.us","username":"loreen_medhurst"}},{"id":10,"access_level":40,"source_id":28,"source_type":"Namespace","user_id":10,"notification_level":3,"created_at":"2020-01-09T12:08:57.918Z","updated_at":"2020-01-09T12:08:57.918Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":10,"email":"glady_green@prohaska.biz","username":"maia_kuhlman"}}],"epics":[{"id":31,"group_id":28,"author_id":13,"assignee_id":null,"iid":1,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.006Z","updated_at":"2020-01-09T12:11:12.006Z","title":"Optio nihil consequatur et vel quaerat cupiditate.","description":"Vel molestias repellendus id voluptatem et non. Blanditiis natus veritatis adipisci qui illo. Sed est veritatis facilis dolore voluptas quibusdam aliquam omnis.\n\nFacere delectus quo architecto explicabo dolores. Quis odit nostrum nobis consequuntur cumque est officiis. Maiores ipsa nobis minus incidunt provident.\n\nVoluptate voluptatem debitis facilis architecto commodi vero. Sit quibusdam consectetur ad quis cupiditate. Exercitationem quasi inventore incidunt itaque optio autem accusantium.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":32,"group_id":28,"author_id":1,"assignee_id":null,"iid":2,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.021Z","updated_at":"2020-01-09T12:11:12.021Z","title":"Maxime cumque totam deleniti excepturi iusto qui sint.","description":"Nesciunt ut sit voluptas iusto rem. Sint doloribus ex et aliquam ea. Nihil necessitatibus distinctio similique incidunt. Consequatur voluptatibus excepturi qui quis quia. Quia optio quod non magnam dolorem id molestiae dignissimos.\n\nAt eligendi fuga veritatis accusamus quo dolores. Eos amet dolores nisi illo voluptatem consequuntur alias. Dolor veniam quas est sed. Ex corporis soluta sit ducimus facere et.\n\nEst odit asperiores vel quae quibusdam maiores quod. Debitis libero quo sed sunt voluptas praesentium. Ut nisi qui et culpa. Consequatur atque aut molestiae sint. Quaerat expedita animi distinctio repellat sed.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":33,"group_id":28,"author_id":8,"assignee_id":null,"iid":3,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.035Z","updated_at":"2020-01-09T12:11:12.035Z","title":"Corrupti perferendis labore omnis pariatur dolores aut repellendus quisquam id.","description":"Eligendi est asperiores minus nulla unde ex. Aspernatur repellat vel deleniti molestiae occaecati odio dicta. Ipsam excepturi quia modi ut autem sed. Omnis quae quam quas ut. Et corrupti aut omnis blanditiis.\n\nDolore dolorem accusamus tempore nihil dolores repellendus sed provident. Commodi consectetur blanditiis et consequatur laborum nulla eveniet facilis. Inventore aut officiis fuga est maiores rerum. Sint aspernatur et necessitatibus omnis qui et blanditiis.\n\nFugiat molestias nulla eos labore rerum perspiciatis non. Minus est et ipsum quis animi et. Id praesentium vitae in eum fugiat incidunt. Voluptas ut nemo ut cum saepe quasi dolores unde.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":34,"group_id":28,"author_id":10,"assignee_id":null,"iid":4,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.049Z","updated_at":"2020-01-09T12:11:12.049Z","title":"Architecto ipsa autem ducimus velit harum doloribus odio fugiat.","description":"Eos perferendis commodi labore id. Ipsa esse non voluptatem sit. Odit et et maiores quis adipisci sed earum.\n\nRerum asperiores consequuntur sed odit. Quis architecto nobis dolor sit consectetur. Inventore praesentium est magnam et reprehenderit impedit occaecati similique.\n\nTemporibus culpa ratione vel facilis perspiciatis rerum. Quisquam ut veniam quia sit totam. Quo ipsam quam dolorum quis. Totam porro nesciunt ut temporibus.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":35,"group_id":28,"author_id":10,"assignee_id":null,"iid":5,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.062Z","updated_at":"2020-01-09T12:11:12.062Z","title":"Accusantium illo a sint nobis qui explicabo eum iusto facere aut.","description":"Modi laudantium possimus beatae dolorem molestias ut neque. Voluptatem libero harum id cupiditate. Officia et enim quia dolores at adipisci.\n\nEx officia quia at et vel aut. Esse consequatur officiis magnam vel velit eius. Sit cumque quo qui laborum tempore rerum in.\n\nQuibusdam provident quis molestiae laborum odio commodi. Impedit iure voluptatem possimus necessitatibus et error non. Iure est et ipsa recusandae et.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]}]} +{"name":"H5bp","path":"h5bp","owner_id":null,"created_at":"2020-01-09 12:08:57 UTC","updated_at":"2020-01-09 12:08:57 UTC","description":"A voluptate non sequi temporibus quam at.","avatar":{"url":null},"membership_lock":false,"share_with_group_lock":false,"visibility_level":20,"request_access_enabled":true,"ldap_sync_status":"ready","ldap_sync_error":null,"ldap_sync_last_update_at":null,"ldap_sync_last_successful_update_at":null,"ldap_sync_last_sync_at":null,"lfs_enabled":null,"parent_id":null,"repository_size_limit":null,"require_two_factor_authentication":false,"two_factor_grace_period":48,"plan_id":null,"project_creation_level":2,"file_template_project_id":null,"saml_discovery_token":"JZGRJbe3","custom_project_templates_group_id":null,"auto_devops_enabled":null,"last_ci_minutes_notification_at":null,"last_ci_minutes_usage_notification_level":null,"subgroup_creation_level":1,"emails_disabled":null,"max_pages_size":null,"max_artifacts_size":null,"mentions_disabled":null,"milestones":[],"badges":[],"labels":[{"id":69,"title":"Amfunc","color":"#2658d0","project_id":null,"created_at":"2020-01-09T12:08:57.693Z","updated_at":"2020-01-09T12:08:57.693Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":68,"title":"Aquacell","color":"#f658e0","project_id":null,"created_at":"2020-01-09T12:08:57.688Z","updated_at":"2020-01-09T12:08:57.688Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#333333"},{"id":62,"title":"Bryns","color":"#16f0b9","project_id":null,"created_at":"2020-01-09T12:08:57.672Z","updated_at":"2020-01-09T12:08:57.672Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":61,"title":"Pephfunc","color":"#556319","project_id":null,"created_at":"2020-01-09T12:08:57.669Z","updated_at":"2020-01-09T12:08:57.669Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":67,"title":"Sinesync","color":"#4c44e8","project_id":null,"created_at":"2020-01-09T12:08:57.685Z","updated_at":"2020-01-09T12:08:57.685Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":65,"title":"Traphwood","color":"#71b900","project_id":null,"created_at":"2020-01-09T12:08:57.679Z","updated_at":"2020-01-09T12:08:57.679Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":66,"title":"Tricell","color":"#179ad3","project_id":null,"created_at":"2020-01-09T12:08:57.683Z","updated_at":"2020-01-09T12:08:57.683Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":63,"title":"Trienceforge","color":"#cb1e0e","project_id":null,"created_at":"2020-01-09T12:08:57.674Z","updated_at":"2020-01-09T12:08:57.674Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"},{"id":64,"title":"Trinix","color":"#66ca41","project_id":null,"created_at":"2020-01-09T12:08:57.677Z","updated_at":"2020-01-09T12:08:57.677Z","template":false,"description":null,"group_id":28,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"}],"boards":[],"members":[{"id":8,"access_level":10,"source_id":28,"source_type":"Namespace","user_id":13,"notification_level":3,"created_at":"2020-01-09T12:08:57.884Z","updated_at":"2020-01-09T12:08:57.884Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":13,"public_email":"lorraine@leannon.info","username":"elina.lakin"}},{"id":7,"access_level":30,"source_id":28,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2020-01-09T12:08:57.129Z","updated_at":"2020-01-09T12:08:57.898Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"public_email":"admin@example.com","username":"root"}},{"id":9,"access_level":20,"source_id":28,"source_type":"Namespace","user_id":8,"notification_level":3,"created_at":"2020-01-09T12:08:57.901Z","updated_at":"2020-01-09T12:08:57.901Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":8,"public_email":"euna_schroeder@bernier.us","username":"loreen_medhurst"}},{"id":10,"access_level":40,"source_id":28,"source_type":"Namespace","user_id":10,"notification_level":3,"created_at":"2020-01-09T12:08:57.918Z","updated_at":"2020-01-09T12:08:57.918Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":10,"public_email":"glady_green@prohaska.biz","username":"maia_kuhlman"}}],"epics":[{"id":31,"group_id":28,"author_id":13,"assignee_id":null,"iid":1,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.006Z","updated_at":"2020-01-09T12:11:12.006Z","title":"Optio nihil consequatur et vel quaerat cupiditate.","description":"Vel molestias repellendus id voluptatem et non. Blanditiis natus veritatis adipisci qui illo. Sed est veritatis facilis dolore voluptas quibusdam aliquam omnis.\n\nFacere delectus quo architecto explicabo dolores. Quis odit nostrum nobis consequuntur cumque est officiis. Maiores ipsa nobis minus incidunt provident.\n\nVoluptate voluptatem debitis facilis architecto commodi vero. Sit quibusdam consectetur ad quis cupiditate. Exercitationem quasi inventore incidunt itaque optio autem accusantium.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":32,"group_id":28,"author_id":1,"assignee_id":null,"iid":2,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.021Z","updated_at":"2020-01-09T12:11:12.021Z","title":"Maxime cumque totam deleniti excepturi iusto qui sint.","description":"Nesciunt ut sit voluptas iusto rem. Sint doloribus ex et aliquam ea. Nihil necessitatibus distinctio similique incidunt. Consequatur voluptatibus excepturi qui quis quia. Quia optio quod non magnam dolorem id molestiae dignissimos.\n\nAt eligendi fuga veritatis accusamus quo dolores. Eos amet dolores nisi illo voluptatem consequuntur alias. Dolor veniam quas est sed. Ex corporis soluta sit ducimus facere et.\n\nEst odit asperiores vel quae quibusdam maiores quod. Debitis libero quo sed sunt voluptas praesentium. Ut nisi qui et culpa. Consequatur atque aut molestiae sint. Quaerat expedita animi distinctio repellat sed.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":33,"group_id":28,"author_id":8,"assignee_id":null,"iid":3,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.035Z","updated_at":"2020-01-09T12:11:12.035Z","title":"Corrupti perferendis labore omnis pariatur dolores aut repellendus quisquam id.","description":"Eligendi est asperiores minus nulla unde ex. Aspernatur repellat vel deleniti molestiae occaecati odio dicta. Ipsam excepturi quia modi ut autem sed. Omnis quae quam quas ut. Et corrupti aut omnis blanditiis.\n\nDolore dolorem accusamus tempore nihil dolores repellendus sed provident. Commodi consectetur blanditiis et consequatur laborum nulla eveniet facilis. Inventore aut officiis fuga est maiores rerum. Sint aspernatur et necessitatibus omnis qui et blanditiis.\n\nFugiat molestias nulla eos labore rerum perspiciatis non. Minus est et ipsum quis animi et. Id praesentium vitae in eum fugiat incidunt. Voluptas ut nemo ut cum saepe quasi dolores unde.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":34,"group_id":28,"author_id":10,"assignee_id":null,"iid":4,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.049Z","updated_at":"2020-01-09T12:11:12.049Z","title":"Architecto ipsa autem ducimus velit harum doloribus odio fugiat.","description":"Eos perferendis commodi labore id. Ipsa esse non voluptatem sit. Odit et et maiores quis adipisci sed earum.\n\nRerum asperiores consequuntur sed odit. Quis architecto nobis dolor sit consectetur. Inventore praesentium est magnam et reprehenderit impedit occaecati similique.\n\nTemporibus culpa ratione vel facilis perspiciatis rerum. Quisquam ut veniam quia sit totam. Quo ipsam quam dolorum quis. Totam porro nesciunt ut temporibus.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]},{"id":35,"group_id":28,"author_id":10,"assignee_id":null,"iid":5,"updated_by_id":null,"last_edited_by_id":null,"lock_version":0,"start_date":null,"end_date":null,"last_edited_at":null,"created_at":"2020-01-09T12:11:12.062Z","updated_at":"2020-01-09T12:11:12.062Z","title":"Accusantium illo a sint nobis qui explicabo eum iusto facere aut.","description":"Modi laudantium possimus beatae dolorem molestias ut neque. Voluptatem libero harum id cupiditate. Officia et enim quia dolores at adipisci.\n\nEx officia quia at et vel aut. Esse consequatur officiis magnam vel velit eius. Sit cumque quo qui laborum tempore rerum in.\n\nQuibusdam provident quis molestiae laborum odio commodi. Impedit iure voluptatem possimus necessitatibus et error non. Iure est et ipsa recusandae et.","start_date_sourcing_milestone_id":null,"due_date_sourcing_milestone_id":null,"start_date_fixed":null,"due_date_fixed":null,"start_date_is_fixed":null,"due_date_is_fixed":null,"closed_by_id":null,"closed_at":null,"parent_id":null,"relative_position":null,"state_id":"opened","start_date_sourcing_epic_id":null,"due_date_sourcing_epic_id":null,"notes":[]}]} diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json index fe885861d00..e3aeace6383 100644 --- a/spec/fixtures/lib/gitlab/import_export/complex/project.json +++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json @@ -2398,7 +2398,7 @@ "requested_at": null, "user": { "id": 16, - "email": "bernard_willms@gitlabexample.com", + "public_email": "bernard_willms@gitlabexample.com", "username": "bernard_willms" } }, @@ -2418,7 +2418,7 @@ "requested_at": null, "user": { "id": 6, - "email": "saul_will@gitlabexample.com", + "public_email": "saul_will@gitlabexample.com", "username": "saul_will" } }, @@ -2438,7 +2438,7 @@ "requested_at": null, "user": { "id": 15, - "email": "breanna_sanford@wolf.com", + "public_email": "breanna_sanford@wolf.com", "username": "emmet.schamberger" } }, @@ -2458,7 +2458,7 @@ "requested_at": null, "user": { "id": 26, - "email": "user4@example.com", + "public_email": "user4@example.com", "username": "user4" } } diff --git a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/project_members.ndjson b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/project_members.ndjson index d8be7b5d164..a010739b32a 100644 --- a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/project_members.ndjson +++ b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/project_members.ndjson @@ -1,4 +1,4 @@ -{"id":36,"access_level":40,"source_id":5,"source_type":"Project","user_id":16,"notification_level":3,"created_at":"2016-06-14T15:02:03.834Z","updated_at":"2016-06-14T15:02:03.834Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":16,"email":"bernard_willms@gitlabexample.com","username":"bernard_willms"}} -{"id":35,"access_level":10,"source_id":5,"source_type":"Project","user_id":6,"notification_level":3,"created_at":"2016-06-14T15:02:03.811Z","updated_at":"2016-06-14T15:02:03.811Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":6,"email":"saul_will@gitlabexample.com","username":"saul_will"}} -{"id":34,"access_level":20,"source_id":5,"source_type":"Project","user_id":15,"notification_level":3,"created_at":"2016-06-14T15:02:03.776Z","updated_at":"2016-06-14T15:02:03.776Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":15,"email":"breanna_sanford@wolf.com","username":"emmet.schamberger"}} -{"id":33,"access_level":20,"source_id":5,"source_type":"Project","user_id":26,"notification_level":3,"created_at":"2016-06-14T15:02:03.742Z","updated_at":"2016-06-14T15:02:03.742Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":26,"email":"user4@example.com","username":"user4"}} +{"id":36,"access_level":40,"source_id":5,"source_type":"Project","user_id":16,"notification_level":3,"created_at":"2016-06-14T15:02:03.834Z","updated_at":"2016-06-14T15:02:03.834Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":16,"public_email":"bernard_willms@gitlabexample.com","username":"bernard_willms"}} +{"id":35,"access_level":10,"source_id":5,"source_type":"Project","user_id":6,"notification_level":3,"created_at":"2016-06-14T15:02:03.811Z","updated_at":"2016-06-14T15:02:03.811Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":6,"public_email":"saul_will@gitlabexample.com","username":"saul_will"}} +{"id":34,"access_level":20,"source_id":5,"source_type":"Project","user_id":15,"notification_level":3,"created_at":"2016-06-14T15:02:03.776Z","updated_at":"2016-06-14T15:02:03.776Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":15,"public_email":"breanna_sanford@wolf.com","username":"emmet.schamberger"}} +{"id":33,"access_level":20,"source_id":5,"source_type":"Project","user_id":26,"notification_level":3,"created_at":"2016-06-14T15:02:03.742Z","updated_at":"2016-06-14T15:02:03.742Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"user":{"id":26,"public_email":"user4@example.com","username":"user4"}} diff --git a/spec/fixtures/lib/gitlab/import_export/designs/project.json b/spec/fixtures/lib/gitlab/import_export/designs/project.json index 1d51a726c4c..16dd805c132 100644 --- a/spec/fixtures/lib/gitlab/import_export/designs/project.json +++ b/spec/fixtures/lib/gitlab/import_export/designs/project.json @@ -425,7 +425,7 @@ "override":false, "user":{ "id":1, - "email":"admin@example.com", + "public_email":"admin@example.com", "username":"root" } }, @@ -448,7 +448,7 @@ "override":false, "user":{ "id":2, - "email":"user_2@gitlabexample.com", + "public_email":"user_2@gitlabexample.com", "username":"user_2" } } diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/group.json b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/group.json index a5a85dc661f..1719e744d04 100644 --- a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/group.json +++ b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/group.json @@ -377,7 +377,7 @@ "override": false, "user": { "id": 42, - "email": "moriah@collinsmurphy.com", + "public_email": "moriah@collinsmurphy.com", "username": "reported_user_15" } }, @@ -400,7 +400,7 @@ "override": false, "user": { "id": 271, - "email": "garret@connellystark.ca", + "public_email": "garret@connellystark.ca", "username": "charlesetta" } }, @@ -423,7 +423,7 @@ "override": false, "user": { "id": 206, - "email": "gwendolyn_robel@gitlabexample.com", + "public_email": "gwendolyn_robel@gitlabexample.com", "username": "gwendolyn_robel" } }, @@ -446,7 +446,7 @@ "override": false, "user": { "id": 39, - "email": "alexis_berge@kerlukeklein.us", + "public_email": "alexis_berge@kerlukeklein.us", "username": "reported_user_12" } }, @@ -469,7 +469,7 @@ "override": false, "user": { "id": 1624, - "email": "adriene.mcclure@gitlabexample.com", + "public_email": "adriene.mcclure@gitlabexample.com", "username": "adriene.mcclure" } }, @@ -492,7 +492,7 @@ "override": false, "user": { "id": 1, - "email": "admin@example.com", + "public_email": "admin@example.com", "username": "root" } } @@ -1338,7 +1338,7 @@ "override": false, "user": { "id": 1087, - "email": "paige@blanda.info", + "public_email": "paige@blanda.info", "username": "billi_auer" } }, @@ -1361,7 +1361,7 @@ "override": false, "user": { "id": 171, - "email": "heidi@bosco.co.uk", + "public_email": "heidi@bosco.co.uk", "username": "gerard.cruickshank" } }, @@ -1384,7 +1384,7 @@ "override": false, "user": { "id": 1157, - "email": "larisa.bruen@carroll.biz", + "public_email": "larisa.bruen@carroll.biz", "username": "milagros.reynolds" } }, @@ -1407,7 +1407,7 @@ "override": false, "user": { "id": 14, - "email": "madlyn_kovacek@wiza.ca", + "public_email": "madlyn_kovacek@wiza.ca", "username": "monique.gusikowski" } }, @@ -1430,7 +1430,7 @@ "override": false, "user": { "id": 1167, - "email": "mirella@koepp.ca", + "public_email": "mirella@koepp.ca", "username": "eileen" } }, @@ -1453,7 +1453,7 @@ "override": false, "user": { "id": 1, - "email": "admin@example.com", + "public_email": "admin@example.com", "username": "root" } } @@ -1909,7 +1909,7 @@ "override": false, "user": { "id": 1533, - "email": "jose@cassin.ca", + "public_email": "jose@cassin.ca", "username": "buster" } }, @@ -1932,7 +1932,7 @@ "override": false, "user": { "id": 1586, - "email": "carie@gleichner.us", + "public_email": "carie@gleichner.us", "username": "dominque" } }, @@ -1955,7 +1955,7 @@ "override": false, "user": { "id": 190, - "email": "delois@funk.biz", + "public_email": "delois@funk.biz", "username": "kittie" } }, @@ -1978,7 +1978,7 @@ "override": false, "user": { "id": 254, - "email": "tyra.lowe@whitemckenzie.co.uk", + "public_email": "tyra.lowe@whitemckenzie.co.uk", "username": "kassie" } }, @@ -2001,7 +2001,7 @@ "override": false, "user": { "id": 503, - "email": "tyesha.brakus@bruen.ca", + "public_email": "tyesha.brakus@bruen.ca", "username": "charise" } }, @@ -2024,7 +2024,7 @@ "override": false, "user": { "id": 1, - "email": "admin@example.com", + "public_email": "admin@example.com", "username": "root" } } diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4351/members.ndjson b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4351/members.ndjson index ec3733a2b2b..74781bfabe2 100644 --- a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4351/members.ndjson +++ b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4351/members.ndjson @@ -1,6 +1,6 @@ -{"id":13766,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":42,"notification_level":3,"created_at":"2019-11-20T17:04:36.184Z","updated_at":"2019-11-20T17:04:36.184Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":42,"email":"moriah@collinsmurphy.com","username":"reported_user_15"}} -{"id":13765,"access_level":40,"source_id":4351,"source_type":"Namespace","user_id":271,"notification_level":3,"created_at":"2019-11-20T17:04:36.044Z","updated_at":"2019-11-20T17:04:36.044Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":271,"email":"garret@connellystark.ca","username":"charlesetta"}} -{"id":13764,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":206,"notification_level":3,"created_at":"2019-11-20T17:04:35.840Z","updated_at":"2019-11-20T17:04:35.840Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":206,"email":"gwendolyn_robel@gitlabexample.com","username":"gwendolyn_robel"}} -{"id":13763,"access_level":10,"source_id":4351,"source_type":"Namespace","user_id":39,"notification_level":3,"created_at":"2019-11-20T17:04:35.704Z","updated_at":"2019-11-20T17:04:35.704Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":39,"email":"alexis_berge@kerlukeklein.us","username":"reported_user_12"}} -{"id":13762,"access_level":20,"source_id":4351,"source_type":"Namespace","user_id":1624,"notification_level":3,"created_at":"2019-11-20T17:04:35.566Z","updated_at":"2019-11-20T17:04:35.566Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1624,"email":"adriene.mcclure@gitlabexample.com","username":"adriene.mcclure"}} -{"id":12920,"access_level":50,"source_id":4351,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:53.505Z","updated_at":"2019-11-20T17:01:53.505Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"email":"admin@example.com","username":"root"}} +{"id":13766,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":42,"notification_level":3,"created_at":"2019-11-20T17:04:36.184Z","updated_at":"2019-11-20T17:04:36.184Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":42,"public_email":"moriah@collinsmurphy.com","username":"reported_user_15"}} +{"id":13765,"access_level":40,"source_id":4351,"source_type":"Namespace","user_id":271,"notification_level":3,"created_at":"2019-11-20T17:04:36.044Z","updated_at":"2019-11-20T17:04:36.044Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":271,"public_email":"garret@connellystark.ca","username":"charlesetta"}} +{"id":13764,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":206,"notification_level":3,"created_at":"2019-11-20T17:04:35.840Z","updated_at":"2019-11-20T17:04:35.840Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":206,"public_email":"gwendolyn_robel@gitlabexample.com","username":"gwendolyn_robel"}} +{"id":13763,"access_level":10,"source_id":4351,"source_type":"Namespace","user_id":39,"notification_level":3,"created_at":"2019-11-20T17:04:35.704Z","updated_at":"2019-11-20T17:04:35.704Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":39,"public_email":"alexis_berge@kerlukeklein.us","username":"reported_user_12"}} +{"id":13762,"access_level":20,"source_id":4351,"source_type":"Namespace","user_id":1624,"notification_level":3,"created_at":"2019-11-20T17:04:35.566Z","updated_at":"2019-11-20T17:04:35.566Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1624,"public_email":"adriene.mcclure@gitlabexample.com","username":"adriene.mcclure"}} +{"id":12920,"access_level":50,"source_id":4351,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:53.505Z","updated_at":"2019-11-20T17:01:53.505Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"public_email":"admin@example.com","username":"root"}} diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4352/members.ndjson b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4352/members.ndjson index 8f9dd22804a..ca586cdcee6 100644 --- a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4352/members.ndjson +++ b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4352/members.ndjson @@ -1,6 +1,6 @@ -{"id":13771,"access_level":30,"source_id":4352,"source_type":"Namespace","user_id":1087,"notification_level":3,"created_at":"2019-11-20T17:04:36.968Z","updated_at":"2019-11-20T17:04:36.968Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1087,"email":"paige@blanda.info","username":"billi_auer"}} -{"id":13770,"access_level":20,"source_id":4352,"source_type":"Namespace","user_id":171,"notification_level":3,"created_at":"2019-11-20T17:04:36.821Z","updated_at":"2019-11-20T17:04:36.821Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":171,"email":"heidi@bosco.co.uk","username":"gerard.cruickshank"}} -{"id":13769,"access_level":30,"source_id":4352,"source_type":"Namespace","user_id":1157,"notification_level":3,"created_at":"2019-11-20T17:04:36.606Z","updated_at":"2019-11-20T17:04:36.606Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1157,"email":"larisa.bruen@carroll.biz","username":"milagros.reynolds"}} -{"id":13768,"access_level":40,"source_id":4352,"source_type":"Namespace","user_id":14,"notification_level":3,"created_at":"2019-11-20T17:04:36.465Z","updated_at":"2019-11-20T17:04:36.465Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":14,"email":"madlyn_kovacek@wiza.ca","username":"monique.gusikowski"}} -{"id":13767,"access_level":10,"source_id":4352,"source_type":"Namespace","user_id":1167,"notification_level":3,"created_at":"2019-11-20T17:04:36.324Z","updated_at":"2019-11-20T17:04:36.324Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1167,"email":"mirella@koepp.ca","username":"eileen"}} -{"id":12921,"access_level":50,"source_id":4352,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:53.953Z","updated_at":"2019-11-20T17:01:53.953Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"email":"admin@example.com","username":"root"}} +{"id":13771,"access_level":30,"source_id":4352,"source_type":"Namespace","user_id":1087,"notification_level":3,"created_at":"2019-11-20T17:04:36.968Z","updated_at":"2019-11-20T17:04:36.968Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1087,"public_email":"paige@blanda.info","username":"billi_auer"}} +{"id":13770,"access_level":20,"source_id":4352,"source_type":"Namespace","user_id":171,"notification_level":3,"created_at":"2019-11-20T17:04:36.821Z","updated_at":"2019-11-20T17:04:36.821Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":171,"public_email":"heidi@bosco.co.uk","username":"gerard.cruickshank"}} +{"id":13769,"access_level":30,"source_id":4352,"source_type":"Namespace","user_id":1157,"notification_level":3,"created_at":"2019-11-20T17:04:36.606Z","updated_at":"2019-11-20T17:04:36.606Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1157,"public_email":"larisa.bruen@carroll.biz","username":"milagros.reynolds"}} +{"id":13768,"access_level":40,"source_id":4352,"source_type":"Namespace","user_id":14,"notification_level":3,"created_at":"2019-11-20T17:04:36.465Z","updated_at":"2019-11-20T17:04:36.465Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":14,"public_email":"madlyn_kovacek@wiza.ca","username":"monique.gusikowski"}} +{"id":13767,"access_level":10,"source_id":4352,"source_type":"Namespace","user_id":1167,"notification_level":3,"created_at":"2019-11-20T17:04:36.324Z","updated_at":"2019-11-20T17:04:36.324Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1167,"public_email":"mirella@koepp.ca","username":"eileen"}} +{"id":12921,"access_level":50,"source_id":4352,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:53.953Z","updated_at":"2019-11-20T17:01:53.953Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"public_email":"admin@example.com","username":"root"}} diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4353/members.ndjson b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4353/members.ndjson index 7a36a035c09..78675c4c6c8 100644 --- a/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4353/members.ndjson +++ b/spec/fixtures/lib/gitlab/import_export/group_exports/complex/tree/groups/4353/members.ndjson @@ -1,6 +1,6 @@ -{"id":13786,"access_level":30,"source_id":4355,"source_type":"Namespace","user_id":1533,"notification_level":3,"created_at":"2019-11-20T17:04:39.405Z","updated_at":"2019-11-20T17:04:39.405Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1533,"email":"jose@cassin.ca","username":"buster"}} -{"id":13785,"access_level":10,"source_id":4355,"source_type":"Namespace","user_id":1586,"notification_level":3,"created_at":"2019-11-20T17:04:39.269Z","updated_at":"2019-11-20T17:04:39.269Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1586,"email":"carie@gleichner.us","username":"dominque"}} -{"id":13784,"access_level":30,"source_id":4355,"source_type":"Namespace","user_id":190,"notification_level":3,"created_at":"2019-11-20T17:04:39.127Z","updated_at":"2019-11-20T17:04:39.127Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":190,"email":"delois@funk.biz","username":"kittie"}} -{"id":13783,"access_level":20,"source_id":4355,"source_type":"Namespace","user_id":254,"notification_level":3,"created_at":"2019-11-20T17:04:38.971Z","updated_at":"2019-11-20T17:04:38.971Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":254,"email":"tyra.lowe@whitemckenzie.co.uk","username":"kassie"}} -{"id":13782,"access_level":40,"source_id":4355,"source_type":"Namespace","user_id":503,"notification_level":3,"created_at":"2019-11-20T17:04:38.743Z","updated_at":"2019-11-20T17:04:38.743Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":503,"email":"tyesha.brakus@bruen.ca","username":"charise"}} -{"id":12924,"access_level":50,"source_id":4355,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:54.145Z","updated_at":"2019-11-20T17:01:54.145Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"email":"admin@example.com","username":"root"}} +{"id":13786,"access_level":30,"source_id":4355,"source_type":"Namespace","user_id":1533,"notification_level":3,"created_at":"2019-11-20T17:04:39.405Z","updated_at":"2019-11-20T17:04:39.405Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1533,"public_email":"jose@cassin.ca","username":"buster"}} +{"id":13785,"access_level":10,"source_id":4355,"source_type":"Namespace","user_id":1586,"notification_level":3,"created_at":"2019-11-20T17:04:39.269Z","updated_at":"2019-11-20T17:04:39.269Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1586,"public_email":"carie@gleichner.us","username":"dominque"}} +{"id":13784,"access_level":30,"source_id":4355,"source_type":"Namespace","user_id":190,"notification_level":3,"created_at":"2019-11-20T17:04:39.127Z","updated_at":"2019-11-20T17:04:39.127Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":190,"public_email":"delois@funk.biz","username":"kittie"}} +{"id":13783,"access_level":20,"source_id":4355,"source_type":"Namespace","user_id":254,"notification_level":3,"created_at":"2019-11-20T17:04:38.971Z","updated_at":"2019-11-20T17:04:38.971Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":254,"public_email":"tyra.lowe@whitemckenzie.co.uk","username":"kassie"}} +{"id":13782,"access_level":40,"source_id":4355,"source_type":"Namespace","user_id":503,"notification_level":3,"created_at":"2019-11-20T17:04:38.743Z","updated_at":"2019-11-20T17:04:38.743Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":503,"public_email":"tyesha.brakus@bruen.ca","username":"charise"}} +{"id":12924,"access_level":50,"source_id":4355,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:54.145Z","updated_at":"2019-11-20T17:01:54.145Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"public_email":"admin@example.com","username":"root"}} diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json b/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json index 158cd22ed2f..2751f9ab8f2 100644 --- a/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json +++ b/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json @@ -299,7 +299,7 @@ "override": false, "user": { "id": 42, - "email": "moriah@collinsmurphy.com", + "public_email": "moriah@collinsmurphy.com", "username": "reported_user_15" } }, @@ -322,7 +322,7 @@ "override": false, "user": { "id": 271, - "email": "garret@connellystark.ca", + "public_email": "garret@connellystark.ca", "username": "charlesetta" } }, @@ -345,7 +345,7 @@ "override": false, "user": { "id": 206, - "email": "margaret.bergnaum@reynolds.us", + "public_email": "margaret.bergnaum@reynolds.us", "username": "gwendolyn_robel" } }, @@ -368,7 +368,7 @@ "override": false, "user": { "id": 39, - "email": "alexis_berge@kerlukeklein.us", + "public_email": "alexis_berge@kerlukeklein.us", "username": "reported_user_12" } }, @@ -391,7 +391,7 @@ "override": false, "user": { "id": 1624, - "email": "nakesha.herzog@powlowski.com", + "public_email": "nakesha.herzog@powlowski.com", "username": "adriene.mcclure" } }, @@ -414,7 +414,7 @@ "override": false, "user": { "id": 1, - "email": "admin@example.com", + "public_email": "admin@example.com", "username": "root" } } diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/tree/groups/4353/members.ndjson b/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/tree/groups/4353/members.ndjson index 740c724ac5d..09a6d2489d7 100644 --- a/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/tree/groups/4353/members.ndjson +++ b/spec/fixtures/lib/gitlab/import_export/group_exports/no_children/tree/groups/4353/members.ndjson @@ -1,6 +1,6 @@ -{"id":13766,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":42,"notification_level":3,"created_at":"2019-11-20T17:04:36.184Z","updated_at":"2019-11-20T17:04:36.184Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":42,"email":"moriah@collinsmurphy.com","username":"reported_user_15"}} -{"id":13765,"access_level":40,"source_id":4351,"source_type":"Namespace","user_id":271,"notification_level":3,"created_at":"2019-11-20T17:04:36.044Z","updated_at":"2019-11-20T17:04:36.044Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":271,"email":"garret@connellystark.ca","username":"charlesetta"}} -{"id":13764,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":206,"notification_level":3,"created_at":"2019-11-20T17:04:35.840Z","updated_at":"2019-11-20T17:04:35.840Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":206,"email":"margaret.bergnaum@reynolds.us","username":"gwendolyn_robel"}} -{"id":13763,"access_level":10,"source_id":4351,"source_type":"Namespace","user_id":39,"notification_level":3,"created_at":"2019-11-20T17:04:35.704Z","updated_at":"2019-11-20T17:04:35.704Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":39,"email":"alexis_berge@kerlukeklein.us","username":"reported_user_12"}} -{"id":13762,"access_level":20,"source_id":4351,"source_type":"Namespace","user_id":1624,"notification_level":3,"created_at":"2019-11-20T17:04:35.566Z","updated_at":"2019-11-20T17:04:35.566Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1624,"email":"nakesha.herzog@powlowski.com","username":"adriene.mcclure"}} -{"id":12920,"access_level":50,"source_id":4351,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:53.505Z","updated_at":"2019-11-20T17:01:53.505Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"email":"admin@example.com","username":"root"}} +{"id":13766,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":42,"notification_level":3,"created_at":"2019-11-20T17:04:36.184Z","updated_at":"2019-11-20T17:04:36.184Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":42,"public_email":"moriah@collinsmurphy.com","username":"reported_user_15"}} +{"id":13765,"access_level":40,"source_id":4351,"source_type":"Namespace","user_id":271,"notification_level":3,"created_at":"2019-11-20T17:04:36.044Z","updated_at":"2019-11-20T17:04:36.044Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":271,"public_email":"garret@connellystark.ca","username":"charlesetta"}} +{"id":13764,"access_level":30,"source_id":4351,"source_type":"Namespace","user_id":206,"notification_level":3,"created_at":"2019-11-20T17:04:35.840Z","updated_at":"2019-11-20T17:04:35.840Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":206,"public_email":"margaret.bergnaum@reynolds.us","username":"gwendolyn_robel"}} +{"id":13763,"access_level":10,"source_id":4351,"source_type":"Namespace","user_id":39,"notification_level":3,"created_at":"2019-11-20T17:04:35.704Z","updated_at":"2019-11-20T17:04:35.704Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":39,"public_email":"alexis_berge@kerlukeklein.us","username":"reported_user_12"}} +{"id":13762,"access_level":20,"source_id":4351,"source_type":"Namespace","user_id":1624,"notification_level":3,"created_at":"2019-11-20T17:04:35.566Z","updated_at":"2019-11-20T17:04:35.566Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1624,"public_email":"nakesha.herzog@powlowski.com","username":"adriene.mcclure"}} +{"id":12920,"access_level":50,"source_id":4351,"source_type":"Namespace","user_id":1,"notification_level":3,"created_at":"2019-11-20T17:01:53.505Z","updated_at":"2019-11-20T17:01:53.505Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"requested_at":null,"expires_at":null,"ldap":false,"override":false,"user":{"id":1,"public_email":"admin@example.com","username":"root"}} diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js index e0ba6b2e8da..661c8d99477 100644 --- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js +++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js @@ -33,8 +33,6 @@ describe('Pipelines filtered search', () => { }; beforeEach(() => { - window.gon = { features: { pipelineSourceFilter: true } }; - mock = new MockAdapter(axios); jest.spyOn(Api, 'projectUsers').mockResolvedValue(users); diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index 76feaaad1ec..aa30062c987 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -105,8 +105,6 @@ describe('Pipelines', () => { }); beforeEach(() => { - window.gon = { features: { pipelineSourceFilter: true } }; - mock = new MockAdapter(axios); jest.spyOn(window.history, 'pushState'); diff --git a/spec/helpers/integrations_helper_spec.rb b/spec/helpers/integrations_helper_spec.rb index 8e652d2f150..3a7d4d12513 100644 --- a/spec/helpers/integrations_helper_spec.rb +++ b/spec/helpers/integrations_helper_spec.rb @@ -98,4 +98,19 @@ RSpec.describe IntegrationsHelper do end end end + + describe '#jira_issue_breadcrumb_link' do + let(:issue_reference) { nil } + + subject { helper.jira_issue_breadcrumb_link(issue_reference) } + + context 'when issue_reference contains HTML' do + let(:issue_reference) { "" } + + it 'escapes issue reference' do + is_expected.not_to include(issue_reference) + is_expected.to include(html_escape(issue_reference)) + end + end + end end diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb index 2cc1bf41d18..32eea82cfdf 100644 --- a/spec/lib/backup/manager_spec.rb +++ b/spec/lib/backup/manager_spec.rb @@ -432,6 +432,77 @@ RSpec.describe Backup::Manager do end end + context 'with AWS with server side encryption' do + let(:connection) { ::Fog::Storage.new(Gitlab.config.backup.upload.connection.symbolize_keys) } + let(:encryption_key) { nil } + let(:encryption) { nil } + let(:storage_options) { nil } + + before do + stub_backup_setting( + upload: { + connection: { + provider: 'AWS', + aws_access_key_id: 'AWS_ACCESS_KEY_ID', + aws_secret_access_key: 'AWS_SECRET_ACCESS_KEY' + }, + remote_directory: 'directory', + multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size, + encryption: encryption, + encryption_key: encryption_key, + storage_options: storage_options, + storage_class: nil + } + ) + + connection.directories.create(key: Gitlab.config.backup.upload.remote_directory) + end + + context 'with SSE-S3 without using storage_options' do + let(:encryption) { 'AES256' } + + it 'sets encryption attributes' do + result = subject.upload + + expect(result.key).to be_present + expect(result.encryption).to eq('AES256') + expect(result.encryption_key).to be_nil + expect(result.kms_key_id).to be_nil + end + end + + context 'with SSE-C (customer-provided keys) options' do + let(:encryption) { 'AES256' } + let(:encryption_key) { SecureRandom.hex } + + it 'sets encryption attributes' do + result = subject.upload + + expect(result.key).to be_present + expect(result.encryption).to eq(encryption) + expect(result.encryption_key).to eq(encryption_key) + expect(result.kms_key_id).to be_nil + end + end + + context 'with SSE-KMS options' do + let(:storage_options) do + { + server_side_encryption: 'aws:kms', + server_side_encryption_kms_key_id: 'arn:aws:kms:12345' + } + end + + it 'sets encryption attributes' do + result = subject.upload + + expect(result.key).to be_present + expect(result.encryption).to eq('aws:kms') + expect(result.kms_key_id).to eq('arn:aws:kms:12345') + end + end + end + context 'with Google provider' do before do stub_backup_setting( diff --git a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb index cb1f3d520a4..d616aabea45 100644 --- a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb @@ -90,11 +90,8 @@ RSpec.describe Banzai::Filter::References::DesignReferenceFilter do [ ['simple.png'], ['SIMPLE.PNG'], - ['has spaces.png'], ['has-hyphen.jpg'], - ['snake_case.svg'], - ['has "quotes".svg'], - ['has characters [o].svg'] + ['snake_case.svg'] ] end @@ -138,40 +135,25 @@ RSpec.describe Banzai::Filter::References::DesignReferenceFilter do end end - context 'a design with a quoted filename' do - let(:filename) { %q{A "very" good file.png} } - let(:design) { create(:design, :with_versions, issue: issue, filename: filename) } - - it 'links to the design' do - expect(doc.css('a').first.attr('href')) - .to eq url_for_design(design) - end - end - context 'internal reference' do it_behaves_like 'a reference containing an element node' - context 'the reference is valid' do - it_behaves_like 'a good link reference' + it_behaves_like 'a good link reference' - context 'the filename needs to be escaped' do - where(:filename) do - [ - ['with some spaces.png'], - ['with